codex-relay 1.4.4 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,2 +1,2 @@
1
- import { $ as RunThreadResponseSchema, $t as promptSkillMentionTextCandidates, A as PairRequestSchema, At as WorkspaceFileMentionSchema, B as PushNotificationIntentSchema, Bt as WorkspaceTerminalOutputResponseSchema, C as ListModelsResponseSchema, Ct as VersionResponseSchema, D as ListWorkspaceDirectoriesResponseSchema, Dt as WorkspaceChangesResponseSchema, E as ListThreadsResponseSchema, Et as WebPreviewTargetSchema, F as PromptAttachmentSchema, Ft as WorkspaceSelectionRequestSchema, G as RateLimitBucketSchema, Gt as chatMessageDetailsFromPromptContext, H as PushNotificationSettingsResponseSchema, Ht as WorkspaceTerminalSessionResponseSchema, I as PromptAttachmentSummarySchema, It as WorkspaceTailscaleServeRequestSchema, J as ReasoningEffortSchema, Jt as normalizePromptContext, K as RateLimitWindowSchema, Kt as createOpenApiDocument, L as PromptContextInputSchema, Lt as WorkspaceTailscaleServeResponseSchema, M as PendingInputRequestOptionSchema, Mt as WorkspaceMarkdownPreviewTargetSchema, N as PendingInputRequestQuestionSchema, Nt as WorkspacePreviewNavigationRequestSchema, O as ListWorkspaceFilesResponseSchema, Ot as WorkspaceDirectoryEntrySchema, P as PendingInputRequestSchema, Pt as WorkspacePreviewTabSchema, Q as RunThreadRequestSchema, Qt as promptSkillMentionMarkdown, R as PromptContextSchema, Rt as WorkspaceTerminalInputRequestSchema, S as KnownReasoningEffortSchema, St as UpdateWorkspaceFileContentRequestSchema, T as ListSkillsResponseSchema, Tt as WORKSPACE_PREVIEW_TAB_VALUES, U as QueuedThreadInputActionResponseSchema, Ut as WorkspaceTerminalStartRequestSchema, V as PushNotificationPreferencesSchema, Vt as WorkspaceTerminalResizeRequestSchema, W as QueuedThreadInputSchema, Wt as apiPaths, X as ResolveApprovalRequestSchema, Xt as promptSkillDisplayName, Y as RegisterPushNotificationRequestSchema, Yt as promptMarkdownWithSkills, Z as ResolveApprovalResponseSchema, Zt as promptSkillMentionLabel, _ as EncryptedPayloadSchema, _t as ThreadRunOptionsSchema, a as ArchiveThreadResponseSchema, at as StatusResponseSchema, b as InterruptThreadRunResponseSchema, bt as UpdateRuntimePreferencesRequestSchema, c as ChatMessageRoleSchema, ct as SubmitThreadInputResponseSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as ThreadDetailResponseSchema, en as stripPromptSkillMentions, et as RuntimeModeSchema, f as CodexModelSchema, ft as ThreadGoalResponseSchema, g as CreateThreadResponseSchema, gt as ThreadMessageDetailResponseSchema, h as CreateThreadRequestSchema, ht as ThreadMessageDetailFieldSchema, i as ApprovalModeSchema, it as SandboxModeSchema, j as PairResponseSchema, jt as WorkspaceGitActionResponseSchema, k as PairEncryptedPayloadSchema, kt as WorkspaceFileContentResponseSchema, l as ChatMessageSchema, lt as ThreadCollaborationModeSchema, m as ContextWindowUsageSchema, mt as ThreadGoalStatusSchema, n as AgentSkillSourceSchema, nt as RuntimePreferencesResponseSchema, o as ChatMessageKindSchema, ot as StreamThreadRunEventSchema, p as CommitPushWorkspaceRequestSchema, pt as ThreadGoalSchema, q as RateLimitsResponseSchema, qt as isPromptSkillMarkdownMention, r as ApprovalDecisionSchema, rt as RuntimePreferencesSchema, s as ChatMessagePromptDetailsSchema, st as StreamThreadRunRequestSchema, t as AgentSkillSchema, tt as RuntimePreferencesByWorkspacePathSchema, u as ChatMessageStateSchema, ut as ThreadContextWindowResponseSchema, v as ErrorResponseSchema, vt as ThreadStateSchema, w as ListQueuedThreadInputsResponseSchema, wt as WORKSPACE_PREVIEW_OPEN_PROTOCOL, x as IsoDateTimeSchema, xt as UpdateThreadGoalRequestSchema, y as ImageAttachmentUploadResponseSchema, yt as ThreadSummarySchema, z as PromptSkillSchema, zt as WorkspaceTerminalOutputChunkSchema } from "./api-schema2.js";
2
- export { AgentSkillSchema, AgentSkillSourceSchema, ApprovalDecisionSchema, ApprovalModeSchema, ArchiveThreadResponseSchema, ChatMessageKindSchema, ChatMessagePromptDetailsSchema, ChatMessageRoleSchema, ChatMessageSchema, ChatMessageStateSchema, CheckoutWorkspaceBranchRequestSchema, CodexModelSchema, CommitPushWorkspaceRequestSchema, ContextWindowUsageSchema, CreateThreadRequestSchema, CreateThreadResponseSchema, EncryptedPayloadSchema, ErrorResponseSchema, ImageAttachmentUploadResponseSchema, InterruptThreadRunResponseSchema, IsoDateTimeSchema, KnownReasoningEffortSchema, ListModelsResponseSchema, ListQueuedThreadInputsResponseSchema, ListSkillsResponseSchema, ListThreadsResponseSchema, ListWorkspaceDirectoriesResponseSchema, ListWorkspaceFilesResponseSchema, PairEncryptedPayloadSchema, PairRequestSchema, PairResponseSchema, PendingInputRequestOptionSchema, PendingInputRequestQuestionSchema, PendingInputRequestSchema, PromptAttachmentSchema, PromptAttachmentSummarySchema, PromptContextInputSchema, PromptContextSchema, PromptSkillSchema, PushNotificationIntentSchema, PushNotificationPreferencesSchema, PushNotificationSettingsResponseSchema, QueuedThreadInputActionResponseSchema, QueuedThreadInputSchema, RateLimitBucketSchema, RateLimitWindowSchema, RateLimitsResponseSchema, ReasoningEffortSchema, RegisterPushNotificationRequestSchema, ResolveApprovalRequestSchema, ResolveApprovalResponseSchema, RunThreadRequestSchema, RunThreadResponseSchema, RuntimeModeSchema, RuntimePreferencesByWorkspacePathSchema, RuntimePreferencesResponseSchema, RuntimePreferencesSchema, SandboxModeSchema, StatusResponseSchema, StreamThreadRunEventSchema, StreamThreadRunRequestSchema, SubmitThreadInputResponseSchema, ThreadCollaborationModeSchema, ThreadContextWindowResponseSchema, ThreadDetailResponseSchema, ThreadGoalResponseSchema, ThreadGoalSchema, ThreadGoalStatusSchema, ThreadMessageDetailFieldSchema, ThreadMessageDetailResponseSchema, ThreadRunOptionsSchema, ThreadStateSchema, ThreadSummarySchema, UpdateRuntimePreferencesRequestSchema, UpdateThreadGoalRequestSchema, UpdateWorkspaceFileContentRequestSchema, VersionResponseSchema, WORKSPACE_PREVIEW_OPEN_PROTOCOL, WORKSPACE_PREVIEW_TAB_VALUES, WebPreviewTargetSchema, WorkspaceChangesResponseSchema, WorkspaceDirectoryEntrySchema, WorkspaceFileContentResponseSchema, WorkspaceFileMentionSchema, WorkspaceGitActionResponseSchema, WorkspaceMarkdownPreviewTargetSchema, WorkspacePreviewNavigationRequestSchema, WorkspacePreviewTabSchema, WorkspaceSelectionRequestSchema, WorkspaceTailscaleServeRequestSchema, WorkspaceTailscaleServeResponseSchema, WorkspaceTerminalInputRequestSchema, WorkspaceTerminalOutputChunkSchema, WorkspaceTerminalOutputResponseSchema, WorkspaceTerminalResizeRequestSchema, WorkspaceTerminalSessionResponseSchema, WorkspaceTerminalStartRequestSchema, apiPaths, chatMessageDetailsFromPromptContext, createOpenApiDocument, isPromptSkillMarkdownMention, normalizePromptContext, promptMarkdownWithSkills, promptSkillDisplayName, promptSkillMentionLabel, promptSkillMentionMarkdown, promptSkillMentionTextCandidates, stripPromptSkillMentions };
1
+ import { $ as ResolveApprovalResponseSchema, $t as promptSkillDisplayName, A as PairRequestSchema, At as WorkspaceChangesResponseSchema, B as PushNotificationIntentSchema, Bt as WorkspaceTailscaleServeResponseSchema, C as ListModelsResponseSchema, Ct as UpdateRuntimePreferencesRequestSchema, D as ListWorkspaceDirectoriesResponseSchema, Dt as WORKSPACE_PREVIEW_OPEN_PROTOCOL, E as ListThreadsResponseSchema, Et as VersionResponseSchema, F as PromptAttachmentSchema, Ft as WorkspaceMarkdownPreviewTargetSchema, G as RateLimitBucketSchema, Gt as WorkspaceTerminalSessionResponseSchema, H as PushNotificationSettingsResponseSchema, Ht as WorkspaceTerminalOutputChunkSchema, I as PromptAttachmentSummarySchema, It as WorkspacePreviewNavigationRequestSchema, J as ReasoningEffortSchema, Jt as chatMessageDetailsFromPromptContext, K as RateLimitWindowSchema, Kt as WorkspaceTerminalStartRequestSchema, L as PromptContextInputSchema, Lt as WorkspacePreviewTabSchema, M as PendingInputRequestOptionSchema, Mt as WorkspaceFileContentResponseSchema, N as PendingInputRequestQuestionSchema, Nt as WorkspaceFileMentionSchema, O as ListWorkspaceFilesResponseSchema, Ot as WORKSPACE_PREVIEW_TAB_VALUES, P as PendingInputRequestSchema, Pt as WorkspaceGitActionResponseSchema, Q as ResolveApprovalRequestSchema, Qt as promptMarkdownWithSkills, R as PromptContextSchema, Rt as WorkspaceSelectionRequestSchema, S as KnownReasoningEffortSchema, St as ThreadSummarySchema, T as ListSkillsResponseSchema, Tt as UpdateWorkspaceFileContentRequestSchema, U as QueuedThreadInputActionResponseSchema, Ut as WorkspaceTerminalOutputResponseSchema, V as PushNotificationPreferencesSchema, Vt as WorkspaceTerminalInputRequestSchema, W as QueuedThreadInputSchema, Wt as WorkspaceTerminalResizeRequestSchema, X as RenameThreadRequestSchema, Xt as isPromptSkillMarkdownMention, Y as RegisterPushNotificationRequestSchema, Yt as createOpenApiDocument, Z as RenameThreadResponseSchema, Zt as normalizePromptContext, _ as EncryptedPayloadSchema, _t as ThreadGoalStatusSchema, a as ArchiveThreadResponseSchema, at as RuntimePreferencesResponseSchema, b as InterruptThreadRunResponseSchema, bt as ThreadRunOptionsSchema, c as ChatMessageRoleSchema, ct as StatusResponseSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as SubmitThreadInputResponseSchema, en as promptSkillMentionLabel, et as RewindThreadRequestSchema, f as CodexModelSchema, ft as ThreadCollaborationModeSchema, g as CreateThreadResponseSchema, gt as ThreadGoalSchema, h as CreateThreadRequestSchema, ht as ThreadGoalResponseSchema, i as ApprovalModeSchema, it as RuntimePreferencesByWorkspacePathSchema, j as PairResponseSchema, jt as WorkspaceDirectoryEntrySchema, k as PairEncryptedPayloadSchema, kt as WebPreviewTargetSchema, l as ChatMessageSchema, lt as StreamThreadRunEventSchema, m as ContextWindowUsageSchema, mt as ThreadDetailResponseSchema, n as AgentSkillSourceSchema, nn as promptSkillMentionTextCandidates, nt as RunThreadResponseSchema, o as ChatMessageKindSchema, ot as RuntimePreferencesSchema, p as CommitPushWorkspaceRequestSchema, pt as ThreadContextWindowResponseSchema, q as RateLimitsResponseSchema, qt as apiPaths, r as ApprovalDecisionSchema, rn as stripPromptSkillMentions, rt as RuntimeModeSchema, s as ChatMessagePromptDetailsSchema, st as SandboxModeSchema, t as AgentSkillSchema, tn as promptSkillMentionMarkdown, tt as RunThreadRequestSchema, u as ChatMessageStateSchema, ut as StreamThreadRunRequestSchema, v as ErrorResponseSchema, vt as ThreadMessageDetailFieldSchema, w as ListQueuedThreadInputsResponseSchema, wt as UpdateThreadGoalRequestSchema, x as IsoDateTimeSchema, xt as ThreadStateSchema, y as ImageAttachmentUploadResponseSchema, yt as ThreadMessageDetailResponseSchema, z as PromptSkillSchema, zt as WorkspaceTailscaleServeRequestSchema } from "./api-schema2.js";
2
+ export { AgentSkillSchema, AgentSkillSourceSchema, ApprovalDecisionSchema, ApprovalModeSchema, ArchiveThreadResponseSchema, ChatMessageKindSchema, ChatMessagePromptDetailsSchema, ChatMessageRoleSchema, ChatMessageSchema, ChatMessageStateSchema, CheckoutWorkspaceBranchRequestSchema, CodexModelSchema, CommitPushWorkspaceRequestSchema, ContextWindowUsageSchema, CreateThreadRequestSchema, CreateThreadResponseSchema, EncryptedPayloadSchema, ErrorResponseSchema, ImageAttachmentUploadResponseSchema, InterruptThreadRunResponseSchema, IsoDateTimeSchema, KnownReasoningEffortSchema, ListModelsResponseSchema, ListQueuedThreadInputsResponseSchema, ListSkillsResponseSchema, ListThreadsResponseSchema, ListWorkspaceDirectoriesResponseSchema, ListWorkspaceFilesResponseSchema, PairEncryptedPayloadSchema, PairRequestSchema, PairResponseSchema, PendingInputRequestOptionSchema, PendingInputRequestQuestionSchema, PendingInputRequestSchema, PromptAttachmentSchema, PromptAttachmentSummarySchema, PromptContextInputSchema, PromptContextSchema, PromptSkillSchema, PushNotificationIntentSchema, PushNotificationPreferencesSchema, PushNotificationSettingsResponseSchema, QueuedThreadInputActionResponseSchema, QueuedThreadInputSchema, RateLimitBucketSchema, RateLimitWindowSchema, RateLimitsResponseSchema, ReasoningEffortSchema, RegisterPushNotificationRequestSchema, RenameThreadRequestSchema, RenameThreadResponseSchema, ResolveApprovalRequestSchema, ResolveApprovalResponseSchema, RewindThreadRequestSchema, RunThreadRequestSchema, RunThreadResponseSchema, RuntimeModeSchema, RuntimePreferencesByWorkspacePathSchema, RuntimePreferencesResponseSchema, RuntimePreferencesSchema, SandboxModeSchema, StatusResponseSchema, StreamThreadRunEventSchema, StreamThreadRunRequestSchema, SubmitThreadInputResponseSchema, ThreadCollaborationModeSchema, ThreadContextWindowResponseSchema, ThreadDetailResponseSchema, ThreadGoalResponseSchema, ThreadGoalSchema, ThreadGoalStatusSchema, ThreadMessageDetailFieldSchema, ThreadMessageDetailResponseSchema, ThreadRunOptionsSchema, ThreadStateSchema, ThreadSummarySchema, UpdateRuntimePreferencesRequestSchema, UpdateThreadGoalRequestSchema, UpdateWorkspaceFileContentRequestSchema, VersionResponseSchema, WORKSPACE_PREVIEW_OPEN_PROTOCOL, WORKSPACE_PREVIEW_TAB_VALUES, WebPreviewTargetSchema, WorkspaceChangesResponseSchema, WorkspaceDirectoryEntrySchema, WorkspaceFileContentResponseSchema, WorkspaceFileMentionSchema, WorkspaceGitActionResponseSchema, WorkspaceMarkdownPreviewTargetSchema, WorkspacePreviewNavigationRequestSchema, WorkspacePreviewTabSchema, WorkspaceSelectionRequestSchema, WorkspaceTailscaleServeRequestSchema, WorkspaceTailscaleServeResponseSchema, WorkspaceTerminalInputRequestSchema, WorkspaceTerminalOutputChunkSchema, WorkspaceTerminalOutputResponseSchema, WorkspaceTerminalResizeRequestSchema, WorkspaceTerminalSessionResponseSchema, WorkspaceTerminalStartRequestSchema, apiPaths, chatMessageDetailsFromPromptContext, createOpenApiDocument, isPromptSkillMarkdownMention, normalizePromptContext, promptMarkdownWithSkills, promptSkillDisplayName, promptSkillMentionLabel, promptSkillMentionMarkdown, promptSkillMentionTextCandidates, stripPromptSkillMentions };
@@ -553,6 +553,9 @@ const ArchiveThreadResponseSchema = z.object({
553
553
  threads: z.array(ThreadSummarySchema),
554
554
  source: z.enum(["app-server", "memory"]).default("memory")
555
555
  });
