Skip to repository content

tenant.openagents/omega

No repository description is available.

OpenAgents Git authority 2026-07-28T00:57:32.952Z Public web read
NIP-34 coordinate30617:7649603503856e5148d571eac2766b288a8ff1e9e35d380337a1d2b0015b4f92:omega
MaintainersHidden in public view
References2 branches · 1 tag
Read-only clonegit clone https://openagents.com/git/tenant.openagents/omega.git

Revision diff

c886698b 7123aca2
diff --git a/crates/acp_thread/src/acp_thread.rs b/crates/acp_thread/src/acp_thread.rs
index ab65edda25..946a87f2ef 100644
--- a/crates/acp_thread/src/acp_thread.rs
+++ b/crates/acp_thread/src/acp_thread.rs
@@ -2225,6 +2225,15 @@ pub enum LoadError {
22252225         status: ExitStatus,
22262226         stderr: Option<SharedString>,
22272227     },
2228+    /// The agent no longer holds the session this thread names.
2229+    ///
2230+    /// Omega's thread record outlives the external agent's session store, so
2231+    /// reopening an old thread after the agent has forgotten it is ordinary
2232+    /// rather than exceptional. It surfaced as "Failed to Launch: Resource not
2233+    /// found: <uuid>", which names a thing the reader cannot act on and reads
2234+    /// like the agent failed to start. Nothing failed to launch: the
2235+    /// conversation is gone and a new one is the way forward.
2236+    SessionGone,
22282237     Other(SharedString),
22292238 }
22302239 
@@ -2243,6 +2252,10 @@ impl Display for LoadError {
22432252             }
22442253             LoadError::FailedToInstall(msg) => write!(f, "Failed to install: {msg}"),
22452254             LoadError::Exited { status, .. } => write!(f, "Server exited with status {status}"),
2255+            LoadError::SessionGone => write!(
2256+                f,
2257+                "the agent no longer has this conversation; start a new thread to keep going"
2258+            ),
22462259             LoadError::Other(msg) => write!(f, "{msg}"),
22472260         }
22482261     }
diff --git a/crates/agent_servers/src/acp.rs b/crates/agent_servers/src/acp.rs
index 4fbb6e3408..9d432d0895 100644
--- a/crates/agent_servers/src/acp.rs
+++ b/crates/agent_servers/src/acp.rs
@@ -1743,7 +1743,7 @@ impl AgentConnection for AcpConnection {
17431743                         )
17441744                         .block_task()
17451745                         .await
1746-                        .map_err(map_acp_error)?;
1746+                        .map_err(map_session_open_error)?;
17471747                     Ok(SessionConfigResponse {
17481748                         modes: response.modes,
17491749                         config_options: response.config_options,
@@ -1788,7 +1788,7 @@ impl AgentConnection for AcpConnection {
17881788                         )
17891789                         .block_task()
17901790                         .await
1791-                        .map_err(map_acp_error)?;
1791+                        .map_err(map_session_open_error)?;
17921792                     Ok(SessionConfigResponse {
17931793                         modes: response.modes,
17941794                         config_options: response.config_options,
@@ -2074,6 +2074,24 @@ fn map_acp_error(err: acp::Error) -> anyhow::Error {
20742074     }
20752075 }
20762076 
2077+/// Map an error from a `session/load` or `session/resume` call.
2078+///
2079+/// `ResourceNotFound` from these two calls means one specific thing: the agent
2080+/// does not have the session we named. Omega keeps its own thread record, and
2081+/// that record outlives the agent's session store, so this is an ordinary end
2082+/// of life rather than a failure to start. Left as a generic error it rendered
2083+/// as "Failed to Launch: Resource not found: <uuid>" — a title that blames
2084+/// startup and a body that names an identifier the reader cannot act on.
2085+///
2086+/// Only the session-scoped calls get this treatment. `ResourceNotFound` from a
2087+/// file read means a missing file and must keep saying so.
2088+fn map_session_open_error(err: acp::Error) -> anyhow::Error {
2089+    if err.code == acp::ErrorCode::ResourceNotFound {
2090+        return anyhow!(LoadError::SessionGone);
2091+    }
2092+    map_acp_error(err)
2093+}
2094+
20772095 #[cfg(any(test, feature = "test-support"))]
20782096 pub mod test_support {
20792097     use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
@@ -5098,3 +5116,47 @@ fn handle_wait_for_terminal_exit(
50985116     })
50995117     .detach();
51005118 }
5119+
5120+#[cfg(test)]
5121+mod session_open_error_tests {
5122+    use super::*;
5123+
5124+    /// A vanished session must not read as a failure to start.
5125+    ///
5126+    /// This shipped as "Failed to Launch: Resource not found: <uuid>" — a
5127+    /// title that blames startup for something startup did not do, and a body
5128+    /// naming an identifier the reader cannot act on.
5129+    #[test]
5130+    fn a_missing_session_is_reported_as_gone_not_as_a_launch_failure() {
5131+        let mapped = map_session_open_error(acp::Error::resource_not_found(Some(
5132+            "1297dcfa-027c-422c-9b56-acb526144c93".into(),
5133+        )));
5134+        let load_error = mapped
5135+            .downcast_ref::<LoadError>()
5136+            .expect("a missing session must map to a LoadError");
5137+        assert!(
5138+            matches!(load_error, LoadError::SessionGone),
5139+            "expected SessionGone, got {load_error:?}"
5140+        );
5141+        let rendered = load_error.to_string();
5142+        assert!(
5143+            !rendered.contains("1297dcfa"),
5144+            "the session id is not actionable and must not be shown: {rendered}"
5145+        );
5146+        assert!(
5147+            rendered.contains("new thread"),
5148+            "the reader needs the way forward: {rendered}"
5149+        );
5150+    }
5151+
5152+    /// Only the session-scoped calls get this treatment. `ResourceNotFound`
5153+    /// from a file read still means a missing file.
5154+    #[test]
5155+    fn other_errors_are_left_alone() {
5156+        let mapped = map_session_open_error(acp::Error::internal_error());
5157+        assert!(
5158+            mapped.downcast_ref::<LoadError>().is_none(),
5159+            "an unrelated error must not be rewritten into SessionGone"
5160+        );
5161+    }
5162+}
diff --git a/crates/agent_ui/src/conversation_view.rs b/crates/agent_ui/src/conversation_view.rs
index ad2c1e9fb4..1e8fb8e90c 100644
--- a/crates/agent_ui/src/conversation_view.rs
+++ b/crates/agent_ui/src/conversation_view.rs
@@ -1533,6 +1533,8 @@ impl ConversationView {
15331533                     format!("Failed to Install {}", self.agent.agent_id()).into()
15341534                 }
15351535                 LoadError::Exited { .. } => format!("{} Exited", self.agent.agent_id()).into(),
1536+                // Deliberately not "Error Loading <agent>": the agent loaded.
1537+                LoadError::SessionGone => "Conversation No Longer Available".into(),
15361538                 LoadError::Other(_) => format!("Error Loading {}", self.agent.agent_id()).into(),
15371539             },
15381540         }
@@ -2617,6 +2619,7 @@ impl ConversationView {
26172619             LoadError::Unsupported { .. } => "unsupported",
26182620             LoadError::FailedToInstall(_) => "failed_to_install",
26192621             LoadError::Exited { .. } => "exited",
2622+            LoadError::SessionGone => "session_gone",
26202623             LoadError::Other(_) => "other",
26212624         };
26222625 
@@ -2660,6 +2663,27 @@ impl ConversationView {
26602663                     .then(|| self.create_copy_button(message.clone()).into_any_element());
26612664                 ("Failed to Launch", message.into(), action_slot)
26622665             }
2666+            // Nothing failed to launch. The agent started fine and does not
2667+            // have this conversation any more, which is ordinary once a thread
2668+            // outlives the agent's own session store. Say that, and give the
2669+            // reader the one action that moves them forward, instead of a
2670+            // launch failure carrying a session id they cannot use.
2671+            LoadError::SessionGone => {
2672+                return Callout::new()
2673+                    .severity(Severity::Warning)
2674+                    .icon(IconName::Info)
2675+                    .title("Conversation No Longer Available")
2676+                    .description(
2677+                        "The agent no longer has this conversation. Its history is still here to \
2678+                         read, and a new thread will pick up where you left off.",
2679+                    )
2680+                    .actions_slot(
2681+                        Button::new("session-gone-new-thread", "New Thread")
2682+                            .on_click(|_, window, cx| window.dispatch_action(NewThread.boxed_clone(), cx))
2683+                            .into_any_element(),
2684+                    )
2685+                    .into_any_element();
2686+            }
26632687             LoadError::Other(msg) => (
26642688                 "Failed to Launch",
26652689                 msg.into(),
diff --git a/crates/component_preview/src/component_preview.rs b/crates/component_preview/src/component_preview.rs
index a4a39d78ef..60e0ef92ce 100644
--- a/crates/component_preview/src/component_preview.rs
+++ b/crates/component_preview/src/component_preview.rs
@@ -692,9 +692,16 @@ impl Render for ComponentPreview {
692692                     ),
693693             )
694694             .child(
695+                // `size_full` would set width to 100% of the whole row, not of
696+                // the space the sidebar leaves, so the pane rendered one
697+                // sidebar-width too wide and its content ran off the right
698+                // edge. `min_w_0` is what lets a flex child shrink below its
699+                // content width; without it `flex_1` still cannot pull the
700+                // pane in.
695701                 v_flex()
696702                     .flex_1()
697-                    .size_full()
703+                    .min_w_0()
704+                    .h_full()
698705                     .child(
699706                         div()
700707                             .p_2()
Served at tenant.openagents/omega Member data and write actions are omitted.