Skip to content

Commit 1cd47d3

Browse files
committed
fix bugs
1 parent a9124c3 commit 1cd47d3

File tree

8 files changed

+66
-30
lines changed

8 files changed

+66
-30
lines changed

Cargo.lock

Lines changed: 14 additions & 14 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ members = [
1818
]
1919

2020
[workspace.package]
21-
version = "0.1.8"
21+
version = "0.1.9"
2222
edition = "2021"
2323
license = "Apache-2.0 OR MIT"
2424
repository = "https://github.com/RightNow-AI/openfang"

crates/openfang-api/src/middleware.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,24 @@ pub async fn auth(
9090
|| path == "/api/profiles"
9191
|| path == "/api/config"
9292
|| path.starts_with("/api/uploads/")
93+
// Dashboard read endpoints — allow unauthenticated so the SPA can
94+
// render before the user enters their API key.
95+
|| path == "/api/models"
96+
|| path == "/api/models/aliases"
97+
|| path == "/api/providers"
98+
|| path == "/api/budget"
99+
|| path == "/api/budget/agents"
100+
|| path.starts_with("/api/budget/agents/")
101+
|| path == "/api/network/status"
102+
|| path == "/api/a2a/agents"
103+
|| path == "/api/approvals"
104+
|| path == "/api/channels"
105+
|| path == "/api/skills"
106+
|| path == "/api/sessions"
107+
|| path == "/api/integrations"
108+
|| path == "/api/integrations/available"
109+
|| path == "/api/integrations/health"
110+
|| path.starts_with("/api/cron/")
93111
{
94112
return next.run(request).await;
95113
}

crates/openfang-api/static/index_body.html

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,10 +1102,12 @@ <h4>No approvals</h4>
11021102
</div>
11031103
<div class="text-sm text-dim mb-2" x-text="a.description"></div>
11041104
<div class="text-xs text-dim">Agent: <span x-text="a.agent_name"></span> &middot; <span x-text="timeAgo(a.created_at)"></span></div>
1105-
<div class="approval-actions" x-show="a.status === 'pending'" style="display:flex;gap:8px;margin-top:12px">
1106-
<button class="btn btn-success btn-sm" @click="approve(a.id)">Approve</button>
1107-
<button class="btn btn-danger btn-sm" @click="reject(a.id)">Reject</button>
1108-
</div>
1105+
<template x-if="a.status === 'pending'">
1106+
<div class="approval-actions" style="display:flex;gap:8px;margin-top:12px">
1107+
<button class="btn btn-success btn-sm" @click="approve(a.id)">Approve</button>
1108+
<button class="btn btn-danger btn-sm" @click="reject(a.id)">Reject</button>
1109+
</div>
1110+
</template>
11091111
</div>
11101112
</template>
11111113
</div>

crates/openfang-api/static/js/app.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ document.addEventListener('alpine:init', function() {
158158
await OpenFangAPI.get('/api/providers');
159159
this.showAuthPrompt = false;
160160
} catch(e) {
161-
if (e.message && e.message.indexOf('401') >= 0) {
161+
if (e.message && (e.message.indexOf('Not authorized') >= 0 || e.message.indexOf('401') >= 0 || e.message.indexOf('Missing Authorization') >= 0)) {
162162
this.showAuthPrompt = true;
163163
}
164164
}

crates/openfang-cli/src/main.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -953,14 +953,20 @@ pub(crate) fn restrict_dir_permissions(_path: &std::path::Path) {}
953953
pub(crate) fn find_daemon() -> Option<String> {
954954
let home_dir = dirs::home_dir()?.join(".openfang");
955955
let info = read_daemon_info(&home_dir)?;
956-
let url = format!("http://{}/api/health", info.listen_addr);
956+
957+
// Normalize listen address: replace 0.0.0.0 with 127.0.0.1 to avoid
958+
// DNS/connectivity issues on macOS where 0.0.0.0 can hang.
959+
let addr = info.listen_addr.replace("0.0.0.0", "127.0.0.1");
960+
let url = format!("http://{addr}/api/health");
961+
957962
let client = reqwest::blocking::Client::builder()
963+
.connect_timeout(std::time::Duration::from_secs(1))
958964
.timeout(std::time::Duration::from_secs(2))
959965
.build()
960966
.ok()?;
961967
let resp = client.get(&url).send().ok()?;
962968
if resp.status().is_success() {
963-
Some(format!("http://{}", info.listen_addr))
969+
Some(format!("http://{addr}"))
964970
} else {
965971
None
966972
}

crates/openfang-kernel/src/cron.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -222,16 +222,24 @@ impl CronScheduler {
222222
}
223223

224224
/// Return jobs whose `next_run` is at or before `now` and are enabled.
225+
///
226+
/// **Important**: This also pre-advances each due job's `next_run` to the
227+
/// next scheduled time. This prevents the same job from being returned as
228+
/// "due" on subsequent tick iterations while it's still executing.
225229
pub fn due_jobs(&self) -> Vec<CronJob> {
226230
let now = Utc::now();
227-
self.jobs
228-
.iter()
229-
.filter(|r| {
230-
let meta = r.value();
231-
meta.job.enabled && meta.job.next_run.map(|t| t <= now).unwrap_or(false)
232-
})
233-
.map(|r| r.value().job.clone())
234-
.collect()
231+
let mut due = Vec::new();
232+
for mut entry in self.jobs.iter_mut() {
233+
let meta = entry.value_mut();
234+
if meta.job.enabled && meta.job.next_run.map(|t| t <= now).unwrap_or(false) {
235+
due.push(meta.job.clone());
236+
// Pre-advance next_run so the job won't fire again on the next
237+
// tick while it's still executing. record_success/record_failure
238+
// will recompute it again after execution completes.
239+
meta.job.next_run = Some(compute_next_run(&meta.job.schedule));
240+
}
241+
}
242+
due
235243
}
236244

237245
// -- Outcome recording --------------------------------------------------

crates/openfang-kernel/src/kernel.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3095,6 +3095,8 @@ impl OpenFangKernel {
30953095
let kernel = Arc::clone(self);
30963096
tokio::spawn(async move {
30973097
let mut interval = tokio::time::interval(std::time::Duration::from_secs(15));
3098+
// Use Skip to avoid burst-firing after a long job blocks the loop.
3099+
interval.set_missed_tick_behavior(tokio::time::MissedTickBehavior::Skip);
30983100
let mut persist_counter = 0u32;
30993101
interval.tick().await; // Skip first immediate tick
31003102
loop {

0 commit comments

Comments
 (0)