Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
d840b24
Mirror user text into realtime (#17520)
aibrahim-oai Apr 12, 2026
0393a48
feat(tui): add reverse history search to composer (#17550)
fcoury-oai Apr 12, 2026
4705101
Remove context status-line meter (#17420)
etraut-openai Apr 12, 2026
46ab997
Expose instruction sources (AGENTS.md) via app server (#17506)
etraut-openai Apr 12, 2026
68a1d82
fix(mcp) pause timer for elicitations (#17566)
dylan-hurd-oai Apr 12, 2026
7c1e41c
Add MCP tool wall time to model output (#17406)
pakrym-oai Apr 13, 2026
d626dc3
Run exec-server fs operations through sandbox helper (#17294)
starr-openai Apr 13, 2026
6550007
Stabilize exec-server process tests (#17605)
etraut-openai Apr 13, 2026
4ffe6c2
feat: ignore keyring on 0.0.0 (#17221)
jif-oai Apr 13, 2026
bacb92b
Build remote exec env from exec-server policy (#17216)
jif-oai Apr 13, 2026
86bd0bc
nit: change consolidation model (#17633)
jif-oai Apr 13, 2026
49ca7c9
fix: stability exec server (#17640)
jif-oai Apr 13, 2026
3f62b5c
fix: dedup compact (#17643)
jif-oai Apr 13, 2026
776246c
Make forked agent spawns keep parent model config (#17247)
friel-openai Apr 13, 2026
a5783f9
Fix custom tool output cleanup on stream failure (#17470)
etraut-openai Apr 13, 2026
ce5ad7b
Emit plan-mode prompt notifications for questionnaires (#17417)
etraut-openai Apr 13, 2026
370be36
Wrap status reset timestamps in narrow layouts (#17481)
etraut-openai Apr 13, 2026
7c797c6
Suppress duplicate compaction and terminal wait events (#17601)
etraut-openai Apr 13, 2026
313ad29
Fix TUI compaction item replay (#17657)
etraut-openai Apr 13, 2026
d25a982
Do not fail thread start when trust persistence fails (#17595)
etraut-openai Apr 13, 2026
ac82443
Use AbsolutePathBuf in skill loading and codex_home (#17407)
pakrym-oai Apr 13, 2026
46a266c
feat: disable memory endpoint (#17626)
jif-oai Apr 13, 2026
0131f99
Include legacy deny paths in elevated Windows sandbox setup (#17365)
iceweasel-oai Apr 13, 2026
d905376
feat: Avoid reloading curated marketplaces for tool-suggest discovera…
jif-oai Apr 13, 2026
a5507b5
app-server: Only unload threads which were unused for some time (#17398)
euroelessar Apr 13, 2026
7b5e1ad
only specify remote ports when the rule needs them (#17669)
iceweasel-oai Apr 13, 2026
7c43f8b
Fix tui compilation (#17691)
davidhao3300 Apr 13, 2026
ec72b1c
Update phase 2 memory model to gpt-5.4 (#17384)
kliu128 Apr 13, 2026
ecdd733
Remove unnecessary tests (#17395)
kliu128 Apr 13, 2026
ec0133f
Cap realtime mirrored user turns (#17685)
aibrahim-oai Apr 13, 2026
0e31dc0
change realtime tool description (#17699)
aibrahim-oai Apr 13, 2026
937dd38
Add `supports_parallel_tool_calls` flag to included mcps (#17667)
josiah-openai Apr 13, 2026
5c8964c
Sync upstream/main into main
manoelcalixto Apr 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions codex-rs/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 7 additions & 0 deletions codex-rs/app-server-protocol/schema/json/ClientRequest.json
Original file line number Diff line number Diff line change
Expand Up @@ -2809,6 +2809,13 @@
},
"type": "object"
},
"ThreadMemoryMode": {
"enum": [
"enabled",
"disabled"
],
"type": "string"
},
"ThreadMetadataGitInfoUpdateParams": {
"properties": {
"branch": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12099,7 +12099,7 @@
"type": "string"
},
"path": {
"type": "string"
"$ref": "#/definitions/v2/AbsolutePathBuf"
},
"scope": {
"$ref": "#/definitions/v2/SkillScope"
Expand Down Expand Up @@ -12152,7 +12152,7 @@
"type": "string"
},
"path": {
"type": "string"
"$ref": "#/definitions/v2/AbsolutePathBuf"
},
"shortDescription": {
"type": [
Expand Down Expand Up @@ -13660,6 +13660,13 @@
"title": "ThreadLoadedListResponse",
"type": "object"
},
"ThreadMemoryMode": {
"enum": [
"enabled",
"disabled"
],
"type": "string"
},
"ThreadMetadataGitInfoUpdateParams": {
"properties": {
"branch": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9947,7 +9947,7 @@
"type": "string"
},
"path": {
"type": "string"
"$ref": "#/definitions/AbsolutePathBuf"
},
"scope": {
"$ref": "#/definitions/SkillScope"
Expand Down Expand Up @@ -10000,7 +10000,7 @@
"type": "string"
},
"path": {
"type": "string"
"$ref": "#/definitions/AbsolutePathBuf"
},
"shortDescription": {
"type": [
Expand Down Expand Up @@ -11508,6 +11508,13 @@
"title": "ThreadLoadedListResponse",
"type": "object"
},
"ThreadMemoryMode": {
"enum": [
"enabled",
"disabled"
],
"type": "string"
},
"ThreadMetadataGitInfoUpdateParams": {
"properties": {
"branch": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -335,7 +335,7 @@
"type": "string"
},
"path": {
"type": "string"
"$ref": "#/definitions/AbsolutePathBuf"
},
"shortDescription": {
"type": [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"AbsolutePathBuf": {
"description": "A path that is guaranteed to be absolute and normalized (though it is not guaranteed to be canonicalized or exist on the filesystem).\n\nIMPORTANT: When deserializing an `AbsolutePathBuf`, a base path must be set using [AbsolutePathBufGuard::new]. If no base path is set, the deserialization will fail unless the path being deserialized is already absolute.",
"type": "string"
},
"SkillDependencies": {
"properties": {
"tools": {
Expand Down Expand Up @@ -103,7 +107,7 @@
"type": "string"
},
"path": {
"type": "string"
"$ref": "#/definitions/AbsolutePathBuf"
},
"scope": {
"$ref": "#/definitions/SkillScope"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
// 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.

export type ThreadMemoryMode = "enabled" | "disabled";
1 change: 1 addition & 0 deletions codex-rs/app-server-protocol/schema/typescript/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export type { SessionSource } from "./SessionSource";
export type { Settings } from "./Settings";
export type { SubAgentSource } from "./SubAgentSource";
export type { ThreadId } from "./ThreadId";
export type { ThreadMemoryMode } from "./ThreadMemoryMode";
export type { Tool } from "./Tool";
export type { Verbosity } from "./Verbosity";
export type { WebSearchAction } from "./WebSearchAction";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +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 { AbsolutePathBuf } from "../AbsolutePathBuf";
import type { SkillDependencies } from "./SkillDependencies";
import type { SkillInterface } from "./SkillInterface";
import type { SkillScope } from "./SkillScope";
Expand All @@ -9,4 +10,4 @@ export type SkillMetadata = { name: string, description: string,
/**
* Legacy short_description from SKILL.md. Prefer SKILL.json interface.short_description.
*/
shortDescription?: string, interface?: SkillInterface, dependencies?: SkillDependencies, path: string, scope: SkillScope, enabled: boolean, };
shortDescription?: string, interface?: SkillInterface, dependencies?: SkillDependencies, path: AbsolutePathBuf, scope: SkillScope, enabled: boolean, };
Original file line number Diff line number Diff line change
@@ -1,6 +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 { AbsolutePathBuf } from "../AbsolutePathBuf";
import type { SkillInterface } from "./SkillInterface";

export type SkillSummary = { name: string, description: string, shortDescription: string | null, interface: SkillInterface | null, path: string, enabled: boolean, };
export type SkillSummary = { name: string, description: string, shortDescription: string | null, interface: SkillInterface | null, path: AbsolutePathBuf, enabled: boolean, };
5 changes: 5 additions & 0 deletions codex-rs/app-server-protocol/src/protocol/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,11 @@ client_request_definitions! {
params: v2::ThreadMetadataUpdateParams,
response: v2::ThreadMetadataUpdateResponse,
},
#[experimental("thread/memoryMode/set")]
ThreadMemoryModeSet => "thread/memoryMode/set" {
params: v2::ThreadMemoryModeSetParams,
response: v2::ThreadMemoryModeSetResponse,
},
ThreadUnarchive => "thread/unarchive" {
params: v2::ThreadUnarchiveParams,
response: v2::ThreadUnarchiveResponse,
Expand Down
41 changes: 39 additions & 2 deletions codex-rs/app-server-protocol/src/protocol/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3056,6 +3056,43 @@ pub struct ThreadMetadataUpdateResponse {
pub thread: Thread,
}

#[derive(Serialize, Deserialize, Debug, Clone, Copy, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "lowercase")]
#[ts(rename_all = "lowercase")]
pub enum ThreadMemoryMode {
Enabled,
Disabled,
}

impl ThreadMemoryMode {
pub fn as_str(self) -> &'static str {
match self {
Self::Enabled => "enabled",
Self::Disabled => "disabled",
}
}

pub fn to_core(self) -> codex_protocol::protocol::ThreadMemoryMode {
match self {
Self::Enabled => codex_protocol::protocol::ThreadMemoryMode::Enabled,
Self::Disabled => codex_protocol::protocol::ThreadMemoryMode::Disabled,
}
}
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct ThreadMemoryModeSetParams {
pub thread_id: String,
pub mode: ThreadMemoryMode,
}

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

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
Expand Down Expand Up @@ -3370,7 +3407,7 @@ pub struct SkillMetadata {
#[serde(default, skip_serializing_if = "Option::is_none")]
#[ts(optional)]
pub dependencies: Option<SkillDependencies>,
pub path: PathBuf,
pub path: AbsolutePathBuf,
pub scope: SkillScope,
pub enabled: bool,
}
Expand Down Expand Up @@ -3516,7 +3553,7 @@ pub struct SkillSummary {
pub description: String,
pub short_description: Option<String>,
pub interface: Option<SkillInterface>,
pub path: PathBuf,
pub path: AbsolutePathBuf,
pub enabled: bool,
}

Expand Down
20 changes: 18 additions & 2 deletions codex-rs/app-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -140,9 +140,10 @@ Example with notification opt-out:
- `thread/loaded/list` — list the thread ids currently loaded in memory.
- `thread/read` — read a stored thread by id without resuming it; optionally include turns via `includeTurns`. The returned `thread` includes `status` (`ThreadStatus`), defaulting to `notLoaded` when the thread is not currently loaded.
- `thread/metadata/update` — patch stored thread metadata in sqlite; currently supports updating persisted `gitInfo` fields and returns the refreshed `thread`.
- `thread/memoryMode/set` — experimental; set a thread’s persisted memory eligibility to `"enabled"` or `"disabled"` for either a loaded thread or a stored rollout; returns `{}` on success.
- `thread/status/changed` — notification emitted when a loaded thread’s status changes (`threadId` + new `status`).
- `thread/archive` — move a thread’s rollout file into the archived directory; returns `{}` on success and emits `thread/archived`.
- `thread/unsubscribe` — unsubscribe this connection from thread turn/item events. If this was the last subscriber, the server shuts down and unloads the thread, then emits `thread/closed`.
- `thread/unsubscribe` — unsubscribe this connection from thread turn/item events. If this was the last subscriber, the server keeps the thread loaded and unloads it only after it has had no subscribers and no thread activity for 30 minutes, then emits `thread/closed`.
- `thread/name/set` — set or update a thread’s user-facing name for either a loaded thread or a persisted rollout; returns `{}` on success and emits `thread/name/updated` to initialized, opted-in clients. Thread names are not required to be unique; name lookups resolve to the most recently updated thread.
- `thread/unarchive` — move an archived rollout file back into the sessions directory; returns the restored `thread` on success and emits `thread/unarchived`.
- `thread/compact/start` — trigger conversation history compaction for a thread; returns `{}` immediately while progress streams through standard turn/item notifications.
Expand Down Expand Up @@ -337,11 +338,16 @@ When `nextCursor` is `null`, you’ve reached the final page.
- `notSubscribed` when the connection was not subscribed to that thread.
- `notLoaded` when the thread is not loaded.

If this was the last subscriber, the server unloads the thread and emits `thread/closed` and a `thread/status/changed` transition to `notLoaded`.
If this was the last subscriber, the server does not unload the thread immediately. It unloads the thread after the thread has had no subscribers and no thread activity for 30 minutes, then emits `thread/closed` and a `thread/status/changed` transition to `notLoaded`.

```json
{ "method": "thread/unsubscribe", "id": 22, "params": { "threadId": "thr_123" } }
{ "id": 22, "result": { "status": "unsubscribed" } }
```

Later, after the idle unload timeout:

```json
{ "method": "thread/status/changed", "params": {
"threadId": "thr_123",
"status": { "type": "notLoaded" }
Expand Down Expand Up @@ -395,6 +401,16 @@ Use `thread/metadata/update` to patch sqlite-backed metadata for a thread withou
} }
```

Experimental: use `thread/memoryMode/set` to change whether a thread remains eligible for future memory generation.

```json
{ "method": "thread/memoryMode/set", "id": 26, "params": {
"threadId": "thr_123",
"mode": "disabled"
} }
{ "id": 26, "result": {} }
```

### Example: Archive a thread

Use `thread/archive` to move the persisted rollout (stored as a JSONL file on disk) into the archived sessions directory.
Expand Down
29 changes: 28 additions & 1 deletion codex-rs/app-server/src/bespoke_event_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1303,6 +1303,11 @@ pub(crate) async fn apply_bespoke_event_handling(
.await;
}
EventMsg::ContextCompacted(..) => {
// Core still fans out this deprecated event for legacy clients;
// v2 clients receive the canonical ContextCompaction item instead.
if matches!(api_version, ApiVersion::V2) {
return;
}
let notification = ContextCompactedNotification {
thread_id: conversation_id.to_string(),
turn_id: event_turn_id.clone(),
Expand Down Expand Up @@ -1599,6 +1604,17 @@ pub(crate) async fn apply_bespoke_event_handling(
.await;
}
EventMsg::ExecCommandBegin(exec_command_begin_event) => {
if matches!(api_version, ApiVersion::V2)
&& matches!(
exec_command_begin_event.source,
codex_protocol::protocol::ExecCommandSource::UnifiedExecInteraction
)
{
// TerminalInteraction is the v2 surface for unified exec
// stdin/poll events. Suppress the legacy CommandExecution
// item so clients do not render the same wait twice.
return;
}
let item_id = exec_command_begin_event.call_id.clone();
let command_actions = exec_command_begin_event
.parsed_cmd
Expand Down Expand Up @@ -1702,6 +1718,17 @@ pub(crate) async fn apply_bespoke_event_handling(
.command_execution_started
.remove(&call_id);
}
if matches!(api_version, ApiVersion::V2)
&& matches!(
exec_command_end_event.source,
codex_protocol::protocol::ExecCommandSource::UnifiedExecInteraction
)
{
// The paired begin event is suppressed above; keep the
// completion out of v2 as well so no orphan legacy item is
// emitted for unified exec interactions.
return;
}

let item = build_command_execution_end_item(&exec_command_end_event);

Expand Down Expand Up @@ -3356,7 +3383,7 @@ mod tests {
codex_core::test_support::thread_manager_with_models_provider_and_home(
CodexAuth::create_dummy_chatgpt_auth_for_testing(),
config.model_provider.clone(),
config.codex_home.clone(),
config.codex_home.to_path_buf(),
Arc::new(codex_exec_server::EnvironmentManager::new(
/*exec_server_url*/ None,
)),
Expand Down
Loading
Loading