mirror of
https://github.com/openai/codex.git
synced 2026-09-16 12:13:30 +00:00
Add app-server APIs for stored thread attachments (#44564)
## What changed - Add `thread/attachment/add`, `thread/attachment/list`, and `thread/attachment/remove` to manage durable resource references without loading the owning thread or changing conversation history. - Identify attachments by thread, `attachmentType`, and `identityKey`. Repeated adds return the existing attachment; repeated removals succeed without emitting another update. Listing supports cursor pagination. - Broadcast `thread/attachment/updated` after creation or deletion, after responding to the requester. Serialize attachment mutations with thread lifecycle operations and reject stores that do not support attachments. - Update protocol schemas, TypeScript and Python bindings, documentation, and TUI notification handling so attachment updates do not add untracked threads to the agent picker. ## Testing Add coverage for unloaded threads, pagination, idempotent addition and removal, reattachment, invalid inputs, unsupported stores, response-before-notification ordering across clients, and TUI notification routing. GitOrigin-RevId: 0d29cf903afd4e931a70a9cf96300475213b34aa
This commit is contained in:
committed by
copyberry
parent
94697375cb
commit
3319d9b296
@@ -54,6 +54,7 @@ from .v2_all import SkillsChangedNotification
|
||||
from .v2_all import StrictReviewRequiredNotification
|
||||
from .v2_all import TerminalInteractionNotification
|
||||
from .v2_all import ThreadArchivedNotification
|
||||
from .v2_all import ThreadAttachmentUpdatedNotification
|
||||
from .v2_all import ThreadClosedNotification
|
||||
from .v2_all import ThreadDeletedNotification
|
||||
from .v2_all import ThreadGoalClearedNotification
|
||||
@@ -135,6 +136,7 @@ KnownNotificationPayload: TypeAlias = (
|
||||
| StrictReviewRequiredNotification
|
||||
| TerminalInteractionNotification
|
||||
| ThreadArchivedNotification
|
||||
| ThreadAttachmentUpdatedNotification
|
||||
| ThreadClosedNotification
|
||||
| ThreadDeletedNotification
|
||||
| ThreadGoalClearedNotification
|
||||
@@ -216,6 +218,7 @@ NOTIFICATION_MODELS: dict[str, type[KnownNotificationPayload]] = {
|
||||
"serverRequest/resolved": ServerRequestResolvedNotification,
|
||||
"skills/changed": SkillsChangedNotification,
|
||||
"thread/archived": ThreadArchivedNotification,
|
||||
"thread/attachment/updated": ThreadAttachmentUpdatedNotification,
|
||||
"thread/closed": ThreadClosedNotification,
|
||||
"thread/compacted": ContextCompactedNotification,
|
||||
"thread/deleted": ThreadDeletedNotification,
|
||||
|
||||
@@ -5034,6 +5034,89 @@ class ThreadArchivedNotification(BaseModel):
|
||||
thread_id: Annotated[str, Field(alias="threadId")]
|
||||
|
||||
|
||||
class ThreadAttachment(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
attachment_type: Annotated[str, Field(alias="attachmentType")]
|
||||
created_at: Annotated[int, Field(alias="createdAt")]
|
||||
id: str
|
||||
identity_key: Annotated[str, Field(alias="identityKey")]
|
||||
payload: Any
|
||||
|
||||
|
||||
class ThreadAttachmentAddOutcome(Enum):
|
||||
created = "created"
|
||||
existing = "existing"
|
||||
|
||||
|
||||
class ThreadAttachmentAddParams(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
attachment_type: Annotated[str, Field(alias="attachmentType")]
|
||||
identity_key: Annotated[str, Field(alias="identityKey")]
|
||||
payload: Any
|
||||
thread_id: Annotated[str, Field(alias="threadId")]
|
||||
|
||||
|
||||
class ThreadAttachmentAddResponse(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
attachment: ThreadAttachment
|
||||
outcome: ThreadAttachmentAddOutcome
|
||||
|
||||
|
||||
class ThreadAttachmentListParams(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
cursor: str | None = None
|
||||
limit: Annotated[int | None, Field(ge=0)] = None
|
||||
thread_id: Annotated[str, Field(alias="threadId")]
|
||||
|
||||
|
||||
class ThreadAttachmentListResponse(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
data: list[ThreadAttachment]
|
||||
next_cursor: Annotated[str | None, Field(alias="nextCursor")] = None
|
||||
|
||||
|
||||
class ThreadAttachmentOperation(Enum):
|
||||
created = "created"
|
||||
deleted = "deleted"
|
||||
|
||||
|
||||
class ThreadAttachmentRemoveParams(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
attachment_type: Annotated[str, Field(alias="attachmentType")]
|
||||
identity_key: Annotated[str, Field(alias="identityKey")]
|
||||
thread_id: Annotated[str, Field(alias="threadId")]
|
||||
|
||||
|
||||
class ThreadAttachmentRemoveResponse(BaseModel):
|
||||
pass
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
|
||||
|
||||
class ThreadAttachmentUpdatedNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
attachment_id: Annotated[str, Field(alias="attachmentId")]
|
||||
attachment_type: Annotated[str, Field(alias="attachmentType")]
|
||||
identity_key: Annotated[str, Field(alias="identityKey")]
|
||||
operation: ThreadAttachmentOperation
|
||||
thread_id: Annotated[str, Field(alias="threadId")]
|
||||
|
||||
|
||||
class ThreadClosedNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@@ -6638,6 +6721,39 @@ class ThreadMetadataUpdateRequest(BaseModel):
|
||||
params: ThreadMetadataUpdateParams
|
||||
|
||||
|
||||
class ThreadAttachmentAddRequest(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
id: RequestId
|
||||
method: Annotated[
|
||||
Literal["thread/attachment/add"], Field(title="Thread/attachment/addRequestMethod")
|
||||
]
|
||||
params: ThreadAttachmentAddParams
|
||||
|
||||
|
||||
class ThreadAttachmentListRequest(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
id: RequestId
|
||||
method: Annotated[
|
||||
Literal["thread/attachment/list"], Field(title="Thread/attachment/listRequestMethod")
|
||||
]
|
||||
params: ThreadAttachmentListParams
|
||||
|
||||
|
||||
class ThreadAttachmentRemoveRequest(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
id: RequestId
|
||||
method: Annotated[
|
||||
Literal["thread/attachment/remove"], Field(title="Thread/attachment/removeRequestMethod")
|
||||
]
|
||||
params: ThreadAttachmentRemoveParams
|
||||
|
||||
|
||||
class ThreadSectionMoveRequest(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@@ -8776,6 +8892,24 @@ class ThreadNameUpdatedServerNotification(BaseModel):
|
||||
params: ThreadNameUpdatedNotification
|
||||
|
||||
|
||||
class ThreadAttachmentUpdatedServerNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
)
|
||||
emitted_at_ms: Annotated[
|
||||
int | None,
|
||||
Field(
|
||||
alias="emittedAtMs",
|
||||
description="Unix timestamp (in milliseconds) when app-server emitted this notification.",
|
||||
),
|
||||
] = None
|
||||
method: Annotated[
|
||||
Literal["thread/attachment/updated"],
|
||||
Field(title="Thread/attachment/updatedNotificationMethod"),
|
||||
]
|
||||
params: ThreadAttachmentUpdatedNotification
|
||||
|
||||
|
||||
class ThreadGoalClearedServerNotification(BaseModel):
|
||||
model_config = ConfigDict(
|
||||
populate_by_name=True,
|
||||
@@ -11957,6 +12091,9 @@ class ClientRequest(
|
||||
| ThreadGoalGetRequest
|
||||
| ThreadGoalClearRequest
|
||||
| ThreadMetadataUpdateRequest
|
||||
| ThreadAttachmentAddRequest
|
||||
| ThreadAttachmentListRequest
|
||||
| ThreadAttachmentRemoveRequest
|
||||
| ThreadSectionMoveRequest
|
||||
| ThreadUnarchiveRequest
|
||||
| ThreadCompactStartRequest
|
||||
@@ -12062,6 +12199,9 @@ class ClientRequest(
|
||||
| ThreadGoalGetRequest
|
||||
| ThreadGoalClearRequest
|
||||
| ThreadMetadataUpdateRequest
|
||||
| ThreadAttachmentAddRequest
|
||||
| ThreadAttachmentListRequest
|
||||
| ThreadAttachmentRemoveRequest
|
||||
| ThreadSectionMoveRequest
|
||||
| ThreadUnarchiveRequest
|
||||
| ThreadCompactStartRequest
|
||||
@@ -12336,6 +12476,7 @@ class ServerNotification(
|
||||
| ThreadRevertedServerNotification
|
||||
| SkillsChangedServerNotification
|
||||
| ThreadNameUpdatedServerNotification
|
||||
| ThreadAttachmentUpdatedServerNotification
|
||||
| ThreadGoalUpdatedServerNotification
|
||||
| ThreadGoalClearedServerNotification
|
||||
| ThreadQueueChangedServerNotification
|
||||
@@ -12423,6 +12564,7 @@ class ServerNotification(
|
||||
| ThreadRevertedServerNotification
|
||||
| SkillsChangedServerNotification
|
||||
| ThreadNameUpdatedServerNotification
|
||||
| ThreadAttachmentUpdatedServerNotification
|
||||
| ThreadGoalUpdatedServerNotification
|
||||
| ThreadGoalClearedServerNotification
|
||||
| ThreadQueueChangedServerNotification
|
||||
|
||||
Reference in New Issue
Block a user