556
+ const RenameThreadRequestSchema = z.object({ title: z.string().trim().min(1).max(120) });
557
+ const RenameThreadResponseSchema = z.object({ thread: ThreadSummarySchema });
558
+ const RewindThreadRequestSchema = z.object({ turnId: z.string().trim().min(1) });
556
559
  const ListModelsResponseSchema = z.object({ models: z.array(CodexModelSchema) });
557
560
  const ListSkillsResponseSchema = z.object({ skills: z.array(AgentSkillSchema) });
558
561
  const ThreadDetailResponseSchema = z.object({
@@ -758,6 +761,8 @@ const apiPaths = {
758
761
  threads: "/v1/threads",
759
762
  thread: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}`,
760
763
  threadArchive: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}`,
764
+ threadName: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}/name`,
765
+ threadRollback: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}/rollback`,
761
766
  threadContextWindow: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}/context-window`,
762
767
  threadGoal: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}/goal`,
763
768
  threadMessageDetail: (threadId, messageId, field) => `/v1/threads/${encodeURIComponent(threadId)}/messages/${encodeURIComponent(messageId)}/details/${encodeURIComponent(field)}`,
@@ -840,6 +845,10 @@ function createOpenApiDocument() {
840
845
  in: "path",
841
846
  required: true,
842
847
  schema: { type: "string" }
848
+ }, {
849
+ name: "refresh",
850
+ in: "query",
851
+ schema: { type: "boolean" }
843
852
  }],
