codex-relay 1.0.3 → 1.0.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.
package/README.md CHANGED
@@ -16,7 +16,7 @@ Run the server from the workspace you want Codex to use:
16
16
  npx codex-relay@latest
17
17
  ```
18
18
 
19
- The CLI prints a QR code, a mobile URL, and a `codex-relay://pair...` pairing payload. Scan the QR code from the mobile app. If scanning is not available, paste the full pairing payload into the app.
19
+ The CLI prints a QR code, a mobile URL, and a `codex-relay://pair...` pairing payload. Scan the QR code from the mobile app. If the relay detects multiple possible network addresses, the QR includes them and the app automatically uses the first address it can reach. If scanning is not available, paste the full pairing payload into the app.
20
20
 
21
21
  When the app shows an approval code, approve it on the computer:
22
22
 
@@ -117,10 +117,11 @@ CODEX_RELAY_WORKSPACE_PATH=/path/to/project npx codex-relay@latest
117
117
 
118
118
  ## Network Notes
119
119
 
120
- The phone must be able to reach the URL printed as `Mobile:` by the relay.
120
+ The phone must be able to reach one of the URLs printed by the relay.
121
121
 
122
122
  - On the same Wi-Fi network, the relay usually prints a local network address.
123
123
  - On Tailscale, the relay prefers your Tailscale address when it can detect one.
124
+ - If several Wi-Fi, VPN, or virtual network addresses are available, the QR includes all detected candidates and the app tries them automatically.
124
125
  - If the printed URL is not reachable from the phone, set `CODEX_RELAY_PUBLIC_URL` to a reachable HTTP URL.
125
126
 
126
127
  ## Troubleshooting
