This commit is contained in:
Eric Traut
2026-03-14 13:14:17 -06:00
parent 2ccb3624a1
commit 1dbe04b994
8 changed files with 160 additions and 135 deletions

View File

@@ -274,8 +274,6 @@ pub struct InProcessAppServerClient {
command_tx: mpsc::Sender<ClientCommand>,
event_rx: mpsc::Receiver<InProcessServerEvent>,
worker_handle: tokio::task::JoinHandle<()>,
auth_manager: Arc<AuthManager>,
thread_manager: Arc<ThreadManager>,
}
impl InProcessAppServerClient {
@@ -439,21 +437,9 @@ impl InProcessAppServerClient {
command_tx,
event_rx,
worker_handle,
auth_manager: shared_core.auth_manager,
thread_manager: shared_core.thread_manager,
})
}
/// Temporary bootstrap escape hatch for embedders migrating toward RPC-only usage.
pub fn auth_manager(&self) -> Arc<AuthManager> {
self.auth_manager.clone()
}
/// Temporary bootstrap escape hatch for embedders migrating toward RPC-only usage.
pub fn thread_manager(&self) -> Arc<ThreadManager> {
self.thread_manager.clone()
}
/// Sends a typed client request and returns raw JSON-RPC result.
///
/// Callers that expect a concrete response type should usually prefer
@@ -597,6 +583,25 @@ impl InProcessAppServerClient {
self.event_rx.recv().await
}
/// Receives the next non-legacy server event from the in-process runtime.
///
/// Legacy bridge notifications are skipped so fully migrated callers can
/// consume only typed app-server notifications and requests.
pub async fn next_typed_event(&mut self) -> Option<InProcessServerEvent> {
loop {
match self.next_event().await {
Some(InProcessServerEvent::LegacyNotification(notification)) => {
warn!(
notification.method = %notification.method,
"dropping legacy in-process app-server notification"
);
}
Some(event) => return Some(event),
None => return None,
}
}
}
/// Shuts down worker and in-process runtime with bounded wait.
///
/// If graceful shutdown exceeds timeout, the worker task is aborted to
@@ -606,8 +611,6 @@ impl InProcessAppServerClient {
command_tx,
event_rx,
worker_handle,
auth_manager: _,
thread_manager: _,
} = self;
let mut worker_handle = worker_handle;
// Drop the caller-facing receiver before asking the worker to shut
@@ -659,8 +662,6 @@ mod tests {
use codex_app_server_protocol::SessionSource as ApiSessionSource;
use codex_app_server_protocol::ThreadStartParams;
use codex_app_server_protocol::ThreadStartResponse;
use codex_core::AuthManager;
use codex_core::ThreadManager;
use codex_core::config::ConfigBuilder;
use pretty_assertions::assert_eq;
use tokio::time::Duration;
@@ -757,7 +758,7 @@ mod tests {
}
#[tokio::test]
async fn shared_thread_manager_tracks_threads_started_via_app_server() {
async fn thread_read_loads_threads_started_via_app_server() {
let client = start_test_client(SessionSource::Cli).await;
let response: ThreadStartResponse = client
@@ -770,17 +771,18 @@ mod tests {
})
.await
.expect("thread/start should succeed");
let created_thread_id = codex_protocol::ThreadId::from_string(&response.thread.id)
.expect("thread id should parse");
timeout(
Duration::from_secs(2),
client.thread_manager().get_thread(created_thread_id),
)
.await
.expect("timed out waiting for retained thread manager to observe started thread")
.expect("started thread should be visible through the shared thread manager");
let thread_ids = client.thread_manager().list_thread_ids().await;
assert!(thread_ids.contains(&created_thread_id));
let thread_id = response.thread.id;
let read: codex_app_server_protocol::ThreadReadResponse = client
.request_typed(ClientRequest::ThreadRead {
request_id: RequestId::Integer(4),
params: codex_app_server_protocol::ThreadReadParams {
thread_id: thread_id.clone(),
include_turns: false,
},
})
.await
.expect("thread/read should succeed");
assert_eq!(read.thread.id, thread_id);
client.shutdown().await.expect("shutdown should complete");
}
@@ -829,22 +831,6 @@ mod tests {
let (command_tx, _command_rx) = mpsc::channel(1);
let (event_tx, event_rx) = mpsc::channel(1);
let worker_handle = tokio::spawn(async {});
let config = build_test_config().await;
let auth_manager = AuthManager::shared(
config.codex_home.clone(),
false,
config.cli_auth_credentials_store_mode,
);
let thread_manager = Arc::new(ThreadManager::new(
&config,
auth_manager.clone(),
SessionSource::Exec,
CollaborationModesConfig {
default_mode_request_user_input: config
.features
.enabled(codex_core::features::Feature::DefaultModeRequestUserInput),
},
));
event_tx
.send(InProcessServerEvent::Lagged { skipped: 3 })
.await
@@ -855,8 +841,6 @@ mod tests {
command_tx,
event_rx,
worker_handle,
auth_manager,
thread_manager,
};
let event = timeout(Duration::from_secs(2), client.next_event())
@@ -901,17 +885,38 @@ mod tests {
}
#[tokio::test]
async fn accessors_expose_retained_shared_managers() {
let client = start_test_client(SessionSource::Cli).await;
async fn next_typed_event_skips_legacy_notifications() {
let (command_tx, _command_rx) = mpsc::channel(1);
let (event_tx, event_rx) = mpsc::channel(2);
let worker_handle = tokio::spawn(async {});
event_tx
.send(InProcessServerEvent::LegacyNotification(
codex_app_server_protocol::JSONRPCNotification {
method: "codex/event/task_complete".to_string(),
params: None,
},
))
.await
.expect("legacy notification should enqueue");
event_tx
.send(InProcessServerEvent::Lagged { skipped: 2 })
.await
.expect("lagged marker should enqueue");
drop(event_tx);
assert!(
Arc::ptr_eq(&client.auth_manager(), &client.auth_manager()),
"auth_manager accessor should clone the retained shared manager"
);
assert!(
Arc::ptr_eq(&client.thread_manager(), &client.thread_manager()),
"thread_manager accessor should clone the retained shared manager"
);
let mut client = InProcessAppServerClient {
command_tx,
event_rx,
worker_handle,
};
let event = timeout(Duration::from_secs(2), client.next_typed_event())
.await
.expect("typed event should arrive before timeout");
assert!(matches!(
event,
Some(InProcessServerEvent::Lagged { skipped: 2 })
));
client.shutdown().await.expect("shutdown should complete");
}

View File

@@ -46,6 +46,8 @@ use codex_ansi_escape::ansi_escape_line;
use codex_app_server_client::InProcessAppServerClient;
use codex_app_server_protocol::ConfigLayerSource;
use codex_app_server_protocol::RequestId;
use codex_app_server_protocol::SkillErrorInfo;
use codex_app_server_protocol::SkillsListEntry;
use codex_core::config::Config;
use codex_core::config::ConfigBuilder;
use codex_core::config::ConfigOverrides;
@@ -71,15 +73,11 @@ use codex_protocol::openai_models::ModelPreset;
use codex_protocol::openai_models::ModelUpgrade;
use codex_protocol::openai_models::ReasoningEffort as ReasoningEffortConfig;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::Event;
use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::FinalOutput;
use codex_protocol::protocol::ListSkillsResponseEvent;
use codex_protocol::protocol::Op;
use codex_protocol::protocol::SandboxPolicy;
use codex_protocol::protocol::SessionConfiguredEvent;
use codex_protocol::protocol::SessionSource;
use codex_protocol::protocol::SkillErrorInfo;
use codex_protocol::protocol::TokenUsage;
use codex_utils_absolute_path::AbsolutePathBuf;
use color_eyre::eyre::Result;
@@ -88,6 +86,11 @@ use crossterm::event::KeyCode;
use crossterm::event::KeyEvent;
use crossterm::event::KeyEventKind;
use ratatui::style::Stylize;
#[cfg(test)]
use codex_protocol::protocol::Event;
#[cfg(test)]
use codex_protocol::protocol::EventMsg;
use ratatui::text::Line;
use ratatui::widgets::Paragraph;
use ratatui::widgets::Wrap;
@@ -201,9 +204,8 @@ fn session_summary(
})
}
fn errors_for_cwd(cwd: &Path, response: &ListSkillsResponseEvent) -> Vec<SkillErrorInfo> {
response
.skills
fn errors_for_cwd(cwd: &Path, skills_entries: &[SkillsListEntry]) -> Vec<SkillErrorInfo> {
skills_entries
.iter()
.find(|entry| entry.cwd.as_path() == cwd)
.map(|entry| entry.errors.clone())
@@ -2274,7 +2276,7 @@ impl App {
Err(err) => break Err(err),
}
}
app_server_event = app_server.next_event(), if listen_for_app_server_events => {
app_server_event = app_server.next_typed_event(), if listen_for_app_server_events => {
match app_server_event {
Some(event) => app.handle_app_server_event(&app_server, event).await,
None => {
@@ -2626,8 +2628,8 @@ impl App {
AppEvent::CommitTick => {
self.chat_widget.on_commit_tick();
}
AppEvent::CodexEvent(event) => {
self.handle_codex_event_now(event);
AppEvent::PushApprovalRequest(request) => {
self.chat_widget.push_approval_request(request);
}
AppEvent::Exit(mode) => {
return Ok(self.handle_exit_mode(app_server, mode).await);
@@ -3810,6 +3812,15 @@ impl App {
}
}
fn handle_skills_list_response_now(&mut self, skills_entries: Vec<SkillsListEntry>) {
let cwd = self.chat_widget.config_ref().cwd.clone();
let errors = errors_for_cwd(&cwd, &skills_entries);
emit_skill_load_warnings(&self.app_event_tx, &errors);
self.chat_widget
.handle_skills_list_response(&skills_entries);
}
#[cfg(test)]
fn handle_codex_event_now(&mut self, event: Event) {
let needs_refresh = matches!(
event.msg,
@@ -3822,11 +3833,6 @@ impl App {
self.suppress_shutdown_complete = false;
return;
}
if let EventMsg::ListSkillsResponse(response) = &event.msg {
let cwd = self.chat_widget.config_ref().cwd.clone();
let errors = errors_for_cwd(&cwd, response);
emit_skill_load_warnings(&self.app_event_tx, &errors);
}
self.handle_backtrack_event(&event.msg);
self.chat_widget.handle_codex_event(event);
@@ -3846,7 +3852,7 @@ impl App {
return;
}
if let ThreadUpdate::ThreadRolledBack { num_turns } = update {
self.handle_backtrack_event(&EventMsg::ThreadRolledBack(
self.handle_backtrack_event(&codex_protocol::protocol::EventMsg::ThreadRolledBack(
codex_protocol::protocol::ThreadRolledBackEvent { num_turns },
));
self.chat_widget

View File

@@ -73,9 +73,6 @@ use codex_protocol::openai_models::ModelPreset;
use codex_protocol::openai_models::ModelUpgrade;
use codex_protocol::openai_models::ReasoningEffortPreset;
use codex_protocol::protocol::AskForApproval;
use codex_protocol::protocol::Event;
use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::ListSkillsResponseEvent;
use codex_protocol::protocol::Op;
use codex_protocol::protocol::ReviewTarget;
use codex_protocol::protocol::SandboxPolicy;
@@ -624,15 +621,7 @@ impl App {
"skills/list",
)
.await?;
let skills = serde_json::from_value(
serde_json::to_value(response.data)
.map_err(|err| format!("failed to encode skills/list response: {err}"))?,
)
.map_err(|err| format!("failed to convert skills/list response: {err}"))?;
self.handle_codex_event_now(Event {
id: String::new(),
msg: EventMsg::ListSkillsResponse(ListSkillsResponseEvent { skills }),
});
self.handle_skills_list_response_now(response.data);
}
Op::RefreshMcpServers { config } => {
let _: McpServerRefreshResponse = send_request_with_response(
@@ -1027,12 +1016,6 @@ impl App {
self.handle_server_notification(app_server_client, notification)
.await;
}
InProcessServerEvent::LegacyNotification(notification) => {
tracing::warn!(
notification.method = %notification.method,
"unexpected legacy notification after TUI app-server typed-event migration"
);
}
InProcessServerEvent::ServerRequest(request) => {
self.note_server_request(&request);
match request.clone() {
@@ -1095,6 +1078,7 @@ impl App {
tracing::warn!("{err}");
}
}
_ => unreachable!("legacy notifications are filtered by next_typed_event"),
}
}

View File

@@ -14,7 +14,6 @@ use codex_chatgpt::connectors::AppInfo;
use codex_file_search::FileMatch;
use codex_protocol::ThreadId;
use codex_protocol::openai_models::ModelPreset;
use codex_protocol::protocol::Event;
use codex_utils_approval_presets::ApprovalPreset;
use crate::bottom_pane::ApprovalRequest;
@@ -68,7 +67,7 @@ pub(crate) struct ConnectorsSnapshot {
#[allow(clippy::large_enum_variant)]
#[derive(Debug)]
pub(crate) enum AppEvent {
CodexEvent(Event),
PushApprovalRequest(ApprovalRequest),
/// Open the agent picker for switching active threads.
OpenAgentPicker,
/// Switch the active thread to the selected agent.

View File

@@ -52,6 +52,8 @@ use crate::text_formatting::proper_join;
use crate::thread_update::ThreadUpdate;
use crate::version::CODEX_CLI_VERSION;
use codex_app_server_protocol::ConfigLayerSource;
use codex_app_server_protocol::SkillMetadata as AppServerSkillMetadata;
use codex_app_server_protocol::SkillsListEntry;
use codex_chatgpt::connectors;
use codex_core::config::Config;
use codex_core::config::Constrained;
@@ -93,21 +95,28 @@ use codex_protocol::items::AgentMessageItem;
use codex_protocol::models::MessagePhase;
use codex_protocol::models::local_image_label_text;
use codex_protocol::parse_command::ParsedCommand;
#[cfg(test)]
use codex_protocol::protocol::AgentMessageDeltaEvent;
#[cfg(test)]
use codex_protocol::protocol::AgentMessageEvent;
#[cfg(test)]
use codex_protocol::protocol::AgentReasoningDeltaEvent;
#[cfg(test)]
use codex_protocol::protocol::AgentReasoningEvent;
#[cfg(test)]
use codex_protocol::protocol::AgentReasoningRawContentDeltaEvent;
#[cfg(test)]
use codex_protocol::protocol::AgentReasoningRawContentEvent;
use codex_protocol::protocol::ApplyPatchApprovalRequestEvent;
#[cfg(test)]
use codex_protocol::protocol::BackgroundEventEvent;
use codex_protocol::protocol::CodexErrorInfo;
#[cfg(test)]
use codex_protocol::protocol::CollabAgentSpawnBeginEvent;
use codex_protocol::protocol::CreditsSnapshot;
use codex_protocol::protocol::DeprecationNoticeEvent;
#[cfg(test)]
use codex_protocol::protocol::ErrorEvent;
use codex_protocol::protocol::Event;
use codex_protocol::protocol::EventMsg;
use codex_protocol::protocol::ExecApprovalRequestEvent;
use codex_protocol::protocol::ExecCommandBeginEvent;
use codex_protocol::protocol::ExecCommandEndEvent;
@@ -119,7 +128,6 @@ use codex_protocol::protocol::GuardianAssessmentStatus;
use codex_protocol::protocol::ImageGenerationBeginEvent;
use codex_protocol::protocol::ImageGenerationEndEvent;
use codex_protocol::protocol::ListCustomPromptsResponseEvent;
use codex_protocol::protocol::ListSkillsResponseEvent;
use codex_protocol::protocol::McpListToolsResponseEvent;
use codex_protocol::protocol::McpStartupCompleteEvent;
use codex_protocol::protocol::McpStartupStatus;
@@ -131,18 +139,21 @@ use codex_protocol::protocol::PatchApplyBeginEvent;
use codex_protocol::protocol::RateLimitSnapshot;
use codex_protocol::protocol::ReviewRequest;
use codex_protocol::protocol::ReviewTarget;
use codex_protocol::protocol::SkillMetadata as ProtocolSkillMetadata;
#[cfg(test)]
use codex_protocol::protocol::StreamErrorEvent;
use codex_protocol::protocol::TerminalInteractionEvent;
use codex_protocol::protocol::TokenUsage;
use codex_protocol::protocol::TokenUsageInfo;
use codex_protocol::protocol::TurnAbortReason;
#[cfg(test)]
use codex_protocol::protocol::TurnCompleteEvent;
#[cfg(test)]
use codex_protocol::protocol::TurnDiffEvent;
use codex_protocol::protocol::UndoCompletedEvent;
use codex_protocol::protocol::UndoStartedEvent;
use codex_protocol::protocol::UserMessageEvent;
use codex_protocol::protocol::ViewImageToolCallEvent;
#[cfg(test)]
use codex_protocol::protocol::WarningEvent;
use codex_protocol::protocol::WebSearchBeginEvent;
use codex_protocol::protocol::WebSearchEndEvent;
@@ -163,6 +174,13 @@ use ratatui::style::Modifier;
use ratatui::style::Style;
use ratatui::style::Stylize;
use ratatui::text::Line;
#[cfg(test)]
use codex_protocol::protocol::Event;
#[cfg(test)]
use codex_protocol::protocol::EventMsg;
#[cfg(test)]
use codex_protocol::protocol::ListSkillsResponseEvent;
use ratatui::widgets::Paragraph;
use ratatui::widgets::Wrap;
use tokio::sync::mpsc::UnboundedSender;
@@ -675,7 +693,7 @@ pub(crate) struct ChatWidget {
running_commands: HashMap<String, RunningCommand>,
pending_collab_spawn_requests: HashMap<String, multi_agents::SpawnRequestSummary>,
suppressed_exec_calls: HashSet<String>,
skills_all: Vec<ProtocolSkillMetadata>,
skills_all: Vec<AppServerSkillMetadata>,
skills_initial_state: Option<HashMap<PathBuf, bool>>,
last_unified_wait: Option<UnifiedExecWaitState>,
unified_exec_wait_streak: Option<UnifiedExecWaitStreak>,
@@ -1386,6 +1404,7 @@ impl ChatWidget {
Constrained::allow_only(event.sandbox_policy.clone());
}
self.config.approvals_reviewer = event.approvals_reviewer;
#[cfg(test)]
let initial_messages = event.initial_messages.clone();
self.last_copyable_output = None;
let forked_from_id = event.forked_from_id;
@@ -1417,6 +1436,7 @@ impl ChatWidget {
);
self.apply_session_info_cell(session_info_cell);
#[cfg(test)]
if let Some(messages) = initial_messages {
self.replay_initial_messages(messages);
}
@@ -4241,23 +4261,16 @@ impl ChatWidget {
}
}
SlashCommand::TestApproval => {
use codex_protocol::protocol::EventMsg;
use std::collections::HashMap;
use codex_protocol::protocol::ApplyPatchApprovalRequestEvent;
use codex_protocol::protocol::FileChange;
self.app_event_tx.send(AppEvent::CodexEvent(Event {
id: "1".to_string(),
// msg: EventMsg::ExecApprovalRequest(ExecApprovalRequestEvent {
// call_id: "1".to_string(),
// command: vec!["git".into(), "apply".into()],
// cwd: self.config.cwd.clone(),
// reason: Some("test".to_string()),
// }),
msg: EventMsg::ApplyPatchApprovalRequest(ApplyPatchApprovalRequestEvent {
call_id: "1".to_string(),
turn_id: "turn-1".to_string(),
self.app_event_tx.send(AppEvent::PushApprovalRequest(
ApprovalRequest::ApplyPatch {
thread_id: self.thread_id.unwrap_or_default(),
thread_label: None,
id: "1".to_string(),
reason: None,
changes: HashMap::from([
(
PathBuf::from("/tmp/test.txt"),
@@ -4273,10 +4286,9 @@ impl ChatWidget {
},
),
]),
reason: None,
grant_root: Some(PathBuf::from("/tmp")),
}),
}));
cwd: PathBuf::from("/tmp"),
},
));
}
}
}
@@ -4815,6 +4827,7 @@ impl ChatWidget {
self.request_redraw();
}
#[cfg(test)]
/// Replay a subset of initial events into the UI to seed the transcript when
/// resuming an existing session. This approximates the live event flow and
/// is intentionally conservative: only safe-to-replay items are rendered to
@@ -4833,6 +4846,7 @@ impl ChatWidget {
}
}
#[cfg(test)]
pub(crate) fn handle_codex_event(&mut self, event: Event) {
let Event { id, msg } = event;
self.dispatch_event_msg(Some(id), msg, None);
@@ -5277,6 +5291,7 @@ impl ChatWidget {
}
}
#[cfg(test)]
/// Dispatch a protocol `EventMsg` to the appropriate handler.
///
/// `id` is `Some` for live events and `None` for replayed events from
@@ -8833,11 +8848,20 @@ impl ChatWidget {
self.bottom_pane.set_custom_prompts(ev.custom_prompts);
}
fn on_list_skills(&mut self, ev: ListSkillsResponseEvent) {
self.set_skills_from_response(&ev);
pub(crate) fn handle_skills_list_response(&mut self, entries: &[SkillsListEntry]) {
self.set_skills_from_entries(entries);
self.refresh_plugin_mentions();
}
#[cfg(test)]
fn on_list_skills(&mut self, ev: ListSkillsResponseEvent) {
let entries: Vec<SkillsListEntry> = serde_json::from_value(
serde_json::to_value(ev.skills).expect("legacy skills list should serialize"),
)
.expect("legacy skills list should map to app-server skills entries");
self.handle_skills_list_response(&entries);
}
pub(crate) fn on_connectors_loaded(
&mut self,
result: Result<ConnectorsSnapshot, String>,

View File

@@ -12,6 +12,8 @@ use crate::bottom_pane::SkillsToggleView;
use crate::bottom_pane::popup_consts::standard_popup_hint_line;
use crate::skills_helpers::skill_description;
use crate::skills_helpers::skill_display_name;
use codex_app_server_protocol::SkillMetadata as AppServerSkillMetadata;
use codex_app_server_protocol::SkillsListEntry;
use codex_chatgpt::connectors::AppInfo;
use codex_core::connectors::connector_mention_slug;
use codex_core::mention_syntax::TOOL_MENTION_SIGIL;
@@ -19,9 +21,7 @@ use codex_core::skills::model::SkillDependencies;
use codex_core::skills::model::SkillInterface;
use codex_core::skills::model::SkillMetadata;
use codex_core::skills::model::SkillToolDependency;
use codex_protocol::protocol::ListSkillsResponseEvent;
use codex_protocol::protocol::SkillMetadata as ProtocolSkillMetadata;
use codex_protocol::protocol::SkillsListEntry;
use codex_protocol::protocol::SkillScope as ProtocolSkillScope;
impl ChatWidget {
pub(crate) fn open_skills_list(&mut self) {
@@ -75,7 +75,7 @@ impl ChatWidget {
.skills_all
.iter()
.map(|skill| {
let core_skill = protocol_skill_to_core(skill);
let core_skill = app_server_skill_to_core(skill);
let display_name = skill_display_name(&core_skill).to_string();
let description = skill_description(&core_skill).to_string();
let name = core_skill.name.clone();
@@ -137,14 +137,14 @@ impl ChatWidget {
);
}
pub(crate) fn set_skills_from_response(&mut self, response: &ListSkillsResponseEvent) {
let skills = skills_for_cwd(&self.config.cwd, &response.skills);
pub(crate) fn set_skills_from_entries(&mut self, entries: &[SkillsListEntry]) {
let skills = skills_for_cwd(&self.config.cwd, entries);
self.skills_all = skills;
self.set_skills(Some(enabled_skills_for_mentions(&self.skills_all)));
}
}
fn skills_for_cwd(cwd: &Path, skills_entries: &[SkillsListEntry]) -> Vec<ProtocolSkillMetadata> {
fn skills_for_cwd(cwd: &Path, skills_entries: &[SkillsListEntry]) -> Vec<AppServerSkillMetadata> {
skills_entries
.iter()
.find(|entry| entry.cwd.as_path() == cwd)
@@ -152,15 +152,15 @@ fn skills_for_cwd(cwd: &Path, skills_entries: &[SkillsListEntry]) -> Vec<Protoco
.unwrap_or_default()
}
fn enabled_skills_for_mentions(skills: &[ProtocolSkillMetadata]) -> Vec<SkillMetadata> {
fn enabled_skills_for_mentions(skills: &[AppServerSkillMetadata]) -> Vec<SkillMetadata> {
skills
.iter()
.filter(|skill| skill.enabled)
.map(protocol_skill_to_core)
.map(app_server_skill_to_core)
.collect()
}
fn protocol_skill_to_core(skill: &ProtocolSkillMetadata) -> SkillMetadata {
fn app_server_skill_to_core(skill: &AppServerSkillMetadata) -> SkillMetadata {
SkillMetadata {
name: skill.name.clone(),
description: skill.description.clone(),
@@ -194,7 +194,16 @@ fn protocol_skill_to_core(skill: &ProtocolSkillMetadata) -> SkillMetadata {
permission_profile: None,
managed_network_override: None,
path_to_skills_md: skill.path.clone(),
scope: skill.scope,
scope: protocol_skill_scope(skill.scope),
}
}
fn protocol_skill_scope(scope: codex_app_server_protocol::SkillScope) -> ProtocolSkillScope {
match scope {
codex_app_server_protocol::SkillScope::User => ProtocolSkillScope::User,
codex_app_server_protocol::SkillScope::Repo => ProtocolSkillScope::Repo,
codex_app_server_protocol::SkillScope::System => ProtocolSkillScope::System,
codex_app_server_protocol::SkillScope::Admin => ProtocolSkillScope::Admin,
}
}

View File

@@ -448,7 +448,7 @@ pub(crate) async fn run_onboarding_app(
&mut onboarding_screen,
).await;
}
app_server_event = app_server.next_event() => {
app_server_event = app_server.next_typed_event() => {
if let Some(event) = app_server_event {
handle_app_server_event(
event,
@@ -595,9 +595,9 @@ async fn handle_app_server_event(
auth_widget.apply_login_completed(payload);
}
}
InProcessServerEvent::LegacyNotification(_)
| InProcessServerEvent::ServerNotification(_)
InProcessServerEvent::ServerNotification(_)
| InProcessServerEvent::ServerRequest(_)
| InProcessServerEvent::Lagged { .. } => {}
_ => {}
}
}

View File

@@ -125,9 +125,7 @@ pub(crate) fn log_inbound_app_event(event: &AppEvent) {
}
match event {
AppEvent::CodexEvent(ev) => {
write_record("to_tui", "codex_event", ev);
}
AppEvent::PushApprovalRequest(_) => {}
AppEvent::NewSession => {
let value = json!({
"ts": now_ts(),