844
853
  responses: {
845
854
  "200": jsonResponse("ThreadDetailResponse"),
@@ -861,6 +870,40 @@ function createOpenApiDocument() {
861
870
  }
862
871
  }
863
872
  },
873
+ "/v1/threads/{threadId}/name": { post: {
874
+ summary: "Rename a Codex app-server thread",
875
+ parameters: [{
876
+ name: "threadId",
877
+ in: "path",
878
+ required: true,
879
+ schema: { type: "string" }
880
+ }],
881
+ requestBody: jsonRequest("RenameThreadRequest"),
882
+ responses: {
883
+ "200": jsonResponse("RenameThreadResponse"),
884
+ "400": jsonResponse("ErrorResponse"),
885
+ "404": jsonResponse("ErrorResponse"),
886
+ "409": jsonResponse("ErrorResponse"),
887
+ "502": jsonResponse("ErrorResponse")
888
+ }
889
+ } },
890
+ "/v1/threads/{threadId}/rollback": { post: {
891
+ summary: "Rewind a Codex app-server thread to before a selected turn",
892
+ parameters: [{
893
+ name: "threadId",
894
+ in: "path",
895
+ required: true,
896
+ schema: { type: "string" }
897
+ }],
898
+ requestBody: jsonRequest("RewindThreadRequest"),
899
+ responses: {
900
+ "200": jsonResponse("ThreadDetailResponse"),
901
+ "400": jsonResponse("ErrorResponse"),
902
+ "404": jsonResponse("ErrorResponse"),
903
+ "409": jsonResponse("ErrorResponse"),
904
+ "502": jsonResponse("ErrorResponse")
905
+ }
906
+ } },
864
907
  "/v1/workspace-directories": { get: {
865
908
  summary: "List directories under the configured workspace",
866
909
  responses: {
@@ -1160,6 +1203,28 @@ function createOpenApiDocument() {
1160
1203
  }, { type: "null" }] }
1161
1204
  }
1162
1205
  },
1206
+ RenameThreadRequest: {
1207
+ type: "object",
1208
+ required: ["title"],
1209
+ properties: { title: {
1210
+ type: "string",
1211
+ minLength: 1,
1212
+ maxLength: 120
1213
+ } }
1214
+ },
1215
+ RenameThreadResponse: {
1216
+ type: "object",
1217
+ required: ["thread"],
1218
+ properties: { thread: { $ref: "#/components/schemas/ThreadSummary" } }
1219
+ },
1220
+ RewindThreadRequest: {
1221
+ type: "object",
1222
+ required: ["turnId"],
1223
+ properties: { turnId: {
1224
+ type: "string",
1225
+ minLength: 1
1226
+ } }
1227
+ },
1163
1228
  ThreadGoalResponse: {
1164
1229
  type: "object",
1165
1230
  required: ["goal", "thread"],
@@ -1801,4 +1866,4 @@ function jsonResponse(schemaName) {
1801
1866
  };
1802
1867
  }
1803
1868
  //#endregion
1804
- export { RunThreadResponseSchema as $, promptSkillMentionTextCandidates as $t, PairRequestSchema as A, WorkspaceFileMentionSchema as At, PushNotificationIntentSchema as B, WorkspaceTerminalOutputResponseSchema as Bt, ListModelsResponseSchema as C, VersionResponseSchema as Ct, ListWorkspaceDirectoriesResponseSchema as D, WorkspaceChangesResponseSchema as Dt, ListThreadsResponseSchema as E, WebPreviewTargetSchema as Et, PromptAttachmentSchema as F, WorkspaceSelectionRequestSchema as Ft, RateLimitBucketSchema as G, chatMessageDetailsFromPromptContext as Gt, PushNotificationSettingsResponseSchema as H, WorkspaceTerminalSessionResponseSchema as Ht, PromptAttachmentSummarySchema as I, WorkspaceTailscaleServeRequestSchema as It, ReasoningEffortSchema as J, normalizePromptContext as Jt, RateLimitWindowSchema as K, createOpenApiDocument as Kt, PromptContextInputSchema as L, WorkspaceTailscaleServeResponseSchema as Lt, PendingInputRequestOptionSchema as M, WorkspaceMarkdownPreviewTargetSchema as Mt, PendingInputRequestQuestionSchema as N, WorkspacePreviewNavigationRequestSchema as Nt, ListWorkspaceFilesResponseSchema as O, WorkspaceDirectoryEntrySchema as Ot, PendingInputRequestSchema as P, WorkspacePreviewTabSchema as Pt, RunThreadRequestSchema as Q, promptSkillMentionMarkdown as Qt, PromptContextSchema as R, WorkspaceTerminalInputRequestSchema as Rt, KnownReasoningEffortSchema as S, UpdateWorkspaceFileContentRequestSchema as St, ListSkillsResponseSchema as T, WORKSPACE_PREVIEW_TAB_VALUES as Tt, QueuedThreadInputActionResponseSchema as U, WorkspaceTerminalStartRequestSchema as Ut, PushNotificationPreferencesSchema as V, WorkspaceTerminalResizeRequestSchema as Vt, QueuedThreadInputSchema as W, apiPaths as Wt, ResolveApprovalRequestSchema as X, promptSkillDisplayName as Xt, RegisterPushNotificationRequestSchema as Y, promptMarkdownWithSkills as Yt, ResolveApprovalResponseSchema as Z, promptSkillMentionLabel as Zt, EncryptedPayloadSchema as _, ThreadRunOptionsSchema as _t, ArchiveThreadResponseSchema as a, StatusResponseSchema as at, InterruptThreadRunResponseSchema as b, UpdateRuntimePreferencesRequestSchema as bt, ChatMessageRoleSchema as c, SubmitThreadInputResponseSchema as ct, CheckoutWorkspaceBranchRequestSchema as d, ThreadDetailResponseSchema as dt, stripPromptSkillMentions as en, RuntimeModeSchema as et, CodexModelSchema as f, ThreadGoalResponseSchema as ft, CreateThreadResponseSchema as g, ThreadMessageDetailResponseSchema as gt, CreateThreadRequestSchema as h, ThreadMessageDetailFieldSchema as ht, ApprovalModeSchema as i, SandboxModeSchema as it, PairResponseSchema as j, WorkspaceGitActionResponseSchema as jt, PairEncryptedPayloadSchema as k, WorkspaceFileContentResponseSchema as kt, ChatMessageSchema as l, ThreadCollaborationModeSchema as lt, ContextWindowUsageSchema as m, ThreadGoalStatusSchema as mt, AgentSkillSourceSchema as n, RuntimePreferencesResponseSchema as nt, ChatMessageKindSchema as o, StreamThreadRunEventSchema as ot, CommitPushWorkspaceRequestSchema as p, ThreadGoalSchema as pt, RateLimitsResponseSchema as q, isPromptSkillMarkdownMention as qt, ApprovalDecisionSchema as r, RuntimePreferencesSchema as rt, ChatMessagePromptDetailsSchema as s, StreamThreadRunRequestSchema as st, AgentSkillSchema as t, RuntimePreferencesByWorkspacePathSchema as tt, ChatMessageStateSchema as u, ThreadContextWindowResponseSchema as ut, ErrorResponseSchema as v, ThreadStateSchema as vt, ListQueuedThreadInputsResponseSchema as w, WORKSPACE_PREVIEW_OPEN_PROTOCOL as wt, IsoDateTimeSchema as x, UpdateThreadGoalRequestSchema as xt, ImageAttachmentUploadResponseSchema as y, ThreadSummarySchema as yt, PromptSkillSchema as z, WorkspaceTerminalOutputChunkSchema as zt };
1869
+ export { ResolveApprovalResponseSchema as $, promptSkillDisplayName as $t, PairRequestSchema as A, WorkspaceChangesResponseSchema as At, PushNotificationIntentSchema as B, WorkspaceTailscaleServeResponseSchema as Bt, ListModelsResponseSchema as C, UpdateRuntimePreferencesRequestSchema as Ct, ListWorkspaceDirectoriesResponseSchema as D, WORKSPACE_PREVIEW_OPEN_PROTOCOL as Dt, ListThreadsResponseSchema as E, VersionResponseSchema as Et, PromptAttachmentSchema as F, WorkspaceMarkdownPreviewTargetSchema as Ft, RateLimitBucketSchema as G, WorkspaceTerminalSessionResponseSchema as Gt, PushNotificationSettingsResponseSchema as H, WorkspaceTerminalOutputChunkSchema as Ht, PromptAttachmentSummarySchema as I, WorkspacePreviewNavigationRequestSchema as It, ReasoningEffortSchema as J, chatMessageDetailsFromPromptContext as Jt, RateLimitWindowSchema as K, WorkspaceTerminalStartRequestSchema as Kt, PromptContextInputSchema as L, WorkspacePreviewTabSchema as Lt, PendingInputRequestOptionSchema as M, WorkspaceFileContentResponseSchema as Mt, PendingInputRequestQuestionSchema as N, WorkspaceFileMentionSchema as Nt, ListWorkspaceFilesResponseSchema as O, WORKSPACE_PREVIEW_TAB_VALUES as Ot, PendingInputRequestSchema as P, WorkspaceGitActionResponseSchema as Pt, ResolveApprovalRequestSchema as Q, promptMarkdownWithSkills as Qt, PromptContextSchema as R, WorkspaceSelectionRequestSchema as Rt, KnownReasoningEffortSchema as S, ThreadSummarySchema as St, ListSkillsResponseSchema as T, UpdateWorkspaceFileContentRequestSchema as Tt, QueuedThreadInputActionResponseSchema as U, WorkspaceTerminalOutputResponseSchema as Ut, PushNotificationPreferencesSchema as V, WorkspaceTerminalInputRequestSchema as Vt, QueuedThreadInputSchema as W, WorkspaceTerminalResizeRequestSchema as Wt, RenameThreadRequestSchema as X, isPromptSkillMarkdownMention as Xt, RegisterPushNotificationRequestSchema as Y, createOpenApiDocument as Yt, RenameThreadResponseSchema as Z, normalizePromptContext as Zt, EncryptedPayloadSchema as _, ThreadGoalStatusSchema as _t, ArchiveThreadResponseSchema as a, RuntimePreferencesResponseSchema as at, InterruptThreadRunResponseSchema as b, ThreadRunOptionsSchema as bt, ChatMessageRoleSchema as c, StatusResponseSchema as ct, CheckoutWorkspaceBranchRequestSchema as d, SubmitThreadInputResponseSchema as dt, promptSkillMentionLabel as en, RewindThreadRequestSchema as et, CodexModelSchema as f, ThreadCollaborationModeSchema as ft, CreateThreadResponseSchema as g, ThreadGoalSchema as gt, CreateThreadRequestSchema as h, ThreadGoalResponseSchema as ht, ApprovalModeSchema as i, RuntimePreferencesByWorkspacePathSchema as it, PairResponseSchema as j, WorkspaceDirectoryEntrySchema as jt, PairEncryptedPayloadSchema as k, WebPreviewTargetSchema as kt, ChatMessageSchema as l, StreamThreadRunEventSchema as lt, ContextWindowUsageSchema as m, ThreadDetailResponseSchema as mt, AgentSkillSourceSchema as n, promptSkillMentionTextCandidates as nn, RunThreadResponseSchema as nt, ChatMessageKindSchema as o, RuntimePreferencesSchema as ot, CommitPushWorkspaceRequestSchema as p, ThreadContextWindowResponseSchema as pt, RateLimitsResponseSchema as q, apiPaths as qt, ApprovalDecisionSchema as r, stripPromptSkillMentions as rn, RuntimeModeSchema as rt, ChatMessagePromptDetailsSchema as s, SandboxModeSchema as st, AgentSkillSchema as t, promptSkillMentionMarkdown as tn, RunThreadRequestSchema as tt, ChatMessageStateSchema as u, StreamThreadRunRequestSchema as ut, ErrorResponseSchema as v, ThreadMessageDetailFieldSchema as vt, ListQueuedThreadInputsResponseSchema as w, UpdateThreadGoalRequestSchema as wt, IsoDateTimeSchema as x, ThreadStateSchema as xt, ImageAttachmentUploadResponseSchema as y, ThreadMessageDetailResponseSchema as yt, PromptSkillSchema as z, WorkspaceTailscaleServeRequestSchema as zt };
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { Wt as apiPaths } from "./api-schema2.js";
2
+ import { qt as apiPaths } from "./api-schema2.js";
3
3
  import { n as codexRelayHome, o as getConnectUrlGuidance, r as legacyCodexRelayDataPath, s as createTursoPairingSessionStore, t as codexRelayDataPath } from "./paths.js";