@@ -1,2 +1,2 @@
1
- import { $ as SandboxModeSchema, A as PairResponseSchema, At as stripPromptSkillMentions, B as QueuedThreadInputSchema, C as ListQueuedThreadInputsResponseSchema, Ct as isPromptSkillMarkdownMention, D as ListWorkspaceFilesResponseSchema, Dt as promptSkillMentionLabel, E as ListWorkspaceDirectoriesResponseSchema, Et as promptSkillDisplayName, F as PromptAttachmentSummarySchema, G as ResolveApprovalRequestSchema, H as RateLimitWindowSchema, I as PromptContextInputSchema, J as RunThreadResponseSchema, K as ResolveApprovalResponseSchema, L as PromptContextSchema, M as PendingInputRequestQuestionSchema, N as PendingInputRequestSchema, O as PairEncryptedPayloadSchema, Ot as promptSkillMentionMarkdown, P as PromptAttachmentSchema, Q as RuntimePreferencesSchema, R as PromptSkillSchema, S as ListModelsResponseSchema, St as createOpenApiDocument, T as ListThreadsResponseSchema, Tt as promptMarkdownWithSkills, U as RateLimitsResponseSchema, V as RateLimitBucketSchema, W as ReasoningEffortSchema, X as RuntimePreferencesByWorkspacePathSchema, Y as RuntimeModeSchema, Z as RuntimePreferencesResponseSchema, _ as EncryptedPayloadSchema, _t as WorkspaceFileMentionSchema, a as ArchiveThreadResponseSchema, at as ThreadContextWindowResponseSchema, b as InterruptThreadRunResponseSchema, bt as apiPaths, 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 WorkspaceDirectoryEntrySchema, h as CreateThreadRequestSchema, ht as WorkspaceChangesResponseSchema, i as ApprovalModeSchema, it as ThreadCollaborationModeSchema, j as PendingInputRequestOptionSchema, k as PairRequestSchema, kt as promptSkillMentionTextCandidates, l as ChatMessageSchema, lt as ThreadRunOptionsSchema, m as ContextWindowUsageSchema, mt as WebPreviewTargetSchema, n as AgentSkillSourceSchema, nt as StreamThreadRunRequestSchema, o as ChatMessageKindSchema, ot as ThreadDetailResponseSchema, p as CommitPushWorkspaceRequestSchema, pt as VersionResponseSchema, 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 WorkspaceGitActionResponseSchema, w as ListSkillsResponseSchema, wt as normalizePromptContext, x as IsoDateTimeSchema, xt as chatMessageDetailsFromPromptContext, y as ImageAttachmentUploadResponseSchema, yt as WorkspaceSelectionRequestSchema, z as QueuedThreadInputActionResponseSchema } 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, VersionResponseSchema, WebPreviewTargetSchema, WorkspaceChangesResponseSchema, WorkspaceDirectoryEntrySchema, WorkspaceFileMentionSchema, WorkspaceGitActionResponseSchema, WorkspaceSelectionRequestSchema, apiPaths, chatMessageDetailsFromPromptContext, createOpenApiDocument, isPromptSkillMarkdownMention, normalizePromptContext, promptMarkdownWithSkills, promptSkillDisplayName, promptSkillMentionLabel, promptSkillMentionMarkdown, promptSkillMentionTextCandidates, stripPromptSkillMentions };
1
+ import { $ as SandboxModeSchema, A as PairResponseSchema, At as isPromptSkillMarkdownMention, B as QueuedThreadInputSchema, C as ListQueuedThreadInputsResponseSchema, Ct as WorkspaceMarkdownPreviewTargetSchema, D as ListWorkspaceFilesResponseSchema, Dt as apiPaths, E as ListWorkspaceDirectoriesResponseSchema, Et as WorkspaceSelectionRequestSchema, F as PromptAttachmentSummarySchema, Ft as promptSkillMentionMarkdown, G as ResolveApprovalRequestSchema, H as RateLimitWindowSchema, I as PromptContextInputSchema, It as promptSkillMentionTextCandidates, J as RunThreadResponseSchema, K as ResolveApprovalResponseSchema, L as PromptContextSchema, Lt as stripPromptSkillMentions, M as PendingInputRequestQuestionSchema, Mt as promptMarkdownWithSkills, N as PendingInputRequestSchema, Nt as promptSkillDisplayName, O as PairEncryptedPayloadSchema, Ot as chatMessageDetailsFromPromptContext, P as PromptAttachmentSchema, Pt as promptSkillMentionLabel, Q as RuntimePreferencesSchema, R as PromptSkillSchema, S as ListModelsResponseSchema, St as WorkspaceGitActionResponseSchema, T as ListThreadsResponseSchema, Tt as WorkspacePreviewTabSchema, U as RateLimitsResponseSchema, V as RateLimitBucketSchema, 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 normalizePromptContext, k as PairRequestSchema, kt as createOpenApiDocument, 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 } 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, apiPaths, chatMessageDetailsFromPromptContext, createOpenApiDocument, isPromptSkillMarkdownMention, normalizePromptContext, promptMarkdownWithSkills, promptSkillDisplayName, promptSkillMentionLabel, promptSkillMentionMarkdown, promptSkillMentionTextCandidates, stripPromptSkillMentions };
@@ -65,6 +65,7 @@ const VersionResponseSchema = z.object({
65
65
  });
