codex-relay 1.1.1 → 1.2.1

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 SandboxModeSchema, A as PairResponseSchema, At as WorkspaceTerminalResizeRequestSchema, B as QueuedThreadInputSchema, Bt as promptSkillMentionLabel, C as ListQueuedThreadInputsResponseSchema, Ct as WorkspaceMarkdownPreviewTargetSchema, D as ListWorkspaceFilesResponseSchema, Dt as WorkspaceTerminalInputRequestSchema, E as ListWorkspaceDirectoriesResponseSchema, Et as WorkspaceSelectionRequestSchema, F as PromptAttachmentSummarySchema, Ft as createOpenApiDocument, G as ResolveApprovalRequestSchema, H as RateLimitWindowSchema, Ht as promptSkillMentionTextCandidates, I as PromptContextInputSchema, It as isPromptSkillMarkdownMention, J as RunThreadResponseSchema, K as ResolveApprovalResponseSchema, L as PromptContextSchema, Lt as normalizePromptContext, M as PendingInputRequestQuestionSchema, Mt as WorkspaceTerminalStartRequestSchema, N as PendingInputRequestSchema, Nt as apiPaths, O as PairEncryptedPayloadSchema, Ot as WorkspaceTerminalOutputChunkSchema, P as PromptAttachmentSchema, Pt as chatMessageDetailsFromPromptContext, Q as RuntimePreferencesSchema, R as PromptSkillSchema, Rt as promptMarkdownWithSkills, S as ListModelsResponseSchema, St as WorkspaceGitActionResponseSchema, T as ListThreadsResponseSchema, Tt as WorkspacePreviewTabSchema, U as RateLimitsResponseSchema, Ut as stripPromptSkillMentions, V as RateLimitBucketSchema, Vt as promptSkillMentionMarkdown, W as ReasoningEffortSchema, X as RuntimePreferencesByWorkspacePathSchema, Y as RuntimeModeSchema, Z as RuntimePreferencesResponseSchema, _ as EncryptedPayloadSchema, _t as WebPreviewTargetSchema, a as ArchiveThreadResponseSchema, at as ThreadContextWindowResponseSchema, b as InterruptThreadRunResponseSchema, bt as WorkspaceFileContentResponseSchema, c as ChatMessageRoleSchema, ct as ThreadMessageDetailResponseSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as ThreadSummarySchema, et as StatusResponseSchema, f as CodexModelSchema, ft as UpdateRuntimePreferencesRequestSchema, g as CreateThreadResponseSchema, gt as WORKSPACE_PREVIEW_TAB_VALUES, h as CreateThreadRequestSchema, ht as WORKSPACE_PREVIEW_OPEN_PROTOCOL, i as ApprovalModeSchema, it as ThreadCollaborationModeSchema, j as PendingInputRequestOptionSchema, jt as WorkspaceTerminalSessionResponseSchema, k as PairRequestSchema, kt as WorkspaceTerminalOutputResponseSchema, l as ChatMessageSchema, lt as ThreadRunOptionsSchema, m as ContextWindowUsageSchema, mt as VersionResponseSchema, n as AgentSkillSourceSchema, nt as StreamThreadRunRequestSchema, o as ChatMessageKindSchema, ot as ThreadDetailResponseSchema, p as CommitPushWorkspaceRequestSchema, pt as UpdateWorkspaceFileContentRequestSchema, q as RunThreadRequestSchema, r as ApprovalDecisionSchema, rt as SubmitThreadInputResponseSchema, s as ChatMessagePromptDetailsSchema, st as ThreadMessageDetailFieldSchema, t as AgentSkillSchema, tt as StreamThreadRunEventSchema, u as ChatMessageStateSchema, ut as ThreadStateSchema, v as ErrorResponseSchema, vt as WorkspaceChangesResponseSchema, w as ListSkillsResponseSchema, wt as WorkspacePreviewNavigationRequestSchema, x as IsoDateTimeSchema, xt as WorkspaceFileMentionSchema, y as ImageAttachmentUploadResponseSchema, yt as WorkspaceDirectoryEntrySchema, z as QueuedThreadInputActionResponseSchema, zt as promptSkillDisplayName } 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, ListModelsResponseSchema, ListQueuedThreadInputsResponseSchema, ListSkillsResponseSchema, ListThreadsResponseSchema, ListWorkspaceDirectoriesResponseSchema, ListWorkspaceFilesResponseSchema, PairEncryptedPayloadSchema, PairRequestSchema, PairResponseSchema, PendingInputRequestOptionSchema, PendingInputRequestQuestionSchema, PendingInputRequestSchema, PromptAttachmentSchema, PromptAttachmentSummarySchema, PromptContextInputSchema, PromptContextSchema, PromptSkillSchema, QueuedThreadInputActionResponseSchema, QueuedThreadInputSchema, RateLimitBucketSchema, RateLimitWindowSchema, RateLimitsResponseSchema, ReasoningEffortSchema, ResolveApprovalRequestSchema, ResolveApprovalResponseSchema, RunThreadRequestSchema, RunThreadResponseSchema, RuntimeModeSchema, RuntimePreferencesByWorkspacePathSchema, RuntimePreferencesResponseSchema, RuntimePreferencesSchema, SandboxModeSchema, StatusResponseSchema, StreamThreadRunEventSchema, StreamThreadRunRequestSchema, SubmitThreadInputResponseSchema, ThreadCollaborationModeSchema, ThreadContextWindowResponseSchema, ThreadDetailResponseSchema, ThreadMessageDetailFieldSchema, ThreadMessageDetailResponseSchema, ThreadRunOptionsSchema, ThreadStateSchema, ThreadSummarySchema, UpdateRuntimePreferencesRequestSchema, UpdateWorkspaceFileContentRequestSchema, VersionResponseSchema, WORKSPACE_PREVIEW_OPEN_PROTOCOL, WORKSPACE_PREVIEW_TAB_VALUES, WebPreviewTargetSchema, WorkspaceChangesResponseSchema, WorkspaceDirectoryEntrySchema, WorkspaceFileContentResponseSchema, WorkspaceFileMentionSchema, WorkspaceGitActionResponseSchema, WorkspaceMarkdownPreviewTargetSchema, WorkspacePreviewNavigationRequestSchema, WorkspacePreviewTabSchema, WorkspaceSelectionRequestSchema, WorkspaceTerminalInputRequestSchema, WorkspaceTerminalOutputChunkSchema, WorkspaceTerminalOutputResponseSchema, WorkspaceTerminalResizeRequestSchema, WorkspaceTerminalSessionResponseSchema, WorkspaceTerminalStartRequestSchema, apiPaths, chatMessageDetailsFromPromptContext, createOpenApiDocument, isPromptSkillMarkdownMention, normalizePromptContext, promptMarkdownWithSkills, promptSkillDisplayName, promptSkillMentionLabel, promptSkillMentionMarkdown, promptSkillMentionTextCandidates, stripPromptSkillMentions };
1
+ import { $ as SandboxModeSchema, A as PairResponseSchema, At as WorkspaceSelectionRequestSchema, B as QueuedThreadInputSchema, Bt as isPromptSkillMarkdownMention, C as ListQueuedThreadInputsResponseSchema, Ct as WorkspaceDirectoryEntrySchema, D as ListWorkspaceFilesResponseSchema, Dt as WorkspaceMarkdownPreviewTargetSchema, E as ListWorkspaceDirectoriesResponseSchema, Et as WorkspaceGitActionResponseSchema, F as PromptAttachmentSummarySchema, Ft as WorkspaceTerminalSessionResponseSchema, G as ResolveApprovalRequestSchema, Gt as promptSkillMentionMarkdown, H as RateLimitWindowSchema, Ht as promptMarkdownWithSkills, I as PromptContextInputSchema, It as WorkspaceTerminalStartRequestSchema, J as RunThreadResponseSchema, K as ResolveApprovalResponseSchema, Kt as promptSkillMentionTextCandidates, L as PromptContextSchema, Lt as apiPaths, M as PendingInputRequestQuestionSchema, Mt as WorkspaceTerminalOutputChunkSchema, N as PendingInputRequestSchema, Nt as WorkspaceTerminalOutputResponseSchema, O as PairEncryptedPayloadSchema, Ot as WorkspacePreviewNavigationRequestSchema, P as PromptAttachmentSchema, Pt as WorkspaceTerminalResizeRequestSchema, Q as RuntimePreferencesSchema, R as PromptSkillSchema, Rt as chatMessageDetailsFromPromptContext, S as ListModelsResponseSchema, St as WorkspaceChangesResponseSchema, T as ListThreadsResponseSchema, Tt as WorkspaceFileMentionSchema, U as RateLimitsResponseSchema, Ut as promptSkillDisplayName, V as RateLimitBucketSchema, Vt as normalizePromptContext, W as ReasoningEffortSchema, Wt as promptSkillMentionLabel, X as RuntimePreferencesByWorkspacePathSchema, Y as RuntimeModeSchema, Z as RuntimePreferencesResponseSchema, _ as EncryptedPayloadSchema, _t as UpdateWorkspaceFileContentRequestSchema, a as ArchiveThreadResponseSchema, at as ThreadContextWindowResponseSchema, b as InterruptThreadRunResponseSchema, bt as WORKSPACE_PREVIEW_TAB_VALUES, c as ChatMessageRoleSchema, ct as ThreadGoalSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as ThreadMessageDetailResponseSchema, et as StatusResponseSchema, f as CodexModelSchema, ft as ThreadRunOptionsSchema, g as CreateThreadResponseSchema, gt as UpdateThreadGoalRequestSchema, h as CreateThreadRequestSchema, ht as UpdateRuntimePreferencesRequestSchema, i as ApprovalModeSchema, it as ThreadCollaborationModeSchema, j as PendingInputRequestOptionSchema, jt as WorkspaceTerminalInputRequestSchema, k as PairRequestSchema, kt as WorkspacePreviewTabSchema, l as ChatMessageSchema, lt as ThreadGoalStatusSchema, m as ContextWindowUsageSchema, mt as ThreadSummarySchema, n as AgentSkillSourceSchema, nt as StreamThreadRunRequestSchema, o as ChatMessageKindSchema, ot as ThreadDetailResponseSchema, p as CommitPushWorkspaceRequestSchema, pt as ThreadStateSchema, q as RunThreadRequestSchema, qt as stripPromptSkillMentions, r as ApprovalDecisionSchema, rt as SubmitThreadInputResponseSchema, s as ChatMessagePromptDetailsSchema, st as ThreadGoalResponseSchema, t as AgentSkillSchema, tt as StreamThreadRunEventSchema, u as ChatMessageStateSchema, ut as ThreadMessageDetailFieldSchema, v as ErrorResponseSchema, vt as VersionResponseSchema, w as ListSkillsResponseSchema, wt as WorkspaceFileContentResponseSchema, x as IsoDateTimeSchema, xt as WebPreviewTargetSchema, y as ImageAttachmentUploadResponseSchema, yt as WORKSPACE_PREVIEW_OPEN_PROTOCOL, z as QueuedThreadInputActionResponseSchema, zt as createOpenApiDocument } 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, ListModelsResponseSchema, ListQueuedThreadInputsResponseSchema, ListSkillsResponseSchema, ListThreadsResponseSchema, ListWorkspaceDirectoriesResponseSchema, ListWorkspaceFilesResponseSchema, PairEncryptedPayloadSchema, PairRequestSchema, PairResponseSchema, PendingInputRequestOptionSchema, PendingInputRequestQuestionSchema, PendingInputRequestSchema, PromptAttachmentSchema, PromptAttachmentSummarySchema, PromptContextInputSchema, PromptContextSchema, PromptSkillSchema, QueuedThreadInputActionResponseSchema, QueuedThreadInputSchema, RateLimitBucketSchema, RateLimitWindowSchema, RateLimitsResponseSchema, ReasoningEffortSchema, 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, WorkspaceTerminalInputRequestSchema, WorkspaceTerminalOutputChunkSchema, WorkspaceTerminalOutputResponseSchema, WorkspaceTerminalResizeRequestSchema, WorkspaceTerminalSessionResponseSchema, WorkspaceTerminalStartRequestSchema, apiPaths, chatMessageDetailsFromPromptContext, createOpenApiDocument, isPromptSkillMarkdownMention, normalizePromptContext, promptMarkdownWithSkills, promptSkillDisplayName, promptSkillMentionLabel, promptSkillMentionMarkdown, promptSkillMentionTextCandidates, stripPromptSkillMentions };
@@ -57,6 +57,14 @@ const ReasoningEffortSchema = z.enum([
57
57
  "xhigh"
58
58
  ]);
