Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions codex-rs/Cargo.lock

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

39 changes: 39 additions & 0 deletions codex-rs/app-server-protocol/schema/json/ServerNotification.json
Original file line number Diff line number Diff line change
Expand Up @@ -3970,6 +3970,25 @@
}
]
},
"WarningNotification": {
"properties": {
"message": {
"description": "Concise warning message for the user.",
"type": "string"
},
"threadId": {
"description": "Optional thread target when the warning applies to a specific thread.",
"type": [
"string",
"null"
]
}
},
"required": [
"message"
],
"type": "object"
},
"WebSearchAction": {
"oneOf": [
{
Expand Down Expand Up @@ -4910,6 +4929,26 @@
"title": "Model/reroutedNotification",
"type": "object"
},
{
"properties": {
"method": {
"enum": [
"warning"
],
"title": "WarningNotificationMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/WarningNotification"
}
},
"required": [
"method",
"params"
],
"title": "WarningNotification",
"type": "object"
},
{
"properties": {
"method": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4279,6 +4279,26 @@
"title": "Model/reroutedNotification",
"type": "object"
},
{
"properties": {
"method": {
"enum": [
"warning"
],
"title": "WarningNotificationMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/v2/WarningNotification"
}
},
"required": [
"method",
"params"
],
"title": "WarningNotification",
"type": "object"
},
{
"properties": {
"method": {
Expand Down Expand Up @@ -15598,6 +15618,27 @@
],
"type": "string"
},
"WarningNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"message": {
"description": "Concise warning message for the user.",
"type": "string"
},
"threadId": {
"description": "Optional thread target when the warning applies to a specific thread.",
"type": [
"string",
"null"
]
}
},
"required": [
"message"
],
"title": "WarningNotification",
"type": "object"
},
"WebSearchAction": {
"oneOf": [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9650,6 +9650,26 @@
"title": "Model/reroutedNotification",
"type": "object"
},
{
"properties": {
"method": {
"enum": [
"warning"
],
"title": "WarningNotificationMethod",
"type": "string"
},
"params": {
"$ref": "#/definitions/WarningNotification"
}
},
"required": [
"method",
"params"
],
"title": "WarningNotification",
"type": "object"
},
{
"properties": {
"method": {
Expand Down Expand Up @@ -13442,6 +13462,27 @@
],
"type": "string"
},
"WarningNotification": {
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"message": {
"description": "Concise warning message for the user.",
"type": "string"
},
"threadId": {
"description": "Optional thread target when the warning applies to a specific thread.",
"type": [
"string",
"null"
]
}
},
"required": [
"message"
],
"title": "WarningNotification",
"type": "object"
},
"WebSearchAction": {
"oneOf": [
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"message": {
"description": "Concise warning message for the user.",
"type": "string"
},
"threadId": {
"description": "Optional thread target when the warning applies to a specific thread.",
"type": [
"string",
"null"
]
}
},
"required": [
"message"
],
"title": "WarningNotification",
"type": "object"
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ import type { TurnCompletedNotification } from "./v2/TurnCompletedNotification";
import type { TurnDiffUpdatedNotification } from "./v2/TurnDiffUpdatedNotification";
import type { TurnPlanUpdatedNotification } from "./v2/TurnPlanUpdatedNotification";
import type { TurnStartedNotification } from "./v2/TurnStartedNotification";
import type { WarningNotification } from "./v2/WarningNotification";
import type { WindowsSandboxSetupCompletedNotification } from "./v2/WindowsSandboxSetupCompletedNotification";
import type { WindowsWorldWritableWarningNotification } from "./v2/WindowsWorldWritableWarningNotification";

/**
* Notification sent from the server to the client.
*/
export type ServerNotification = { "method": "error", "params": ErrorNotification } | { "method": "thread/started", "params": ThreadStartedNotification } | { "method": "thread/status/changed", "params": ThreadStatusChangedNotification } | { "method": "thread/archived", "params": ThreadArchivedNotification } | { "method": "thread/unarchived", "params": ThreadUnarchivedNotification } | { "method": "thread/closed", "params": ThreadClosedNotification } | { "method": "skills/changed", "params": SkillsChangedNotification } | { "method": "thread/name/updated", "params": ThreadNameUpdatedNotification } | { "method": "thread/tokenUsage/updated", "params": ThreadTokenUsageUpdatedNotification } | { "method": "turn/started", "params": TurnStartedNotification } | { "method": "hook/started", "params": HookStartedNotification } | { "method": "turn/completed", "params": TurnCompletedNotification } | { "method": "hook/completed", "params": HookCompletedNotification } | { "method": "turn/diff/updated", "params": TurnDiffUpdatedNotification } | { "method": "turn/plan/updated", "params": TurnPlanUpdatedNotification } | { "method": "item/started", "params": ItemStartedNotification } | { "method": "item/autoApprovalReview/started", "params": ItemGuardianApprovalReviewStartedNotification } | { "method": "item/autoApprovalReview/completed", "params": ItemGuardianApprovalReviewCompletedNotification } | { "method": "item/completed", "params": ItemCompletedNotification } | { "method": "rawResponseItem/completed", "params": RawResponseItemCompletedNotification } | { "method": "item/agentMessage/delta", "params": AgentMessageDeltaNotification } | { "method": "item/plan/delta", "params": PlanDeltaNotification } | { "method": "command/exec/outputDelta", "params": CommandExecOutputDeltaNotification } | { "method": "item/commandExecution/outputDelta", "params": CommandExecutionOutputDeltaNotification } | { "method": "item/commandExecution/terminalInteraction", "params": TerminalInteractionNotification } | { "method": "item/fileChange/outputDelta", "params": FileChangeOutputDeltaNotification } | { "method": "serverRequest/resolved", "params": ServerRequestResolvedNotification } | { "method": "item/mcpToolCall/progress", "params": McpToolCallProgressNotification } | { "method": "mcpServer/oauthLogin/completed", "params": McpServerOauthLoginCompletedNotification } | { "method": "mcpServer/startupStatus/updated", "params": McpServerStatusUpdatedNotification } | { "method": "account/updated", "params": AccountUpdatedNotification } | { "method": "account/rateLimits/updated", "params": AccountRateLimitsUpdatedNotification } | { "method": "app/list/updated", "params": AppListUpdatedNotification } | { "method": "externalAgentConfig/import/completed", "params": ExternalAgentConfigImportCompletedNotification } | { "method": "fs/changed", "params": FsChangedNotification } | { "method": "item/reasoning/summaryTextDelta", "params": ReasoningSummaryTextDeltaNotification } | { "method": "item/reasoning/summaryPartAdded", "params": ReasoningSummaryPartAddedNotification } | { "method": "item/reasoning/textDelta", "params": ReasoningTextDeltaNotification } | { "method": "thread/compacted", "params": ContextCompactedNotification } | { "method": "model/rerouted", "params": ModelReroutedNotification } | { "method": "deprecationNotice", "params": DeprecationNoticeNotification } | { "method": "configWarning", "params": ConfigWarningNotification } | { "method": "fuzzyFileSearch/sessionUpdated", "params": FuzzyFileSearchSessionUpdatedNotification } | { "method": "fuzzyFileSearch/sessionCompleted", "params": FuzzyFileSearchSessionCompletedNotification } | { "method": "thread/realtime/started", "params": ThreadRealtimeStartedNotification } | { "method": "thread/realtime/itemAdded", "params": ThreadRealtimeItemAddedNotification } | { "method": "thread/realtime/transcript/delta", "params": ThreadRealtimeTranscriptDeltaNotification } | { "method": "thread/realtime/transcript/done", "params": ThreadRealtimeTranscriptDoneNotification } | { "method": "thread/realtime/outputAudio/delta", "params": ThreadRealtimeOutputAudioDeltaNotification } | { "method": "thread/realtime/sdp", "params": ThreadRealtimeSdpNotification } | { "method": "thread/realtime/error", "params": ThreadRealtimeErrorNotification } | { "method": "thread/realtime/closed", "params": ThreadRealtimeClosedNotification } | { "method": "windows/worldWritableWarning", "params": WindowsWorldWritableWarningNotification } | { "method": "windowsSandbox/setupCompleted", "params": WindowsSandboxSetupCompletedNotification } | { "method": "account/login/completed", "params": AccountLoginCompletedNotification };
export type ServerNotification = { "method": "error", "params": ErrorNotification } | { "method": "thread/started", "params": ThreadStartedNotification } | { "method": "thread/status/changed", "params": ThreadStatusChangedNotification } | { "method": "thread/archived", "params": ThreadArchivedNotification } | { "method": "thread/unarchived", "params": ThreadUnarchivedNotification } | { "method": "thread/closed", "params": ThreadClosedNotification } | { "method": "skills/changed", "params": SkillsChangedNotification } | { "method": "thread/name/updated", "params": ThreadNameUpdatedNotification } | { "method": "thread/tokenUsage/updated", "params": ThreadTokenUsageUpdatedNotification } | { "method": "turn/started", "params": TurnStartedNotification } | { "method": "hook/started", "params": HookStartedNotification } | { "method": "turn/completed", "params": TurnCompletedNotification } | { "method": "hook/completed", "params": HookCompletedNotification } | { "method": "turn/diff/updated", "params": TurnDiffUpdatedNotification } | { "method": "turn/plan/updated", "params": TurnPlanUpdatedNotification } | { "method": "item/started", "params": ItemStartedNotification } | { "method": "item/autoApprovalReview/started", "params": ItemGuardianApprovalReviewStartedNotification } | { "method": "item/autoApprovalReview/completed", "params": ItemGuardianApprovalReviewCompletedNotification } | { "method": "item/completed", "params": ItemCompletedNotification } | { "method": "rawResponseItem/completed", "params": RawResponseItemCompletedNotification } | { "method": "item/agentMessage/delta", "params": AgentMessageDeltaNotification } | { "method": "item/plan/delta", "params": PlanDeltaNotification } | { "method": "command/exec/outputDelta", "params": CommandExecOutputDeltaNotification } | { "method": "item/commandExecution/outputDelta", "params": CommandExecutionOutputDeltaNotification } | { "method": "item/commandExecution/terminalInteraction", "params": TerminalInteractionNotification } | { "method": "item/fileChange/outputDelta", "params": FileChangeOutputDeltaNotification } | { "method": "serverRequest/resolved", "params": ServerRequestResolvedNotification } | { "method": "item/mcpToolCall/progress", "params": McpToolCallProgressNotification } | { "method": "mcpServer/oauthLogin/completed", "params": McpServerOauthLoginCompletedNotification } | { "method": "mcpServer/startupStatus/updated", "params": McpServerStatusUpdatedNotification } | { "method": "account/updated", "params": AccountUpdatedNotification } | { "method": "account/rateLimits/updated", "params": AccountRateLimitsUpdatedNotification } | { "method": "app/list/updated", "params": AppListUpdatedNotification } | { "method": "externalAgentConfig/import/completed", "params": ExternalAgentConfigImportCompletedNotification } | { "method": "fs/changed", "params": FsChangedNotification } | { "method": "item/reasoning/summaryTextDelta", "params": ReasoningSummaryTextDeltaNotification } | { "method": "item/reasoning/summaryPartAdded", "params": ReasoningSummaryPartAddedNotification } | { "method": "item/reasoning/textDelta", "params": ReasoningTextDeltaNotification } | { "method": "thread/compacted", "params": ContextCompactedNotification } | { "method": "model/rerouted", "params": ModelReroutedNotification } | { "method": "warning", "params": WarningNotification } | { "method": "deprecationNotice", "params": DeprecationNoticeNotification } | { "method": "configWarning", "params": ConfigWarningNotification } | { "method": "fuzzyFileSearch/sessionUpdated", "params": FuzzyFileSearchSessionUpdatedNotification } | { "method": "fuzzyFileSearch/sessionCompleted", "params": FuzzyFileSearchSessionCompletedNotification } | { "method": "thread/realtime/started", "params": ThreadRealtimeStartedNotification } | { "method": "thread/realtime/itemAdded", "params": ThreadRealtimeItemAddedNotification } | { "method": "thread/realtime/transcript/delta", "params": ThreadRealtimeTranscriptDeltaNotification } | { "method": "thread/realtime/transcript/done", "params": ThreadRealtimeTranscriptDoneNotification } | { "method": "thread/realtime/outputAudio/delta", "params": ThreadRealtimeOutputAudioDeltaNotification } | { "method": "thread/realtime/sdp", "params": ThreadRealtimeSdpNotification } | { "method": "thread/realtime/error", "params": ThreadRealtimeErrorNotification } | { "method": "thread/realtime/closed", "params": ThreadRealtimeClosedNotification } | { "method": "windows/worldWritableWarning", "params": WindowsWorldWritableWarningNotification } | { "method": "windowsSandbox/setupCompleted", "params": WindowsSandboxSetupCompletedNotification } | { "method": "account/login/completed", "params": AccountLoginCompletedNotification };
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// 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 WarningNotification = {
/**
* Optional thread target when the warning applies to a specific thread.
*/
threadId: string | null,
/**
* Concise warning message for the user.
*/
message: string, };
1 change: 1 addition & 0 deletions codex-rs/app-server-protocol/schema/typescript/v2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ export type { TurnStatus } from "./TurnStatus";
export type { TurnSteerParams } from "./TurnSteerParams";
export type { TurnSteerResponse } from "./TurnSteerResponse";
export type { UserInput } from "./UserInput";
export type { WarningNotification } from "./WarningNotification";
export type { WebSearchAction } from "./WebSearchAction";
export type { WindowsSandboxSetupCompletedNotification } from "./WindowsSandboxSetupCompletedNotification";
export type { WindowsSandboxSetupMode } from "./WindowsSandboxSetupMode";
Expand Down
1 change: 1 addition & 0 deletions codex-rs/app-server-protocol/src/protocol/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1025,6 +1025,7 @@ server_notification_definitions! {
/// Deprecated: Use `ContextCompaction` item type instead.
ContextCompacted => "thread/compacted" (v2::ContextCompactedNotification),
ModelRerouted => "model/rerouted" (v2::ModelReroutedNotification),
Warning => "warning" (v2::WarningNotification),
DeprecationNotice => "deprecationNotice" (v2::DeprecationNoticeNotification),
ConfigWarning => "configWarning" (v2::ConfigWarningNotification),
FuzzyFileSearchSessionUpdated => "fuzzyFileSearch/sessionUpdated" (FuzzyFileSearchSessionUpdatedNotification),
Expand Down
10 changes: 10 additions & 0 deletions codex-rs/app-server-protocol/src/protocol/v2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6569,6 +6569,16 @@ pub struct DeprecationNoticeNotification {
pub details: Option<String>,
}

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
pub struct WarningNotification {
/// Optional thread target when the warning applies to a specific thread.
pub thread_id: Option<String>,
/// Concise warning message for the user.
pub message: String,
}

Comment on lines +6575 to +6581
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

should we add thread_id and make the warning thread-scoped? otherwise the notification isnt bound to a single thread and would show up globally regardless of what the active thread is

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Why should it be tied to a specific thread? The backend should decide when to send it, but the UI should just render it regardless?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

i think there's a notion of global vs thread server notification targets here. if that distinction is not relevant for how we plan to render it in app-server clients, global is fine

Copy link
Copy Markdown
Collaborator Author

@xl-openai xl-openai Apr 17, 2026

Choose a reason for hiding this comment

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

Let me make thread_id optional. In general, WarningNotification can be global, so tying it to a thread should be an option rather than a requirement. For the current case it does apply.

#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, JsonSchema, TS)]
#[serde(rename_all = "camelCase")]
#[ts(export_to = "v2/")]
Expand Down
4 changes: 4 additions & 0 deletions codex-rs/app-server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -937,6 +937,10 @@ Event notifications are the server-initiated event stream for thread lifecycles,

Thread realtime uses a separate thread-scoped notification surface. `thread/realtime/*` notifications are ephemeral transport events, not `ThreadItem`s, and are not returned by `thread/read`, `thread/resume`, or `thread/fork`.

Recoverable configuration and initialization warnings use the existing `configWarning` notification: `{ summary, details?, path?, range? }`. App-server may emit it during initialization for config parsing and related setup diagnostics.

Generic runtime warnings use the `warning` notification: `{ threadId?, message }`. App-server emits this for non-fatal warnings from the core event stream, including cases where not all enabled skills are included in the model-visible skills list for a session.

### Notification opt-out

Clients can suppress specific notifications per connection by sending exact method names in `initialize.params.capabilities.optOutNotificationMethods`.
Expand Down
17 changes: 16 additions & 1 deletion codex-rs/app-server/src/bespoke_event_handling.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ use codex_app_server_protocol::TurnPlanStep;
use codex_app_server_protocol::TurnPlanUpdatedNotification;
use codex_app_server_protocol::TurnStartedNotification;
use codex_app_server_protocol::TurnStatus;
use codex_app_server_protocol::WarningNotification;
use codex_app_server_protocol::build_command_execution_end_item;
use codex_app_server_protocol::build_file_change_approval_request_item;
use codex_app_server_protocol::build_file_change_begin_item;
Expand Down Expand Up @@ -268,7 +269,21 @@ pub(crate) async fn apply_bespoke_event_handling(
.await;
}
}
EventMsg::Warning(_warning_event) => {}
EventMsg::Warning(warning_event) => {
if let ApiVersion::V2 = api_version {
let notification = WarningNotification {
thread_id: Some(conversation_id.to_string()),
message: warning_event.message,
};
if let Some(analytics_events_client) = analytics_events_client.as_ref() {
analytics_events_client
.track_notification(ServerNotification::Warning(notification.clone()));
}
outgoing
.send_server_notification(ServerNotification::Warning(notification))
.await;
}
}
EventMsg::GuardianAssessment(assessment) => {
if let ApiVersion::V2 = api_version {
let pending_command_execution = match build_item_from_guardian_event(
Expand Down
1 change: 1 addition & 0 deletions codex-rs/app-server/src/codex_message_processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4144,6 +4144,7 @@ impl CodexMessageProcessor {
thread_id,
thread: codex_thread,
session_configured,
..
}) => {
let SessionConfiguredEvent { rollout_path, .. } = session_configured;
let Some(rollout_path) = rollout_path else {
Expand Down
Loading
Loading