Skip to content
Draft
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
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@ pub struct UnifiedSessionRecord {
pub merge_status: Option<String>,
pub project_slug: Option<String>,
pub agent_definition_id: Option<String>,
/// Agent Org roster member id for `session_type::ORG_MEMBER` rows.
/// This identifies the member instance, while `agent_definition_id`
/// identifies which AgentDefinition that member runs.
/// Agent Org roster member id. Worker rows use `session_type::ORG_MEMBER`;
/// a coordinator root keeps its primary session type and uses the
/// coordinator member id. `agent_definition_id` identifies which
/// AgentDefinition that member runs.
pub org_member_id: Option<String>,

pub parent_session_id: Option<String>,
Expand Down
104 changes: 101 additions & 3 deletions src-tauri/crates/agent-core/src/core/session/persistence/sidebar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ use database::db::get_connection;
pub type NativeSessionPageCursor<'a> = (&'a str, &'a str);

/// Return one bounded sidebar page of unpinned coding sessions that are not
/// roots of any persisted Agent Org run.
/// members or roots of any persisted Agent Org run.
///
/// Pin state and root membership are applied before LIMIT, so pinned rows,
/// Agent Org roots, and worker rows cannot consume standalone page capacity.
/// Pin state and Agent Org membership are applied before LIMIT, so pinned
/// rows, roots, workers, and orphaned member rows cannot consume standalone
/// page capacity.
pub fn list_standalone_coding_sessions_page(
limit: usize,
cursor: Option<NativeSessionPageCursor<'_>>,
Expand Down Expand Up @@ -53,6 +54,10 @@ fn list_agent_sessions_page(
agent_org_root: Option<bool>,
) -> Result<Vec<UnifiedSessionRecord>, String> {
let conn = get_connection().map_err(|err| err.to_string())?;
let member_predicate = match agent_org_root {
Some(false) => "AND s.org_member_id IS NULL",
Some(true) | None => "",
};
let root_predicate = match agent_org_root {
Some(true) => {
"AND EXISTS (
Expand All @@ -79,6 +84,7 @@ fn list_agent_sessions_page(
AND s.status != ?2
AND s.pinned = 0
AND s.parent_session_id IS NULL
{member_predicate}
{root_predicate}
AND (
s.updated_at < ?3
Expand Down Expand Up @@ -111,6 +117,7 @@ fn list_agent_sessions_page(
AND s.status != ?2
AND s.pinned = 0
AND s.parent_session_id IS NULL
{member_predicate}
{root_predicate}
ORDER BY s.updated_at DESC, s.session_id DESC
LIMIT ?3"
Expand Down Expand Up @@ -163,6 +170,26 @@ mod tests {
type_name: &str,
parent_session_id: Option<&str>,
pinned: bool,
) {
upsert_sidebar_session_with_pin_and_member(
session_id,
updated_at,
status,
type_name,
parent_session_id,
pinned,
None,
);
}

fn upsert_sidebar_session_with_pin_and_member(
session_id: &str,
updated_at: &str,
status: &str,
type_name: &str,
parent_session_id: Option<&str>,
pinned: bool,
org_member_id: Option<&str>,
) {
ensure_runtime_schemas();
super::super::upsert_session(&UnifiedSessionRecord {
Expand All @@ -174,6 +201,7 @@ mod tests {
created_at: updated_at.to_string(),
updated_at: updated_at.to_string(),
pinned,
org_member_id: org_member_id.map(str::to_string),
..Default::default()
})
.expect("upsert sidebar session");
Expand Down Expand Up @@ -351,6 +379,75 @@ mod tests {
assert!(second.iter().all(|session| !session.pinned));
}

#[test]
fn orphan_agent_org_members_do_not_consume_standalone_page_capacity() {
let _sandbox = test_helpers::test_env::sandbox();
let coordinator_member_id = crate::coordination::agent_org_runs::COORDINATOR_MEMBER_ID;

for index in 0..8 {
upsert_sidebar_session_with_pin_and_member(
&format!("orphan-coordinator-{index:02}"),
&format!("2026-07-29T13:{index:02}:00Z"),
"idle",
session_type::CODING,
None,
false,
Some(coordinator_member_id),
);
}
upsert_sidebar_session_with_pin_and_member(
"valid-agent-org-root",
"2026-07-29T13:08:00Z",
"idle",
session_type::CODING,
None,
false,
Some(coordinator_member_id),
);
insert_agent_org_run(
"run-valid-agent-org-root",
"valid-agent-org-root",
"2026-07-29T13:08:00Z",
);
for index in 0..11 {
upsert_sidebar_session(
&format!("regular-{index:02}"),
&format!("2026-07-29T12:{index:02}:00Z"),
"idle",
session_type::CODING,
None,
);
}

let first = list_standalone_coding_sessions_page(10, None).expect("first page");
assert_eq!(first.len(), 10);
assert!(first.iter().all(|session| session.org_member_id.is_none()));
assert_eq!(
first.first().map(|session| session.session_id.as_str()),
Some("regular-10")
);
assert_eq!(
first.last().map(|session| session.session_id.as_str()),
Some("regular-01")
);
let cursor = first.last().expect("first page cursor");
let second = list_standalone_coding_sessions_page(
10,
Some((&cursor.updated_at, &cursor.session_id)),
)
.expect("second page");
assert_eq!(second.len(), 1);
assert_eq!(second[0].session_id, "regular-00");

let roots = list_agent_org_root_sessions_page(10, None).expect("Agent Org root page");
assert_eq!(roots.len(), 1);
assert_eq!(roots[0].session_id, "valid-agent-org-root");
assert_eq!(
roots[0].org_member_id.as_deref(),
Some(coordinator_member_id)
);
}

#[test]
fn native_sidebar_query_uses_bounded_order_and_membership_indexes() {
let _sandbox = test_helpers::test_env::sandbox();
Expand All @@ -365,6 +462,7 @@ mod tests {
AND s.session_type = 'sde'
AND s.status != 'archived'
AND s.parent_session_id IS NULL
AND s.org_member_id IS NULL
AND NOT EXISTS (
SELECT 1
FROM agent_org_runs r
Expand Down
114 changes: 109 additions & 5 deletions src-tauri/src/agent_sessions/session_directory/aggregation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1273,6 +1273,14 @@ fn list_pinned_native_sidebar_sessions(
AND s.status != ?1
AND s.parent_session_id IS NULL
AND s.session_type IN (?2, ?3, ?4)
AND (
s.org_member_id IS NULL
OR EXISTS (
SELECT 1
FROM agent_org_runs r
WHERE r.root_session_id = s.session_id
)
)
{agent_cursor}
UNION ALL
SELECT c.session_id, c.updated_at, 'cli' AS source_kind
Expand Down Expand Up @@ -1654,18 +1662,39 @@ mod tests {
}

#[test]
fn pinned_native_page_merges_agent_and_cli_roots_in_stable_order() {
fn pinned_native_page_merges_roots_without_orphan_member_capacity() {
let _sandbox = crate::test_utils::test_env::sandbox();
let conn = get_connection().expect("sandbox database");
agent_core::coordination::agent_org_runs::init_schema(&conn).expect("Agent Org run schema");
let coordinator_member_id = agent_core::coordination::agent_org_runs::COORDINATOR_MEMBER_ID;

for (session_id, session_type, updated_at, pinned, parent, status) in [
for (session_id, session_type, updated_at, pinned, parent, status, member) in [
(
"orphan-coordinator-pinned",
session_type::CODING,
"2026-07-30T18:00:00Z",
true,
None,
"idle",
Some(coordinator_member_id),
),
(
"agent-org-root-pinned",
session_type::CODING,
"2026-07-30T17:00:00Z",
true,
None,
"idle",
Some(coordinator_member_id),
),
(
"sdeagent-pinned",
session_type::CODING,
"2026-07-30T14:00:00Z",
true,
None,
"idle",
None,
),
(
"osagent-pinned",
Expand All @@ -1674,6 +1703,7 @@ mod tests {
true,
None,
"idle",
None,
),
(
"humansession-pinned",
Expand All @@ -1682,6 +1712,7 @@ mod tests {
true,
None,
"completed",
None,
),
(
"sdeagent-unpinned",
Expand All @@ -1690,6 +1721,7 @@ mod tests {
false,
None,
"idle",
None,
),
(
"sdeagent-worker",
Expand All @@ -1698,6 +1730,7 @@ mod tests {
true,
Some("sdeagent-pinned"),
"running",
None,
),
(
"sdeagent-archived",
Expand All @@ -1706,6 +1739,7 @@ mod tests {
true,
None,
"archived",
None,
),
] {
session_persistence::upsert_session(&UnifiedSessionRecord {
Expand All @@ -1714,13 +1748,30 @@ mod tests {
status: status.to_string(),
session_type: session_type.to_string(),
parent_session_id: parent.map(str::to_string),
org_member_id: member.map(str::to_string),
created_at: updated_at.to_string(),
updated_at: updated_at.to_string(),
pinned,
..Default::default()
})
.expect("seed native session");
}
conn.execute(
"INSERT INTO agent_org_runs (
id, org_id, coordinator_agent_id, root_session_id,
entry_mode, status, created_at, updated_at
) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?7)",
params![
"run-agent-org-root-pinned",
"org-pinned",
"builtin:sde",
"agent-org-root-pinned",
"standalone_session",
"running",
"2026-07-30T17:00:00Z",
],
)
.expect("seed pinned Agent Org run");

for (session_id, updated_at, pinned, parent) in [
("cliagent-pinned", "2026-07-30T13:00:00Z", true, None),
Expand All @@ -1742,7 +1793,7 @@ mod tests {
.expect("seed CLI session");
}

let page = list_native_sidebar_sessions(NativeSidebarSessionStream::PinnedNative, None, 10)
let page = list_native_sidebar_sessions(NativeSidebarSessionStream::PinnedNative, None, 4)
.expect("load global pinned page");

assert_eq!(
Expand All @@ -1751,14 +1802,67 @@ mod tests {
.map(|session| session.session_id.as_str())
.collect::<Vec<_>>(),
vec![
"agent-org-root-pinned",
"sdeagent-pinned",
"cliagent-pinned",
"osagent-pinned",
"humansession-pinned",
]
);
assert!(page.sessions.iter().all(|session| session.pinned));
assert!(!page.has_more);
assert!(page.has_more);
let root = page
.sessions
.first()
.expect("valid Agent Org root remains pinned");
assert_eq!(root.agent_org_id.as_deref(), Some("org-pinned"));
}

#[test]
fn pinned_native_query_uses_bounded_order_and_root_membership_indexes() {
let _sandbox = crate::test_utils::test_env::sandbox();
let conn = get_connection().expect("sandbox database");
agent_core::coordination::agent_org_runs::init_schema(&conn).expect("Agent Org run schema");
let mut stmt = conn
.prepare(
"EXPLAIN QUERY PLAN
SELECT s.session_id, s.updated_at, 'agent' AS source_kind
FROM agent_sessions s
WHERE s.pinned = 1
AND s.status != 'archived'
AND s.parent_session_id IS NULL
AND s.session_type IN ('sde', 'os', 'human')
AND (
s.org_member_id IS NULL
OR EXISTS (
SELECT 1
FROM agent_org_runs r
WHERE r.root_session_id = s.session_id
)
)
UNION ALL
SELECT c.session_id, c.updated_at, 'cli' AS source_kind
FROM code_sessions c
WHERE c.pinned = 1
AND c.parent_session_id IS NULL
ORDER BY updated_at DESC, session_id DESC
LIMIT 11",
)
.expect("prepare pinned native query plan");
let details = stmt
.query_map([], |row| row.get::<_, String>(3))
.expect("read pinned native query plan")
.collect::<Result<Vec<_>, _>>()
.expect("collect pinned native query plan")
.join("\n");

assert!(
details.contains("idx_agent_sessions_sidebar"),
"pinned agent page did not use ordered sidebar index:\n{details}"
);
assert!(
details.contains("idx_agent_org_runs_root_session"),
"pinned root membership probe did not use root-session index:\n{details}"
);
}

#[test]
Expand Down
Loading