diff --git a/codex-rs/app-server-protocol/schema/json/ClientRequest.json b/codex-rs/app-server-protocol/schema/json/ClientRequest.json index b2f4d55bab..3582754110 100644 --- a/codex-rs/app-server-protocol/schema/json/ClientRequest.json +++ b/codex-rs/app-server-protocol/schema/json/ClientRequest.json @@ -916,7 +916,7 @@ "itemTypeResults": { "description": "Completed results grouped by imported item type.", "items": { - "$ref": "#/definitions/ExternalAgentConfigImportTypeResult" + "$ref": "#/definitions/ExternalAgentConfigImportHistoryRecordTypeResultParams" }, "type": "array" }, @@ -931,6 +931,68 @@ ], "type": "object" }, + "ExternalAgentConfigImportHistoryRecordSuccessParams": { + "properties": { + "cwd": { + "type": [ + "string", + "null" + ] + }, + "itemType": { + "$ref": "#/definitions/ExternalAgentConfigMigrationItemType" + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "target": { + "type": [ + "string", + "null" + ] + }, + "title": { + "default": null, + "description": "Original title for an imported session, when available.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "itemType" + ], + "type": "object" + }, + "ExternalAgentConfigImportHistoryRecordTypeResultParams": { + "properties": { + "failures": { + "items": { + "$ref": "#/definitions/ExternalAgentConfigImportItemTypeFailure" + }, + "type": "array" + }, + "itemType": { + "$ref": "#/definitions/ExternalAgentConfigMigrationItemType" + }, + "successes": { + "items": { + "$ref": "#/definitions/ExternalAgentConfigImportHistoryRecordSuccessParams" + }, + "type": "array" + } + }, + "required": [ + "failures", + "itemType", + "successes" + ], + "type": "object" + }, "ExternalAgentConfigImportItemTypeFailure": { "properties": { "cwd": { @@ -974,35 +1036,6 @@ ], "type": "object" }, - "ExternalAgentConfigImportItemTypeSuccess": { - "properties": { - "cwd": { - "type": [ - "string", - "null" - ] - }, - "itemType": { - "$ref": "#/definitions/ExternalAgentConfigMigrationItemType" - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "target": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "itemType" - ], - "type": "object" - }, "ExternalAgentConfigImportParams": { "properties": { "migrationItems": { @@ -1038,31 +1071,6 @@ ], "type": "object" }, - "ExternalAgentConfigImportTypeResult": { - "properties": { - "failures": { - "items": { - "$ref": "#/definitions/ExternalAgentConfigImportItemTypeFailure" - }, - "type": "array" - }, - "itemType": { - "$ref": "#/definitions/ExternalAgentConfigMigrationItemType" - }, - "successes": { - "items": { - "$ref": "#/definitions/ExternalAgentConfigImportItemTypeSuccess" - }, - "type": "array" - } - }, - "required": [ - "failures", - "itemType", - "successes" - ], - "type": "object" - }, "ExternalAgentConfigMigrationItem": { "properties": { "cwd": { diff --git a/codex-rs/app-server-protocol/schema/json/ServerNotification.json b/codex-rs/app-server-protocol/schema/json/ServerNotification.json index 551d1709da..839f6bcd31 100644 --- a/codex-rs/app-server-protocol/schema/json/ServerNotification.json +++ b/codex-rs/app-server-protocol/schema/json/ServerNotification.json @@ -1275,6 +1275,14 @@ "string", "null" ] + }, + "title": { + "default": null, + "description": "Original title for an imported session; null for other item types.", + "type": [ + "string", + "null" + ] } }, "required": [ diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json index 723b469575..4f3f01e79c 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json @@ -9837,7 +9837,7 @@ "itemTypeResults": { "description": "Completed results grouped by imported item type.", "items": { - "$ref": "#/definitions/v2/ExternalAgentConfigImportTypeResult" + "$ref": "#/definitions/v2/ExternalAgentConfigImportHistoryRecordTypeResultParams" }, "type": "array" }, @@ -9866,6 +9866,68 @@ "title": "ExternalAgentConfigImportHistoryRecordResponse", "type": "object" }, + "ExternalAgentConfigImportHistoryRecordSuccessParams": { + "properties": { + "cwd": { + "type": [ + "string", + "null" + ] + }, + "itemType": { + "$ref": "#/definitions/v2/ExternalAgentConfigMigrationItemType" + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "target": { + "type": [ + "string", + "null" + ] + }, + "title": { + "default": null, + "description": "Original title for an imported session, when available.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "itemType" + ], + "type": "object" + }, + "ExternalAgentConfigImportHistoryRecordTypeResultParams": { + "properties": { + "failures": { + "items": { + "$ref": "#/definitions/v2/ExternalAgentConfigImportItemTypeFailure" + }, + "type": "array" + }, + "itemType": { + "$ref": "#/definitions/v2/ExternalAgentConfigMigrationItemType" + }, + "successes": { + "items": { + "$ref": "#/definitions/v2/ExternalAgentConfigImportHistoryRecordSuccessParams" + }, + "type": "array" + } + }, + "required": [ + "failures", + "itemType", + "successes" + ], + "type": "object" + }, "ExternalAgentConfigImportItemTypeFailure": { "properties": { "cwd": { @@ -9931,6 +9993,14 @@ "string", "null" ] + }, + "title": { + "default": null, + "description": "Original title for an imported session; null for other item types.", + "type": [ + "string", + "null" + ] } }, "required": [ diff --git a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json index 0e281dc566..f998192a83 100644 --- a/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json +++ b/codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.v2.schemas.json @@ -6015,7 +6015,7 @@ "itemTypeResults": { "description": "Completed results grouped by imported item type.", "items": { - "$ref": "#/definitions/ExternalAgentConfigImportTypeResult" + "$ref": "#/definitions/ExternalAgentConfigImportHistoryRecordTypeResultParams" }, "type": "array" }, @@ -6044,6 +6044,68 @@ "title": "ExternalAgentConfigImportHistoryRecordResponse", "type": "object" }, + "ExternalAgentConfigImportHistoryRecordSuccessParams": { + "properties": { + "cwd": { + "type": [ + "string", + "null" + ] + }, + "itemType": { + "$ref": "#/definitions/ExternalAgentConfigMigrationItemType" + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "target": { + "type": [ + "string", + "null" + ] + }, + "title": { + "default": null, + "description": "Original title for an imported session, when available.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "itemType" + ], + "type": "object" + }, + "ExternalAgentConfigImportHistoryRecordTypeResultParams": { + "properties": { + "failures": { + "items": { + "$ref": "#/definitions/ExternalAgentConfigImportItemTypeFailure" + }, + "type": "array" + }, + "itemType": { + "$ref": "#/definitions/ExternalAgentConfigMigrationItemType" + }, + "successes": { + "items": { + "$ref": "#/definitions/ExternalAgentConfigImportHistoryRecordSuccessParams" + }, + "type": "array" + } + }, + "required": [ + "failures", + "itemType", + "successes" + ], + "type": "object" + }, "ExternalAgentConfigImportItemTypeFailure": { "properties": { "cwd": { @@ -6109,6 +6171,14 @@ "string", "null" ] + }, + "title": { + "default": null, + "description": "Original title for an imported session; null for other item types.", + "type": [ + "string", + "null" + ] } }, "required": [ diff --git a/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportCompletedNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportCompletedNotification.json index f9ce7c2a01..ee6902e391 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportCompletedNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportCompletedNotification.json @@ -66,6 +66,14 @@ "string", "null" ] + }, + "title": { + "default": null, + "description": "Original title for an imported session; null for other item types.", + "type": [ + "string", + "null" + ] } }, "required": [ diff --git a/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportHistoriesReadResponse.json b/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportHistoriesReadResponse.json index 0e88e3f882..16353fd716 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportHistoriesReadResponse.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportHistoriesReadResponse.json @@ -102,6 +102,14 @@ "string", "null" ] + }, + "title": { + "default": null, + "description": "Original title for an imported session; null for other item types.", + "type": [ + "string", + "null" + ] } }, "required": [ diff --git a/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportHistoryRecordParams.json b/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportHistoryRecordParams.json index 8902c2916d..7b8166464a 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportHistoryRecordParams.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportHistoryRecordParams.json @@ -1,6 +1,68 @@ { "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { + "ExternalAgentConfigImportHistoryRecordSuccessParams": { + "properties": { + "cwd": { + "type": [ + "string", + "null" + ] + }, + "itemType": { + "$ref": "#/definitions/ExternalAgentConfigMigrationItemType" + }, + "source": { + "type": [ + "string", + "null" + ] + }, + "target": { + "type": [ + "string", + "null" + ] + }, + "title": { + "default": null, + "description": "Original title for an imported session, when available.", + "type": [ + "string", + "null" + ] + } + }, + "required": [ + "itemType" + ], + "type": "object" + }, + "ExternalAgentConfigImportHistoryRecordTypeResultParams": { + "properties": { + "failures": { + "items": { + "$ref": "#/definitions/ExternalAgentConfigImportItemTypeFailure" + }, + "type": "array" + }, + "itemType": { + "$ref": "#/definitions/ExternalAgentConfigMigrationItemType" + }, + "successes": { + "items": { + "$ref": "#/definitions/ExternalAgentConfigImportHistoryRecordSuccessParams" + }, + "type": "array" + } + }, + "required": [ + "failures", + "itemType", + "successes" + ], + "type": "object" + }, "ExternalAgentConfigImportItemTypeFailure": { "properties": { "cwd": { @@ -44,60 +106,6 @@ ], "type": "object" }, - "ExternalAgentConfigImportItemTypeSuccess": { - "properties": { - "cwd": { - "type": [ - "string", - "null" - ] - }, - "itemType": { - "$ref": "#/definitions/ExternalAgentConfigMigrationItemType" - }, - "source": { - "type": [ - "string", - "null" - ] - }, - "target": { - "type": [ - "string", - "null" - ] - } - }, - "required": [ - "itemType" - ], - "type": "object" - }, - "ExternalAgentConfigImportTypeResult": { - "properties": { - "failures": { - "items": { - "$ref": "#/definitions/ExternalAgentConfigImportItemTypeFailure" - }, - "type": "array" - }, - "itemType": { - "$ref": "#/definitions/ExternalAgentConfigMigrationItemType" - }, - "successes": { - "items": { - "$ref": "#/definitions/ExternalAgentConfigImportItemTypeSuccess" - }, - "type": "array" - } - }, - "required": [ - "failures", - "itemType", - "successes" - ], - "type": "object" - }, "ExternalAgentConfigMigrationItemType": { "enum": [ "AGENTS_MD", @@ -118,7 +126,7 @@ "itemTypeResults": { "description": "Completed results grouped by imported item type.", "items": { - "$ref": "#/definitions/ExternalAgentConfigImportTypeResult" + "$ref": "#/definitions/ExternalAgentConfigImportHistoryRecordTypeResultParams" }, "type": "array" }, diff --git a/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportProgressNotification.json b/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportProgressNotification.json index 48d2dfaf47..35e7bd43d9 100644 --- a/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportProgressNotification.json +++ b/codex-rs/app-server-protocol/schema/json/v2/ExternalAgentConfigImportProgressNotification.json @@ -66,6 +66,14 @@ "string", "null" ] + }, + "title": { + "default": null, + "description": "Original title for an imported session; null for other item types.", + "type": [ + "string", + "null" + ] } }, "required": [ diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportHistoryRecordParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportHistoryRecordParams.ts index 71a20b6563..379c1e11e8 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportHistoryRecordParams.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportHistoryRecordParams.ts @@ -1,7 +1,7 @@ // GENERATED CODE! DO NOT MODIFY BY HAND! // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. -import type { ExternalAgentConfigImportTypeResult } from "./ExternalAgentConfigImportTypeResult"; +import type { ExternalAgentConfigImportHistoryRecordTypeResultParams } from "./ExternalAgentConfigImportHistoryRecordTypeResultParams"; export type ExternalAgentConfigImportHistoryRecordParams = { /** @@ -11,4 +11,4 @@ providerId: string, /** * Completed results grouped by imported item type. */ -itemTypeResults: Array, }; +itemTypeResults: Array, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportHistoryRecordSuccessParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportHistoryRecordSuccessParams.ts new file mode 100644 index 0000000000..a2f475d325 --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportHistoryRecordSuccessParams.ts @@ -0,0 +1,10 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ExternalAgentConfigMigrationItemType } from "./ExternalAgentConfigMigrationItemType"; + +export type ExternalAgentConfigImportHistoryRecordSuccessParams = { itemType: ExternalAgentConfigMigrationItemType, cwd: string | null, source: string | null, target: string | null, +/** + * Original title for an imported session, when available. + */ +title?: string | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportHistoryRecordTypeResultParams.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportHistoryRecordTypeResultParams.ts new file mode 100644 index 0000000000..6a5d053f3a --- /dev/null +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportHistoryRecordTypeResultParams.ts @@ -0,0 +1,8 @@ +// GENERATED CODE! DO NOT MODIFY BY HAND! + +// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. +import type { ExternalAgentConfigImportHistoryRecordSuccessParams } from "./ExternalAgentConfigImportHistoryRecordSuccessParams"; +import type { ExternalAgentConfigImportItemTypeFailure } from "./ExternalAgentConfigImportItemTypeFailure"; +import type { ExternalAgentConfigMigrationItemType } from "./ExternalAgentConfigMigrationItemType"; + +export type ExternalAgentConfigImportHistoryRecordTypeResultParams = { itemType: ExternalAgentConfigMigrationItemType, successes: Array, failures: Array, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportItemTypeSuccess.ts b/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportItemTypeSuccess.ts index d94ad4a9c5..5142313989 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportItemTypeSuccess.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/ExternalAgentConfigImportItemTypeSuccess.ts @@ -3,4 +3,8 @@ // This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually. import type { ExternalAgentConfigMigrationItemType } from "./ExternalAgentConfigMigrationItemType"; -export type ExternalAgentConfigImportItemTypeSuccess = { itemType: ExternalAgentConfigMigrationItemType, cwd: string | null, source: string | null, target: string | null, }; +export type ExternalAgentConfigImportItemTypeSuccess = { itemType: ExternalAgentConfigMigrationItemType, cwd: string | null, source: string | null, target: string | null, +/** + * Original title for an imported session; null for other item types. + */ +title: string | null, }; diff --git a/codex-rs/app-server-protocol/schema/typescript/v2/index.ts b/codex-rs/app-server-protocol/schema/typescript/v2/index.ts index 5ee103a587..36f51b235b 100644 --- a/codex-rs/app-server-protocol/schema/typescript/v2/index.ts +++ b/codex-rs/app-server-protocol/schema/typescript/v2/index.ts @@ -122,6 +122,8 @@ export type { ExternalAgentConfigImportHistoriesReadResponse } from "./ExternalA export type { ExternalAgentConfigImportHistory } from "./ExternalAgentConfigImportHistory"; export type { ExternalAgentConfigImportHistoryRecordParams } from "./ExternalAgentConfigImportHistoryRecordParams"; export type { ExternalAgentConfigImportHistoryRecordResponse } from "./ExternalAgentConfigImportHistoryRecordResponse"; +export type { ExternalAgentConfigImportHistoryRecordSuccessParams } from "./ExternalAgentConfigImportHistoryRecordSuccessParams"; +export type { ExternalAgentConfigImportHistoryRecordTypeResultParams } from "./ExternalAgentConfigImportHistoryRecordTypeResultParams"; export type { ExternalAgentConfigImportItemTypeFailure } from "./ExternalAgentConfigImportItemTypeFailure"; export type { ExternalAgentConfigImportItemTypeSuccess } from "./ExternalAgentConfigImportItemTypeSuccess"; export type { ExternalAgentConfigImportParams } from "./ExternalAgentConfigImportParams"; diff --git a/codex-rs/app-server-protocol/src/protocol/v2/config.rs b/codex-rs/app-server-protocol/src/protocol/v2/config.rs index cbd9803fb4..aaafb255b2 100644 --- a/codex-rs/app-server-protocol/src/protocol/v2/config.rs +++ b/codex-rs/app-server-protocol/src/protocol/v2/config.rs @@ -787,6 +787,9 @@ pub struct ExternalAgentConfigImportItemTypeSuccess { pub cwd: Option, pub source: Option, pub target: Option, + /// Original title for an imported session; null for other item types. + #[serde(default)] + pub title: Option, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] @@ -798,6 +801,29 @@ pub struct ExternalAgentConfigImportTypeResult { pub failures: Vec, } +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct ExternalAgentConfigImportHistoryRecordSuccessParams { + pub item_type: ExternalAgentConfigMigrationItemType, + pub cwd: Option, + pub source: Option, + pub target: Option, + /// Original title for an imported session, when available. + #[serde(default)] + #[ts(optional = nullable)] + pub title: Option, +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] +#[serde(rename_all = "camelCase")] +#[ts(export_to = "v2/")] +pub struct ExternalAgentConfigImportHistoryRecordTypeResultParams { + pub item_type: ExternalAgentConfigMigrationItemType, + pub successes: Vec, + pub failures: Vec, +} + #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] #[serde(rename_all = "camelCase")] #[ts(export_to = "v2/")] @@ -805,7 +831,7 @@ pub struct ExternalAgentConfigImportHistoryRecordParams { /// Opaque provider identifier for the externally completed import. pub provider_id: String, /// Completed results grouped by imported item type. - pub item_type_results: Vec, + pub item_type_results: Vec, } #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)] diff --git a/codex-rs/app-server/README.md b/codex-rs/app-server/README.md index 0d97360376..bc69103e2a 100644 --- a/codex-rs/app-server/README.md +++ b/codex-rs/app-server/README.md @@ -248,7 +248,7 @@ Example with notification opt-out: - `config/read` — fetch the runtime-effective config after resolving config layering and managed requirements, including opaque `desktop` values stored in `config.toml`. - `externalAgentConfig/detect` — detect migratable external-agent artifacts with `includeHome`, optional `cwds`, and an optional `migrationSource` selector. Omitted, `null`, or unrecognized migration-source values retain the default behavior. The deprecated optional `source` field remains accepted for compatibility but does not select the migration source. Each detected item includes `cwd` (`null` for home), and multi-item migrations may additionally include structured `details` with plugin ids, skill names, memory, session metadata, or other artifact names. - `externalAgentConfig/import` — apply selected external-agent migration items by passing explicit `migrationItems` with `cwd` (`null` for home) and any `details` returned by detect. Pass the same optional `migrationSource` used for detection so the server reads from the matching source; omitted, `null`, or unrecognized values retain the default behavior. The optional `source` identifies the product that initiated the import, while the optional opaque `providerId` attributes analytics to the provider selected by that product without affecting migration-source selection. The response acknowledges the synchronous import phase with an `importId`. Expected migration failures are reported as per-item failures rather than JSON-RPC errors, so the server still returns that `importId` and emits `externalAgentConfig/import/completed` with the same ID once all synchronous and background work finishes. The completion notification contains type-level `itemTypeResults` with successes and failures, including raw failure messages for the client to report separately. -- `externalAgentConfig/import/readHistories` — read completed import histories and connector candidates detected from successfully imported session histories. Connector candidates include a normalized display `name`, the number of imported sessions that used the connector, and the source metadata field used for detection. +- `externalAgentConfig/import/readHistories` — read completed import histories and connector candidates detected from successfully imported session histories. Successful session entries include the original imported title when one was available. Connector candidates include a normalized display `name`, the number of imported sessions that used the connector, and the source metadata field used for detection. - `config/value/write` — write a single config key/value to the user's config.toml on disk; dotted paths such as `desktop.someKey` use the same generic write surface. Writes that overlap a managed requirement are rejected with `configRequirementReadonly`. - `config/batchWrite` — apply multiple config edits atomically to the user's config.toml on disk, with optional `reloadUserConfig: true` to hot-reload loaded threads, including multiple `desktop.*` edits. Session-static model, reasoning-effort, Plan-mode reasoning-effort, service-tier, and personality defaults do not reload existing threads. - `configRequirements/read` — fetch loaded requirements constraints from `requirements.toml` and/or MDM (or `null` if none are configured), including exact managed values (`sqliteHome`, `logDir`, `modelCatalogJson`, `checkForUpdateOnStartup`, `allowLoginShell`, `feedback.enabled`, and `windowsSandboxPrivateDesktop`), allow-lists (`allowedApprovalPolicies`, `allowedSandboxModes`, `allowedWebSearchModes`), the layered permission-profile allow map (`allowedPermissionProfiles`), the managed permission-profile default (`defaultPermissions`), lifecycle hook lockdown (`allowManagedHooksOnly`), remote-control policy (`allowRemoteControl`; `false` force-disables remote control while `true` or `null` preserves existing behavior), computer use policy (`computerUse`), Browser Use policy (`browserUse.disableAutoReview`), pinned feature values (`featureRequirements`, including the default-allowed `in_app_updates` policy that administrators can set to `false`), managed lifecycle hooks (`hooks`, including each command handler's optional `additionalContextLimit`), `enforceResidency`, managed new-thread defaults (`models.newThread.model`, `models.newThread.modelReasoningEffort`, and `models.newThread.serviceTier`), and `network` constraints such as canonical domain/socket permissions plus `managedAllowedDomainsOnly` and `dangerFullAccessDenylistOnly`. diff --git a/codex-rs/app-server/src/external_agent_migration/processor.rs b/codex-rs/app-server/src/external_agent_migration/processor.rs index 568ca110f0..7433067419 100644 --- a/codex-rs/app-server/src/external_agent_migration/processor.rs +++ b/codex-rs/app-server/src/external_agent_migration/processor.rs @@ -17,6 +17,7 @@ use codex_app_server_protocol::ExternalAgentConfigImportHistoriesReadResponse; use codex_app_server_protocol::ExternalAgentConfigImportHistoryRecordParams; use codex_app_server_protocol::ExternalAgentConfigImportHistoryRecordResponse; 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; @@ -390,11 +391,30 @@ impl ExternalAgentConfigRequestProcessor { .as_ref() .ok_or_else(|| internal_error("state database is unavailable"))?; let import_id = Uuid::new_v4().to_string(); + let item_type_results = params + .item_type_results + .into_iter() + .map(|type_result| ProtocolImportTypeResult { + item_type: type_result.item_type, + successes: type_result + .successes + .into_iter() + .map(|success| ProtocolImportSuccess { + item_type: success.item_type, + cwd: success.cwd, + source: success.source, + target: success.target, + title: success.title, + }) + .collect(), + failures: type_result.failures, + }) + .collect::>(); record_import_history( state_db, import_id.as_str(), Some(params.provider_id.as_str()), - ¶ms.item_type_results, + &item_type_results, ) .await .map_err(|err| internal_error(format!("failed to record import history: {err}")))?; @@ -639,6 +659,7 @@ async fn record_import_history( cwd: success.cwd.clone(), source: success.source.clone(), target: success.target.clone(), + title: success.title.clone(), }) }) .collect::>>()?; @@ -672,7 +693,11 @@ fn apply_plugin_outcome_to_item_result( plugin_outcome: PluginImportOutcome, ) { for plugin_id in plugin_outcome.succeeded_plugin_ids { - item_result.record_success(Some(plugin_id.clone()), Some(plugin_id)); + item_result.record_success( + Some(plugin_id.clone()), + Some(plugin_id), + /*title*/ None, + ); } for raw_error in plugin_outcome.raw_errors { item_result.record_error(raw_error); diff --git a/codex-rs/app-server/src/external_agent_migration/protocol.rs b/codex-rs/app-server/src/external_agent_migration/protocol.rs index 06289ac671..702554bde3 100644 --- a/codex-rs/app-server/src/external_agent_migration/protocol.rs +++ b/codex-rs/app-server/src/external_agent_migration/protocol.rs @@ -225,6 +225,7 @@ fn protocol_import_success_record( cwd: record.cwd, source: record.source, target: record.target, + title: record.title, }) } @@ -326,6 +327,7 @@ fn protocol_import_success(success: &ExternalAgentConfigImportSuccess) -> Protoc cwd: success.cwd.clone(), source: success.source.clone(), target: success.target.clone(), + title: success.title.clone(), } } diff --git a/codex-rs/app-server/src/external_agent_migration/session_importer.rs b/codex-rs/app-server/src/external_agent_migration/session_importer.rs index 6fc2e2eb63..3f70821e57 100644 --- a/codex-rs/app-server/src/external_agent_migration/session_importer.rs +++ b/codex-rs/app-server/src/external_agent_migration/session_importer.rs @@ -113,6 +113,7 @@ impl ExternalAgentSessionImporter { item_result.record_success( Some(completed_import.import.source_path.display().to_string()), Some(completed_import.import.imported_thread_id.to_string()), + completed_import.import.title.clone(), ); completed_imports.push(completed_import); } @@ -211,6 +212,7 @@ impl ExternalAgentSessionImporter { session_id: session_id.to_string(), server_ids: pending_import.attributed_mcp_server_ids, }); + let title = pending_import.session.title.clone(); let imported_thread_id = self.persist_session(pending_import.session) .await @@ -226,6 +228,7 @@ impl ExternalAgentSessionImporter { source_content_sha256: pending_import.source_content_sha256, imported_thread_id, connector_names: Vec::new(), + title, }, connector_attribution, })) diff --git a/codex-rs/app-server/tests/suite/v2/external_agent_config.rs b/codex-rs/app-server/tests/suite/v2/external_agent_config.rs index cf84e53e16..9ee7953ebb 100644 --- a/codex-rs/app-server/tests/suite/v2/external_agent_config.rs +++ b/codex-rs/app-server/tests/suite/v2/external_agent_config.rs @@ -654,6 +654,7 @@ async fn external_agent_config_records_externally_completed_import_history() -> "cwd": "/repo", "source": "/source/session.jsonl", "target": "thread-1", + "title": null, }]) ); assert_eq!(entry.failures, Vec::new()); @@ -1655,6 +1656,13 @@ async fn external_agent_config_import_creates_session_rollouts() -> Result<()> { source: ExternalAgentImportedConnectorSource::RemoteMcpServersConfig, }] ); + let imported_session = response + .data + .iter() + .flat_map(|history| history.successes.iter()) + .find(|success| success.item_type == ExternalAgentConfigMigrationItemType::Sessions) + .expect("imported session history should be available"); + assert_eq!(imported_session.title.as_deref(), Some("Fix auth flow")); let request_id = mcp .send_thread_list_request(ThreadListParams { diff --git a/codex-rs/external-agent-migration/src/model.rs b/codex-rs/external-agent-migration/src/model.rs index 555d0b0e89..4f475ef198 100644 --- a/codex-rs/external-agent-migration/src/model.rs +++ b/codex-rs/external-agent-migration/src/model.rs @@ -122,13 +122,19 @@ impl ExternalAgentConfigImportItemResult { self.raw_errors.push(raw_error); } - pub fn record_success(&mut self, source: Option, target: Option) { + pub fn record_success( + &mut self, + source: Option, + target: Option, + title: Option, + ) { self.success_count = self.success_count.saturating_add(1); self.successes.push(ExternalAgentConfigImportSuccess { item_type: self.item_type, cwd: self.cwd.clone(), source, target, + title, }); } } @@ -139,6 +145,7 @@ pub struct ExternalAgentConfigImportSuccess { pub cwd: Option, pub source: Option, pub target: Option, + pub title: Option, } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/codex-rs/external-agent-migration/src/service.rs b/codex-rs/external-agent-migration/src/service.rs index e798db2667..67b7e2c391 100644 --- a/codex-rs/external-agent-migration/src/service.rs +++ b/codex-rs/external-agent-migration/src/service.rs @@ -173,7 +173,7 @@ impl ExternalAgentConfigService { if let Some((source, target)) = self.import_config(migration_item.cwd.as_deref())? { - item_result.record_success(Some(source), Some(target)); + item_result.record_success(Some(source), Some(target), /*title*/ None); } emit_migration_metric( EXTERNAL_AGENT_CONFIG_IMPORT_METRIC, @@ -190,7 +190,11 @@ impl ExternalAgentConfigService { Some(imported_skills.len()), ); for skill_name in imported_skills { - item_result.record_success(Some(skill_name.clone()), Some(skill_name)); + item_result.record_success( + Some(skill_name.clone()), + Some(skill_name), + /*title*/ None, + ); } Ok(()) })(), @@ -198,7 +202,7 @@ impl ExternalAgentConfigService { if let Some((source, target)) = self.import_agents_md(migration_item.cwd.as_deref())? { - item_result.record_success(Some(source), Some(target)); + item_result.record_success(Some(source), Some(target), /*title*/ None); } emit_migration_metric( EXTERNAL_AGENT_CONFIG_IMPORT_METRIC, @@ -260,8 +264,11 @@ impl ExternalAgentConfigService { } }; for plugin_id in plugin_outcome.succeeded_plugin_ids { - item_result - .record_success(Some(plugin_id.clone()), Some(plugin_id)); + item_result.record_success( + Some(plugin_id.clone()), + Some(plugin_id), + /*title*/ None, + ); } for raw_error in plugin_outcome.raw_errors { item_result.record_error(raw_error); @@ -292,7 +299,11 @@ impl ExternalAgentConfigService { /*skills_count*/ None, ); for server_name in migrated_server_names { - item_result.record_success(Some(server_name.clone()), Some(server_name)); + item_result.record_success( + Some(server_name.clone()), + Some(server_name), + /*title*/ None, + ); } Ok(()) })(), @@ -305,8 +316,11 @@ impl ExternalAgentConfigService { Some(imported_subagents.len()), ); for subagent_name in imported_subagents { - item_result - .record_success(Some(subagent_name.clone()), Some(subagent_name)); + item_result.record_success( + Some(subagent_name.clone()), + Some(subagent_name), + /*title*/ None, + ); } Ok(()) })(), @@ -318,7 +332,11 @@ impl ExternalAgentConfigService { /*skills_count*/ None, ); for hook_name in migrated_hook_names { - item_result.record_success(Some(hook_name.clone()), Some(hook_name)); + item_result.record_success( + Some(hook_name.clone()), + Some(hook_name), + /*title*/ None, + ); } Ok(()) })(), @@ -330,7 +348,11 @@ impl ExternalAgentConfigService { Some(imported_commands.len()), ); for command_name in imported_commands { - item_result.record_success(Some(command_name.clone()), Some(command_name)); + item_result.record_success( + Some(command_name.clone()), + Some(command_name), + /*title*/ None, + ); } Ok(()) })(), @@ -358,6 +380,7 @@ impl ExternalAgentConfigService { item_result.record_success( Some(project_key), Some(target_path.display().to_string()), + /*title*/ None, ); } for failure in memory_outcome.failures { diff --git a/codex-rs/external-agent-migration/src/service_tests.rs b/codex-rs/external-agent-migration/src/service_tests.rs index 377ab9ad19..2ddc1017a3 100644 --- a/codex-rs/external-agent-migration/src/service_tests.rs +++ b/codex-rs/external-agent-migration/src/service_tests.rs @@ -66,6 +66,7 @@ fn import_success( cwd, source: Some(source.into()), target: Some(target.into()), + title: None, } } diff --git a/codex-rs/external-agent-migration/src/service_tests/general/config_import.rs b/codex-rs/external-agent-migration/src/service_tests/general/config_import.rs index 93d86b40f4..02e3cba393 100644 --- a/codex-rs/external-agent-migration/src/service_tests/general/config_import.rs +++ b/codex-rs/external-agent-migration/src/service_tests/general/config_import.rs @@ -390,6 +390,7 @@ async fn import_local_plugins_returns_completed_status() { cwd: None, source: Some("cloudflare@my-plugins".to_string()), target: Some("cloudflare@my-plugins".to_string()), + title: None, }], raw_errors: Vec::new(), }] diff --git a/codex-rs/external-agent-migration/src/sessions/ledger.rs b/codex-rs/external-agent-migration/src/sessions/ledger.rs index 63f6aac1d6..86bcef58c4 100644 --- a/codex-rs/external-agent-migration/src/sessions/ledger.rs +++ b/codex-rs/external-agent-migration/src/sessions/ledger.rs @@ -31,6 +31,8 @@ struct ImportedExternalAgentSessionRecord { source_modified_at: Option, #[serde(default)] connector_names: Vec, + #[serde(default)] + title: Option, } #[derive(Debug, PartialEq, Eq)] @@ -39,6 +41,7 @@ pub struct CompletedExternalAgentSessionImport { pub source_content_sha256: String, pub imported_thread_id: ThreadId, pub connector_names: Vec, + pub title: Option, } #[derive(Debug, Clone, PartialEq, Eq)] @@ -74,6 +77,7 @@ pub(crate) fn record_imported_session( source_path, imported_thread_id, connector_names: Vec::new(), + title: None, }], ) } @@ -98,6 +102,7 @@ pub fn record_completed_session_imports( record.imported_at = imported_at; record.source_modified_at = source_modified_at.or(record.source_modified_at); record.connector_names = import.connector_names; + record.title = import.title; ledger.records.push(record); continue; } @@ -108,6 +113,7 @@ pub fn record_completed_session_imports( imported_at, source_modified_at, connector_names: import.connector_names, + title: import.title, }); } save_import_ledger(codex_home, &ledger) diff --git a/codex-rs/external-agent-migration/src/sessions/ledger_tests.rs b/codex-rs/external-agent-migration/src/sessions/ledger_tests.rs index fd8843d442..1ca425a660 100644 --- a/codex-rs/external-agent-migration/src/sessions/ledger_tests.rs +++ b/codex-rs/external-agent-migration/src/sessions/ledger_tests.rs @@ -38,6 +38,7 @@ fn completed_imports_do_not_read_source_files() { source_content_sha256: format!("{:x}", Sha256::digest(contents)), imported_thread_id, connector_names: Vec::new(), + title: Some("Imported session".to_string()), }], ) .expect("record completed imports"); @@ -47,6 +48,7 @@ fn completed_imports_do_not_read_source_files() { assert_eq!(ledger.records[0].source_path, source_path); assert_eq!(ledger.records[0].imported_thread_id, imported_thread_id); assert_eq!(ledger.records[0].source_modified_at, None); + assert_eq!(ledger.records[0].title.as_deref(), Some("Imported session")); } #[test] @@ -68,6 +70,7 @@ fn completed_import_refreshes_existing_record_metadata() { source_content_sha256: content_sha256.clone(), imported_thread_id: first_thread_id, connector_names: vec!["Gmail".to_string()], + title: Some("First title".to_string()), }], ) .expect("record first import"); @@ -78,6 +81,7 @@ fn completed_import_refreshes_existing_record_metadata() { source_content_sha256: content_sha256, imported_thread_id: second_thread_id, connector_names: vec!["Slack".to_string()], + title: Some("Second title".to_string()), }], ) .expect("record replacement import"); @@ -88,6 +92,7 @@ fn completed_import_refreshes_existing_record_metadata() { assert_eq!(ledger.records[0].imported_thread_id, second_thread_id); assert!(ledger.records[0].source_modified_at.is_some()); assert_eq!(ledger.records[0].connector_names, vec!["Slack"]); + assert_eq!(ledger.records[0].title.as_deref(), Some("Second title")); } #[test] @@ -105,18 +110,21 @@ fn connector_candidates_use_latest_import_for_each_source() { source_content_sha256: "first-version".to_string(), imported_thread_id: ThreadId::new(), connector_names: vec!["Gmail".to_string()], + title: None, }, CompletedExternalAgentSessionImport { source_path: first_source, source_content_sha256: "second-version".to_string(), imported_thread_id: ThreadId::new(), connector_names: vec!["Slack".to_string()], + title: None, }, CompletedExternalAgentSessionImport { source_path: second_source, source_content_sha256: "only-version".to_string(), imported_thread_id: ThreadId::new(), connector_names: vec!["Gmail".to_string(), "Slack".to_string()], + title: None, }, ], ) diff --git a/codex-rs/state/src/runtime/external_agent_config_imports.rs b/codex-rs/state/src/runtime/external_agent_config_imports.rs index 3e4aab3a65..6a6c2edf6d 100644 --- a/codex-rs/state/src/runtime/external_agent_config_imports.rs +++ b/codex-rs/state/src/runtime/external_agent_config_imports.rs @@ -12,6 +12,8 @@ pub struct ExternalAgentConfigImportSuccessRecord { pub cwd: Option, pub source: Option, pub target: Option, + #[serde(default)] + pub title: Option, } #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] diff --git a/codex-rs/state/src/runtime/external_agent_config_imports_tests.rs b/codex-rs/state/src/runtime/external_agent_config_imports_tests.rs index a3040ba651..8239879358 100644 --- a/codex-rs/state/src/runtime/external_agent_config_imports_tests.rs +++ b/codex-rs/state/src/runtime/external_agent_config_imports_tests.rs @@ -20,6 +20,7 @@ async fn records_completion_by_import_id() -> anyhow::Result<()> { cwd: None, source: Some("settings.json".to_string()), target: Some("config.toml".to_string()), + title: None, }], &[], ) @@ -34,12 +35,14 @@ async fn records_completion_by_import_id() -> anyhow::Result<()> { cwd: None, source: Some("settings.json".to_string()), target: Some("config.toml".to_string()), + title: None, }, ExternalAgentConfigImportSuccessRecord { item_type: "MCP_SERVER_CONFIG".to_string(), cwd: None, source: Some("github".to_string()), target: Some("github".to_string()), + title: None, }, ], &[ExternalAgentConfigImportFailureRecord { @@ -65,12 +68,14 @@ async fn records_completion_by_import_id() -> anyhow::Result<()> { cwd: None, source: Some("settings.json".to_string()), target: Some("config.toml".to_string()), + title: None, }, ExternalAgentConfigImportSuccessRecord { item_type: "MCP_SERVER_CONFIG".to_string(), cwd: None, source: Some("github".to_string()), target: Some("github".to_string()), + title: None, } ], failures: vec![ExternalAgentConfigImportFailureRecord { @@ -106,12 +111,14 @@ async fn records_completion_by_import_id() -> anyhow::Result<()> { cwd: None, source: Some("settings.json".to_string()), target: Some("config.toml".to_string()), + title: None, }, ExternalAgentConfigImportSuccessRecord { item_type: "MCP_SERVER_CONFIG".to_string(), cwd: None, source: Some("github".to_string()), target: Some("github".to_string()), + title: None, } ], vec![ExternalAgentConfigImportFailureRecord { diff --git a/codex-rs/tui/src/external_agent_config_migration_flow_tests.rs b/codex-rs/tui/src/external_agent_config_migration_flow_tests.rs index 3e8b69c10d..bc5cc6d667 100644 --- a/codex-rs/tui/src/external_agent_config_migration_flow_tests.rs +++ b/codex-rs/tui/src/external_agent_config_migration_flow_tests.rs @@ -127,6 +127,7 @@ fn completed_notification() -> ExternalAgentConfigImportCompletedNotification { cwd: None, source: Some("settings.json".to_string()), target: Some("config.toml".to_string()), + title: None, }], failures: Vec::new(), }, @@ -138,12 +139,14 @@ fn completed_notification() -> ExternalAgentConfigImportCompletedNotification { cwd: None, source: Some("project-a".to_string()), target: Some("memory resources".to_string()), + title: None, }, ExternalAgentConfigImportItemTypeSuccess { item_type: ExternalAgentConfigMigrationItemType::Memory, cwd: None, source: Some("project-b".to_string()), target: Some("memory resources".to_string()), + title: None, }, ], failures: Vec::new(), @@ -155,6 +158,7 @@ fn completed_notification() -> ExternalAgentConfigImportCompletedNotification { cwd: None, source: Some("formatter@example".to_string()), target: Some("formatter@example".to_string()), + title: None, }], failures: vec![ExternalAgentConfigImportItemTypeFailure { item_type: ExternalAgentConfigMigrationItemType::Plugins,