66
66
  const ThreadRunOptionsSchema = z.object({
67
67
  model: z.string().trim().min(1).optional(),
68
+ serviceTier: z.string().trim().min(1).optional(),
68
69
  runtimeMode: RuntimeModeSchema.optional(),
69
70
  approvalPolicy: ApprovalModeSchema.optional(),
70
71
  sandboxMode: SandboxModeSchema.optional(),
@@ -73,12 +74,14 @@ const ThreadRunOptionsSchema = z.object({
73
74
  });
74
75
  const RuntimePreferencesSchema = z.object({
75
76
  model: z.string().trim().min(1).optional(),
77
+ serviceTier: z.string().trim().min(1).optional(),
76
78
  runtimeMode: RuntimeModeSchema.default("default"),
77
79
  reasoningEffort: ReasoningEffortSchema.optional()
78
80
  });
79
81
  const RuntimePreferencesByWorkspacePathSchema = z.record(z.string().trim().min(1), RuntimePreferencesSchema);
80
82
  const UpdateRuntimePreferencesRequestSchema = z.object({
81
83
  model: z.string().trim().min(1).nullable().optional(),
84
+ serviceTier: z.string().trim().min(1).nullable().optional(),
82
85
  runtimeMode: RuntimeModeSchema.optional(),
83
86
  reasoningEffort: ReasoningEffortSchema.nullable().optional(),
84
87
  threadId: z.string().trim().min(1).optional(),
@@ -97,7 +100,12 @@ const CodexModelSchema = z.object({
97
100
  description: z.string().optional(),
98
101
  isDefault: z.boolean().default(false),
99
102
  defaultReasoningEffort: ReasoningEffortSchema.optional(),
100
- supportedReasoningEfforts: z.array(ReasoningEffortSchema).default([])
103
+ supportedReasoningEfforts: z.array(ReasoningEffortSchema).default([]),
104
+ serviceTiers: z.array(z.object({
105
+ id: z.string().min(1),
106
+ name: z.string().min(1),
107
+ description: z.string().optional()
108
+ })).default([])
101
109
  });
102
110
  const AgentSkillSourceSchema = z.enum([
103
111
  "workspace",
@@ -169,10 +177,28 @@ const WorkspaceFileMentionSchema = z.object({
169
177
  path: z.string().min(1)
170
178
  });
171
179
  const ListWorkspaceFilesResponseSchema = z.object({
180
+ directory: z.string(),
172
181
  files: z.array(WorkspaceFileMentionSchema),
182
+ parentDirectory: z.string().nullable(),
173
183
  query: z.string(),
174
184
  workspacePath: z.string().min(1)
175
185
  });
186
+ const WorkspaceFileContentResponseSchema = z.object({
187
+ binary: z.boolean(),
188
+ content: z.string(),
189
+ directory: z.string(),
190
+ language: z.string(),
191
+ name: z.string().min(1),
192
+ path: z.string().min(1),
193
+ size: z.number().int().nonnegative(),
194
+ truncated: z.boolean(),
195
+ workspacePath: z.string().min(1)
196
+ });
197
+ const UpdateWorkspaceFileContentRequestSchema = z.object({
198
+ content: z.string().max(1024 * 1024),
199
+ path: z.string().trim().min(1),
200
+ workspacePath: z.string().trim().min(1).optional()
201
+ });
176
202
  const PendingInputRequestOptionSchema = z.object({
177
203
  label: z.string().min(1),
178
204
  description: z.string().optional()
@@ -208,6 +234,7 @@ const ThreadSummarySchema = z.object({
208
234
  updatedAt: IsoDateTimeSchema,
209
235
  state: ThreadStateSchema,
210
236
  model: z.string().optional(),
237
+ serviceTier: z.string().optional(),
211
238
  runtimeMode: RuntimeModeSchema.optional(),
212
239
  approvalPolicy: ApprovalModeSchema.optional(),
213
240
  sandboxMode: SandboxModeSchema.optional(),
@@ -282,6 +309,19 @@ const WorkspaceGitActionResponseSchema = z.object({
282
309
  message: z.string().min(1),
283
310
  output: z.string().default("")
284
311
  });
312
+ const WORKSPACE_PREVIEW_TAB_VALUES = [
313
+ "git",
314
+ "files",
315
+ "markdown",
316
+ "web"
317
+ ];
318
+ const WorkspacePreviewTabSchema = z.enum(WORKSPACE_PREVIEW_TAB_VALUES);
319
+ const WorkspaceMarkdownPreviewTargetSchema = z.object({
320
+ name: z.string().trim().min(1).optional(),
321
+ path: z.string().trim().min(1),
322
+ workspacePath: z.string().trim().min(1).optional()
323
+ });
324
+ const WORKSPACE_PREVIEW_OPEN_PROTOCOL = "workspace-preview.open";
285
325
  const WebPreviewTargetSchema = z.object({
286
326
  kind: z.literal("web"),
287
327
  url: z.string().url(),
@@ -299,6 +339,25 @@ const WebPreviewTargetSchema = z.object({
299
339
  ]),
300
340
  detectedAt: IsoDateTimeSchema
301
341
  });
342
+ const WorkspacePreviewOpenBaseSchema = z.object({
343
+ protocol: z.literal(WORKSPACE_PREVIEW_OPEN_PROTOCOL),
344
+ workspacePath: z.string().trim().min(1).optional()
345
+ });
346
+ const WorkspacePreviewNavigationRequestSchema = z.discriminatedUnion("tab", [
347
+ WorkspacePreviewOpenBaseSchema.extend({ tab: z.literal("git") }),
348
+ WorkspacePreviewOpenBaseSchema.extend({
349
+ tab: z.literal("files"),
350
+ target: z.object({ path: z.string().trim().min(1).optional() }).optional()
351
+ }),
352
+ WorkspacePreviewOpenBaseSchema.extend({
353
+ tab: z.literal("markdown"),
354
+ target: WorkspaceMarkdownPreviewTargetSchema
355
+ }),
356
+ WorkspacePreviewOpenBaseSchema.extend({
357
+ tab: z.literal("web"),
358
+ target: WebPreviewTargetSchema.optional()
359
+ })
360
+ ]);
302
361
  const PairRequestSchema = z.object({
303
362
  clientSessionId: z.string().trim().min(1).max(120).optional(),
304
363
  clientName: z.string().trim().min(1).max(80).optional(),
@@ -581,6 +640,7 @@ const apiPaths = {
581
640
  pair: "/v1/pair",
582
641
  pairApproval: (approvalCode) => `/v1/pair/${encodeURIComponent(approvalCode)}`,
583
642
  pairApprove: "/v1/pair/approve",
643
+ sessionsClear: "/v1/sessions/clear",
584
644
  sessionRefresh: "/v1/session/refresh",
585
645
  status: "/v1/status",
586
646
  preferences: "/v1/preferences",
@@ -588,6 +648,7 @@ const apiPaths = {
588
648
  models: "/v1/models",
589
649
  skills: "/v1/skills",
590
650
  workspaceFiles: "/v1/workspace/files",
651
+ workspaceFileContent: "/v1/workspace/file",
591
652
  workspaceDirectories: "/v1/workspace-directories",
592
653
  workspaceChanges: "/v1/workspace/changes",
593
654
  workspaceCheckout: "/v1/workspace/checkout",
@@ -681,6 +742,35 @@ function createOpenApiDocument() {
681
742
  "400": jsonResponse("ErrorResponse")
682
743
  }
683
744
  } },
745
+ "/v1/workspace/files": { get: {
746
+ summary: "List files under the configured workspace",
747
+ responses: {
748
+ "200": jsonResponse("ListWorkspaceFilesResponse"),
749
+ "400": jsonResponse("ErrorResponse"),
750
+ "502": jsonResponse("ErrorResponse")
751
+ }
752
+ } },
753
+ "/v1/workspace/file": {
754
+ get: {
755
+ summary: "Read a workspace file preview",
756
+ responses: {
757
+ "200": jsonResponse("WorkspaceFileContentResponse"),
758
+ "400": jsonResponse("ErrorResponse"),
759
+ "404": jsonResponse("ErrorResponse"),
760
+ "502": jsonResponse("ErrorResponse")
761
+ }
762
+ },
763
+ put: {
764
+ summary: "Update a workspace text file",
765
+ requestBody: jsonRequest("UpdateWorkspaceFileContentRequest"),
766
+ responses: {
767
+ "200": jsonResponse("WorkspaceFileContentResponse"),
768
+ "400": jsonResponse("ErrorResponse"),
769
+ "404": jsonResponse("ErrorResponse"),
770
+ "502": jsonResponse("ErrorResponse")
771
+ }
772
+ }
773
+ },
684
774
  "/v1/threads/{threadId}/runs": { post: {
685
775
  summary: "Run a prompt on a Codex thread",
686
776
  parameters: [{
@@ -814,6 +904,7 @@ function createOpenApiDocument() {
814
904
  minimum: 0
815
905
  },
816
906
  model: { type: "string" },
907
+ serviceTier: { type: "string" },
817
908
  runtimeMode: { $ref: "#/components/schemas/RuntimeMode" },
818
909
  approvalPolicy: {
819
910
  type: "string",
@@ -901,6 +992,7 @@ function createOpenApiDocument() {
901
992
  required: ["runtimeMode"],
902
993
  properties: {
903
994
  model: { type: "string" },
995
+ serviceTier: { type: "string" },
904
996
  runtimeMode: {
905
997
  type: "string",
906
998
  enum: [
@@ -932,6 +1024,10 @@ function createOpenApiDocument() {
932
1024
  type: "string",
933
1025
  nullable: true
934
1026
  },
1027
+ serviceTier: {
1028
+ type: "string",
1029
+ nullable: true
1030
+ },
935
1031
  runtimeMode: {
936
1032
  type: "string",
937
1033
  enum: [
@@ -996,6 +1092,87 @@ function createOpenApiDocument() {
996
1092
  }
997
1093
  }
998
1094
  },
1095
+ WorkspaceFileMention: {
1096
+ type: "object",
1097
+ required: [
1098
+ "directory",
1099
+ "kind",
1100
+ "name",
1101
+ "path"
1102
+ ],
1103
+ properties: {
1104
+ directory: { type: "string" },
1105
+ kind: {
1106
+ type: "string",
1107
+ enum: ["directory", "file"]
1108
+ },
1109
+ name: { type: "string" },
1110
+ path: { type: "string" }
1111
+ }
1112
+ },
1113
+ ListWorkspaceFilesResponse: {
1114
+ type: "object",
1115
+ required: [
1116
+ "directory",
1117
+ "files",
1118
+ "parentDirectory",
1119
+ "query",
1120
+ "workspacePath"
1121
+ ],
1122
+ properties: {
1123
+ directory: { type: "string" },
1124
+ files: {
1125
+ type: "array",
1126
+ items: { $ref: "#/components/schemas/WorkspaceFileMention" }
1127
+ },
1128
+ parentDirectory: {
1129
+ type: "string",
1130
+ nullable: true
1131
+ },
1132
+ query: { type: "string" },
1133
+ workspacePath: { type: "string" }
1134
+ }
1135
+ },
1136
+ WorkspaceFileContentResponse: {
1137
+ type: "object",
1138
+ required: [
1139
+ "binary",
1140
+ "content",
1141
+ "directory",
1142
+ "language",
1143
+ "name",
1144
+ "path",
1145
+ "size",
1146
+ "truncated",
1147
+ "workspacePath"
1148
+ ],
1149
+ properties: {
1150
+ binary: { type: "boolean" },
1151
+ content: { type: "string" },
1152
+ directory: { type: "string" },
1153
+ language: { type: "string" },
1154
+ name: { type: "string" },
1155
+ path: { type: "string" },
1156
+ size: {
1157
+ type: "integer",
1158
+ minimum: 0
1159
+ },
1160
+ truncated: { type: "boolean" },
1161
+ workspacePath: { type: "string" }
1162
+ }
1163
+ },
1164
+ UpdateWorkspaceFileContentRequest: {
1165
+ type: "object",
1166
+ required: ["content", "path"],
1167
+ properties: {
1168
+ content: {
1169
+ type: "string",
1170
+ maxLength: 1048576
1171
+ },
1172
+ path: { type: "string" },
1173
+ workspacePath: { type: "string" }
1174
+ }
1175
+ },
999
1176
  CreateThreadRequest: {
1000
1177
  type: "object",
1001
1178
  properties: {
@@ -1346,4 +1523,4 @@ function jsonResponse(schemaName) {
1346
1523
  };
1347
1524
  }
1348
1525
  //#endregion
1349
- export { SandboxModeSchema as $, PairResponseSchema as A, stripPromptSkillMentions as At, QueuedThreadInputSchema as B, ListQueuedThreadInputsResponseSchema as C, isPromptSkillMarkdownMention as Ct, ListWorkspaceFilesResponseSchema as D, promptSkillMentionLabel as Dt, ListWorkspaceDirectoriesResponseSchema as E, promptSkillDisplayName as Et, PromptAttachmentSummarySchema as F, ResolveApprovalRequestSchema as G, RateLimitWindowSchema as H, PromptContextInputSchema as I, RunThreadResponseSchema as J, ResolveApprovalResponseSchema as K, PromptContextSchema as L, PendingInputRequestQuestionSchema as M, PendingInputRequestSchema as N, PairEncryptedPayloadSchema as O, promptSkillMentionMarkdown as Ot, PromptAttachmentSchema as P, RuntimePreferencesSchema as Q, PromptSkillSchema as R, ListModelsResponseSchema as S, createOpenApiDocument as St, ListThreadsResponseSchema as T, promptMarkdownWithSkills as Tt, RateLimitsResponseSchema as U, RateLimitBucketSchema as V, ReasoningEffortSchema as W, RuntimePreferencesByWorkspacePathSchema as X, RuntimeModeSchema as Y, RuntimePreferencesResponseSchema as Z, EncryptedPayloadSchema as _, WorkspaceFileMentionSchema as _t, ArchiveThreadResponseSchema as a, ThreadContextWindowResponseSchema as at, InterruptThreadRunResponseSchema as b, apiPaths 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, WorkspaceDirectoryEntrySchema as gt, CreateThreadRequestSchema as h, WorkspaceChangesResponseSchema as ht, ApprovalModeSchema as i, ThreadCollaborationModeSchema as it, PendingInputRequestOptionSchema as j, PairRequestSchema as k, promptSkillMentionTextCandidates as kt, ChatMessageSchema as l, ThreadRunOptionsSchema as lt, ContextWindowUsageSchema as m, WebPreviewTargetSchema as mt, AgentSkillSourceSchema as n, StreamThreadRunRequestSchema as nt, ChatMessageKindSchema as o, ThreadDetailResponseSchema as ot, CommitPushWorkspaceRequestSchema as p, VersionResponseSchema 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, WorkspaceGitActionResponseSchema as vt, ListSkillsResponseSchema as w, normalizePromptContext as wt, IsoDateTimeSchema as x, chatMessageDetailsFromPromptContext as xt, ImageAttachmentUploadResponseSchema as y, WorkspaceSelectionRequestSchema as yt, QueuedThreadInputActionResponseSchema as z };
1526
+ export { SandboxModeSchema as $, PairResponseSchema as A, isPromptSkillMarkdownMention as At, QueuedThreadInputSchema as B, ListQueuedThreadInputsResponseSchema as C, WorkspaceMarkdownPreviewTargetSchema as Ct, ListWorkspaceFilesResponseSchema as D, apiPaths as Dt, ListWorkspaceDirectoriesResponseSchema as E, WorkspaceSelectionRequestSchema as Et, PromptAttachmentSummarySchema as F, promptSkillMentionMarkdown as Ft, ResolveApprovalRequestSchema as G, RateLimitWindowSchema as H, PromptContextInputSchema as I, promptSkillMentionTextCandidates as It, RunThreadResponseSchema as J, ResolveApprovalResponseSchema as K, PromptContextSchema as L, stripPromptSkillMentions as Lt, PendingInputRequestQuestionSchema as M, promptMarkdownWithSkills as Mt, PendingInputRequestSchema as N, promptSkillDisplayName as Nt, PairEncryptedPayloadSchema as O, chatMessageDetailsFromPromptContext as Ot, PromptAttachmentSchema as P, promptSkillMentionLabel as Pt, RuntimePreferencesSchema as Q, PromptSkillSchema as R, ListModelsResponseSchema as S, WorkspaceGitActionResponseSchema as St, ListThreadsResponseSchema as T, WorkspacePreviewTabSchema as Tt, RateLimitsResponseSchema as U, RateLimitBucketSchema as V, 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, normalizePromptContext as jt, PairRequestSchema as k, createOpenApiDocument 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 };
package/dist/cli.js CHANGED
@@ -1,11 +1,11 @@
1
1
  #!/usr/bin/env node
2
- import { bt as apiPaths } from "./api-schema2.js";
3
- import { n as codexRelayHome, r as legacyCodexRelayDataPath, t as codexRelayDataPath } from "./paths.js";
2
+ import { Dt as apiPaths } from "./api-schema2.js";
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";
6
6
  import { spawn } from "node:child_process";
7
7
  import { closeSync, openSync } from "node:fs";
8
- import { mkdir, readFile, unlink } from "node:fs/promises";
8
+ import { access, mkdir, readFile, rm, unlink } from "node:fs/promises";
9
9
  import { dirname } from "node:path";
10
10
  import { setTimeout } from "node:timers/promises";
11
11
  import { fileURLToPath } from "node:url";
@@ -17,6 +17,7 @@ Examples:
17
17
  ${npxCommand} Start the relay and print a pairing QR
18
18
  ${npxCommand} --bg Start the relay in the background
19
19
  ${npxCommand} qr Print the current pairing QR
20
+ ${npxCommand} clear Sign out every paired mobile app
20
21
  ${npxCommand} approve CODE Approve a pending mobile pairing request`).action(async (options) => {
21
22
  if (options.debug) process.env.CODEX_RELAY_DEBUG = "1";
22
23
  if (options.dangerouslyAutoApprove) process.env.CODEX_RELAY_DANGEROUSLY_AUTO_APPROVE = "1";
@@ -32,6 +33,9 @@ program.command("qr").description("Print the current pairing QR for an already r
32
33
  program.command("approve").description("Approve a pending mobile pairing request.").argument("<approval-code>", "approval code shown in the mobile app").action(async (approvalCode) => {
33
34
  await approvePairing(approvalCode);
34
35
  });
36
+ program.command("clear").description("Sign out every paired mobile app.").option("--debug", "also delete debug.log").action(async (options, command) => {
37
+ await clearPairings({ clearDebugLog: Boolean(options.debug || command.optsWithGlobals().debug) });
38
+ });
35
39
  await program.parseAsync();
36
40
  async function startBackgroundServer() {
37
41
  const logPath = codexRelayDataPath("server.log");
@@ -135,6 +139,74 @@ async function approvePairing(rawCode) {
135
139
  }
136
140
  console.log("Approved Codex Relay pairing request.");
137
141
  }
142
+ async function clearPairings(options) {
143
+ const result = await clearPairingsViaServer().catch(async (error) => {
144
+ if (await hasRunningBackgroundServer()) throw error;
145
+ return clearPairingsFromLocalStore();
146
+ });
147
+ const removedDebugLogs = options.clearDebugLog ? await clearDebugLogs() : [];
148
+ console.log(`Signed out ${result.sessionsCleared} paired mobile app${result.sessionsCleared === 1 ? "" : "s"}.`);
149
+ if (result.pendingPairingsCleared > 0) console.log(`Removed ${result.pendingPairingsCleared} pending pairing request${result.pendingPairingsCleared === 1 ? "" : "s"}.`);
150
+ if (options.clearDebugLog) console.log(removedDebugLogs.length > 0 ? `Deleted debug logs: ${removedDebugLogs.join(", ")}` : "No debug logs found.");
151
+ }
152
+ async function clearPairingsViaServer() {
153
+ const endpoint = await getApprovalEndpoint();
154
+ const secret = await readApprovalSecret();
155
+ const response = await fetch(`${endpoint}${apiPaths.sessionsClear}`, {
156
+ method: "POST",
157
+ headers: {
158
+ accept: "application/json",
159
+ "x-codex-relay-approve-secret": secret
160
+ }
161
+ });
162
+ const payload = await response.json().catch(() => void 0);
163
+ if (!response.ok) {
164
+ const message = payload && typeof payload === "object" && "error" in payload && payload.error && typeof payload.error === "object" && "message" in payload.error ? String(payload.error.message) : `Codex Relay server returned ${response.status}`;
165
+ throw new Error(message);
166
+ }
167
+ return parseClearPairingResult(payload);
168
+ }
169
+ async function clearPairingsFromLocalStore() {
170
+ const dbPath = await resolveAuthDbPath();
171
+ if (!dbPath) return {
172
+ pendingPairingsCleared: 0,
173
+ sessionsCleared: 0
174
+ };
175
+ return (await createTursoPairingSessionStore(dbPath)).clearAll();
176
+ }
177
+ async function resolveAuthDbPath() {
178
+ if (process.env.CODEX_RELAY_AUTH_DB_PATH) return process.env.CODEX_RELAY_AUTH_DB_PATH;
179
+ const primary = codexRelayDataPath("auth.db");
180
+ if (await pathExists(primary)) return primary;
181
+ const legacy = legacyCodexRelayDataPath("auth.db");
182
+ if (await pathExists(legacy)) return legacy;
183
+ }
184
+ async function clearDebugLogs() {
185
+ const paths = [...new Set([codexRelayDataPath("debug.log"), legacyCodexRelayDataPath("debug.log")])];
186
+ const removed = [];
187
+ for (const path of paths) {
188
+ if (!await pathExists(path)) continue;
189
+ await rm(path, { force: true });
190
+ removed.push(path);
191
+ }
192
+ return removed;
193
+ }
194
+ async function hasRunningBackgroundServer() {
195
+ return Boolean(await readRunningPid(codexRelayDataPath("server.pid")));
196
+ }
197
+ async function pathExists(path) {
198
+ return access(path).then(() => true, () => false);
199
+ }
200
+ function parseClearPairingResult(payload) {
201
+ if (!payload || typeof payload !== "object") return {
202
+ pendingPairingsCleared: 0,
203
+ sessionsCleared: 0
204
+ };
205
+ return {
206
+ pendingPairingsCleared: "pendingPairingsCleared" in payload ? Number(payload.pendingPairingsCleared) || 0 : 0,
207
+ sessionsCleared: "sessionsCleared" in payload ? Number(payload.sessionsCleared) || 0 : 0
208
+ };
209
+ }
138
210
  async function printPairingQr() {
139
211
  const storedState = await readServerState();
140
212
  const state = storedState?.pairingPayload ? storedState : await readServerLogState();
@@ -148,7 +220,15 @@ async function printPairingQr() {
148
220
  console.log("");
149
221
  qrcode.generate(state.pairingPayload, { small: true });
150
222
  console.log("");
151
- if (state.connectUrl) console.log(`Mobile: ${state.connectUrl}`);
223
+ if (state.connectUrl) {
224
+ console.log(`Mobile: ${state.connectUrl}`);
225
+ const guidance = getConnectUrlGuidance(state.connectUrl);
226
+ if (guidance) console.log(`Network: ${guidance}`);
227
+ }
228
+ if (state.connectUrlCandidates && state.connectUrlCandidates.length > 1) {
229
+ console.log(`Candidate addresses: ${state.connectUrlCandidates.length}`);
230
+ for (const candidate of state.connectUrlCandidates.slice(1)) console.log(` ${candidate.label}: ${candidate.url}`);
231
+ }
152
232
  if (state.listenUrl) console.log(`Server: ${state.listenUrl}`);
153
233
  console.log("");
154
234
  console.log(`Pairing: ${state.pairingPayload}`);
@@ -206,6 +286,7 @@ async function readServerState() {
206
286
  if (!state) return;
207
287
  return {
208
288
  connectUrl: typeof state.connectUrl === "string" ? state.connectUrl : void 0,
289
+ connectUrlCandidates: parseConnectUrlCandidates(state.connectUrlCandidates),
209
290
  host: typeof state.host === "string" ? state.host : void 0,
210
291
  listenUrl: typeof state.listenUrl === "string" ? state.listenUrl : void 0,
211
292
  pairingPayload: typeof state.pairingPayload === "string" ? state.pairingPayload : void 0,
@@ -235,6 +316,18 @@ function lastLogValue(log, label) {
235
316
  for (const match of log.matchAll(pattern)) value = match[1];
236
317
  return value;
237
318
  }
319
+ function parseConnectUrlCandidates(value) {
320
+ if (!Array.isArray(value)) return;
321
+ return value.map((candidate) => {
322
+ if (!candidate || typeof candidate !== "object") return;
323
+ const label = "label" in candidate ? candidate.label : void 0;
324
+ const url = "url" in candidate ? candidate.url : void 0;
325
+ return typeof label === "string" && typeof url === "string" ? {
326
+ label,
327
+ url
328
+ } : void 0;
329
+ }).filter((candidate) => Boolean(candidate));
330
+ }
238
331
  function isDatabaseLockError(error) {
239
332
  const message = error instanceof Error ? error.message : String(error);
240
333
  return message.includes("failed to open database") && message.includes("Locking error");