59
59
  const ThreadCollaborationModeSchema = z.enum(["default", "plan"]);
60
+ const ThreadGoalStatusSchema = z.enum([
61
+ "active",
62
+ "paused",
63
+ "blocked",
64
+ "usageLimited",
65
+ "budgetLimited",
66
+ "complete"
67
+ ]);
60
68
  const VersionResponseSchema = z.object({
61
69
  ok: z.boolean(),
62
70
  service: z.literal("codex-relay-server"),
@@ -145,6 +153,16 @@ const ThreadContextWindowResponseSchema = z.object({
145
153
  usage: ContextWindowUsageSchema.nullable(),
146
154
  rolloutPath: z.string().nullable().optional()
147
155
  });
156
+ const ThreadGoalSchema = z.object({
157
+ threadId: z.string().min(1),
158
+ objective: z.string().trim().min(1),
159
+ status: ThreadGoalStatusSchema,
160
+ tokenBudget: z.number().int().positive().nullable(),
161
+ tokensUsed: z.number().int().nonnegative(),
162
+ timeUsedSeconds: z.number().int().nonnegative(),
163
+ createdAt: IsoDateTimeSchema,
164
+ updatedAt: IsoDateTimeSchema
165
+ });
148
166
  const PromptAttachmentBaseSchema = z.object({
149
167
  type: z.literal("image"),
150
168
  mimeType: z.string().trim().startsWith("image/").optional(),
@@ -247,7 +265,8 @@ const ThreadSummarySchema = z.object({
247
265
  lastActivityAt: IsoDateTimeSchema.optional(),
248
266
  lastPrompt: z.string().optional(),
249
267
  lastResult: z.string().optional(),
250
- lastError: z.string().optional()
268
+ lastError: z.string().optional(),
269
+ goal: ThreadGoalSchema.nullable().optional()
251
270
  });
252
271
  const StatusResponseSchema = z.object({
253
272
  ok: z.boolean(),
@@ -473,6 +492,15 @@ const QueuedThreadInputActionResponseSchema = z.object({
473
492
  queueLength: z.number().int().nonnegative(),
474
493
  thread: ThreadSummarySchema
475
494
  });
495
+ const UpdateThreadGoalRequestSchema = z.object({
496
+ objective: z.string().trim().min(1).optional(),
497
+ status: ThreadGoalStatusSchema.optional(),
498
+ tokenBudget: z.number().int().positive().nullable().optional()
499
+ }).refine((input) => input.objective || input.status || input.tokenBudget !== void 0, { message: "At least one goal field is required." });
500
+ const ThreadGoalResponseSchema = z.object({
501
+ goal: ThreadGoalSchema.nullable(),
502
+ thread: ThreadSummarySchema
503
+ });
476
504
  const InterruptThreadRunResponseSchema = z.object({ thread: ThreadSummarySchema });
477
505
  const ListQueuedThreadInputsResponseSchema = z.object({
478
506
  inputs: z.array(QueuedThreadInputSchema),
@@ -533,6 +561,11 @@ const StreamThreadRunEventSchema = z.discriminatedUnion("type", [
533
561
  type: z.literal("thread.state.changed"),
534
562
  thread: ThreadSummarySchema
535
563
  }),
564
+ z.object({
565
+ type: z.literal("thread.goal.updated"),
566
+ thread: ThreadSummarySchema,
567
+ goal: ThreadGoalSchema.nullable()
568
+ }),
536
569
  z.object({
537
570
  type: z.literal("thread.error"),
538
571
  thread: ThreadSummarySchema.optional(),
@@ -697,6 +730,7 @@ const apiPaths = {
697
730
  thread: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}`,
698
731
  threadArchive: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}`,
699
732
  threadContextWindow: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}/context-window`,
733
+ threadGoal: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}/goal`,
700
734
  threadMessageDetail: (threadId, messageId, field) => `/v1/threads/${encodeURIComponent(threadId)}/messages/${encodeURIComponent(messageId)}/details/${encodeURIComponent(field)}`,
701
735
  approval: (approvalId) => `/v1/approvals/${encodeURIComponent(approvalId)}`,
702
736
  threadInput: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}/input`,
@@ -711,7 +745,7 @@ function createOpenApiDocument() {
711
745
  openapi: "3.1.0",
712
746
  info: {
713
747
  title: "Codex Relay Local Codex API",
714
- version: "0.1.0"
748
+ version: "1.2.0"
715
749
  },
716
750
  paths: {
717
751
  "/version": { get: {
@@ -838,6 +872,36 @@ function createOpenApiDocument() {
838
872
  "409": jsonResponse("ErrorResponse")
839
873
  }
840
874
  } },
875
+ "/v1/threads/{threadId}/goal": {
876
+ get: {
877
+ summary: "Read the active goal for a Codex app-server thread",
878
+ responses: {
879
+ "200": jsonResponse("ThreadGoalResponse"),
880
+ "404": jsonResponse("ErrorResponse"),
881
+ "502": jsonResponse("ErrorResponse")
882
+ }
883
+ },
884
+ post: {
885
+ summary: "Update the active goal for a Codex app-server thread",
886
+ requestBody: jsonRequest("UpdateThreadGoalRequest"),
887
+ responses: {
888
+ "200": jsonResponse("ThreadGoalResponse"),
889
+ "400": jsonResponse("ErrorResponse"),
890
+ "404": jsonResponse("ErrorResponse"),
891
+ "409": jsonResponse("ErrorResponse"),
892
+ "502": jsonResponse("ErrorResponse")
893
+ }
894
+ },
895
+ delete: {
896
+ summary: "Clear the active goal for a Codex app-server thread",
897
+ responses: {
898
+ "200": jsonResponse("ThreadGoalResponse"),
899
+ "404": jsonResponse("ErrorResponse"),
900
+ "409": jsonResponse("ErrorResponse"),
901
+ "502": jsonResponse("ErrorResponse")
902
+ }
903
+ }
904
+ },
841
905
  "/v1/threads/{threadId}/input": {
842
906
  post: {
843
907
  summary: "Submit input to an already-running Codex thread",
@@ -970,7 +1034,71 @@ function createOpenApiDocument() {
970
1034
  },
971
1035
  lastPrompt: { type: "string" },
972
1036
  lastResult: { type: "string" },
973
- lastError: { type: "string" }
1037
+ lastError: { type: "string" },
1038
+ goal: { anyOf: [{ $ref: "#/components/schemas/ThreadGoal" }, { type: "null" }] }
1039
+ }
1040
+ },
1041
+ ThreadGoal: {
1042
+ type: "object",
1043
+ required: [
1044
+ "threadId",
1045
+ "objective",
1046
+ "status",
1047
+ "tokenBudget",
1048
+ "tokensUsed",
1049
+ "timeUsedSeconds",
1050
+ "createdAt",
1051
+ "updatedAt"
1052
+ ],
1053
+ properties: {
1054
+ threadId: { type: "string" },
1055
+ objective: { type: "string" },
1056
+ status: {
1057
+ type: "string",
1058
+ enum: ThreadGoalStatusSchema.options
1059
+ },
1060
+ tokenBudget: { anyOf: [{
1061
+ type: "integer",
1062
+ minimum: 1
1063
+ }, { type: "null" }] },
1064
+ tokensUsed: {
1065
+ type: "integer",
1066
+ minimum: 0
1067
+ },
1068
+ timeUsedSeconds: {
1069
+ type: "integer",
1070
+ minimum: 0
1071
+ },
1072
+ createdAt: {
1073
+ type: "string",
1074
+ format: "date-time"
1075
+ },
1076
+ updatedAt: {
1077
+ type: "string",
1078
+ format: "date-time"
1079
+ }
1080
+ }
1081
+ },
1082
+ UpdateThreadGoalRequest: {
1083
+ type: "object",
1084
+ properties: {
1085
+ objective: { type: "string" },
1086
+ status: {
1087
+ type: "string",
1088
+ enum: ThreadGoalStatusSchema.options
1089
+ },
1090
+ tokenBudget: { anyOf: [{
1091
+ type: "integer",
1092
+ minimum: 1
1093
+ }, { type: "null" }] }
1094
+ }
1095
+ },
1096
+ ThreadGoalResponse: {
1097
+ type: "object",
1098
+ required: ["goal", "thread"],
1099
+ properties: {
1100
+ goal: { anyOf: [{ $ref: "#/components/schemas/ThreadGoal" }, { type: "null" }] },
1101
+ thread: { $ref: "#/components/schemas/ThreadSummary" }
974
1102
  }
975
1103
  },
976
1104
  StatusResponse: {
@@ -1561,4 +1689,4 @@ function jsonResponse(schemaName) {
1561
1689
  };
1562
1690
  }
1563
1691
  //#endregion
1564
- export { SandboxModeSchema as $, PairResponseSchema as A, WorkspaceTerminalResizeRequestSchema as At, QueuedThreadInputSchema as B, promptSkillMentionLabel as Bt, ListQueuedThreadInputsResponseSchema as C, WorkspaceMarkdownPreviewTargetSchema as Ct, ListWorkspaceFilesResponseSchema as D, WorkspaceTerminalInputRequestSchema as Dt, ListWorkspaceDirectoriesResponseSchema as E, WorkspaceSelectionRequestSchema as Et, PromptAttachmentSummarySchema as F, createOpenApiDocument as Ft, ResolveApprovalRequestSchema as G, RateLimitWindowSchema as H, promptSkillMentionTextCandidates as Ht, PromptContextInputSchema as I, isPromptSkillMarkdownMention as It, RunThreadResponseSchema as J, ResolveApprovalResponseSchema as K, PromptContextSchema as L, normalizePromptContext as Lt, PendingInputRequestQuestionSchema as M, WorkspaceTerminalStartRequestSchema as Mt, PendingInputRequestSchema as N, apiPaths as Nt, PairEncryptedPayloadSchema as O, WorkspaceTerminalOutputChunkSchema as Ot, PromptAttachmentSchema as P, chatMessageDetailsFromPromptContext as Pt, RuntimePreferencesSchema as Q, PromptSkillSchema as R, promptMarkdownWithSkills as Rt, ListModelsResponseSchema as S, WorkspaceGitActionResponseSchema as St, ListThreadsResponseSchema as T, WorkspacePreviewTabSchema as Tt, RateLimitsResponseSchema as U, stripPromptSkillMentions as Ut, RateLimitBucketSchema as V, promptSkillMentionMarkdown as Vt, ReasoningEffortSchema as W, RuntimePreferencesByWorkspacePathSchema as X, RuntimeModeSchema as Y, RuntimePreferencesResponseSchema as Z, EncryptedPayloadSchema as _, WebPreviewTargetSchema as _t, ArchiveThreadResponseSchema as a, ThreadContextWindowResponseSchema as at, InterruptThreadRunResponseSchema as b, WorkspaceFileContentResponseSchema as bt, ChatMessageRoleSchema as c, ThreadMessageDetailResponseSchema as ct, CheckoutWorkspaceBranchRequestSchema as d, ThreadSummarySchema as dt, StatusResponseSchema as et, CodexModelSchema as f, UpdateRuntimePreferencesRequestSchema as ft, CreateThreadResponseSchema as g, WORKSPACE_PREVIEW_TAB_VALUES as gt, CreateThreadRequestSchema as h, WORKSPACE_PREVIEW_OPEN_PROTOCOL as ht, ApprovalModeSchema as i, ThreadCollaborationModeSchema as it, PendingInputRequestOptionSchema as j, WorkspaceTerminalSessionResponseSchema as jt, PairRequestSchema as k, WorkspaceTerminalOutputResponseSchema as kt, ChatMessageSchema as l, ThreadRunOptionsSchema as lt, ContextWindowUsageSchema as m, VersionResponseSchema as mt, AgentSkillSourceSchema as n, StreamThreadRunRequestSchema as nt, ChatMessageKindSchema as o, ThreadDetailResponseSchema as ot, CommitPushWorkspaceRequestSchema as p, UpdateWorkspaceFileContentRequestSchema as pt, RunThreadRequestSchema as q, ApprovalDecisionSchema as r, SubmitThreadInputResponseSchema as rt, ChatMessagePromptDetailsSchema as s, ThreadMessageDetailFieldSchema as st, AgentSkillSchema as t, StreamThreadRunEventSchema as tt, ChatMessageStateSchema as u, ThreadStateSchema as ut, ErrorResponseSchema as v, WorkspaceChangesResponseSchema as vt, ListSkillsResponseSchema as w, WorkspacePreviewNavigationRequestSchema as wt, IsoDateTimeSchema as x, WorkspaceFileMentionSchema as xt, ImageAttachmentUploadResponseSchema as y, WorkspaceDirectoryEntrySchema as yt, QueuedThreadInputActionResponseSchema as z, promptSkillDisplayName as zt };
1692
+ export { SandboxModeSchema as $, PairResponseSchema as A, WorkspaceSelectionRequestSchema as At, QueuedThreadInputSchema as B, isPromptSkillMarkdownMention as Bt, ListQueuedThreadInputsResponseSchema as C, WorkspaceDirectoryEntrySchema as Ct, ListWorkspaceFilesResponseSchema as D, WorkspaceMarkdownPreviewTargetSchema as Dt, ListWorkspaceDirectoriesResponseSchema as E, WorkspaceGitActionResponseSchema as Et, PromptAttachmentSummarySchema as F, WorkspaceTerminalSessionResponseSchema as Ft, ResolveApprovalRequestSchema as G, promptSkillMentionMarkdown as Gt, RateLimitWindowSchema as H, promptMarkdownWithSkills as Ht, PromptContextInputSchema as I, WorkspaceTerminalStartRequestSchema as It, RunThreadResponseSchema as J, ResolveApprovalResponseSchema as K, promptSkillMentionTextCandidates as Kt, PromptContextSchema as L, apiPaths as Lt, PendingInputRequestQuestionSchema as M, WorkspaceTerminalOutputChunkSchema as Mt, PendingInputRequestSchema as N, WorkspaceTerminalOutputResponseSchema as Nt, PairEncryptedPayloadSchema as O, WorkspacePreviewNavigationRequestSchema as Ot, PromptAttachmentSchema as P, WorkspaceTerminalResizeRequestSchema as Pt, RuntimePreferencesSchema as Q, PromptSkillSchema as R, chatMessageDetailsFromPromptContext as Rt, ListModelsResponseSchema as S, WorkspaceChangesResponseSchema as St, ListThreadsResponseSchema as T, WorkspaceFileMentionSchema as Tt, RateLimitsResponseSchema as U, promptSkillDisplayName as Ut, RateLimitBucketSchema as V, normalizePromptContext as Vt, ReasoningEffortSchema as W, promptSkillMentionLabel as Wt, RuntimePreferencesByWorkspacePathSchema as X, RuntimeModeSchema as Y, RuntimePreferencesResponseSchema as Z, EncryptedPayloadSchema as _, UpdateWorkspaceFileContentRequestSchema as _t, ArchiveThreadResponseSchema as a, ThreadContextWindowResponseSchema as at, InterruptThreadRunResponseSchema as b, WORKSPACE_PREVIEW_TAB_VALUES as bt, ChatMessageRoleSchema as c, ThreadGoalSchema as ct, CheckoutWorkspaceBranchRequestSchema as d, ThreadMessageDetailResponseSchema as dt, StatusResponseSchema as et, CodexModelSchema as f, ThreadRunOptionsSchema as ft, CreateThreadResponseSchema as g, UpdateThreadGoalRequestSchema as gt, CreateThreadRequestSchema as h, UpdateRuntimePreferencesRequestSchema as ht, ApprovalModeSchema as i, ThreadCollaborationModeSchema as it, PendingInputRequestOptionSchema as j, WorkspaceTerminalInputRequestSchema as jt, PairRequestSchema as k, WorkspacePreviewTabSchema as kt, ChatMessageSchema as l, ThreadGoalStatusSchema as lt, ContextWindowUsageSchema as m, ThreadSummarySchema as mt, AgentSkillSourceSchema as n, StreamThreadRunRequestSchema as nt, ChatMessageKindSchema as o, ThreadDetailResponseSchema as ot, CommitPushWorkspaceRequestSchema as p, ThreadStateSchema as pt, RunThreadRequestSchema as q, stripPromptSkillMentions as qt, ApprovalDecisionSchema as r, SubmitThreadInputResponseSchema as rt, ChatMessagePromptDetailsSchema as s, ThreadGoalResponseSchema as st, AgentSkillSchema as t, StreamThreadRunEventSchema as tt, ChatMessageStateSchema as u, ThreadMessageDetailFieldSchema as ut, ErrorResponseSchema as v, VersionResponseSchema as vt, ListSkillsResponseSchema as w, WorkspaceFileContentResponseSchema as wt, IsoDateTimeSchema as x, WebPreviewTargetSchema as xt, ImageAttachmentUploadResponseSchema as y, WORKSPACE_PREVIEW_OPEN_PROTOCOL as yt, QueuedThreadInputActionResponseSchema as z, createOpenApiDocument as zt };
package/dist/cli.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { Nt as apiPaths } from "./api-schema2.js";
2
+ import { Lt 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 PairResponseSchema, At as WorkspaceTerminalResizeRequestSchema, C as ListQueuedThreadInputsResponseSchema, D as ListWorkspaceFilesResponseSchema, Dt as WorkspaceTerminalInputRequestSchema, E as ListWorkspaceDirectoriesResponseSchema, Ft as createOpenApiDocument, G as ResolveApprovalRequestSchema, K as ResolveApprovalResponseSchema, Lt as normalizePromptContext, Mt as WorkspaceTerminalStartRequestSchema, Nt as apiPaths, Pt as chatMessageDetailsFromPromptContext, Q as RuntimePreferencesSchema, Rt as promptMarkdownWithSkills, S as ListModelsResponseSchema, St as WorkspaceGitActionResponseSchema, T as ListThreadsResponseSchema, U as RateLimitsResponseSchema, Ut as stripPromptSkillMentions, X as RuntimePreferencesByWorkspacePathSchema, Z as RuntimePreferencesResponseSchema, _ as EncryptedPayloadSchema, a as ArchiveThreadResponseSchema, at as ThreadContextWindowResponseSchema, b as InterruptThreadRunResponseSchema, bt as WorkspaceFileContentResponseSchema, ct as ThreadMessageDetailResponseSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as ThreadSummarySchema, et as StatusResponseSchema, ft as UpdateRuntimePreferencesRequestSchema, h as CreateThreadRequestSchema, jt as WorkspaceTerminalSessionResponseSchema, k as PairRequestSchema, kt as WorkspaceTerminalOutputResponseSchema, l as ChatMessageSchema, m as ContextWindowUsageSchema, mt as VersionResponseSchema, nt as StreamThreadRunRequestSchema, ot as ThreadDetailResponseSchema, p as CommitPushWorkspaceRequestSchema, pt as UpdateWorkspaceFileContentRequestSchema, q as RunThreadRequestSchema, rt as SubmitThreadInputResponseSchema, st as ThreadMessageDetailFieldSchema, tt as StreamThreadRunEventSchema, vt as WorkspaceChangesResponseSchema, w as ListSkillsResponseSchema, y as ImageAttachmentUploadResponseSchema, z as QueuedThreadInputActionResponseSchema } from "./api-schema2.js";
1
+ import { A as PairResponseSchema, C as ListQueuedThreadInputsResponseSchema, D as ListWorkspaceFilesResponseSchema, E as ListWorkspaceDirectoriesResponseSchema, Et as WorkspaceGitActionResponseSchema, Ft as WorkspaceTerminalSessionResponseSchema, G as ResolveApprovalRequestSchema, Ht as promptMarkdownWithSkills, It as WorkspaceTerminalStartRequestSchema, K as ResolveApprovalResponseSchema, Lt as apiPaths, Nt as WorkspaceTerminalOutputResponseSchema, Pt as WorkspaceTerminalResizeRequestSchema, Q as RuntimePreferencesSchema, Rt as chatMessageDetailsFromPromptContext, S as ListModelsResponseSchema, St as WorkspaceChangesResponseSchema, T as ListThreadsResponseSchema, U as RateLimitsResponseSchema, Vt as normalizePromptContext, X as RuntimePreferencesByWorkspacePathSchema, Z as RuntimePreferencesResponseSchema, _ as EncryptedPayloadSchema, _t as UpdateWorkspaceFileContentRequestSchema, a as ArchiveThreadResponseSchema, at as ThreadContextWindowResponseSchema, b as InterruptThreadRunResponseSchema, ct as ThreadGoalSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as ThreadMessageDetailResponseSchema, et as StatusResponseSchema, gt as UpdateThreadGoalRequestSchema, h as CreateThreadRequestSchema, ht as UpdateRuntimePreferencesRequestSchema, jt as WorkspaceTerminalInputRequestSchema, k as PairRequestSchema, l as ChatMessageSchema, lt as ThreadGoalStatusSchema, m as ContextWindowUsageSchema, mt as ThreadSummarySchema, nt as StreamThreadRunRequestSchema, ot as ThreadDetailResponseSchema, p as CommitPushWorkspaceRequestSchema, q as RunThreadRequestSchema, qt as stripPromptSkillMentions, rt as SubmitThreadInputResponseSchema, st as ThreadGoalResponseSchema, tt as StreamThreadRunEventSchema, ut as ThreadMessageDetailFieldSchema, vt as VersionResponseSchema, w as ListSkillsResponseSchema, wt as WorkspaceFileContentResponseSchema, y as ImageAttachmentUploadResponseSchema, z as QueuedThreadInputActionResponseSchema, zt as createOpenApiDocument } 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";
@@ -9,7 +9,7 @@ import path, { basename, dirname, extname, isAbsolute, join, relative, resolve }
9
9
  import { fileURLToPath } from "node:url";
10
10
  import { z } from "zod";
11
11
  import { fromByteArray, toByteArray } from "base64-js";
12
- import os, { homedir, hostname } from "node:os";
12
+ import os, { homedir, hostname, platform } from "node:os";
13
13
  import { serve } from "@hono/node-server";
14
14
  import { createHash, randomBytes, randomUUID } from "node:crypto";
15
15
  import pc from "picocolors";
@@ -25,6 +25,32 @@ import { randomBytes as randomBytes$1, utf8ToBytes } from "@noble/ciphers/utils.
25
25
  import { ed25519, x25519 } from "@noble/curves/ed25519.js";
26
26
  import { hkdf } from "@noble/hashes/hkdf.js";
27
27
  import { sha256 } from "@noble/hashes/sha2.js";
28
+ //#region src/codex-binary.ts
29
+ const appServerArgs = [
30
+ "app-server",
31
+ "--listen",
32
+ "stdio://"
33
+ ];
34
+ const windowsShellExtensions = new Set([".bat", ".cmd"]);
35
+ function resolveCodexAppServerSpawn(input = {}) {
36
+ const platform$1 = input.platform ?? platform();
37
+ const command = resolveCodexBinary(input.env ?? process.env);
38
+ const isWindows = platform$1 === "win32";
39
+ return {
40
+ command,
41
+ args: [...appServerArgs],
42
+ shell: isWindows && shouldUseWindowsShell(command),
43
+ windowsHide: isWindows
44
+ };
45
+ }
46
+ function resolveCodexBinary(env) {
47
+ return env.CODEX_BIN?.trim() || "codex";
48
+ }
49
+ function shouldUseWindowsShell(command) {
50
+ const extension = extname(command).toLowerCase();
51
+ return extension === "" || windowsShellExtensions.has(extension);
52
+ }
53
+ //#endregion
28
54
  //#region src/app-server.ts
29
55
  var CodexAppServerClient = class {
30
56
  child;
@@ -73,6 +99,15 @@ var CodexAppServerClient = class {
73
99
  async archiveThread(params) {
74
100
  await this.request("thread/archive", params);
75
101
  }
102
+ async getThreadGoal(params) {
103
+ return (await this.request("thread/goal/get", params)).goal;
104
+ }
105
+ async setThreadGoal(params) {
106
+ return (await this.request("thread/goal/set", params)).goal;
107
+ }
108
+ async clearThreadGoal(params) {
109
+ await this.request("thread/goal/clear", params);
110
+ }
76
111
  onNotification(handler) {
77
112
  this.notificationHandlers.add(handler);
78
113
  return () => this.notificationHandlers.delete(handler);
@@ -132,11 +167,12 @@ var CodexAppServerClient = class {
132
167
  return this.initialized;
133
168
  }
134
169
  start() {
135
- this.child = spawn(resolveCodexBinary(), [
136
- "app-server",
137
- "--listen",
138
- "stdio://"
139
- ], { env: process.env });
170
+ const spawnConfig = resolveCodexAppServerSpawn();
171
+ this.child = spawn(spawnConfig.command, spawnConfig.args, {
172
+ env: process.env,
173
+ shell: spawnConfig.shell,
174
+ windowsHide: spawnConfig.windowsHide
175
+ });
140
176
  this.readline = createInterface({
141
177
  input: this.child.stdout,
142
178
  crlfDelay: Infinity
@@ -155,7 +191,7 @@ var CodexAppServerClient = class {
155
191
  clientInfo: {
156
192
  name: "codex-relay",
157
193
  title: "Codex Relay Mobile Server",
158
- version: "0.1.0"
194
+ version: "1.2.0"
159
195
  },
160
196
  capabilities: { experimentalApi: true }
161
197
  }).then(() => void 0);
@@ -236,9 +272,6 @@ var CodexAppServerClient = class {
236
272
  this.pending.clear();
237
273
  }
238
274
  };
239
- function resolveCodexBinary() {
240
- return process.env.CODEX_BIN ?? "codex";
241
- }
242
275
  function debugAppServer(kind, method, id, detail) {
243
276
  if (process.env.CODEX_RELAY_DEBUG_APP_SERVER !== "1") return;
244
277
  console.log(`[app-server] ${kind}${id === void 0 ? "" : ` #${id}`}${method ? ` ${method}` : ""}${detail ? ` ${detail}` : ""}`);
@@ -822,6 +855,16 @@ const defaultWebPreviewPorts = [
822
855
  19006
823
856
  ];
824
857
  const PairApproveRequestSchema = z.object({ approvalCode: z.string().trim().min(1) });
858
+ const AppServerThreadGoalPayloadSchema = z.object({
859
+ threadId: z.string().min(1),
860
+ objective: z.string().trim().min(1),
861
+ status: ThreadGoalStatusSchema,
862
+ tokenBudget: z.number().int().positive().nullable(),
863
+ tokensUsed: z.number().int().nonnegative(),
864
+ timeUsedSeconds: z.number().int().nonnegative(),
865
+ createdAt: z.number(),
866
+ updatedAt: z.number()
867
+ });
825
868
  const maxResolvedApprovals = 100;
826
869
  const maxWorkspaceTerminalOutputChunks = 2e3;
827
870
  function createApp(options = {}) {
@@ -1570,6 +1613,72 @@ function createApp(options = {}) {
1570
1613
  usage: result.usage
1571
1614
  }));
1572
1615
  });
1616
+ app.get("/v1/threads/:threadId/goal", async (c) => {
1617
+ const threadId = c.req.param("threadId");
1618
+ if (!appServer) {
1619
+ const thread = threads.get(threadId);
1620
+ if (!thread) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("not_found", `Thread ${threadId} is not known to this server.`), 404);
1621
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, ThreadGoalResponseSchema.parse({
1622
+ goal: thread.goal ?? null,
1623
+ thread
1624
+ }));
1625
+ }
1626
+ try {
1627
+ const thread = rememberAppServerThread(threads, await appServer.readThread(threadId, { includeTurns: false }));
1628
+ const goal = mapAppServerThreadGoal(await appServer.getThreadGoal({ threadId }));
1629
+ const threadWithGoal = rememberThreadGoal(threads, thread, goal);
1630
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, ThreadGoalResponseSchema.parse({
1631
+ goal,
1632
+ thread: threadWithGoal
1633
+ }));
1634
+ } catch (error) {
1635
+ const message = errorMessage(error);
1636
+ const status = /not found|no rollout found/i.test(message) ? 404 : 502;
1637
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError(status === 404 ? "not_found" : "goal_unavailable", message), status);
1638
+ }
1639
+ });
1640
+ app.post("/v1/threads/:threadId/goal", async (c) => {
1641
+ const threadId = c.req.param("threadId");
1642
+ if (!appServer) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("unsupported", "Thread goals require the Codex app-server."), 409);
1643
+ const parsed = await parseRequestJson(c, options.pairing, secureSessionsByTokenHash, UpdateThreadGoalRequestSchema);
1644
+ if (!parsed.success) return secureJson(c, options.pairing, secureSessionsByTokenHash, validationError(parsed.error), 400);
1645
+ try {
1646
+ const body = parsed.data;
1647
+ const thread = rememberAppServerThread(threads, await appServer.readThread(threadId, { includeTurns: false }));
1648
+ const goal = mapAppServerThreadGoal(await appServer.setThreadGoal({
1649
+ threadId,
1650
+ objective: body.objective,
1651
+ status: body.status,
1652
+ tokenBudget: body.tokenBudget
1653
+ }));
1654
+ const threadWithGoal = rememberThreadGoal(threads, thread, goal);
1655
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, ThreadGoalResponseSchema.parse({
1656
+ goal,
1657
+ thread: threadWithGoal
1658
+ }));
1659
+ } catch (error) {
1660
+ const message = errorMessage(error);
1661
+ const status = /not found|no rollout found/i.test(message) ? 404 : 502;
1662
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError(status === 404 ? "not_found" : "goal_unavailable", message), status);
1663
+ }
1664
+ });
1665
+ app.delete("/v1/threads/:threadId/goal", async (c) => {
1666
+ const threadId = c.req.param("threadId");
1667
+ if (!appServer) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("unsupported", "Thread goals require the Codex app-server."), 409);
1668
+ try {
1669
+ const thread = rememberAppServerThread(threads, await appServer.readThread(threadId, { includeTurns: false }));
1670
+ await appServer.clearThreadGoal({ threadId });
1671
+ const threadWithoutGoal = rememberThreadGoal(threads, thread, null);
1672
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, ThreadGoalResponseSchema.parse({
1673
+ goal: null,
1674
+ thread: threadWithoutGoal
1675
+ }));
1676
+ } catch (error) {
1677
+ const message = errorMessage(error);
1678
+ const status = /not found|no rollout found/i.test(message) ? 404 : 502;
1679
+ return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError(status === 404 ? "not_found" : "goal_unavailable", message), status);
1680
+ }
1681
+ });
1573
1682
  app.get("/openapi.json", (c) => secureJson(c, options.pairing, secureSessionsByTokenHash, createOpenApiDocument()));
1574
1683
  app.post("/v1/approvals/:approvalId", async (c) => {
1575
1684
  const approvalId = c.req.param("approvalId");
@@ -2460,6 +2569,19 @@ async function streamRunningAppServerThread(input) {
2460
2569
  }
2461
2570
  return;
2462
2571
  }
2572
+ case "thread/goal/updated":
2573
+ case "thread/goal/cleared": {
2574
+ const goal = notification.method === "thread/goal/updated" ? mapAppServerThreadGoal(appServerThreadGoalFromParams(params)) : null;
2575
+ const currentThreadSummary = threadSummary ?? input.threads.get(input.threadId);
2576
+ if (!currentThreadSummary) return;
2577
+ threadSummary = rememberThreadGoal(input.threads, currentThreadSummary, goal);
2578
+ sendSse(input.controller, input.encoder, input.secureSession, {
2579
+ type: "thread.goal.updated",
2580
+ thread: threadSummary,
2581
+ goal
2582
+ });
2583
+ return;
2584
+ }
2463
2585
  case "turn/started":
2464
2586
  observedTurnActivity = true;
2465
2587
  activeTurnId = firstString(params, ["turnId"]) ?? turnIdFromParams(params);
@@ -2699,6 +2821,17 @@ async function runAppServerPromptStreamed(input) {
2699
2821
  });
2700
2822
  return;
2701
2823
  }
2824
+ case "thread/goal/updated":
2825
+ case "thread/goal/cleared": {
2826
+ const goal = notification.method === "thread/goal/updated" ? mapAppServerThreadGoal(appServerThreadGoalFromParams(params)) : null;
2827
+ threadSummary = rememberThreadGoal(input.threads, threadSummary, goal);
2828
+ sendSse(input.controller, input.encoder, input.secureSession, {
2829
+ type: "thread.goal.updated",
2830
+ thread: threadSummary,
2831
+ goal
2832
+ });
2833
+ return;
2834
+ }
2702
2835
  case "turn/started":
2703
2836
  activeTurnId = firstString(params, ["turnId"]) ?? turnIdFromParams(params);
2704
2837
  if (activeTurnId) input.activeAppServerTurnIdsByThreadId.set(activeThreadId, activeTurnId);
@@ -3944,12 +4077,33 @@ function rememberAppServerThread(threads, thread) {
3944
4077
  const mappedThread = mapAppServerThread(thread, existingThread?.messageCount);
3945
4078
  const threadWithLocalRuntime = ThreadSummarySchema.parse({
3946
4079
  ...mappedThread,
4080
+ goal: existingThread?.goal ?? mappedThread.goal,
3947
4081
  ...runtimeMetadataFromOptions(existingThread ?? {}),
3948
4082
  model: existingThread?.model ?? mappedThread.model
3949
4083
  });
3950
4084
  threads.set(threadWithLocalRuntime.id, threadWithLocalRuntime);
3951
4085
  return threadWithLocalRuntime;
3952
4086
  }
4087
+ function mapAppServerThreadGoal(goal) {
4088
+ if (!goal) return null;
4089
+ return ThreadGoalSchema.parse({
4090
+ ...goal,
4091
+ createdAt: fromUnixSeconds(goal.createdAt),
4092
+ updatedAt: fromUnixSeconds(goal.updatedAt)
4093
+ });
4094
+ }
4095
+ function appServerThreadGoalFromParams(params) {
4096
+ const parsed = AppServerThreadGoalPayloadSchema.safeParse(params?.goal);
4097
+ return parsed.success ? parsed.data : null;
4098
+ }
4099
+ function rememberThreadGoal(threads, thread, goal) {
4100
+ const next = ThreadSummarySchema.parse({
4101
+ ...thread,
4102
+ goal
4103
+ });
4104
+ threads.set(next.id, next);
4105
+ return next;
4106
+ }
3953
4107
  function preserveKnownRunningThreadState(thread, wasKnownRunning) {
3954
4108
  if (!wasKnownRunning || thread.state === "running") return thread;
3955
4109
  return ThreadSummarySchema.parse({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codex-relay",
3
- "version": "1.1.1",
3
+ "version": "1.2.1",
4
4
  "description": "Local Codex Relay CLI bridge for the Codex Relay mobile app.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -40,7 +40,7 @@
40
40
  "@noble/ciphers": "2.2.0",
41
41
  "@noble/curves": "2.2.0",
42
42
  "@noble/hashes": "2.2.0",
43
- "@openai/codex-sdk": "^0.130.0",
43
+ "@openai/codex-sdk": "0.137.0",
44
44
  "@tursodatabase/database": "^0.5.3",
45
45
  "base64-js": "1.5.1",
46
46
  "commander": "^14.0.3",
package/src/api-schema.ts CHANGED
@@ -32,6 +32,14 @@ export const RuntimeModeSchema = z.enum(["default", "auto", "full-access", "on-r
32
32
  export const SandboxModeSchema = z.enum(["workspace-write", "danger-full-access", "read-only"]);
33
33
  export const ReasoningEffortSchema = z.enum(["minimal", "low", "medium", "high", "xhigh"]);
34
34
  export const ThreadCollaborationModeSchema = z.enum(["default", "plan"]);
35
+ export const ThreadGoalStatusSchema = z.enum([
36
+ "active",
37
+ "paused",
38
+ "blocked",
39
+ "usageLimited",
40
+ "budgetLimited",
41
+ "complete",
42
+ ]);
35
43
 
36
44
  export const VersionResponseSchema = z.object({
37
45
  ok: z.boolean(),
@@ -139,6 +147,17 @@ export const ThreadContextWindowResponseSchema = z.object({
139
147
  rolloutPath: z.string().nullable().optional(),
140
148
  });
141
149
 
150
+ export const ThreadGoalSchema = z.object({
151
+ threadId: z.string().min(1),
152
+ objective: z.string().trim().min(1),
153
+ status: ThreadGoalStatusSchema,
154
+ tokenBudget: z.number().int().positive().nullable(),
155
+ tokensUsed: z.number().int().nonnegative(),
156
+ timeUsedSeconds: z.number().int().nonnegative(),
157
+ createdAt: IsoDateTimeSchema,
158
+ updatedAt: IsoDateTimeSchema,
159
+ });
160
+
142
161
  const PromptAttachmentBaseSchema = z.object({
143
162
  type: z.literal("image"),
144
163
  mimeType: z.string().trim().startsWith("image/").optional(),
@@ -266,6 +285,7 @@ export const ThreadSummarySchema = z.object({
266
285
  lastPrompt: z.string().optional(),
267
286
  lastResult: z.string().optional(),
268
287
  lastError: z.string().optional(),
288
+ goal: ThreadGoalSchema.nullable().optional(),
269
289
  });
270
290
 
271
291
  export const StatusResponseSchema = z.object({
@@ -567,6 +587,21 @@ export const QueuedThreadInputActionResponseSchema = z.object({
567
587
  thread: ThreadSummarySchema,
568
588
  });
569
589
 
590
+ export const UpdateThreadGoalRequestSchema = z
591
+ .object({
592
+ objective: z.string().trim().min(1).optional(),
593
+ status: ThreadGoalStatusSchema.optional(),
594
+ tokenBudget: z.number().int().positive().nullable().optional(),
595
+ })
596
+ .refine((input) => input.objective || input.status || input.tokenBudget !== undefined, {
597
+ message: "At least one goal field is required.",
598
+ });
599
+
600
+ export const ThreadGoalResponseSchema = z.object({
601
+ goal: ThreadGoalSchema.nullable(),
602
+ thread: ThreadSummarySchema,
603
+ });
604
+
570
605
  export const InterruptThreadRunResponseSchema = z.object({
571
606
  thread: ThreadSummarySchema,
572
607
  });
@@ -642,6 +677,11 @@ export const StreamThreadRunEventSchema = z.discriminatedUnion("type", [
642
677
  type: z.literal("thread.state.changed"),
643
678
  thread: ThreadSummarySchema,
644
679
  }),
680
+ z.object({
681
+ type: z.literal("thread.goal.updated"),
682
+ thread: ThreadSummarySchema,
683
+ goal: ThreadGoalSchema.nullable(),
684
+ }),
645
685
  z.object({
646
686
  type: z.literal("thread.error"),
647
687
  thread: ThreadSummarySchema.optional(),
@@ -691,6 +731,9 @@ export type RateLimitBucket = z.infer<typeof RateLimitBucketSchema>;
691
731
  export type RateLimitWindow = z.infer<typeof RateLimitWindowSchema>;
692
732
  export type RateLimitsResponse = z.infer<typeof RateLimitsResponseSchema>;
693
733
  export type ThreadContextWindowResponse = z.infer<typeof ThreadContextWindowResponseSchema>;
734
+ export type ThreadGoal = z.infer<typeof ThreadGoalSchema>;
735
+ export type ThreadGoalResponse = z.infer<typeof ThreadGoalResponseSchema>;
736
+ export type ThreadGoalStatus = z.infer<typeof ThreadGoalStatusSchema>;
694
737
  export type PromptAttachment = z.infer<typeof PromptAttachmentSchema>;
695
738
  export type PendingInputRequest = z.infer<typeof PendingInputRequestSchema>;
696
739
  export type PendingInputRequestQuestion = z.infer<typeof PendingInputRequestQuestionSchema>;
@@ -734,6 +777,7 @@ export type ImageAttachmentUploadResponse = z.infer<typeof ImageAttachmentUpload
734
777
  export type QueuedThreadInput = z.infer<typeof QueuedThreadInputSchema>;
735
778
  export type SubmitThreadInputResponse = z.infer<typeof SubmitThreadInputResponseSchema>;
736
779
  export type QueuedThreadInputActionResponse = z.infer<typeof QueuedThreadInputActionResponseSchema>;
780
+ export type UpdateThreadGoalRequest = z.infer<typeof UpdateThreadGoalRequestSchema>;
737
781
  export type InterruptThreadRunResponse = z.infer<typeof InterruptThreadRunResponseSchema>;
738
782
  export type ListQueuedThreadInputsResponse = z.infer<typeof ListQueuedThreadInputsResponseSchema>;
739
783
  export type ApprovalDecision = z.infer<typeof ApprovalDecisionSchema>;
@@ -988,6 +1032,7 @@ export const apiPaths = {
988
1032
  threadArchive: (threadId: string) => `/v1/threads/${encodeURIComponent(threadId)}`,
989
1033
  threadContextWindow: (threadId: string) =>
990
1034
  `/v1/threads/${encodeURIComponent(threadId)}/context-window`,
1035
+ threadGoal: (threadId: string) => `/v1/threads/${encodeURIComponent(threadId)}/goal`,
991
1036
  threadMessageDetail: (threadId: string, messageId: string, field: ThreadMessageDetailField) =>
992
1037
  `/v1/threads/${encodeURIComponent(threadId)}/messages/${encodeURIComponent(messageId)}/details/${encodeURIComponent(field)}`,
993
1038
  approval: (approvalId: string) => `/v1/approvals/${encodeURIComponent(approvalId)}`,
@@ -1007,7 +1052,7 @@ export function createOpenApiDocument() {
1007
1052
  openapi: "3.1.0",
1008
1053
  info: {
1009
1054
  title: "Codex Relay Local Codex API",
1010
- version: "0.1.0",
1055
+ version: "1.2.0",
1011
1056
  },
1012
1057
  paths: {
1013
1058
  "/version": {
@@ -1162,6 +1207,36 @@ export function createOpenApiDocument() {
1162
1207
  },
1163
1208
  },
1164
1209
  },
1210
+ "/v1/threads/{threadId}/goal": {
1211
+ get: {
1212
+ summary: "Read the active goal for a Codex app-server thread",
1213
+ responses: {
1214
+ "200": jsonResponse("ThreadGoalResponse"),
1215
+ "404": jsonResponse("ErrorResponse"),
1216
+ "502": jsonResponse("ErrorResponse"),
1217
+ },
1218
+ },
1219
+ post: {
1220
+ summary: "Update the active goal for a Codex app-server thread",
1221
+ requestBody: jsonRequest("UpdateThreadGoalRequest"),
1222
+ responses: {
1223
+ "200": jsonResponse("ThreadGoalResponse"),
1224
+ "400": jsonResponse("ErrorResponse"),
1225
+ "404": jsonResponse("ErrorResponse"),
1226
+ "409": jsonResponse("ErrorResponse"),
1227
+ "502": jsonResponse("ErrorResponse"),
1228
+ },
1229
+ },
1230
+ delete: {
1231
+ summary: "Clear the active goal for a Codex app-server thread",
1232
+ responses: {
1233
+ "200": jsonResponse("ThreadGoalResponse"),
1234
+ "404": jsonResponse("ErrorResponse"),
1235
+ "409": jsonResponse("ErrorResponse"),
1236
+ "502": jsonResponse("ErrorResponse"),
1237
+ },
1238
+ },
1239
+ },
1165
1240
  "/v1/threads/{threadId}/input": {
1166
1241
  post: {
1167
1242
  summary: "Submit input to an already-running Codex thread",
@@ -1245,6 +1320,50 @@ export function createOpenApiDocument() {
1245
1320
  lastPrompt: { type: "string" },
1246
1321
  lastResult: { type: "string" },
1247
1322
  lastError: { type: "string" },
1323
+ goal: {
1324
+ anyOf: [{ $ref: "#/components/schemas/ThreadGoal" }, { type: "null" }],
1325
+ },
1326
+ },
1327
+ },
1328
+ ThreadGoal: {
1329
+ type: "object",
1330
+ required: [
1331
+ "threadId",
1332
+ "objective",
1333
+ "status",
1334
+ "tokenBudget",
1335
+ "tokensUsed",
1336
+ "timeUsedSeconds",
1337
+ "createdAt",
1338
+ "updatedAt",
1339
+ ],
1340
+ properties: {
1341
+ threadId: { type: "string" },
1342
+ objective: { type: "string" },
1343
+ status: { type: "string", enum: ThreadGoalStatusSchema.options },
1344
+ tokenBudget: { anyOf: [{ type: "integer", minimum: 1 }, { type: "null" }] },
1345
+ tokensUsed: { type: "integer", minimum: 0 },
1346
+ timeUsedSeconds: { type: "integer", minimum: 0 },
1347
+ createdAt: { type: "string", format: "date-time" },
1348
+ updatedAt: { type: "string", format: "date-time" },
1349
+ },
1350
+ },
1351
+ UpdateThreadGoalRequest: {
1352
+ type: "object",
1353
+ properties: {
1354
+ objective: { type: "string" },
1355
+ status: { type: "string", enum: ThreadGoalStatusSchema.options },
1356
+ tokenBudget: { anyOf: [{ type: "integer", minimum: 1 }, { type: "null" }] },
1357
+ },
1358
+ },
1359
+ ThreadGoalResponse: {
1360
+ type: "object",
1361
+ required: ["goal", "thread"],
1362
+ properties: {
1363
+ goal: {
1364
+ anyOf: [{ $ref: "#/components/schemas/ThreadGoal" }, { type: "null" }],
1365
+ },
1366
+ thread: { $ref: "#/components/schemas/ThreadSummary" },
1248
1367
  },
1249
1368
  },
1250
1369
  StatusResponse: {