Skip to content

Commit 1f54496

Browse files
authored
app-server: expose loaded thread status via read/list and notifications (openai#11786)
Motivation - Today, a newly connected client has no direct way to determine the current runtime status of threads from read/list responses alone. - This forces clients to infer state from transient events, which can lead to stale or inconsistent UI when reconnecting or attaching late. Changes - Add `status` to `thread/read` responses. - Add `statuses` to `thread/list` responses. - Emit `thread/status/changed` notifications with `threadId` and the new status. - Track runtime status for all loaded threads and default unknown threads to `idle`. - Update protocol/docs/tests/schema fixtures for the revised API. Testing - Validated protocol API changes with automated protocol tests and regenerated schema/type fixtures. - Validated app-server behavior with unit and integration test suites, including status transitions and notifications.
1 parent 216fe7f commit 1f54496

34 files changed

+2559
-115
lines changed

codex-rs/app-server-protocol/schema/json/ServerNotification.json

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6527,6 +6527,14 @@
65276527
],
65286528
"description": "Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.)."
65296529
},
6530+
"status": {
6531+
"allOf": [
6532+
{
6533+
"$ref": "#/definitions/ThreadStatus"
6534+
}
6535+
],
6536+
"description": "Current runtime status for the thread."
6537+
},
65306538
"turns": {
65316539
"description": "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.",
65326540
"items": {
@@ -6548,11 +6556,19 @@
65486556
"modelProvider",
65496557
"preview",
65506558
"source",
6559+
"status",
65516560
"turns",
65526561
"updatedAt"
65536562
],
65546563
"type": "object"
65556564
},
6565+
"ThreadActiveFlag": {
6566+
"enum": [
6567+
"waitingOnApproval",
6568+
"waitingOnUserInput"
6569+
],
6570+
"type": "string"
6571+
},
65566572
"ThreadArchivedNotification": {
65576573
"properties": {
65586574
"threadId": {
@@ -7078,6 +7094,96 @@
70787094
],
70797095
"type": "object"
70807096
},
7097+
"ThreadStatus": {
7098+
"oneOf": [
7099+
{
7100+
"properties": {
7101+
"type": {
7102+
"enum": [
7103+
"notLoaded"
7104+
],
7105+
"title": "NotLoadedThreadStatusType",
7106+
"type": "string"
7107+
}
7108+
},
7109+
"required": [
7110+
"type"
7111+
],
7112+
"title": "NotLoadedThreadStatus",
7113+
"type": "object"
7114+
},
7115+
{
7116+
"properties": {
7117+
"type": {
7118+
"enum": [
7119+
"idle"
7120+
],
7121+
"title": "IdleThreadStatusType",
7122+
"type": "string"
7123+
}
7124+
},
7125+
"required": [
7126+
"type"
7127+
],
7128+
"title": "IdleThreadStatus",
7129+
"type": "object"
7130+
},
7131+
{
7132+
"properties": {
7133+
"type": {
7134+
"enum": [
7135+
"systemError"
7136+
],
7137+
"title": "SystemErrorThreadStatusType",
7138+
"type": "string"
7139+
}
7140+
},
7141+
"required": [
7142+
"type"
7143+
],
7144+
"title": "SystemErrorThreadStatus",
7145+
"type": "object"
7146+
},
7147+
{
7148+
"properties": {
7149+
"activeFlags": {
7150+
"items": {
7151+
"$ref": "#/definitions/ThreadActiveFlag"
7152+
},
7153+
"type": "array"
7154+
},
7155+
"type": {
7156+
"enum": [
7157+
"active"
7158+
],
7159+
"title": "ActiveThreadStatusType",
7160+
"type": "string"
7161+
}
7162+
},
7163+
"required": [
7164+
"activeFlags",
7165+
"type"
7166+
],
7167+
"title": "ActiveThreadStatus",
7168+
"type": "object"
7169+
}
7170+
]
7171+
},
7172+
"ThreadStatusChangedNotification": {
7173+
"properties": {
7174+
"status": {
7175+
"$ref": "#/definitions/ThreadStatus"
7176+
},
7177+
"threadId": {
7178+
"type": "string"
7179+
}
7180+
},
7181+
"required": [
7182+
"status",
7183+
"threadId"
7184+
],
7185+
"type": "object"
7186+
},
70817187
"ThreadTokenUsage": {
70827188
"properties": {
70837189
"last": {
@@ -8151,6 +8257,26 @@
81518257
"title": "Thread/startedNotification",
81528258
"type": "object"
81538259
},
8260+
{
8261+
"properties": {
8262+
"method": {
8263+
"enum": [
8264+
"thread/status/changed"
8265+
],
8266+
"title": "Thread/status/changedNotificationMethod",
8267+
"type": "string"
8268+
},
8269+
"params": {
8270+
"$ref": "#/definitions/ThreadStatusChangedNotification"
8271+
}
8272+
},
8273+
"required": [
8274+
"method",
8275+
"params"
8276+
],
8277+
"title": "Thread/status/changedNotification",
8278+
"type": "object"
8279+
},
81548280
{
81558281
"properties": {
81568282
"method": {

codex-rs/app-server-protocol/schema/json/codex_app_server_protocol.schemas.json

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8108,6 +8108,26 @@
81088108
"title": "Thread/startedNotification",
81098109
"type": "object"
81108110
},
8111+
{
8112+
"properties": {
8113+
"method": {
8114+
"enum": [
8115+
"thread/status/changed"
8116+
],
8117+
"title": "Thread/status/changedNotificationMethod",
8118+
"type": "string"
8119+
},
8120+
"params": {
8121+
"$ref": "#/definitions/v2/ThreadStatusChangedNotification"
8122+
}
8123+
},
8124+
"required": [
8125+
"method",
8126+
"params"
8127+
],
8128+
"title": "Thread/status/changedNotification",
8129+
"type": "object"
8130+
},
81118131
{
81128132
"properties": {
81138133
"method": {
@@ -15168,6 +15188,14 @@
1516815188
],
1516915189
"description": "Origin of the thread (CLI, VSCode, codex exec, codex app-server, etc.)."
1517015190
},
15191+
"status": {
15192+
"allOf": [
15193+
{
15194+
"$ref": "#/definitions/v2/ThreadStatus"
15195+
}
15196+
],
15197+
"description": "Current runtime status for the thread."
15198+
},
1517115199
"turns": {
1517215200
"description": "Only populated on `thread/resume`, `thread/rollback`, `thread/fork`, and `thread/read` (when `includeTurns` is true) responses. For all other responses and notifications returning a Thread, the turns field will be an empty list.",
1517315201
"items": {
@@ -15189,11 +15217,19 @@
1518915217
"modelProvider",
1519015218
"preview",
1519115219
"source",
15220+
"status",
1519215221
"turns",
1519315222
"updatedAt"
1519415223
],
1519515224
"type": "object"
1519615225
},
15226+
"ThreadActiveFlag": {
15227+
"enum": [
15228+
"waitingOnApproval",
15229+
"waitingOnUserInput"
15230+
],
15231+
"type": "string"
15232+
},
1519715233
"ThreadArchiveParams": {
1519815234
"$schema": "http://json-schema.org/draft-07/schema#",
1519915235
"properties": {
@@ -16375,6 +16411,98 @@
1637516411
"title": "ThreadStartedNotification",
1637616412
"type": "object"
1637716413
},
16414+
"ThreadStatus": {
16415+
"oneOf": [
16416+
{
16417+
"properties": {
16418+
"type": {
16419+
"enum": [
16420+
"notLoaded"
16421+
],
16422+
"title": "NotLoadedThreadStatusType",
16423+
"type": "string"
16424+
}
16425+
},
16426+
"required": [
16427+
"type"
16428+
],
16429+
"title": "NotLoadedThreadStatus",
16430+
"type": "object"
16431+
},
16432+
{
16433+
"properties": {
16434+
"type": {
16435+
"enum": [
16436+
"idle"
16437+
],
16438+
"title": "IdleThreadStatusType",
16439+
"type": "string"
16440+
}
16441+
},
16442+
"required": [
16443+
"type"
16444+
],
16445+
"title": "IdleThreadStatus",
16446+
"type": "object"
16447+
},
16448+
{
16449+
"properties": {
16450+
"type": {
16451+
"enum": [
16452+
"systemError"
16453+
],
16454+
"title": "SystemErrorThreadStatusType",
16455+
"type": "string"
16456+
}
16457+
},
16458+
"required": [
16459+
"type"
16460+
],
16461+
"title": "SystemErrorThreadStatus",
16462+
"type": "object"
16463+
},
16464+
{
16465+
"properties": {
16466+
"activeFlags": {
16467+
"items": {
16468+
"$ref": "#/definitions/v2/ThreadActiveFlag"
16469+
},
16470+
"type": "array"
16471+
},
16472+
"type": {
16473+
"enum": [
16474+
"active"
16475+
],
16476+
"title": "ActiveThreadStatusType",
16477+
"type": "string"
16478+
}
16479+
},
16480+
"required": [
16481+
"activeFlags",
16482+
"type"
16483+
],
16484+
"title": "ActiveThreadStatus",
16485+
"type": "object"
16486+
}
16487+
]
16488+
},
16489+
"ThreadStatusChangedNotification": {
16490+
"$schema": "http://json-schema.org/draft-07/schema#",
16491+
"properties": {
16492+
"status": {
16493+
"$ref": "#/definitions/v2/ThreadStatus"
16494+
},
16495+
"threadId": {
16496+
"type": "string"
16497+
}
16498+
},
16499+
"required": [
16500+
"status",
16501+
"threadId"
16502+
],
16503+
"title": "ThreadStatusChangedNotification",
16504+
"type": "object"
16505+
},
1637816506
"ThreadTokenUsage": {
1637916507
"properties": {
1638016508
"last": {

0 commit comments

Comments
 (0)