4
4
  import { Command } from "@commander-js/extra-typings";
5
5
  import qrcode from "qrcode-terminal";
package/dist/src.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A as PairRequestSchema, Bt as WorkspaceTerminalOutputResponseSchema, C as ListModelsResponseSchema, Ct as VersionResponseSchema, D as ListWorkspaceDirectoriesResponseSchema, Dt as WorkspaceChangesResponseSchema, E as ListThreadsResponseSchema, Gt as chatMessageDetailsFromPromptContext, H as PushNotificationSettingsResponseSchema, Ht as WorkspaceTerminalSessionResponseSchema, It as WorkspaceTailscaleServeRequestSchema, J as ReasoningEffortSchema, Jt as normalizePromptContext, Kt as createOpenApiDocument, Lt as WorkspaceTailscaleServeResponseSchema, O as ListWorkspaceFilesResponseSchema, Q as RunThreadRequestSchema, Rt as WorkspaceTerminalInputRequestSchema, S as KnownReasoningEffortSchema, St as UpdateWorkspaceFileContentRequestSchema, T as ListSkillsResponseSchema, U as QueuedThreadInputActionResponseSchema, Ut as WorkspaceTerminalStartRequestSchema, Vt as WorkspaceTerminalResizeRequestSchema, Wt as apiPaths, X as ResolveApprovalRequestSchema, Y as RegisterPushNotificationRequestSchema, Yt as promptMarkdownWithSkills, Z as ResolveApprovalResponseSchema, _ as EncryptedPayloadSchema, a as ArchiveThreadResponseSchema, at as StatusResponseSchema, b as InterruptThreadRunResponseSchema, bt as UpdateRuntimePreferencesRequestSchema, ct as SubmitThreadInputResponseSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as ThreadDetailResponseSchema, en as stripPromptSkillMentions, ft as ThreadGoalResponseSchema, gt as ThreadMessageDetailResponseSchema, h as CreateThreadRequestSchema, ht as ThreadMessageDetailFieldSchema, j as PairResponseSchema, jt as WorkspaceGitActionResponseSchema, kt as WorkspaceFileContentResponseSchema, l as ChatMessageSchema, m as ContextWindowUsageSchema, mt as ThreadGoalStatusSchema, nt as RuntimePreferencesResponseSchema, ot as StreamThreadRunEventSchema, p as CommitPushWorkspaceRequestSchema, pt as ThreadGoalSchema, q as RateLimitsResponseSchema, rt as RuntimePreferencesSchema, st as StreamThreadRunRequestSchema, ut as ThreadContextWindowResponseSchema, w as ListQueuedThreadInputsResponseSchema, xt as UpdateThreadGoalRequestSchema, y as ImageAttachmentUploadResponseSchema, yt as ThreadSummarySchema } from "./api-schema2.js";
1
+ import { $ as ResolveApprovalResponseSchema, A as PairRequestSchema, At as WorkspaceChangesResponseSchema, Bt as WorkspaceTailscaleServeResponseSchema, C as ListModelsResponseSchema, Ct as UpdateRuntimePreferencesRequestSchema, D as ListWorkspaceDirectoriesResponseSchema, E as ListThreadsResponseSchema, Et as VersionResponseSchema, Gt as WorkspaceTerminalSessionResponseSchema, H as PushNotificationSettingsResponseSchema, J as ReasoningEffortSchema, Jt as chatMessageDetailsFromPromptContext, Kt as WorkspaceTerminalStartRequestSchema, Mt as WorkspaceFileContentResponseSchema, O as ListWorkspaceFilesResponseSchema, Pt as WorkspaceGitActionResponseSchema, Q as ResolveApprovalRequestSchema, Qt as promptMarkdownWithSkills, S as KnownReasoningEffortSchema, St as ThreadSummarySchema, T as ListSkillsResponseSchema, Tt as UpdateWorkspaceFileContentRequestSchema, U as QueuedThreadInputActionResponseSchema, Ut as WorkspaceTerminalOutputResponseSchema, Vt as WorkspaceTerminalInputRequestSchema, Wt as WorkspaceTerminalResizeRequestSchema, X as RenameThreadRequestSchema, Y as RegisterPushNotificationRequestSchema, Yt as createOpenApiDocument, Z as RenameThreadResponseSchema, Zt as normalizePromptContext, _ as EncryptedPayloadSchema, _t as ThreadGoalStatusSchema, a as ArchiveThreadResponseSchema, at as RuntimePreferencesResponseSchema, b as InterruptThreadRunResponseSchema, ct as StatusResponseSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as SubmitThreadInputResponseSchema, et as RewindThreadRequestSchema, gt as ThreadGoalSchema, h as CreateThreadRequestSchema, ht as ThreadGoalResponseSchema, j as PairResponseSchema, l as ChatMessageSchema, lt as StreamThreadRunEventSchema, m as ContextWindowUsageSchema, mt as ThreadDetailResponseSchema, ot as RuntimePreferencesSchema, p as CommitPushWorkspaceRequestSchema, pt as ThreadContextWindowResponseSchema, q as RateLimitsResponseSchema, qt as apiPaths, rn as stripPromptSkillMentions, tt as RunThreadRequestSchema, ut as StreamThreadRunRequestSchema, vt as ThreadMessageDetailFieldSchema, w as ListQueuedThreadInputsResponseSchema, wt as UpdateThreadGoalRequestSchema, y as ImageAttachmentUploadResponseSchema, yt as ThreadMessageDetailResponseSchema, zt as WorkspaceTailscaleServeRequestSchema } from "./api-schema2.js";
2
2
  import { a as getConnectUrlCandidates, i as createPairingQrPayload, o as getConnectUrlGuidance, r as legacyCodexRelayDataPath, s as createTursoPairingSessionStore, t as codexRelayDataPath } from "./paths.js";
3
3
  import { createRequire } from "node:module";
4
4
  import qrcode from "qrcode-terminal";
