mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Move external agent migration into its crate (#33456)
## What changed - Move migration detection, import orchestration, models, and reporting from `codex-app-server` into `codex-external-agent-migration`. - Keep app-server protocol conversion in a dedicated boundary module. - Organize source-specific configuration, sessions, hooks, plugins, commands, subagents, and memory handling behind shared migration adapters. - Relocate and split the migration tests alongside the extracted service. GitOrigin-RevId: 3378ec2064806a28136d6ac98664ca1d75414a4e
This commit is contained in:
1 parent
2edad72de3
commit
e7efc5b04b
57 files changed
+7713
-7471
No files matched your search
@@ -9,31 +9,29 @@ use crate::request_processors::ConfigRequestProcessor;
|
||||
use codex_analytics::AnalyticsEventsClient;
|
||||
use codex_analytics::ExternalAgentConfigImportCompletedInput;
|
||||
use codex_analytics::ExternalAgentConfigImportFailureInput;
|
||||
use codex_app_server_protocol::CommandMigration;
|
||||
use codex_app_server_protocol::ExternalAgentConfigDetectParams;
|
||||
use codex_app_server_protocol::ExternalAgentConfigDetectResponse;
|
||||
use codex_app_server_protocol::ExternalAgentConfigImportCompletedNotification;
|
||||
use codex_app_server_protocol::ExternalAgentConfigImportHistoriesReadResponse;
|
||||
use codex_app_server_protocol::ExternalAgentConfigImportHistory;
|
||||
use codex_app_server_protocol::ExternalAgentConfigImportItemTypeFailure as ProtocolImportFailure;
|
||||
use codex_app_server_protocol::ExternalAgentConfigImportItemTypeSuccess as ProtocolImportSuccess;
|
||||
use codex_app_server_protocol::ExternalAgentConfigImportParams;
|
||||
use codex_app_server_protocol::ExternalAgentConfigImportProgressNotification;
|
||||
use codex_app_server_protocol::ExternalAgentConfigImportResponse;
|
||||
use codex_app_server_protocol::ExternalAgentConfigImportTypeResult as ProtocolImportTypeResult;
|
||||
use codex_app_server_protocol::ExternalAgentConfigMigrationItem;
|
||||
use codex_app_server_protocol::ExternalAgentConfigMigrationItemType;
|
||||
use codex_app_server_protocol::ExternalAgentImportedConnectorCandidate;
|
||||
use codex_app_server_protocol::ExternalAgentImportedConnectorSource;
|
||||
use codex_app_server_protocol::HookMigration;
|
||||
use codex_app_server_protocol::JSONRPCErrorError;
|
||||
use codex_app_server_protocol::McpServerMigration;
|
||||
use codex_app_server_protocol::MigrationDetails;
|
||||
use codex_app_server_protocol::PluginsMigration;
|
||||
use codex_app_server_protocol::ServerNotification;
|
||||
use codex_app_server_protocol::SkillMigration;
|
||||
use codex_arg0::Arg0DispatchPaths;
|
||||
use codex_core::ThreadManager;
|
||||
use codex_external_agent_migration::ExternalAgentConfigDetectOptions;
|
||||
use codex_external_agent_migration::ExternalAgentConfigImportItemResult as CoreImportItemResult;
|
||||
use codex_external_agent_migration::ExternalAgentConfigImportOutcome as CoreImportOutcome;
|
||||
use codex_external_agent_migration::ExternalAgentConfigMigrationItemType as CoreMigrationItemType;
|
||||
use codex_external_agent_migration::ExternalAgentConfigService;
|
||||
use codex_external_agent_migration::PluginImportOutcome;
|
||||
use codex_external_agent_migration::record_import_error;
|
||||
use codex_external_agent_migration::sessions::ExternalAgentSessionMigration as CoreSessionMigration;
|
||||
use codex_external_agent_migration::sessions::read_imported_connector_candidates;
|
||||
use codex_features::Feature;
|
||||
@@ -44,16 +42,11 @@ use codex_thread_store::ThreadStore;
|
||||
use std::collections::HashSet;
|
||||
use std::path::PathBuf;
|
||||
|
||||
use super::service::ExternalAgentConfigDetectOptions;
|
||||
use super::service::ExternalAgentConfigImportItemResult as CoreImportItemResult;
|
||||
use super::service::ExternalAgentConfigImportOutcome as CoreImportOutcome;
|
||||
use super::service::ExternalAgentConfigImportRawError as CoreImportRawError;
|
||||
use super::service::ExternalAgentConfigMigrationItem as CoreMigrationItem;
|
||||
use super::service::ExternalAgentConfigMigrationItemType as CoreMigrationItemType;
|
||||
use super::service::ExternalAgentConfigService;
|
||||
use super::service::NamedMigration as CoreNamedMigration;
|
||||
use super::service::PluginImportOutcome;
|
||||
use super::service::record_import_error;
|
||||
use super::protocol::completed_notification;
|
||||
use super::protocol::core_migration_items;
|
||||
use super::protocol::detect_response;
|
||||
use super::protocol::protocol_import_history;
|
||||
use super::protocol::protocol_import_type_result;
|
||||
use super::session_importer::ExternalAgentSessionImporter;
|
||||
use uuid::Uuid;
|
||||
|
||||
@@ -101,7 +94,7 @@ impl ExternalAgentConfigRequestProcessor {
|
||||
);
|
||||
let session_importer = ExternalAgentSessionImporter::new(
|
||||
codex_home,
|
||||
migration_service.connector_metadata_roots.clone(),
|
||||
migration_service.connector_metadata_roots().to_vec(),
|
||||
Arc::clone(&thread_manager),
|
||||
thread_store,
|
||||
config_manager.clone(),
|
||||
@@ -136,94 +129,7 @@ impl ExternalAgentConfigRequestProcessor {
|
||||
.await
|
||||
.map_err(|err| internal_error(err.to_string()))?;
|
||||
|
||||
Ok(ExternalAgentConfigDetectResponse {
|
||||
items: items
|
||||
.into_iter()
|
||||
.map(|migration_item| ExternalAgentConfigMigrationItem {
|
||||
item_type: match migration_item.item_type {
|
||||
CoreMigrationItemType::Config => {
|
||||
ExternalAgentConfigMigrationItemType::Config
|
||||
}
|
||||
CoreMigrationItemType::Skills => {
|
||||
ExternalAgentConfigMigrationItemType::Skills
|
||||
}
|
||||
CoreMigrationItemType::AgentsMd => {
|
||||
ExternalAgentConfigMigrationItemType::AgentsMd
|
||||
}
|
||||
CoreMigrationItemType::Plugins => {
|
||||
ExternalAgentConfigMigrationItemType::Plugins
|
||||
}
|
||||
CoreMigrationItemType::McpServerConfig => {
|
||||
ExternalAgentConfigMigrationItemType::McpServerConfig
|
||||
}
|
||||
CoreMigrationItemType::Subagents => {
|
||||
ExternalAgentConfigMigrationItemType::Subagents
|
||||
}
|
||||
CoreMigrationItemType::Hooks => ExternalAgentConfigMigrationItemType::Hooks,
|
||||
CoreMigrationItemType::Commands => {
|
||||
ExternalAgentConfigMigrationItemType::Commands
|
||||
}
|
||||
CoreMigrationItemType::Memory => {
|
||||
ExternalAgentConfigMigrationItemType::Memory
|
||||
}
|
||||
CoreMigrationItemType::Sessions => {
|
||||
ExternalAgentConfigMigrationItemType::Sessions
|
||||
}
|
||||
},
|
||||
description: migration_item.description,
|
||||
cwd: migration_item.cwd,
|
||||
details: migration_item.details.map(|details| MigrationDetails {
|
||||
plugins: details
|
||||
.plugins
|
||||
.into_iter()
|
||||
.map(|plugin| PluginsMigration {
|
||||
marketplace_name: plugin.marketplace_name,
|
||||
plugin_names: plugin.plugin_names,
|
||||
})
|
||||
.collect(),
|
||||
skills: details
|
||||
.skills
|
||||
.into_iter()
|
||||
.map(|skill| SkillMigration { name: skill.name })
|
||||
.collect(),
|
||||
sessions: details
|
||||
.sessions
|
||||
.into_iter()
|
||||
.map(|session| codex_app_server_protocol::SessionMigration {
|
||||
path: session.path,
|
||||
cwd: session.cwd,
|
||||
title: session.title,
|
||||
})
|
||||
.collect(),
|
||||
mcp_servers: details
|
||||
.mcp_servers
|
||||
.into_iter()
|
||||
.map(|mcp_server| McpServerMigration {
|
||||
name: mcp_server.name,
|
||||
})
|
||||
.collect(),
|
||||
hooks: details
|
||||
.hooks
|
||||
.into_iter()
|
||||
.map(|hook| HookMigration { name: hook.name })
|
||||
.collect(),
|
||||
subagents: details
|
||||
.subagents
|
||||
.into_iter()
|
||||
.map(|subagent| codex_app_server_protocol::SubagentMigration {
|
||||
name: subagent.name,
|
||||
})
|
||||
.collect(),
|
||||
commands: details
|
||||
.commands
|
||||
.into_iter()
|
||||
.map(|command| CommandMigration { name: command.name })
|
||||
.collect(),
|
||||
memory: details.memory,
|
||||
}),
|
||||
})
|
||||
.collect(),
|
||||
})
|
||||
Ok(detect_response(items))
|
||||
}
|
||||
|
||||
pub(crate) async fn import(
|
||||
@@ -437,7 +343,7 @@ impl ExternalAgentConfigRequestProcessor {
|
||||
.into_iter()
|
||||
.map(protocol_import_history)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let connectors = read_imported_connector_candidates(&self.migration_service.codex_home)
|
||||
let connectors = read_imported_connector_candidates(self.migration_service.codex_home())
|
||||
.map_err(|err| {
|
||||
internal_error(format!(
|
||||
"failed to read imported connector candidates: {err}"
|
||||
@@ -525,105 +431,13 @@ impl ExternalAgentConfigRequestProcessor {
|
||||
migration_service: &ExternalAgentConfigService,
|
||||
) -> CoreImportOutcome {
|
||||
migration_service
|
||||
.import(
|
||||
.import(core_migration_items(
|
||||
params
|
||||
.migration_items
|
||||
.into_iter()
|
||||
.filter(|migration_item| {
|
||||
!matches!(
|
||||
migration_item.item_type,
|
||||
ExternalAgentConfigMigrationItemType::Sessions
|
||||
)
|
||||
})
|
||||
.map(|migration_item| CoreMigrationItem {
|
||||
item_type: match migration_item.item_type {
|
||||
ExternalAgentConfigMigrationItemType::Config => {
|
||||
CoreMigrationItemType::Config
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::Skills => {
|
||||
CoreMigrationItemType::Skills
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::AgentsMd => {
|
||||
CoreMigrationItemType::AgentsMd
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::Plugins => {
|
||||
CoreMigrationItemType::Plugins
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::McpServerConfig => {
|
||||
CoreMigrationItemType::McpServerConfig
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::Subagents => {
|
||||
CoreMigrationItemType::Subagents
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::Hooks => {
|
||||
CoreMigrationItemType::Hooks
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::Commands => {
|
||||
CoreMigrationItemType::Commands
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::Memory => {
|
||||
CoreMigrationItemType::Memory
|
||||
}
|
||||
ExternalAgentConfigMigrationItemType::Sessions => {
|
||||
CoreMigrationItemType::Sessions
|
||||
}
|
||||
},
|
||||
description: migration_item.description,
|
||||
cwd: migration_item.cwd,
|
||||
details: migration_item.details.map(|details| {
|
||||
super::service::MigrationDetails {
|
||||
plugins: details
|
||||
.plugins
|
||||
.into_iter()
|
||||
.map(|plugin| super::service::PluginsMigration {
|
||||
marketplace_name: plugin.marketplace_name,
|
||||
plugin_names: plugin.plugin_names,
|
||||
})
|
||||
.collect(),
|
||||
skills: details
|
||||
.skills
|
||||
.into_iter()
|
||||
.map(|skill| CoreNamedMigration { name: skill.name })
|
||||
.collect(),
|
||||
sessions: details
|
||||
.sessions
|
||||
.into_iter()
|
||||
.map(|session| CoreSessionMigration {
|
||||
path: session.path,
|
||||
cwd: session.cwd,
|
||||
title: session.title,
|
||||
})
|
||||
.collect(),
|
||||
mcp_servers: details
|
||||
.mcp_servers
|
||||
.into_iter()
|
||||
.map(|mcp_server| CoreNamedMigration {
|
||||
name: mcp_server.name,
|
||||
})
|
||||
.collect(),
|
||||
hooks: details
|
||||
.hooks
|
||||
.into_iter()
|
||||
.map(|hook| CoreNamedMigration { name: hook.name })
|
||||
.collect(),
|
||||
subagents: details
|
||||
.subagents
|
||||
.into_iter()
|
||||
.map(|subagent| CoreNamedMigration {
|
||||
name: subagent.name,
|
||||
})
|
||||
.collect(),
|
||||
commands: details
|
||||
.commands
|
||||
.into_iter()
|
||||
.map(|command| CoreNamedMigration { name: command.name })
|
||||
.collect(),
|
||||
memory: details.memory,
|
||||
}
|
||||
}),
|
||||
})
|
||||
.filter(|item| item.item_type != ExternalAgentConfigMigrationItemType::Sessions)
|
||||
.collect(),
|
||||
)
|
||||
))
|
||||
.await
|
||||
}
|
||||
}
|
||||
@@ -783,171 +597,6 @@ async fn record_completed_import_notification(
|
||||
.await
|
||||
}
|
||||
|
||||
fn protocol_import_history(
|
||||
record: codex_state::ExternalAgentConfigImportHistoryRecord,
|
||||
) -> Result<ExternalAgentConfigImportHistory, JSONRPCErrorError> {
|
||||
let successes = record
|
||||
.successes
|
||||
.into_iter()
|
||||
.map(protocol_import_success_record)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
let failures = record
|
||||
.failures
|
||||
.into_iter()
|
||||
.map(protocol_import_failure_record)
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
Ok(ExternalAgentConfigImportHistory {
|
||||
import_id: record.import_id,
|
||||
completed_at_ms: record.completed_at_ms,
|
||||
successes,
|
||||
failures,
|
||||
})
|
||||
}
|
||||
|
||||
fn protocol_import_success_record(
|
||||
record: ExternalAgentConfigImportSuccessRecord,
|
||||
) -> Result<ProtocolImportSuccess, JSONRPCErrorError> {
|
||||
Ok(ProtocolImportSuccess {
|
||||
item_type: protocol_import_record_item_type(record.item_type)?,
|
||||
cwd: record.cwd,
|
||||
source: record.source,
|
||||
target: record.target,
|
||||
})
|
||||
}
|
||||
|
||||
fn protocol_import_failure_record(
|
||||
record: ExternalAgentConfigImportFailureRecord,
|
||||
) -> Result<ProtocolImportFailure, JSONRPCErrorError> {
|
||||
Ok(ProtocolImportFailure {
|
||||
item_type: protocol_import_record_item_type(record.item_type)?,
|
||||
error_type: record.error_type,
|
||||
sub_error_type: record.sub_error_type,
|
||||
failure_stage: record.failure_stage,
|
||||
message: record.message,
|
||||
cwd: record.cwd,
|
||||
source: record.source,
|
||||
})
|
||||
}
|
||||
|
||||
fn protocol_import_record_item_type(
|
||||
item_type: String,
|
||||
) -> Result<ExternalAgentConfigMigrationItemType, JSONRPCErrorError> {
|
||||
serde_json::from_value(serde_json::Value::String(item_type.clone())).map_err(|err| {
|
||||
internal_error(format!(
|
||||
"failed to decode import item type {item_type}: {err}"
|
||||
))
|
||||
})
|
||||
}
|
||||
|
||||
fn completed_notification(
|
||||
import_id: String,
|
||||
item_results: &[CoreImportItemResult],
|
||||
) -> ExternalAgentConfigImportCompletedNotification {
|
||||
let mut protocol_type_results: Vec<ProtocolImportTypeResult> = Vec::new();
|
||||
for item_result in item_results {
|
||||
let item_raw_errors = item_result
|
||||
.raw_errors
|
||||
.iter()
|
||||
.map(protocol_import_raw_error)
|
||||
.collect::<Vec<_>>();
|
||||
let item_successes = item_result
|
||||
.successes
|
||||
.iter()
|
||||
.map(protocol_import_success)
|
||||
.collect::<Vec<_>>();
|
||||
let item_type = protocol_migration_item_type(item_result.item_type);
|
||||
if let Some(type_result) = protocol_type_results
|
||||
.iter_mut()
|
||||
.find(|type_result| type_result.item_type == item_type)
|
||||
{
|
||||
type_result.successes.extend(item_successes);
|
||||
type_result.failures.extend(item_raw_errors);
|
||||
} else {
|
||||
protocol_type_results.push(ProtocolImportTypeResult {
|
||||
item_type,
|
||||
successes: item_successes,
|
||||
failures: item_raw_errors,
|
||||
});
|
||||
}
|
||||
}
|
||||
protocol_type_results.sort_by_key(|type_result| match type_result.item_type {
|
||||
ExternalAgentConfigMigrationItemType::Config => 0,
|
||||
ExternalAgentConfigMigrationItemType::Skills => 1,
|
||||
ExternalAgentConfigMigrationItemType::AgentsMd => 2,
|
||||
ExternalAgentConfigMigrationItemType::Plugins => 3,
|
||||
ExternalAgentConfigMigrationItemType::McpServerConfig => 4,
|
||||
ExternalAgentConfigMigrationItemType::Subagents => 5,
|
||||
ExternalAgentConfigMigrationItemType::Hooks => 6,
|
||||
ExternalAgentConfigMigrationItemType::Commands => 7,
|
||||
ExternalAgentConfigMigrationItemType::Sessions => 8,
|
||||
ExternalAgentConfigMigrationItemType::Memory => 9,
|
||||
});
|
||||
|
||||
ExternalAgentConfigImportCompletedNotification {
|
||||
import_id,
|
||||
item_type_results: protocol_type_results,
|
||||
}
|
||||
}
|
||||
|
||||
fn protocol_import_type_result(item_result: &CoreImportItemResult) -> ProtocolImportTypeResult {
|
||||
ProtocolImportTypeResult {
|
||||
item_type: protocol_migration_item_type(item_result.item_type),
|
||||
successes: item_result
|
||||
.successes
|
||||
.iter()
|
||||
.map(protocol_import_success)
|
||||
.collect(),
|
||||
failures: item_result
|
||||
.raw_errors
|
||||
.iter()
|
||||
.map(protocol_import_raw_error)
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
|
||||
fn protocol_import_success(
|
||||
success: &super::service::ExternalAgentConfigImportSuccess,
|
||||
) -> ProtocolImportSuccess {
|
||||
ProtocolImportSuccess {
|
||||
item_type: protocol_migration_item_type(success.item_type),
|
||||
cwd: success.cwd.clone(),
|
||||
source: success.source.clone(),
|
||||
target: success.target.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn protocol_import_raw_error(raw_error: &CoreImportRawError) -> ProtocolImportFailure {
|
||||
ProtocolImportFailure {
|
||||
item_type: protocol_migration_item_type(raw_error.item_type),
|
||||
error_type: raw_error.error_type.clone(),
|
||||
sub_error_type: raw_error.sub_error_type.clone(),
|
||||
failure_stage: raw_error.failure_stage.clone(),
|
||||
message: raw_error.message.clone(),
|
||||
cwd: raw_error.cwd.clone(),
|
||||
source: raw_error.source.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
fn protocol_migration_item_type(
|
||||
item_type: CoreMigrationItemType,
|
||||
) -> ExternalAgentConfigMigrationItemType {
|
||||
match item_type {
|
||||
CoreMigrationItemType::Config => ExternalAgentConfigMigrationItemType::Config,
|
||||
CoreMigrationItemType::Skills => ExternalAgentConfigMigrationItemType::Skills,
|
||||
CoreMigrationItemType::AgentsMd => ExternalAgentConfigMigrationItemType::AgentsMd,
|
||||
CoreMigrationItemType::Plugins => ExternalAgentConfigMigrationItemType::Plugins,
|
||||
CoreMigrationItemType::McpServerConfig => {
|
||||
ExternalAgentConfigMigrationItemType::McpServerConfig
|
||||
}
|
||||
CoreMigrationItemType::Subagents => ExternalAgentConfigMigrationItemType::Subagents,
|
||||
CoreMigrationItemType::Hooks => ExternalAgentConfigMigrationItemType::Hooks,
|
||||
CoreMigrationItemType::Commands => ExternalAgentConfigMigrationItemType::Commands,
|
||||
CoreMigrationItemType::Memory => ExternalAgentConfigMigrationItemType::Memory,
|
||||
CoreMigrationItemType::Sessions => ExternalAgentConfigMigrationItemType::Sessions,
|
||||
}
|
||||
}
|
||||
|
||||
fn apply_plugin_outcome_to_item_result(
|
||||
item_result: &mut CoreImportItemResult,
|
||||
plugin_outcome: PluginImportOutcome,
|
||||
|
||||
Reference in new issue
Block a user