create-ekka-desktop-app 0.2.2 → 0.2.3
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/package.json +1 -1
- package/template/src-tauri/Cargo.toml +1 -0
- package/template/src-tauri/build.rs +46 -0
- package/template/src-tauri/src/commands.rs +13 -9
- package/template/src-tauri/src/engine_process.rs +3 -3
- package/template/src-tauri/src/main.rs +13 -4
- package/template/src-tauri/src/node_auth.rs +5 -3
- package/template/src-tauri/src/ops/home.rs +5 -5
- package/template/src-tauri/src/state.rs +12 -11
package/package.json
CHANGED
|
@@ -1,3 +1,49 @@
|
|
|
1
1
|
fn main() {
|
|
2
|
+
// Rerun if env files change (check both src-tauri and project root)
|
|
3
|
+
println!("cargo:rerun-if-changed=.env");
|
|
4
|
+
println!("cargo:rerun-if-changed=.env.local");
|
|
5
|
+
println!("cargo:rerun-if-changed=../.env");
|
|
6
|
+
println!("cargo:rerun-if-changed=../.env.local");
|
|
7
|
+
|
|
8
|
+
// Load env files: try src-tauri first, then project root
|
|
9
|
+
// .env.local takes precedence over .env
|
|
10
|
+
let _ = dotenvy::from_filename(".env.local");
|
|
11
|
+
let _ = dotenvy::from_filename(".env");
|
|
12
|
+
let _ = dotenvy::from_filename("../.env.local");
|
|
13
|
+
let _ = dotenvy::from_filename("../.env");
|
|
14
|
+
|
|
15
|
+
// EKKA_ENGINE_URL is required at build time
|
|
16
|
+
let engine_url = std::env::var("EKKA_ENGINE_URL").unwrap_or_else(|_| {
|
|
17
|
+
panic!(
|
|
18
|
+
"\n\n\
|
|
19
|
+
╔══════════════════════════════════════════════════════════════════╗\n\
|
|
20
|
+
║ BUILD ERROR: EKKA_ENGINE_URL is not set ║\n\
|
|
21
|
+
╠══════════════════════════════════════════════════════════════════╣\n\
|
|
22
|
+
║ Add EKKA_ENGINE_URL to .env.local or .env before building: ║\n\
|
|
23
|
+
║ ║\n\
|
|
24
|
+
║ echo 'EKKA_ENGINE_URL=https://api.ekka.ai' >> .env.local ║\n\
|
|
25
|
+
║ ║\n\
|
|
26
|
+
╚══════════════════════════════════════════════════════════════════╝\n\n"
|
|
27
|
+
)
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
if engine_url.trim().is_empty() {
|
|
31
|
+
panic!(
|
|
32
|
+
"\n\n\
|
|
33
|
+
╔══════════════════════════════════════════════════════════════════╗\n\
|
|
34
|
+
║ BUILD ERROR: EKKA_ENGINE_URL is empty ║\n\
|
|
35
|
+
╠══════════════════════════════════════════════════════════════════╣\n\
|
|
36
|
+
║ Set a valid URL in .env.local or .env: ║\n\
|
|
37
|
+
║ ║\n\
|
|
38
|
+
║ EKKA_ENGINE_URL=https://api.ekka.ai ║\n\
|
|
39
|
+
║ ║\n\
|
|
40
|
+
╚══════════════════════════════════════════════════════════════════╝\n\n"
|
|
41
|
+
)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Bake EKKA_ENGINE_URL into the binary at compile time
|
|
45
|
+
println!("cargo:rustc-env=EKKA_ENGINE_URL={}", engine_url);
|
|
46
|
+
|
|
47
|
+
// Continue with tauri build
|
|
2
48
|
tauri_build::build()
|
|
3
49
|
}
|
|
@@ -455,9 +455,10 @@ fn handle_node_credentials_clear() -> EngineResponse {
|
|
|
455
455
|
fn handle_runner_task_stats(state: &EngineState) -> EngineResponse {
|
|
456
456
|
use crate::state::NodeAuthState;
|
|
457
457
|
|
|
458
|
-
// Get engine URL (
|
|
459
|
-
let engine_url =
|
|
460
|
-
.
|
|
458
|
+
// Get engine URL (baked at build time)
|
|
459
|
+
let engine_url = option_env!("EKKA_ENGINE_URL")
|
|
460
|
+
.unwrap_or("https://api.ekka.ai")
|
|
461
|
+
.to_string();
|
|
461
462
|
|
|
462
463
|
// Get node auth token for Authorization header
|
|
463
464
|
let node_token = match state.get_node_auth_token() {
|
|
@@ -819,8 +820,9 @@ fn handle_bootstrap_node_session(payload: &Value, state: &EngineState) -> Engine
|
|
|
819
820
|
if start_runner {
|
|
820
821
|
// Build runner config from node auth token
|
|
821
822
|
let runner_config = node_auth::NodeSessionRunnerConfig {
|
|
822
|
-
engine_url:
|
|
823
|
-
.
|
|
823
|
+
engine_url: option_env!("EKKA_ENGINE_URL")
|
|
824
|
+
.map(|s| s.to_string())
|
|
825
|
+
.or_else(|| std::env::var("ENGINE_URL").ok())
|
|
824
826
|
.unwrap_or_default(),
|
|
825
827
|
node_url: std::env::var("NODE_URL").unwrap_or_else(|_| "http://127.0.0.1:7777".to_string()),
|
|
826
828
|
session_token: node_token.token.clone(),
|
|
@@ -913,8 +915,9 @@ fn build_security_headers(jwt: Option<&str>, module: &str, action: &str) -> Vec<
|
|
|
913
915
|
|
|
914
916
|
/// Create a workflow run (POST /engine/workflow-runs)
|
|
915
917
|
fn handle_workflow_runs_create(payload: &Value) -> EngineResponse {
|
|
916
|
-
let engine_url =
|
|
917
|
-
.
|
|
918
|
+
let engine_url = option_env!("EKKA_ENGINE_URL")
|
|
919
|
+
.unwrap_or("http://localhost:3200")
|
|
920
|
+
.to_string();
|
|
918
921
|
|
|
919
922
|
// Extract request body
|
|
920
923
|
let request = match payload.get("request") {
|
|
@@ -974,8 +977,9 @@ fn handle_workflow_runs_create(payload: &Value) -> EngineResponse {
|
|
|
974
977
|
|
|
975
978
|
/// Get a workflow run (GET /engine/workflow-runs/{id})
|
|
976
979
|
fn handle_workflow_runs_get(payload: &Value) -> EngineResponse {
|
|
977
|
-
let engine_url =
|
|
978
|
-
.
|
|
980
|
+
let engine_url = option_env!("EKKA_ENGINE_URL")
|
|
981
|
+
.unwrap_or("http://localhost:3200")
|
|
982
|
+
.to_string();
|
|
979
983
|
|
|
980
984
|
// Extract workflow run ID
|
|
981
985
|
let id = match payload.get("id").and_then(|v| v.as_str()) {
|
|
@@ -46,9 +46,9 @@ fn build_engine_env() -> Result<Vec<(&'static str, String)>, &'static str> {
|
|
|
46
46
|
// EKKA_RUNNER_MODE=engine (always set)
|
|
47
47
|
env.push(("EKKA_RUNNER_MODE", "engine".to_string()));
|
|
48
48
|
|
|
49
|
-
// EKKA_ENGINE_URL -
|
|
50
|
-
if let
|
|
51
|
-
env.push(("EKKA_ENGINE_URL", url));
|
|
49
|
+
// EKKA_ENGINE_URL - baked at build time
|
|
50
|
+
if let Some(url) = option_env!("EKKA_ENGINE_URL") {
|
|
51
|
+
env.push(("EKKA_ENGINE_URL", url.to_string()));
|
|
52
52
|
}
|
|
53
53
|
|
|
54
54
|
// EKKA_INTERNAL_SERVICE_KEY - required for engine mode
|
|
@@ -74,6 +74,14 @@ fn main() {
|
|
|
74
74
|
"Required security env vars"
|
|
75
75
|
);
|
|
76
76
|
|
|
77
|
+
// Log build-time baked engine URL presence (not the URL itself)
|
|
78
|
+
let engine_url_baked = option_env!("EKKA_ENGINE_URL").is_some();
|
|
79
|
+
tracing::info!(
|
|
80
|
+
op = "desktop.engine_url.baked",
|
|
81
|
+
present = engine_url_baked,
|
|
82
|
+
"EKKA_ENGINE_URL baked at build time"
|
|
83
|
+
);
|
|
84
|
+
|
|
77
85
|
// Check for stored node credentials (vault-backed)
|
|
78
86
|
let has_creds = node_credentials::has_credentials();
|
|
79
87
|
|
|
@@ -112,13 +120,14 @@ fn main() {
|
|
|
112
120
|
}
|
|
113
121
|
|
|
114
122
|
// Authenticate node with server before spawning engine
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
123
|
+
// EKKA_ENGINE_URL is baked at build time via build.rs
|
|
124
|
+
let engine_url = match option_env!("EKKA_ENGINE_URL") {
|
|
125
|
+
Some(url) => url.to_string(),
|
|
126
|
+
None => {
|
|
118
127
|
tracing::warn!(
|
|
119
128
|
op = "desktop.engine.start.blocked",
|
|
120
129
|
reason = "missing_engine_url",
|
|
121
|
-
"Engine start blocked - EKKA_ENGINE_URL not
|
|
130
|
+
"Engine start blocked - EKKA_ENGINE_URL not baked at build time"
|
|
122
131
|
);
|
|
123
132
|
return;
|
|
124
133
|
}
|
|
@@ -770,9 +770,11 @@ pub struct NodeSessionRunnerConfig {
|
|
|
770
770
|
|
|
771
771
|
impl NodeSessionRunnerConfig {
|
|
772
772
|
pub fn from_session(session: &NodeSession, node_id: Uuid) -> Result<Self, String> {
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
.
|
|
773
|
+
// EKKA_ENGINE_URL baked at build time, ENGINE_URL as runtime fallback
|
|
774
|
+
let engine_url = option_env!("EKKA_ENGINE_URL")
|
|
775
|
+
.map(|s| s.to_string())
|
|
776
|
+
.or_else(|| std::env::var("ENGINE_URL").ok())
|
|
777
|
+
.ok_or("EKKA_ENGINE_URL not baked at build time and ENGINE_URL not set")?;
|
|
776
778
|
|
|
777
779
|
let node_url = std::env::var("NODE_URL").unwrap_or_else(|_| "http://127.0.0.1:7777".to_string());
|
|
778
780
|
|
|
@@ -80,13 +80,13 @@ pub fn handle_grant(state: &EngineState) -> EngineResponse {
|
|
|
80
80
|
None => return EngineResponse::err("MARKER_INVALID", "Marker missing instance_id"),
|
|
81
81
|
};
|
|
82
82
|
|
|
83
|
-
// 4. Get engine URL
|
|
84
|
-
let engine_url = match
|
|
85
|
-
|
|
86
|
-
|
|
83
|
+
// 4. Get engine URL (baked at build time)
|
|
84
|
+
let engine_url = match option_env!("EKKA_ENGINE_URL") {
|
|
85
|
+
Some(u) => u,
|
|
86
|
+
None => {
|
|
87
87
|
return EngineResponse::err(
|
|
88
88
|
"ENGINE_NOT_CONFIGURED",
|
|
89
|
-
"EKKA_ENGINE_URL not
|
|
89
|
+
"EKKA_ENGINE_URL not baked at build time. Rebuild with EKKA_ENGINE_URL set.",
|
|
90
90
|
)
|
|
91
91
|
}
|
|
92
92
|
};
|
|
@@ -179,7 +179,7 @@ impl Default for RunnerStatus {
|
|
|
179
179
|
enabled: false,
|
|
180
180
|
state: RunnerLoopState::Stopped,
|
|
181
181
|
runner_id: None,
|
|
182
|
-
engine_url:
|
|
182
|
+
engine_url: option_env!("EKKA_ENGINE_URL").map(|s| s.to_string()),
|
|
183
183
|
last_poll_at: None,
|
|
184
184
|
last_claim_at: None,
|
|
185
185
|
last_complete_at: None,
|
|
@@ -259,9 +259,10 @@ impl RunnerState {
|
|
|
259
259
|
s.enabled = true;
|
|
260
260
|
s.state = RunnerLoopState::Running;
|
|
261
261
|
s.runner_id = Some(runner_id.to_string());
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
.
|
|
262
|
+
// EKKA_ENGINE_URL baked at build time, ENGINE_URL as runtime fallback
|
|
263
|
+
s.engine_url = option_env!("EKKA_ENGINE_URL")
|
|
264
|
+
.map(|s| s.to_string())
|
|
265
|
+
.or_else(|| std::env::var("ENGINE_URL").ok());
|
|
265
266
|
s.last_error = None;
|
|
266
267
|
});
|
|
267
268
|
}
|
|
@@ -511,11 +512,11 @@ impl GrantIssuer for EngineHttpGrantIssuer {
|
|
|
511
512
|
EkkaError::new(ops::codes::NOT_AUTHENTICATED, "Must login before requesting grant")
|
|
512
513
|
})?;
|
|
513
514
|
|
|
514
|
-
// Get engine URL
|
|
515
|
-
let engine_url =
|
|
515
|
+
// Get engine URL (baked at build time)
|
|
516
|
+
let engine_url = option_env!("EKKA_ENGINE_URL").ok_or_else(|| {
|
|
516
517
|
EkkaError::new(
|
|
517
518
|
ops::codes::ENGINE_ERROR,
|
|
518
|
-
"EKKA_ENGINE_URL not
|
|
519
|
+
"EKKA_ENGINE_URL not baked at build time. Rebuild with EKKA_ENGINE_URL set.",
|
|
519
520
|
)
|
|
520
521
|
})?;
|
|
521
522
|
|
|
@@ -613,10 +614,10 @@ impl GrantIssuer for EngineHttpGrantIssuer {
|
|
|
613
614
|
EkkaError::new(ops::codes::NOT_AUTHENTICATED, "Must login to revoke grant")
|
|
614
615
|
})?;
|
|
615
616
|
|
|
616
|
-
// Get engine URL (optional - revoke is best effort)
|
|
617
|
-
let engine_url = match
|
|
618
|
-
|
|
619
|
-
|
|
617
|
+
// Get engine URL (baked at build time, optional - revoke is best effort)
|
|
618
|
+
let engine_url = match option_env!("EKKA_ENGINE_URL") {
|
|
619
|
+
Some(url) => url,
|
|
620
|
+
None => return Ok(()), // No engine baked, just return success
|
|
620
621
|
};
|
|
621
622
|
|
|
622
623
|
// Make revoke request (best effort)
|