@@ -209,6 +209,12 @@ var CodexAppServerClient = class {
209
209
  async archiveThread(params) {
210
210
  await this.request("thread/archive", params);
211
211
  }
212
+ async setThreadName(params) {
213
+ await this.request("thread/name/set", params);
214
+ }
215
+ async rollbackThread(params) {
216
+ return (await this.request("thread/rollback", params)).thread;
217
+ }
212
218
  async getThreadGoal(params) {
213
219
  return (await this.request("thread/goal/get", params)).goal;
214
220
  }
@@ -1463,6 +1469,7 @@ function createApp(options = {}) {
1463
1469
  const resolvedApprovals = /* @__PURE__ */ new Map();
1464
1470
  const queuedInputsByThreadId = /* @__PURE__ */ new Map();
1465
1471
  const threadOperationTails = /* @__PURE__ */ new Map();
1472
+ const appServerMutationTails = /* @__PURE__ */ new Map();
1466
1473
  const workspaceTerminalSessions = /* @__PURE__ */ new Map();
1467
1474
  const activeAppServerTurnIdsByThreadId = /* @__PURE__ */ new Map();
1468
1475
  const appServerHistoryLoadsByThreadId = /* @__PURE__ */ new Map();
@@ -1479,6 +1486,15 @@ function createApp(options = {}) {
1479
1486
  });
1480
1487
  return result;
1481
1488
  }
1489
+ function runAppServerMutation(threadId, operation) {
1490
+ const result = (appServerMutationTails.get(threadId) ?? Promise.resolve()).then(operation, operation);
1491
+ const tail = result.then(() => void 0, () => void 0);
1492
+ appServerMutationTails.set(threadId, tail);
1493
+ tail.finally(() => {
1494
+ if (appServerMutationTails.get(threadId) === tail) appServerMutationTails.delete(threadId);
1495
+ });
1496
+ return result;
1497
+ }
1482
1498
  const pushNotificationDispatcher = options.pairing ? createPushNotificationDispatcher({
1483
1499
  sender: options.pushNotificationSender ?? createExpoPushNotificationSender(),
1484
1500
  sessions: options.pairing.sessions
@@ -1492,7 +1508,7 @@ function createApp(options = {}) {
1492
1508
  threadId
1493
1509
  });
1494
1510
  const load = appServer.readThread(threadId, { includeTurns: true }).then((threadWithTurns) => {
1495
- const mappedThread = rememberAppServerThread(threads, threadWithTurns);
1511
+ const mappedThread = rememberAppServerThread(threads, threadWithTurns, { authoritativeMessageCount: true });
1496
1512
  const messages = mergeAppServerMessagesWithLocalStatus(mapAppServerMessages(threadWithTurns), messagesByThreadId.get(threadId) ?? cachedMessages);
1497
1513
  messagesByThreadId.set(threadId, messages);
1498
1514
  relayDebugLog("thread.detail.history.background_completed", {
@@ -2151,8 +2167,73 @@ function createApp(options = {}) {
2151
2167
  });
2152
2168
  return secureJson(c, options.pairing, secureSessionsByTokenHash, response);
2153
2169
  });
2170
+ app.post("/v1/threads/:threadId/name", async (c) => {
2171
+ const threadId = c.req.param("threadId");
2172
+ if (!appServer) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("unsupported", "Renaming threads requires the Codex app-server."), 409);
2173
+ if (!await ensureKnownThread({
2174
+ appServer,
2175
+ threadId,
2176
+ messagesByThreadId,
2177
+ threads
2178
+ })) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("not_found", `Thread ${threadId} is not known to this server.`), 404);
2179
+ const parsed = await parseRequestJson(c, options.pairing, secureSessionsByTokenHash, RenameThreadRequestSchema);
2180
+ if (!parsed.success) return secureJson(c, options.pairing, secureSessionsByTokenHash, validationError(parsed.error), 400);
2181
+ try {
2182
+ const body = parsed.data;
2183
+ const thread = await runAppServerMutation(threadId, async () => {
2184
+ await appServer.setThreadName({
2185
+ name: body.title,
2186
+ threadId
2187
+ });
2188
+ return rememberAppServerThread(threads, await appServer.readThread(threadId, { includeTurns: false }));
2189
+ });
2190
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, RenameThreadResponseSchema.parse({ thread }));
2191
+ } catch (error) {
2192
+ const message = errorMessage(error);
2193
+ const status = /not found|no rollout found/i.test(message) ? 404 : 502;
2194
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError(status === 404 ? "not_found" : "rename_unavailable", message), status);
2195
+ }
2196
+ });
2197
+ app.post("/v1/threads/:threadId/rollback", async (c) => {
2198
+ const threadId = c.req.param("threadId");
2199
+ if (!appServer) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("unsupported", "Rewinding threads requires the Codex app-server."), 409);
2200
+ const parsed = await parseRequestJson(c, options.pairing, secureSessionsByTokenHash, RewindThreadRequestSchema);
2201
+ if (!parsed.success) return secureJson(c, options.pairing, secureSessionsByTokenHash, validationError(parsed.error), 400);
2202
+ return runThreadOperation(threadId, () => runAppServerMutation(threadId, async () => {
2203
+ try {
2204
+ const threadBeforeRewind = await appServer.readThread(threadId, { includeTurns: true });
2205
+ if (isSubagentThread(threadBeforeRewind)) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("not_found", `Thread ${threadId} is not known to this server.`), 404);
2206
+ if (mapAppServerThreadState(threadBeforeRewind.status, threadBeforeRewind.turns) === "running" || activeAppServerTurnIdsByThreadId.has(threadId)) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("thread_running", "Stop the current turn before rewinding this chat."), 409);
2207
+ const turns = threadBeforeRewind.turns ?? [];
2208
+ const turnIndex = turns.findIndex((turn) => turn.id === parsed.data.turnId);
2209
+ if (turnIndex < 0) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("not_found", "The selected message is no longer available to rewind."), 404);
2210
+ const rolledBackThread = await appServer.rollbackThread({
2211
+ threadId,
2212
+ numTurns: turns.length - turnIndex
2213
+ });
2214
+ const threadWithTurns = rolledBackThread.turns === void 0 ? await appServer.readThread(threadId, { includeTurns: true }) : rolledBackThread;
2215
+ const thread = rememberAppServerThread(threads, threadWithTurns, { authoritativeMessageCount: true });
2216
+ const messages = mapAppServerMessages(threadWithTurns);
2217
+ messagesByThreadId.set(threadId, messages);
2218
+ liveThreads.delete(threadId);
2219
+ activeAppServerTurnIdsByThreadId.delete(threadId);
2220
+ queuedInputsByThreadId.delete(threadId);
2221
+ steeringThreads.delete(threadId);
2222
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, threadDetailResponse({
2223
+ thread,
2224
+ messages,
2225
+ pendingInputRequests: []
2226
+ }));
2227
+ } catch (error) {
2228
+ const message = errorMessage(error);
2229
+ const status = /not found|no rollout found/i.test(message) ? 404 : 502;
2230
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError(status === 404 ? "not_found" : "rewind_unavailable", message), status);
2231
+ }
2232
+ }));
2233
+ });
2154
2234
  app.get("/v1/threads/:threadId", async (c) => {
2155
2235
  const threadId = c.req.param("threadId");
2236
+ const forceRefresh = c.req.query("refresh") === "true";
2156
2237
  const detailStartedAt = Date.now();
2157
2238
  relayDebugLog("thread.detail.requested", { threadId });
2158
2239
  const knownThread = threads.get(threadId);
@@ -2166,21 +2247,29 @@ function createApp(options = {}) {
2166
2247
  let loadedMessages = false;
2167
2248
  let messages = cachedMessages;
2168
2249
  let responseThread = preserveKnownRunningThreadState(mappedThread, wasKnownRunning);
2169
- const rolloutHistory = readRolloutThreadMessages(threadId, workspacePath);
2170
- if (rolloutHistory.messages.length > 0) {
2171
- messages = mergeThreadMessagePages(rolloutHistory.messages, cachedMessages);
2172
- responseThread = rememberRolloutThreadMessages(threads, responseThread, messages, rolloutHistory.messageCountLowerBound);
2173
- responseThread = preserveKnownRunningThreadState(responseThread, wasKnownRunning);
2250
+ if (forceRefresh && responseThread.state !== "running") {
2251
+ const threadWithTurns = await appServer.readThread(threadId, { includeTurns: true });
2252
+ responseThread = rememberAppServerThread(threads, threadWithTurns, { authoritativeMessageCount: true });
2253
+ messages = mapAppServerMessages(threadWithTurns);
2174
2254
  messagesByThreadId.set(threadId, messages);
2175
2255
  loadedMessages = true;
2176
- } else if (cachedMessages.length > 0) {
2177
- messages = dedupeThreadMessages(cachedMessages);
2178
- if (messages.length !== cachedMessages.length) messagesByThreadId.set(threadId, messages);
2179
- loadedMessages = true;
2256
+ } else {
2257
+ const rolloutHistory = readRolloutThreadMessages(threadId, workspacePath);
2258
+ if (rolloutHistory.messages.length > 0) {
2259
+ messages = mergeThreadMessagePages(rolloutHistory.messages, cachedMessages);
2260
+ responseThread = rememberRolloutThreadMessages(threads, responseThread, messages, rolloutHistory.messageCountLowerBound);
2261
+ responseThread = preserveKnownRunningThreadState(responseThread, wasKnownRunning);
2262
+ messagesByThreadId.set(threadId, messages);
2263
+ loadedMessages = true;
2264
+ } else if (cachedMessages.length > 0) {
2265
+ messages = dedupeThreadMessages(cachedMessages);
2266
+ if (messages.length !== cachedMessages.length) messagesByThreadId.set(threadId, messages);
2267
+ loadedMessages = true;
2268
+ }
2180
2269
  }
2181
2270
  if (!loadedMessages && responseThread.state !== "running") {
2182
2271
  const threadWithTurns = await appServer.readThread(threadId, { includeTurns: true });
2183
- responseThread = rememberAppServerThread(threads, threadWithTurns);
2272
+ responseThread = rememberAppServerThread(threads, threadWithTurns, { authoritativeMessageCount: true });
2184
2273
  messages = mergeAppServerMessagesWithLocalStatus(mapAppServerMessages(threadWithTurns), cachedMessages);
2185
2274
  messagesByThreadId.set(threadId, messages);
2186
2275
  loadedMessages = true;
@@ -2507,30 +2596,32 @@ function createApp(options = {}) {
2507
2596
  app.post("/v1/threads/:threadId/input/:inputId/steer", async (c) => {
2508
2597
  const threadId = c.req.param("threadId");
2509
2598
  const inputId = c.req.param("inputId");
2510
- const knownThread = await ensureKnownThread({
2511
- appServer,
2512
- threadId,
2513
- messagesByThreadId,
2514
- threads
2515
- });
2516
- if (!knownThread) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("not_found", `Thread ${threadId} is not known to this server.`), 404);
2517
- if (!appServer) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("unsupported", "Running-thread input requires the Codex app-server."), 409);
2518
- if (knownThread.state !== "running") return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("thread_not_running", `Thread ${threadId} is not currently running.`), 409);
2519
- const queuedInput = removeQueuedInput(queuedInputsByThreadId, threadId, inputId);
2520
- if (!queuedInput) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("not_found", `Queued input ${inputId} is not known to this thread.`), 404);
2521
- steeringThreads.add(threadId);
2522
- await startAppServerTurn(appServer, threadId, queuedInput);
2523
- const thread = updateThread(threads, messagesByThreadId, threadId, {
2524
- state: "running",
2525
- lastPrompt: promptWithAttachmentReferences(queuedInput.prompt, queuedInput.attachments),
2526
- lastError: void 0
2527
- });
2528
- const response = QueuedThreadInputActionResponseSchema.parse({
2529
- input: queuedThreadInputSummary(queuedInput),
2530
- queueLength: queuedInputsByThreadId.get(threadId)?.length ?? 0,
2531
- thread
2599
+ return runThreadOperation(threadId, async () => {
2600
+ const knownThread = await ensureKnownThread({
2601
+ appServer,
2602
+ threadId,
2603
+ messagesByThreadId,
2604
+ threads
2605
+ });
2606
+ if (!knownThread) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("not_found", `Thread ${threadId} is not known to this server.`), 404);
2607
+ if (!appServer) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("unsupported", "Running-thread input requires the Codex app-server."), 409);
2608
+ if (knownThread.state !== "running") return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("thread_not_running", `Thread ${threadId} is not currently running.`), 409);
2609
+ const queuedInput = removeQueuedInput(queuedInputsByThreadId, threadId, inputId);
2610
+ if (!queuedInput) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("not_found", `Queued input ${inputId} is not known to this thread.`), 404);
2611
+ steeringThreads.add(threadId);
2612
+ await runAppServerMutation(threadId, () => startAppServerTurn(appServer, threadId, queuedInput));
2613
+ const thread = updateThread(threads, messagesByThreadId, threadId, {
2614
+ state: "running",
2615
+ lastPrompt: promptWithAttachmentReferences(queuedInput.prompt, queuedInput.attachments),
2616
+ lastError: void 0
2617
+ });
2618
+ const response = QueuedThreadInputActionResponseSchema.parse({
2619
+ input: queuedThreadInputSummary(queuedInput),
2620
+ queueLength: queuedInputsByThreadId.get(threadId)?.length ?? 0,
2621
+ thread
2622
+ });
2623
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, response, 202);
2532
2624
  });
2533
- return secureJson(c, options.pairing, secureSessionsByTokenHash, response, 202);
2534
2625
  });
