Skip to content

[codex] Add external agent import result accounting#28008

Draft
charlesgong-openai wants to merge 1 commit into
codex/fix-image-generation-path-urifrom
dev/charlesgong/external-agent-import-api-accounting
Draft

[codex] Add external agent import result accounting#28008
charlesgong-openai wants to merge 1 commit into
codex/fix-image-generation-path-urifrom
dev/charlesgong/external-agent-import-api-accounting

Conversation

@charlesgong-openai

Copy link
Copy Markdown
Contributor

Summary

Adds the import response and completed notification contract needed to correlate external-agent config imports and report artifact-level import results.

This PR includes:

  • importId in externalAgentConfig/import responses
  • completed notification itemResults grouped by migration item type
  • raw error/result protocol types and generated schema/TypeScript updates
  • completed-notification delivery classification while keeping progress best-effort
  • artifact-level success/error accounting in the import service, including no-op imports reporting 0 successes

Stack note: this is based on codex/fix-image-generation-path-uri because current origin/main does not include the image-generation PathUri compile fix and app-server tests fail before reaching this change without that base.

Validation

  • just test -p codex-app-server-protocol
  • env -u CODEX_SQLITE_HOME just test -p codex-app-server external_agent_config
  • just test -p codex-app-server-client event_requires_delivery
  • just fix -p codex-app-server -p codex-app-server-protocol -p codex-app-server-client
  • git diff --check

@charlesgong-openai charlesgong-openai left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added inline walkthrough notes for the main PR1 sections: protocol contract, delivery classification, service accounting, request processor aggregation, session behavior, and tests.

#[ts(export_to = "v2/")]
pub struct ExternalAgentConfigImportResponse {}
pub struct ExternalAgentConfigImportResponse {
pub import_id: String,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough: this is the correlation hook for the import RPC. The response now returns the generated importId so the app can bind later completed/progress notifications back to the request that started the import.

#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ExternalAgentConfigImportCompletedNotification {}
pub struct ExternalAgentConfigImportRawError {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough: rawErrors are the per-failure details the UI can surface or log. They carry the item type, failure stage, message, optional cwd, and optional source path/name without making the whole import fail.

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ExternalAgentConfigImportItemResult {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough: itemResults at the progress layer are step-scoped. They keep the description/cwd so intermediate events can say which concrete migration item just ran.

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ExternalAgentConfigImportTypeResult {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough: completed itemResults are type-scoped. The final notification collapses duplicate migration steps by itemType and reports artifact-level success/error counts plus all raw errors.

AccountRateLimitsUpdated => "account/rateLimits/updated" (v2::AccountRateLimitsUpdatedNotification),
AppListUpdated => "app/list/updated" (v2::AppListUpdatedNotification),
RemoteControlStatusChanged => "remoteControl/status/changed" (v2::RemoteControlStatusChangedNotification),
ExternalAgentConfigImportProgress => "externalAgentConfig/import/progress" (v2::ExternalAgentConfigImportProgressNotification),

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough: this registers the progress notification method in the v2 protocol. PR1 defines the wire shape; PR2 is the slice that starts emitting these progress events.

request_id: ConnectionRequestId,
params: ExternalAgentConfigImportParams,
) -> Result<(), JSONRPCErrorError> {
let import_id = Uuid::new_v4().to_string();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough: the importId is generated before import work starts and returned in the immediate RPC response. Completed notifications reuse the same ID for request correlation.

{
Ok(Some(canonical_path)) => canonical_path,
Ok(None) => {
record_import_error(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough: selected session validation is no longer all-or-nothing. Undetected or unresolvable sessions become raw item errors, while valid sessions continue into the import path.

}
}

fn completed_notification(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough: this is the final API aggregation step. It groups item outcomes by itemType, adds success/error counts, concatenates raw errors, and sorts the result so clients and tests get stable ordering.

}

pub(super) async fn import_sessions(&self, sessions: Vec<ExternalAgentSessionMigration>) {
pub(super) async fn import_sessions(

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough: session import now returns an item result instead of only side-effecting. That lets background session imports contribute success and error counts to ExternalAgentConfigImportCompleted.

assert_eq!(completed.import_id, import_id);
let raw_errors = completed.item_results[0].raw_errors.clone();
assert_eq!(
completed.item_results,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Walkthrough: this integration test locks the mixed-session behavior. One valid session is imported and one undetected session is reported as a raw error in the same completed payload.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant