Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
66ddaf2
Merge remote-tracking branch 'upstream/master'
alecuba16 Sep 18, 2026
52d3b55
Keep mermaid/math on halfblocks inside herdr-webui panes
alecuba16 Sep 19, 2026
37c5c38
Add process-level HERDR_WEBUI protocol gate regression test
alecuba16 Sep 19, 2026
c261a73
Fix pre-existing clippy 1.96 lint debt across workspace
alecuba16 Sep 19, 2026
1e41bac
test: refresh stale guardrail baselines
alecuba16 Sep 19, 2026
40ccf97
Remove dead linux-only helper orphaned by upstream notice shortening
alecuba16 Sep 19, 2026
7973bde
Fix clippy 1.98 lints: needless_late_init, chunks_exact_to_as_chunks
alecuba16 Sep 19, 2026
8b4d2c1
Bump h2/rustls to fix RUSTSEC-2026-0258 and RUSTSEC-2026-0285
alecuba16 Sep 19, 2026
e666802
ci: merge duplicate workflow env maps (fixes #1191)
alecuba16 Sep 19, 2026
08502ab
ci: retrigger workflows after enabling Actions
alecuba16 Sep 19, 2026
d831b05
ci: retrigger after allowing marketplace actions
alecuba16 Sep 19, 2026
c15a527
ci: make SSH deploy-key steps optional for forks without the secret
alecuba16 Sep 19, 2026
7b3d092
fix(review): strip reasoning markup from judge transcripts
alecuba16 Sep 19, 2026
1ee1d06
fix(tui): wrap long plan intentions instead of truncating them
alecuba16 Sep 19, 2026
416bee7
test(tui): refresh expectations for upstream behavior changes
alecuba16 Sep 19, 2026
627b605
style: cargo fmt
alecuba16 Sep 19, 2026
b99abe5
refactor(tui): split todo card rendering into its own module
alecuba16 Sep 19, 2026
f52fb5b
test(tui): keep oversized test files within the ratchet budget
alecuba16 Sep 19, 2026
bd87755
fix(tui): avoid new swallowed-error usage in intent wrap
alecuba16 Sep 19, 2026
4746bd9
fix(auth): add OrcaRouter to the provider choice mapping
alecuba16 Sep 19, 2026
51b2d93
test: refresh provider_init size baseline for OrcaRouter mapping
alecuba16 Sep 19, 2026
c3ba239
fix(session): persist debug and canary headless sessions
alecuba16 Sep 19, 2026
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
24 changes: 17 additions & 7 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
name: CI

env:
JCODE_CI: "1"

on:
push:
branches: [main, master]
Expand All @@ -14,6 +11,7 @@ concurrency:
cancel-in-progress: true

env:
JCODE_CI: "1"
CARGO_TERM_COLOR: always
SCCACHE_GHA_ENABLED: "true"

Expand All @@ -30,8 +28,11 @@ jobs:

- name: Configure SSH for cargo git dependencies
uses: webfactory/ssh-agent@v0.9.0
if: env.DEPLOY_KEY != ''
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
with:
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
ssh-private-key: ${{ env.DEPLOY_KEY }}

- uses: dtolnay/rust-toolchain@stable
with:
Expand Down Expand Up @@ -156,8 +157,11 @@ jobs:

- name: Configure SSH for cargo git dependencies
uses: webfactory/ssh-agent@v0.9.0
if: env.DEPLOY_KEY != ''
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
with:
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
ssh-private-key: ${{ env.DEPLOY_KEY }}

- uses: dtolnay/rust-toolchain@stable
with:
Expand Down Expand Up @@ -396,8 +400,11 @@ jobs:

- name: Configure SSH for cargo git dependencies
uses: webfactory/ssh-agent@v0.9.0
if: env.DEPLOY_KEY != ''
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
with:
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
ssh-private-key: ${{ env.DEPLOY_KEY }}

- uses: ilammy/msvc-dev-cmd@v1
with:
Expand Down Expand Up @@ -649,8 +656,11 @@ jobs:

- name: Configure SSH for cargo git dependencies
uses: webfactory/ssh-agent@v0.9.0
if: env.DEPLOY_KEY != ''
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
with:
ssh-private-key: ${{ secrets.DEPLOY_KEY }}
ssh-private-key: ${{ env.DEPLOY_KEY }}

- uses: dtolnay/rust-toolchain@stable
with:
Expand Down
13 changes: 13 additions & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,19 @@

## Development Workflow

- **Commit as you go** - Make small, focused commits after completing each feature or fix
- If the git state is not clean, or there are other agents working in the codebase in parallel, do your best to still commit your work.
- **Push when done** - Push all commits to remote when finishing a task or session
- **Use fast iteration by default** - Prefer `cargo check`, targeted tests, and dev builds while iterating
- **Rebuild when done** - When you are done making changes, build the source.
- **Bump version for releases** - Update version in `Cargo.toml` when making releases. When cutting a new release, look at all the changes that happened since the last release and determine what the version bump should be ie patch or minor, etc.
- **Remote builds available** - Use `scripts/remote_build.sh` to offload heavy cargo work to another machine. If your build is terminated, likely is because there are not enough resources on this machine to build. use remote build in that case. Try checking the resource avaliablity on the machine before you run a build.

## Logs
- Logs are written to `~/.jcode/logs/` (daily files like `jcode-YYYY-MM-DD.log`).

## Debug Socket
- Use the debug socket for runtime level debugging
- **Use the user's Git identity** - Create commits with the configured
`user.name` and `user.email`. Do not override them with `Jcode`, `Jcode agent`,
or a fabricated agent email. Preserve existing contributor attribution when
Expand Down
35 changes: 18 additions & 17 deletions Cargo.lock

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

17 changes: 11 additions & 6 deletions crates/jcode-app-core/src/agent_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1782,12 +1782,17 @@ fn empty_post_tool_response_gets_more_than_one_retry() {
// transient hiccup, not a finished task. With only one retry allowed, a
// single empty response (observed once in 43 turns) ended a 20-hour agent
// run with the work half-done and the submission unoptimized.
assert!(
Agent::MAX_EMPTY_POST_TOOL_CONTINUATION_ATTEMPTS > 1,
"a single retry lets one transient empty response end a long run"
);
// Bounded, so a genuinely finished agent still exits instead of looping.
assert!(Agent::MAX_EMPTY_POST_TOOL_CONTINUATION_ATTEMPTS <= 10);
// assertions_on_constants fires because both bounds are compile-known; the
// guard is kept as a readable regression test, not dead code.
#[allow(clippy::assertions_on_constants)]
{
assert!(
Agent::MAX_EMPTY_POST_TOOL_CONTINUATION_ATTEMPTS > 1,
"a single retry lets one transient empty response end a long run"
);
// Bounded, so a genuinely finished agent still exits instead of looping.
assert!(Agent::MAX_EMPTY_POST_TOOL_CONTINUATION_ATTEMPTS <= 10);
}
}

#[test]
Expand Down
4 changes: 2 additions & 2 deletions crates/jcode-app-core/src/network_retry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,12 @@ pub fn wait_plan() -> NetworkWaitPlan {
}
#[cfg(target_os = "macos")]
{
return NetworkWaitPlan {
NetworkWaitPlan {
reason: "stream interrupted by a likely network disconnect".to_string(),
listener_summary:
"listening for macOS route/interface changes via `route -n monitor`; also verifying with reconnect probes"
.to_string(),
};
}
}
#[cfg(not(any(target_os = "linux", target_os = "macos")))]
{
Expand Down
70 changes: 35 additions & 35 deletions crates/jcode-app-core/src/server/background_tasks.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,6 +583,41 @@ fn cap_chars(s: &str, cap: usize) -> String {
out
}

pub(super) async fn dispatch_ui_activity(
activity: &crate::bus::UiActivity,
swarm_members: &Arc<RwLock<HashMap<String, SwarmMember>>>,
) {
if activity.message.trim().is_empty() {
return;
}
let Some(session_id) = activity.session_id.as_deref() else {
return;
};

if fanout_session_event(
swarm_members,
session_id,
ServerEvent::Notification {
from_session: "jcode".to_string(),
from_name: Some("Jcode".to_string()),
notification_type: NotificationType::Message {
scope: Some(activity.kind.scope().to_string()),
channel: None,
tldr: None,
},
message: activity.message.clone(),
},
)
.await
== 0
{
crate::logging::warn(&format!(
"Failed to notify attached clients for UI activity on session {}",
session_id
));
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -673,38 +708,3 @@ mod tests {
assert!(!update_active_todo_batch_progress(&mut items, &progress));
}
}

pub(super) async fn dispatch_ui_activity(
activity: &crate::bus::UiActivity,
swarm_members: &Arc<RwLock<HashMap<String, SwarmMember>>>,
) {
if activity.message.trim().is_empty() {
return;
}
let Some(session_id) = activity.session_id.as_deref() else {
return;
};

if fanout_session_event(
swarm_members,
session_id,
ServerEvent::Notification {
from_session: "jcode".to_string(),
from_name: Some("Jcode".to_string()),
notification_type: NotificationType::Message {
scope: Some(activity.kind.scope().to_string()),
channel: None,
tldr: None,
},
message: activity.message.clone(),
},
)
.await
== 0
{
crate::logging::warn(&format!(
"Failed to notify attached clients for UI activity on session {}",
session_id
));
}
}
6 changes: 2 additions & 4 deletions crates/jcode-app-core/src/server/client_lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1297,10 +1297,8 @@ pub(super) async fn handle_client(
active_turn_registered,
session_connection_busy,
);
if start {
if let Some(info) = connections.get_mut(&client_connection_id) {
info.is_processing = true;
}
if start && let Some(info) = connections.get_mut(&client_connection_id) {
info.is_processing = true;
}
start
};
Expand Down
1 change: 1 addition & 0 deletions crates/jcode-app-core/src/server/client_lifecycle_tests.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![allow(clippy::await_holding_lock)] // env guards held across async test bodies
use super::*;
use crate::message::{ContentBlock, Message, StreamEvent, ToolDefinition};
use crate::provider::{EventStream, Provider};
Expand Down
8 changes: 4 additions & 4 deletions crates/jcode-app-core/src/server/comm_session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -549,10 +549,6 @@ async fn register_visible_spawned_member(
broadcast_swarm_status(swarm_id, swarm_members, swarms_by_id).await;
}

#[expect(
clippy::too_many_arguments,
reason = "server-side swarm spawning needs session, swarm state, provider, and event sinks together"
)]
/// Resolve the reasoning effort for a spawned swarm worker (#1165).
///
/// Precedence mirrors the model path: an explicit `effort` on the spawn call
Expand All @@ -571,6 +567,10 @@ pub(super) fn resolve_swarm_spawn_effort(
clean(requested_effort).or_else(|| clean(configured_swarm_effort))
}

#[expect(
clippy::too_many_arguments,
reason = "server-side swarm spawning needs session, swarm state, provider, and event sinks together"
)]
pub(super) async fn spawn_swarm_agent(
req_session_id: &str,
swarm_id: &str,
Expand Down
2 changes: 1 addition & 1 deletion crates/jcode-app-core/src/server/debug_command_exec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -653,7 +653,7 @@ mod tests {
use jcode_agent_runtime::InterruptSignal;
use std::collections::HashMap;
use std::ffi::OsString;
use std::sync::{Arc, Mutex, OnceLock};
use std::sync::Arc;
use std::time::{Duration, Instant};
use tokio::sync::{Mutex as AsyncMutex, RwLock};

Expand Down
Loading
Loading