2535
2626
  app.post("/v1/threads/:threadId/runs/interrupt", async (c) => {
2536
2627
  const threadId = c.req.param("threadId");
@@ -2717,6 +2808,7 @@ function createApp(options = {}) {
2717
2808
  messagesByThreadId,
2718
2809
  pendingApprovals,
2719
2810
  queuedInputsByThreadId,
2811
+ runAppServerMutation,
2720
2812
  runThreadOperation,
2721
2813
  prompt: rawPrompt,
2722
2814
  attachments: runOptions.attachments ?? [],
@@ -2929,6 +3021,7 @@ async function runPromptStreamed(input) {
2929
3021
  messagesByThreadId: input.messagesByThreadId,
2930
3022
  pendingApprovals: input.pendingApprovals,
2931
3023
  queuedInputsByThreadId: input.queuedInputsByThreadId,
3024
+ runAppServerMutation: input.runAppServerMutation,
2932
3025
  runThreadOperation: input.runThreadOperation,
2933
3026
  prompt: input.prompt,
2934
3027
  runOptions: input.runOptions,
@@ -3549,7 +3642,7 @@ async function runAppServerPromptStreamed(input) {
3549
3642
  observedInputRequest = false;
3550
3643
  producedTurnOutput = false;
3551
3644
  }
3552
- function finishTerminalTurn(options) {
3645
+ async function finishTerminalTurn(options) {
3553
3646
  const terminalTurnId = options.turnId ?? activeTurnId;
3554
3647
  if (terminalTurnId && finalizedTurnIds.has(terminalTurnId)) return;
3555
3648
  if (terminalTurnId) {
@@ -3627,25 +3720,36 @@ async function runAppServerPromptStreamed(input) {
3627
3720
  handedOffToQueuedTurn = true;
3628
3721
  resetTurnTracking();
3629
3722
  input.steeringThreads.add(activeThreadId);
3630
- startAppServerTurn(input.appServer, activeThreadId, nextQueuedInput).then(processReturnedTurn).catch((error) => {
3631
- cleanupNotificationHandler();
3632
- rejectCompleted(error);
3633
- });
3723
+ await processReturnedTurn(await startAppServerTurn(input.appServer, activeThreadId, nextQueuedInput));
3634
3724
  return;
3635
3725
  }
3636
3726
  input.steeringThreads.delete(activeThreadId);
3637
3727
  cleanupNotificationHandler();
3638
3728
  resolveCompleted();
3639
3729
  }
3640
- function processReturnedTurn(turn) {
3730
+ async function processReturnedTurn(turn) {
3641
3731
  if (finalizedTurnIds.has(turn.id)) return;
3642
3732
  activeTurnId = turn.id;
3643
3733
  input.activeAppServerTurnIdsByThreadId.set(activeThreadId, turn.id);
3644
3734
  const turnIsRunning = isAppServerTurnRunning(turn);
3645
3735
  for (const item of turn.items) {
3736
+ const previousUserMessage = userMessage;
3646
3737
  const canonicalUserMessage = replaceDuplicateInitialUserMessage(input.messagesByThreadId, activeThreadId, turn.id, item, userMessage.id, displayPrompt);
3647
3738
  if (canonicalUserMessage) {
3648
3739
  userMessage = canonicalUserMessage;
3740
+ if (canonicalUserMessage.id !== previousUserMessage.id || canonicalUserMessage.turnId !== previousUserMessage.turnId) {
3741
+ relayDebugLog("app_server.user_message.canonicalized", {
3742
+ messageId: canonicalUserMessage.id,
3743
+ previousMessageId: previousUserMessage.id,
3744
+ threadId: activeThreadId,
3745
+ turnId: canonicalUserMessage.turnId
3746
+ });
3747
+ sendSse(input.controller, input.encoder, input.secureSession, {
3748
+ type: "thread.message.created",
3749
+ thread: threadSummary,
3750
+ message: canonicalUserMessage
3751
+ });
3752
+ }
3649
3753
  continue;
3650
3754
  }
3651
3755
  const message = upsertAppServerItemMessage(input.messagesByThreadId, activeThreadId, turn.id, item);
@@ -3665,13 +3769,20 @@ async function runAppServerPromptStreamed(input) {
3665
3769
  if (turnIsRunning) return;
3666
3770
  const params = { turn };
3667
3771
  const state = terminalTurnState("turn/completed", params);
3668
- finishTerminalTurn({
3772
+ await finishTerminalTurn({
3669
3773
  lastError: state === "failed" ? turnErrorMessage(params) : void 0,
3670
3774
  method: "turn/returned",
3671
3775
  state,
3672
3776
  turnId: turn.id
3673
3777
  });
3674
3778
  }
3779
+ function startAndProcessAppServerTurn(threadId, queuedInput) {
3780
+ return input.runAppServerMutation(threadId, async () => {
3781
+ const turn = await startAppServerTurn(input.appServer, threadId, queuedInput);
3782
+ await processReturnedTurn(turn);
3783
+ return turn;
3784
+ });
3785
+ }
3675
3786
  const completed = new Promise((resolve, reject) => {
3676
3787
  resolveCompleted = resolve;
3677
3788
  rejectCompleted = reject;
@@ -3711,9 +3822,23 @@ async function runAppServerPromptStreamed(input) {
3711
3822
  case "item/completed": {
3712
3823
  const item = params?.item;
3713
3824
  if (!item || typeof item !== "object") return;
3825
+ const previousUserMessage = userMessage;
3714
3826
  const canonicalUserMessage = replaceDuplicateInitialUserMessage(input.messagesByThreadId, activeThreadId, firstString(params, ["turnId"]) ?? activeTurnId, item, userMessage.id, displayPrompt);
3715
3827
  if (canonicalUserMessage) {
3716
3828
  userMessage = canonicalUserMessage;
3829
+ if (canonicalUserMessage.id !== previousUserMessage.id || canonicalUserMessage.turnId !== previousUserMessage.turnId) {
3830
+ relayDebugLog("app_server.user_message.canonicalized", {
3831
+ messageId: canonicalUserMessage.id,
3832
+ previousMessageId: previousUserMessage.id,
3833
+ threadId: activeThreadId,
3834
+ turnId: canonicalUserMessage.turnId
3835
+ });
3836
+ sendSse(input.controller, input.encoder, input.secureSession, {
3837
+ type: "thread.message.created",
3838
+ thread: threadSummary,
3839
+ message: canonicalUserMessage
3840
+ });
3841
+ }
3717
3842
  return;
3718
3843
  }
3719
3844
  const turnId = firstString(params, ["turnId"]) ?? activeTurnId;
@@ -3784,12 +3909,12 @@ async function runAppServerPromptStreamed(input) {
3784
3909
  const state = terminalTurnState(notification.method, params);
3785
3910
  const terminalTurnId = firstString(params, ["turnId"]) ?? turnIdFromParams(params) ?? activeTurnId;
3786
3911
  input.runThreadOperation(activeThreadId, async () => {
3787
- finishTerminalTurn({
3912
+ await input.runAppServerMutation(activeThreadId, () => finishTerminalTurn({
3788
3913
  lastError: state === "failed" ? turnErrorMessage(params) : void 0,
3789
3914
  method: notification.method,
3790
3915
  state,
3791
3916
  turnId: terminalTurnId
3792
- });
3917
+ }));
3793
3918
  }).catch((error) => {
3794
3919
  cleanupNotificationHandler();
3795
3920
  rejectCompleted(error);
@@ -3850,7 +3975,7 @@ async function runAppServerPromptStreamed(input) {
3850
3975
  debugStream("start turn begin", activeThreadId);
3851
3976
  let turn;
3852
3977
  try {
3853
- turn = await startAppServerTurn(input.appServer, activeThreadId, {
3978
+ turn = await startAndProcessAppServerTurn(activeThreadId, {
3854
3979
  attachments: input.attachments,
3855
3980
  id: randomUUID(),
3856
3981
  prompt,
@@ -3884,7 +4009,7 @@ async function runAppServerPromptStreamed(input) {
3884
4009
  thread: threadSummary,
3885
4010
  message: userMessage
3886
4011
  });
3887
- turn = await startAppServerTurn(input.appServer, activeThreadId, {
4012
+ turn = await startAndProcessAppServerTurn(activeThreadId, {
3888
4013
  attachments: input.attachments,
3889
4014
  id: randomUUID(),
3890
4015
  prompt,
@@ -3894,7 +4019,6 @@ async function runAppServerPromptStreamed(input) {
3894
4019
  });
3895
4020
  }
3896
4021
  debugStream("start turn complete", activeThreadId, turn.id);
3897
- processReturnedTurn(turn);
3898
4022
  await completed;
3899
4023
  } catch (error) {
3900
4024
  debugStream(`failed ${errorMessage(error)}`, activeThreadId, activeTurnId);
@@ -4862,9 +4986,9 @@ function mapAppServerThread(thread, fallbackMessageCount) {
4862
4986
  lastActivityAt: updatedAt
4863
4987
  });
4864
4988
  }
4865
- function rememberAppServerThread(threads, thread) {
4989
+ function rememberAppServerThread(threads, thread, options = {}) {
4866
4990
  const existingThread = threads.get(thread.id);
4867
- const mappedThread = mapAppServerThread(thread, existingThread?.messageCount);
4991
+ const mappedThread = mapAppServerThread(thread, options.authoritativeMessageCount ? void 0 : existingThread?.messageCount);
4868
4992
  const threadWithLocalRuntime = ThreadSummarySchema.parse({
4869
4993
  ...mappedThread,
4870
4994
  goal: existingThread?.goal ?? mappedThread.goal,
@@ -5053,6 +5177,7 @@ function readRolloutThreadMessages(threadId, workspacePath = defaultWorkspacePat
5053
5177
  const applyPatchInputs = /* @__PURE__ */ new Map();
5054
5178
  const handledApplyPatchCallIds = /* @__PURE__ */ new Set();
5055
5179
  const pendingApplyPatchChanges = [];
5180
+ let activeTurnId;
5056
5181
  const lines = readFileSync(rolloutPath, "utf8").split("\n");
5057
5182
  for (let index = 0; index < lines.length; index += 1) {
5058
5183
  const line = lines[index];
@@ -5061,14 +5186,17 @@ function readRolloutThreadMessages(threadId, workspacePath = defaultWorkspacePat
5061
5186
  if (!isRolloutMessageLine(line)) continue;
5062
5187
  try {
5063
5188
  const record = JSON.parse(line);
5189
+ activeTurnId = firstString(record.payload, ["turn_id", "turnId"]) ?? activeTurnId;
5064
5190
  rememberRolloutApplyPatchInput(record, applyPatchInputs);
5065
5191
  collectRolloutApplyPatchOutput(record, workspacePath, applyPatchInputs, handledApplyPatchCallIds, pendingApplyPatchChanges);
5066
5192
  if (isRolloutTaskComplete(record) && pendingApplyPatchChanges.length > 0) {
5067
5193
  collected.push(rolloutApplyPatchSummaryMessage(threadId, record, `rollout:${lineNumber}:apply_patch`, pendingApplyPatchChanges));
5068
5194
  pendingApplyPatchChanges.length = 0;
5195
+ activeTurnId = void 0;
5069
5196
  continue;
5070
5197
  }
5071
- const message = rolloutRecordMessage(threadId, record, `rollout:${lineNumber}`, workspacePath);
5198
+ const message = rolloutRecordMessage(threadId, record, `rollout:${lineNumber}`, workspacePath, activeTurnId);
5199
+ if (isRolloutTaskComplete(record)) activeTurnId = void 0;
5072
5200
  if (!message) continue;
5073
5201
  collected.push(message);
5074
5202
  const patchApplyEndCallId = rolloutPatchApplyEndCallId(record);
@@ -5103,7 +5231,7 @@ function findRolloutFileForThread(threadId) {
5103
5231
  function isRolloutTaskComplete(record) {
5104
5232
  return record.type === "event_msg" && record.payload?.type === "task_complete";
5105
5233
  }
5106
- function rolloutRecordMessage(threadId, record, messageKey, workspacePath = defaultWorkspacePath) {
5234
+ function rolloutRecordMessage(threadId, record, messageKey, workspacePath = defaultWorkspacePath, turnId) {
5107
5235
  const timestamp = typeof record.timestamp === "string" ? record.timestamp : (/* @__PURE__ */ new Date()).toISOString();
5108
5236
  const payload = record.payload;
5109
5237
  if (!payload) return;
@@ -5117,7 +5245,8 @@ function rolloutRecordMessage(threadId, record, messageKey, workspacePath = defa
5117
5245
  content,
5118
5246
  details: rolloutUserMessageDetails(payload),
5119
5247
  createdAt: timestamp,
5120
- state: "completed"
5248
+ state: "completed",
5249
+ turnId
5121
5250
  });
5122
5251
  }
5123
5252
  if (record.type === "event_msg" && payload.type === "agent_message") {
@@ -5131,7 +5260,8 @@ function rolloutRecordMessage(threadId, record, messageKey, workspacePath = defa
5131
5260
  content: messageParts.content,
5132
5261
  details: messageParts.details,
5133
5262
  createdAt: timestamp,
5134
- state: "completed"
5263
+ state: "completed",
5264
+ turnId
5135
5265
  });
5136
5266
  }
5137
5267
  if (record.type === "event_msg" && payload.type === "patch_apply_end") {
@@ -5339,7 +5469,7 @@ function fileUrlPath(value) {
5339
5469
  }
5340
5470
  }
5341
5471
  function isRolloutMessageLine(line) {
5342
- return line.includes("\"type\":\"event_msg\"") && (line.includes("\"type\":\"user_message\"") || line.includes("\"type\":\"agent_message\"") || line.includes("\"type\":\"patch_apply_end\"") || line.includes("\"type\":\"task_complete\"") || line.includes("\"type\":\"exec_command_end\"") || line.includes("\"type\":\"mcp_tool_call_end\"")) || line.includes("\"type\":\"response_item\"") && (line.includes("\"type\":\"custom_tool_call\"") || line.includes("\"type\":\"custom_tool_call_output\""));
5472
+ return line.includes("\"type\":\"event_msg\"") && (line.includes("\"type\":\"user_message\"") || line.includes("\"type\":\"agent_message\"") || line.includes("\"type\":\"patch_apply_end\"") || line.includes("\"type\":\"task_started\"") || line.includes("\"type\":\"task_complete\"") || line.includes("\"type\":\"exec_command_end\"") || line.includes("\"type\":\"mcp_tool_call_end\"")) || line.includes("\"type\":\"response_item\"") && (line.includes("\"type\":\"custom_tool_call\"") || line.includes("\"type\":\"custom_tool_call_output\""));
5343
5473
  }
5344
5474
  function threadDetailResponse(input) {
5345
5475
  return ThreadDetailResponseSchema.parse({
@@ -5836,7 +5966,6 @@ function isApprovalServerRequest(method) {
5836
5966
  }
5837
5967
  function observeAppServerPushNotifications(appServer, dispatcher) {
5838
5968
  const dispatchedEventIds = /* @__PURE__ */ new Set();
5839
- const subagentThreadIds = /* @__PURE__ */ new Set();
5840
5969
  const rememberEventId = (eventId) => {
5841
5970
  if (dispatchedEventIds.size >= 1e3) dispatchedEventIds.clear();
5842
5971
  dispatchedEventIds.add(eventId);
@@ -5844,7 +5973,9 @@ function observeAppServerPushNotifications(appServer, dispatcher) {
5844
5973
  const dispatch = (event, eventId) => {
5845
5974
  if (dispatchedEventIds.has(eventId)) return;
5846
5975
  rememberEventId(eventId);
5847
- dispatcher.dispatch(event).catch((error) => {
5976
+ appServer.readThread(event.threadId, { includeTurns: false }).then((thread) => {
5977
+ if (!isSubagentThread(thread)) return dispatcher.dispatch(event);
5978
+ }).catch((error) => {
5848
5979
  relayDebugLog("push_notification.dispatch_failed", {
5849
5980
  error: errorMessage(error),
5850
5981
  intent: event.intent,
@@ -5854,36 +5985,16 @@ function observeAppServerPushNotifications(appServer, dispatcher) {
5854
5985
  });
5855
5986
  };
5856
5987
  appServer.onNotification((notification) => {
5857
- rememberSubagentThreadIds(notification, subagentThreadIds);
5858
5988
  const event = pushNotificationEventFromTerminalNotification(notification);
5859
5989
  if (!event) return;
5860
- const eventId = `${event.intent}:${event.threadId}:${event.turnId ?? ""}`;
5861
- if (subagentThreadIds.delete(event.threadId)) {
5862
- rememberEventId(eventId);
5863
- return;
5864
- }
5865
- dispatch(event, eventId);
5990
+ dispatch(event, `${event.intent}:${event.threadId}:${event.turnId ?? ""}`);
5866
5991
  });
5867
5992
  appServer.onRequest((request) => {
5868
5993
  const event = pushNotificationEventFromApprovalRequest(request);
5869
5994
  if (!event) return;
5870
- const eventId = `${event.intent}:${event.threadId}:${event.turnId ?? ""}:${request.id}`;
5871
- if (subagentThreadIds.has(event.threadId)) {
5872
- rememberEventId(eventId);
5873
- return;
5874
- }
5875
- dispatch(event, eventId);
5995
+ dispatch(event, `${event.intent}:${event.threadId}:${event.turnId ?? ""}:${request.id}`);
5876
5996
  });
5877
5997
  }
5878
- function rememberSubagentThreadIds(notification, subagentThreadIds) {
5879
- const item = objectRecord(recordParams(notification)?.item);
5880
- if (item?.type !== "collabAgentToolCall" || ![
5881
- "spawnAgent",
5882
- "sendInput",
5883
- "resumeAgent"
5884
- ].includes(String(item.tool))) return;
5885
- for (const threadId of stringArray(item.receiverThreadIds)) subagentThreadIds.add(threadId);
5886
- }
5887
5998
  function pushNotificationEventFromTerminalNotification(notification) {
5888
5999
  if (notification.method !== "turn/completed" && notification.method !== "turn/failed") return;
5889
6000
  const params = recordParams(notification);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-relay",
3
- "version": "1.4.4",
3
+ "version": "1.4.5",
4
4
  "description": "Local Codex Relay CLI bridge for the Codex Relay mobile app.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
package/src/api-schema.ts CHANGED
@@ -681,6 +681,18 @@ export const ArchiveThreadResponseSchema = z.object({
681
681
  source: z.enum(["app-server", "memory"]).default("memory"),
682
682
  });
683
683
 
684
+ export const RenameThreadRequestSchema = z.object({
685
+ title: z.string().trim().min(1).max(120),
686
+ });
687
+
688
+ export const RenameThreadResponseSchema = z.object({
689
+ thread: ThreadSummarySchema,
690
+ });
691
+
692
+ export const RewindThreadRequestSchema = z.object({
693
+ turnId: z.string().trim().min(1),
694
+ });
695
+
684
696
  export const ListModelsResponseSchema = z.object({
685
697
  models: z.array(CodexModelSchema),
686
698
  });
@@ -844,6 +856,9 @@ export type UpdateRuntimePreferencesRequest = z.infer<typeof UpdateRuntimePrefer
844
856
  export type VersionResponse = z.infer<typeof VersionResponseSchema>;
845
857
  export type ListThreadsResponse = z.infer<typeof ListThreadsResponseSchema>;
846
858
  export type ArchiveThreadResponse = z.infer<typeof ArchiveThreadResponseSchema>;
859
+ export type RenameThreadRequest = z.infer<typeof RenameThreadRequestSchema>;
860
+ export type RenameThreadResponse = z.infer<typeof RenameThreadResponseSchema>;
861
+ export type RewindThreadRequest = z.infer<typeof RewindThreadRequestSchema>;
847
862
  export type ListModelsResponse = z.infer<typeof ListModelsResponseSchema>;
848
863
  export type ListSkillsResponse = z.infer<typeof ListSkillsResponseSchema>;
849
864
  export type ListWorkspaceFilesResponse = z.infer<typeof ListWorkspaceFilesResponseSchema>;
@@ -1089,6 +1104,8 @@ export const apiPaths = {
1089
1104
  threads: "/v1/threads",
1090
1105
  thread: (threadId: string) => `/v1/threads/${encodeURIComponent(threadId)}`,
1091
1106
  threadArchive: (threadId: string) => `/v1/threads/${encodeURIComponent(threadId)}`,
1107
+ threadName: (threadId: string) => `/v1/threads/${encodeURIComponent(threadId)}/name`,
1108
+ threadRollback: (threadId: string) => `/v1/threads/${encodeURIComponent(threadId)}/rollback`,
1092
1109
  threadContextWindow: (threadId: string) =>
1093
1110
  `/v1/threads/${encodeURIComponent(threadId)}/context-window`,
1094
1111
  threadGoal: (threadId: string) => `/v1/threads/${encodeURIComponent(threadId)}/goal`,
@@ -1191,6 +1208,11 @@ export function createOpenApiDocument() {
1191
1208
  required: true,
1192
1209
  schema: { type: "string" },
1193
1210
  },
1211
+ {
1212
+ name: "refresh",
1213
+ in: "query",
1214
+ schema: { type: "boolean" },
1215
+ },
1194
1216
  ],
1195
1217
  responses: {
1196
1218
  "200": jsonResponse("ThreadDetailResponse"),
@@ -1214,6 +1236,48 @@ export function createOpenApiDocument() {
1214
1236
  },
1215
1237
  },
1216
1238
  },
1239
+ "/v1/threads/{threadId}/name": {
1240
+ post: {
1241
+ summary: "Rename a Codex app-server thread",
1242
+ parameters: [
1243
+ {
1244
+ name: "threadId",
1245
+ in: "path",
1246
+ required: true,
1247
+ schema: { type: "string" },
1248
+ },
1249
+ ],
1250
+ requestBody: jsonRequest("RenameThreadRequest"),
1251
+ responses: {
1252
+ "200": jsonResponse("RenameThreadResponse"),
1253
+ "400": jsonResponse("ErrorResponse"),
1254
+ "404": jsonResponse("ErrorResponse"),
1255
+ "409": jsonResponse("ErrorResponse"),
1256
+ "502": jsonResponse("ErrorResponse"),
1257
+ },
1258
+ },
1259
+ },
1260
+ "/v1/threads/{threadId}/rollback": {
1261
+ post: {
1262
+ summary: "Rewind a Codex app-server thread to before a selected turn",
1263
+ parameters: [
1264
+ {
1265
+ name: "threadId",
1266
+ in: "path",
1267
+ required: true,
1268
+ schema: { type: "string" },
1269
+ },
1270
+ ],
1271
+ requestBody: jsonRequest("RewindThreadRequest"),
1272
+ responses: {
1273
+ "200": jsonResponse("ThreadDetailResponse"),
1274
+ "400": jsonResponse("ErrorResponse"),
1275
+ "404": jsonResponse("ErrorResponse"),
1276
+ "409": jsonResponse("ErrorResponse"),
1277
+ "502": jsonResponse("ErrorResponse"),
1278
+ },
1279
+ },
1280
+ },
1217
1281
  "/v1/workspace-directories": {
1218
1282
  get: {
1219
1283
  summary: "List directories under the configured workspace",
@@ -1452,6 +1516,27 @@ export function createOpenApiDocument() {
1452
1516
  tokenBudget: { anyOf: [{ type: "integer", minimum: 1 }, { type: "null" }] },
1453
1517
  },
1454
1518
  },
1519
+ RenameThreadRequest: {
1520
+ type: "object",
1521
+ required: ["title"],
1522
+ properties: {
1523
+ title: { type: "string", minLength: 1, maxLength: 120 },
1524
+ },
1525
+ },
1526
+ RenameThreadResponse: {
1527
+ type: "object",
1528
+ required: ["thread"],
1529
+ properties: {
1530
+ thread: { $ref: "#/components/schemas/ThreadSummary" },
1531
+ },
1532
+ },
1533
+ RewindThreadRequest: {
1534
+ type: "object",
1535
+ required: ["turnId"],
1536
+ properties: {
1537
+ turnId: { type: "string", minLength: 1 },
1538
+ },
1539
+ },
1455
1540
  ThreadGoalResponse: {
1456
1541
  type: "object",
1457
1542
  required: ["goal", "thread"],