codex-relay 1.2.2 → 1.2.3
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 +0 -7
- package/dist/api-schema.js +2 -2
- package/dist/api-schema2.js +38 -1
- package/dist/cli.js +1 -1
- package/dist/paths.js +1 -9
- package/dist/src.js +112 -3
- package/package.json +1 -1
- package/src/api-schema.ts +38 -0
package/README.md
CHANGED
|
@@ -95,7 +95,6 @@ The relay listens on `0.0.0.0:8787` by default. Configure it with environment va
|
|
|
95
95
|
| -------------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
96
96
|
| `PORT` | Server port. Defaults to `8787`. |
|
|
97
97
|
| `HOST` | Listen host. Defaults to `0.0.0.0`. |
|
|
98
|
-
| `CODEX_RELAY_PUBLIC_URL` | URL printed into the pairing QR, for example a Tailscale or tunnel URL. |
|
|
99
98
|
| `CODEX_RELAY_WORKSPACE_PATH` | Workspace path Codex should use. Defaults to the directory where you run `npx codex-relay@latest`. |
|
|
100
99
|
| `CODEX_RELAY_AUTH_DB_PATH` | Pairing and session database path. Defaults to `.codex-relay/auth.db`. |
|
|
101
100
|
| `CODEX_RELAY_APPROVAL_SECRET` | Secret used by the local approve command. Usually generated automatically. |
|
|
@@ -109,10 +108,6 @@ Examples:
|
|
|
109
108
|
PORT=8788 npx codex-relay@latest
|
|
110
109
|
```
|
|
111
110
|
|
|
112
|
-
```sh
|
|
113
|
-
CODEX_RELAY_PUBLIC_URL=http://100.64.0.10:8787 npx codex-relay@latest
|
|
114
|
-
```
|
|
115
|
-
|
|
116
111
|
```sh
|
|
117
112
|
CODEX_RELAY_WORKSPACE_PATH=/path/to/project npx codex-relay@latest
|
|
118
113
|
```
|
|
@@ -124,7 +119,6 @@ The phone must be able to reach one of the URLs printed by the relay.
|
|
|
124
119
|
- On the same Wi-Fi network, the relay usually prints a local network address.
|
|
125
120
|
- On Tailscale, the relay prefers your Tailscale address when it can detect one.
|
|
126
121
|
- If several Wi-Fi, VPN, or virtual network addresses are available, the QR includes all detected candidates and the app tries them automatically.
|
|
127
|
-
- If the printed URL is not reachable from the phone, set `CODEX_RELAY_PUBLIC_URL` to a reachable HTTP URL.
|
|
128
122
|
|
|
129
123
|
## Troubleshooting
|
|
130
124
|
|
|
@@ -154,4 +148,3 @@ Connection checklist:
|
|
|
154
148
|
- If keeping the same network is difficult, are both devices connected through Tailscale or another reachable private network?
|
|
155
149
|
- Can the phone open the exact `Mobile:` URL printed by the relay?
|
|
156
150
|
- Does the computer firewall allow inbound traffic on the relay port, usually `8787`?
|
|
157
|
-
- If the printed URL is not reachable, did you set `CODEX_RELAY_PUBLIC_URL` to a reachable LAN, Tailscale, or tunnel URL?
|
package/dist/api-schema.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as SandboxModeSchema, A as PairResponseSchema, At as WorkspaceSelectionRequestSchema, B as QueuedThreadInputSchema, Bt as
|
|
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 };
|
|
1
|
+
import { $ as SandboxModeSchema, A as PairResponseSchema, At as WorkspaceSelectionRequestSchema, B as QueuedThreadInputSchema, Bt as chatMessageDetailsFromPromptContext, C as ListQueuedThreadInputsResponseSchema, Ct as WorkspaceDirectoryEntrySchema, D as ListWorkspaceFilesResponseSchema, Dt as WorkspaceMarkdownPreviewTargetSchema, E as ListWorkspaceDirectoriesResponseSchema, Et as WorkspaceGitActionResponseSchema, F as PromptAttachmentSummarySchema, Ft as WorkspaceTerminalOutputResponseSchema, G as ResolveApprovalRequestSchema, Gt as promptSkillDisplayName, H as RateLimitWindowSchema, Ht as isPromptSkillMarkdownMention, I as PromptContextInputSchema, It as WorkspaceTerminalResizeRequestSchema, J as RunThreadResponseSchema, Jt as promptSkillMentionTextCandidates, K as ResolveApprovalResponseSchema, Kt as promptSkillMentionLabel, L as PromptContextSchema, Lt as WorkspaceTerminalSessionResponseSchema, M as PendingInputRequestQuestionSchema, Mt as WorkspaceTailscaleServeResponseSchema, N as PendingInputRequestSchema, Nt as WorkspaceTerminalInputRequestSchema, O as PairEncryptedPayloadSchema, Ot as WorkspacePreviewNavigationRequestSchema, P as PromptAttachmentSchema, Pt as WorkspaceTerminalOutputChunkSchema, Q as RuntimePreferencesSchema, R as PromptSkillSchema, Rt as WorkspaceTerminalStartRequestSchema, S as ListModelsResponseSchema, St as WorkspaceChangesResponseSchema, T as ListThreadsResponseSchema, Tt as WorkspaceFileMentionSchema, U as RateLimitsResponseSchema, Ut as normalizePromptContext, V as RateLimitBucketSchema, Vt as createOpenApiDocument, W as ReasoningEffortSchema, Wt as promptMarkdownWithSkills, X as RuntimePreferencesByWorkspacePathSchema, Y as RuntimeModeSchema, Yt as stripPromptSkillMentions, 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 WorkspaceTailscaleServeRequestSchema, 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 promptSkillMentionMarkdown, 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 apiPaths } 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, WorkspaceTailscaleServeRequestSchema, WorkspaceTailscaleServeResponseSchema, WorkspaceTerminalInputRequestSchema, WorkspaceTerminalOutputChunkSchema, WorkspaceTerminalOutputResponseSchema, WorkspaceTerminalResizeRequestSchema, WorkspaceTerminalSessionResponseSchema, WorkspaceTerminalStartRequestSchema, apiPaths, chatMessageDetailsFromPromptContext, createOpenApiDocument, isPromptSkillMarkdownMention, normalizePromptContext, promptMarkdownWithSkills, promptSkillDisplayName, promptSkillMentionLabel, promptSkillMentionMarkdown, promptSkillMentionTextCandidates, stripPromptSkillMentions };
|
package/dist/api-schema2.js
CHANGED
|
@@ -409,6 +409,11 @@ const WorkspaceTerminalResizeRequestSchema = z.object({
|
|
|
409
409
|
cols: z.number().int().min(2).max(300),
|
|
410
410
|
rows: z.number().int().min(2).max(120)
|
|
411
411
|
});
|
|
412
|
+
const WorkspaceTailscaleServeRequestSchema = z.object({ url: z.string().url() });
|
|
413
|
+
const WorkspaceTailscaleServeResponseSchema = z.object({
|
|
414
|
+
port: z.number().int().positive(),
|
|
415
|
+
url: z.string().url()
|
|
416
|
+
});
|
|
412
417
|
const PairRequestSchema = z.object({
|
|
413
418
|
clientSessionId: z.string().trim().min(1).max(120).optional(),
|
|
414
419
|
clientName: z.string().trim().min(1).max(80).optional(),
|
|
@@ -724,6 +729,7 @@ const apiPaths = {
|
|
|
724
729
|
workspaceTerminalOutput: (sessionId) => `/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/output`,
|
|
725
730
|
workspaceTerminalOutputStream: (sessionId) => `/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/output/stream`,
|
|
726
731
|
workspaceTerminalResize: (sessionId) => `/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/resize`,
|
|
732
|
+
workspaceTailscaleServe: "/v1/workspace/tailscale/serve",
|
|
727
733
|
imageAttachments: "/v1/attachments/images",
|
|
728
734
|
imageAttachment: (attachmentId) => `/v1/attachments/images/${encodeURIComponent(attachmentId)}`,
|
|
729
735
|
threads: "/v1/threads",
|
|
@@ -843,6 +849,15 @@ function createOpenApiDocument() {
|
|
|
843
849
|
}
|
|
844
850
|
}
|
|
845
851
|
},
|
|
852
|
+
"/v1/workspace/tailscale/serve": { post: {
|
|
853
|
+
summary: "Start Tailscale Serve for a workspace preview URL",
|
|
854
|
+
requestBody: jsonRequest("WorkspaceTailscaleServeRequest"),
|
|
855
|
+
responses: {
|
|
856
|
+
"200": jsonResponse("WorkspaceTailscaleServeResponse"),
|
|
857
|
+
"400": jsonResponse("ErrorResponse"),
|
|
858
|
+
"502": jsonResponse("ErrorResponse")
|
|
859
|
+
}
|
|
860
|
+
} },
|
|
846
861
|
"/v1/threads/{threadId}/runs": { post: {
|
|
847
862
|
summary: "Run a prompt on a Codex thread",
|
|
848
863
|
parameters: [{
|
|
@@ -1339,6 +1354,28 @@ function createOpenApiDocument() {
|
|
|
1339
1354
|
workspacePath: { type: "string" }
|
|
1340
1355
|
}
|
|
1341
1356
|
},
|
|
1357
|
+
WorkspaceTailscaleServeRequest: {
|
|
1358
|
+
type: "object",
|
|
1359
|
+
required: ["url"],
|
|
1360
|
+
properties: { url: {
|
|
1361
|
+
type: "string",
|
|
1362
|
+
format: "uri"
|
|
1363
|
+
} }
|
|
1364
|
+
},
|
|
1365
|
+
WorkspaceTailscaleServeResponse: {
|
|
1366
|
+
type: "object",
|
|
1367
|
+
required: ["url", "port"],
|
|
1368
|
+
properties: {
|
|
1369
|
+
url: {
|
|
1370
|
+
type: "string",
|
|
1371
|
+
format: "uri"
|
|
1372
|
+
},
|
|
1373
|
+
port: {
|
|
1374
|
+
type: "integer",
|
|
1375
|
+
minimum: 1
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
},
|
|
1342
1379
|
CreateThreadRequest: {
|
|
1343
1380
|
type: "object",
|
|
1344
1381
|
properties: {
|
|
@@ -1689,4 +1726,4 @@ function jsonResponse(schemaName) {
|
|
|
1689
1726
|
};
|
|
1690
1727
|
}
|
|
1691
1728
|
//#endregion
|
|
1692
|
-
export { SandboxModeSchema as $, PairResponseSchema as A, WorkspaceSelectionRequestSchema as At, QueuedThreadInputSchema as B,
|
|
1729
|
+
export { SandboxModeSchema as $, PairResponseSchema as A, WorkspaceSelectionRequestSchema as At, QueuedThreadInputSchema as B, chatMessageDetailsFromPromptContext as Bt, ListQueuedThreadInputsResponseSchema as C, WorkspaceDirectoryEntrySchema as Ct, ListWorkspaceFilesResponseSchema as D, WorkspaceMarkdownPreviewTargetSchema as Dt, ListWorkspaceDirectoriesResponseSchema as E, WorkspaceGitActionResponseSchema as Et, PromptAttachmentSummarySchema as F, WorkspaceTerminalOutputResponseSchema as Ft, ResolveApprovalRequestSchema as G, promptSkillDisplayName as Gt, RateLimitWindowSchema as H, isPromptSkillMarkdownMention as Ht, PromptContextInputSchema as I, WorkspaceTerminalResizeRequestSchema as It, RunThreadResponseSchema as J, promptSkillMentionTextCandidates as Jt, ResolveApprovalResponseSchema as K, promptSkillMentionLabel as Kt, PromptContextSchema as L, WorkspaceTerminalSessionResponseSchema as Lt, PendingInputRequestQuestionSchema as M, WorkspaceTailscaleServeResponseSchema as Mt, PendingInputRequestSchema as N, WorkspaceTerminalInputRequestSchema as Nt, PairEncryptedPayloadSchema as O, WorkspacePreviewNavigationRequestSchema as Ot, PromptAttachmentSchema as P, WorkspaceTerminalOutputChunkSchema as Pt, RuntimePreferencesSchema as Q, PromptSkillSchema as R, WorkspaceTerminalStartRequestSchema as Rt, ListModelsResponseSchema as S, WorkspaceChangesResponseSchema as St, ListThreadsResponseSchema as T, WorkspaceFileMentionSchema as Tt, RateLimitsResponseSchema as U, normalizePromptContext as Ut, RateLimitBucketSchema as V, createOpenApiDocument as Vt, ReasoningEffortSchema as W, promptMarkdownWithSkills as Wt, RuntimePreferencesByWorkspacePathSchema as X, RuntimeModeSchema as Y, stripPromptSkillMentions as Yt, 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, WorkspaceTailscaleServeRequestSchema 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, promptSkillMentionMarkdown 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, apiPaths as zt };
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { zt 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/paths.js
CHANGED
|
@@ -252,7 +252,7 @@ function resultRows(result) {
|
|
|
252
252
|
function getConnectUrlGuidance(url) {
|
|
253
253
|
const host = parseUrlHost(url);
|
|
254
254
|
if (!host) return;
|
|
255
|
-
if (isLocalhost(host) || isUnspecifiedHost(host)) return "This address is only reachable from this computer. Use a same-Wi-Fi address
|
|
255
|
+
if (isLocalhost(host) || isUnspecifiedHost(host)) return "This address is only reachable from this computer. Use a same-Wi-Fi address or Tailscale for mobile pairing.";
|
|
256
256
|
if (isTailscaleHost(host)) return "Using Tailscale. Keep Tailscale connected on both this computer and the phone.";
|
|
257
257
|
if (isPrivateIPv4Host(host) || isLocalIPv6Host(host)) return "Using a local Wi-Fi/LAN address. Keep the phone and computer on the same network; if pairing is flaky, try Tailscale.";
|
|
258
258
|
return "Using a configured or public address. Make sure the phone can reach it before pairing.";
|
|
@@ -269,7 +269,6 @@ function createPairingQrPayload(details) {
|
|
|
269
269
|
}
|
|
270
270
|
function getConnectUrlCandidates(details) {
|
|
271
271
|
return dedupeCandidates([
|
|
272
|
-
...configuredConnectUrlCandidates(),
|
|
273
272
|
...tailscaleConnectUrlCandidates(details.port),
|
|
274
273
|
...localNetworkConnectUrlCandidates(details.port),
|
|
275
274
|
{
|
|
@@ -289,13 +288,6 @@ function normalizeUrl(value) {
|
|
|
289
288
|
return;
|
|
290
289
|
}
|
|
291
290
|
}
|
|
292
|
-
function configuredConnectUrlCandidates() {
|
|
293
|
-
const configuredUrl = normalizeUrl(process.env.CODEX_RELAY_PUBLIC_URL);
|
|
294
|
-
return configuredUrl ? [{
|
|
295
|
-
label: "Configured",
|
|
296
|
-
url: configuredUrl
|
|
297
|
-
}] : [];
|
|
298
|
-
}
|
|
299
291
|
function tailscaleConnectUrlCandidates(port) {
|
|
300
292
|
const status = getTailscaleStatus();
|
|
301
293
|
const candidates = [];
|
package/dist/src.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as PairResponseSchema, C as ListQueuedThreadInputsResponseSchema, D as ListWorkspaceFilesResponseSchema, E as ListWorkspaceDirectoriesResponseSchema, Et as WorkspaceGitActionResponseSchema, Ft as
|
|
1
|
+
import { A as PairResponseSchema, Bt as chatMessageDetailsFromPromptContext, C as ListQueuedThreadInputsResponseSchema, D as ListWorkspaceFilesResponseSchema, E as ListWorkspaceDirectoriesResponseSchema, Et as WorkspaceGitActionResponseSchema, Ft as WorkspaceTerminalOutputResponseSchema, G as ResolveApprovalRequestSchema, It as WorkspaceTerminalResizeRequestSchema, K as ResolveApprovalResponseSchema, Lt as WorkspaceTerminalSessionResponseSchema, Mt as WorkspaceTailscaleServeResponseSchema, Nt as WorkspaceTerminalInputRequestSchema, Q as RuntimePreferencesSchema, Rt as WorkspaceTerminalStartRequestSchema, S as ListModelsResponseSchema, St as WorkspaceChangesResponseSchema, T as ListThreadsResponseSchema, U as RateLimitsResponseSchema, Ut as normalizePromptContext, Vt as createOpenApiDocument, Wt as promptMarkdownWithSkills, X as RuntimePreferencesByWorkspacePathSchema, Yt as stripPromptSkillMentions, 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 WorkspaceTailscaleServeRequestSchema, 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, 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 apiPaths } 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";
|
|
@@ -828,6 +828,102 @@ function dedupe(items, keyFor) {
|
|
|
828
828
|
});
|
|
829
829
|
}
|
|
830
830
|
//#endregion
|
|
831
|
+
//#region src/tailscale-serve.ts
|
|
832
|
+
var TailscaleServeInvalidUrlError = class extends Error {
|
|
833
|
+
constructor(message) {
|
|
834
|
+
super(message);
|
|
835
|
+
this.name = "TailscaleServeInvalidUrlError";
|
|
836
|
+
}
|
|
837
|
+
};
|
|
838
|
+
var TailscaleServeCommandError = class extends Error {
|
|
839
|
+
constructor(message) {
|
|
840
|
+
super(message);
|
|
841
|
+
this.name = "TailscaleServeCommandError";
|
|
842
|
+
}
|
|
843
|
+
};
|
|
844
|
+
const execFileAsync$1 = promisify(execFile);
|
|
845
|
+
const tailscaleServeOptions = {
|
|
846
|
+
maxBuffer: 1024 * 1024,
|
|
847
|
+
timeout: 15e3
|
|
848
|
+
};
|
|
849
|
+
const tailscaleServeUrlPattern = /https:\/\/[^\s]+\.ts\.net\b[^\s]*/;
|
|
850
|
+
function parseTailscaleServePreviewUrl(url) {
|
|
851
|
+
let parsedUrl;
|
|
852
|
+
try {
|
|
853
|
+
parsedUrl = new URL(url);
|
|
854
|
+
} catch {
|
|
855
|
+
throw new TailscaleServeInvalidUrlError("Preview URL must be a valid URL.");
|
|
856
|
+
}
|
|
857
|
+
if (parsedUrl.protocol !== "http:") throw new TailscaleServeInvalidUrlError("Preview URL must use HTTP.");
|
|
858
|
+
if (!parsedUrl.port) throw new TailscaleServeInvalidUrlError("Preview URL must include an explicit port.");
|
|
859
|
+
const port = Number(parsedUrl.port);
|
|
860
|
+
if (!Number.isInteger(port) || port < 1 || port > 65535) throw new TailscaleServeInvalidUrlError("Preview URL port must be between 1 and 65535.");
|
|
861
|
+
if (!isAllowedTailscaleHost(parsedUrl.hostname)) throw new TailscaleServeInvalidUrlError("Preview URL must use a Tailscale 100.64.0.0/10 or .ts.net host.");
|
|
862
|
+
return {
|
|
863
|
+
port,
|
|
864
|
+
sourceUrl: parsedUrl.href
|
|
865
|
+
};
|
|
866
|
+
}
|
|
867
|
+
async function startTailscaleServeForPreviewUrl(input) {
|
|
868
|
+
const preview = parseTailscaleServePreviewUrl(input.url);
|
|
869
|
+
const execFile = input.execFile ?? defaultExecFile;
|
|
870
|
+
let result;
|
|
871
|
+
try {
|
|
872
|
+
result = await execFile("tailscale", [
|
|
873
|
+
"serve",
|
|
874
|
+
"--bg",
|
|
875
|
+
String(preview.port)
|
|
876
|
+
], tailscaleServeOptions);
|
|
877
|
+
} catch (error) {
|
|
878
|
+
throw new TailscaleServeCommandError(errorMessage$1(error));
|
|
879
|
+
}
|
|
880
|
+
const serveUrl = `${result.stdout}\n${result.stderr}`.match(tailscaleServeUrlPattern)?.[0];
|
|
881
|
+
if (!serveUrl) throw new TailscaleServeCommandError("Tailscale Serve did not report a .ts.net HTTPS URL.");
|
|
882
|
+
return {
|
|
883
|
+
port: preview.port,
|
|
884
|
+
url: serveUrl
|
|
885
|
+
};
|
|
886
|
+
}
|
|
887
|
+
async function defaultExecFile(file, args, options) {
|
|
888
|
+
const result = await execFileAsync$1(file, [...args], options);
|
|
889
|
+
return {
|
|
890
|
+
stderr: result.stderr,
|
|
891
|
+
stdout: result.stdout
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
function isAllowedTailscaleHost(hostname) {
|
|
895
|
+
const lowerHostname = hostname.toLowerCase();
|
|
896
|
+
return lowerHostname.endsWith(".ts.net") || isTailscaleIpv4Host(lowerHostname);
|
|
897
|
+
}
|
|
898
|
+
function isTailscaleIpv4Host(hostname) {
|
|
899
|
+
const parts = hostname.split(".");
|
|
900
|
+
if (parts.length !== 4) return false;
|
|
901
|
+
const octets = parts.map((part) => Number(part));
|
|
902
|
+
if (!octets.every((octet) => Number.isInteger(octet) && octet >= 0 && octet <= 255)) return false;
|
|
903
|
+
const first = octets[0];
|
|
904
|
+
const second = octets[1];
|
|
905
|
+
return first === 100 && second !== void 0 && second >= 64 && second <= 127;
|
|
906
|
+
}
|
|
907
|
+
function errorMessage$1(error) {
|
|
908
|
+
return error instanceof Error ? error.message : "Tailscale Serve command failed.";
|
|
909
|
+
}
|
|
910
|
+
//#endregion
|
|
911
|
+
//#region src/workspace-terminal-shell.ts
|
|
912
|
+
function resolveWorkspaceTerminalShell(input) {
|
|
913
|
+
const env = input?.env ?? process.env;
|
|
914
|
+
if ((input?.platform ?? process.platform) === "win32") return {
|
|
915
|
+
args: [],
|
|
916
|
+
command: shellEnvValue(env.COMSPEC) || "powershell.exe"
|
|
917
|
+
};
|
|
918
|
+
return {
|
|
919
|
+
args: ["-l"],
|
|
920
|
+
command: shellEnvValue(env.SHELL) || "/bin/sh"
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
function shellEnvValue(value) {
|
|
924
|
+
return value?.trim() ?? "";
|
|
925
|
+
}
|
|
926
|
+
//#endregion
|
|
831
927
|
//#region src/app.ts
|
|
832
928
|
const defaultWorkspacePath = process.cwd();
|
|
833
929
|
const defaultCodexModel = "gpt-5.5";
|
|
@@ -1222,6 +1318,19 @@ function createApp(options = {}) {
|
|
|
1222
1318
|
return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("workspace_terminal_start_failed", errorMessage(error)), 400);
|
|
1223
1319
|
}
|
|
1224
1320
|
});
|
|
1321
|
+
app.post(apiPaths.workspaceTailscaleServe, async (c) => {
|
|
1322
|
+
const parsed = await parseRequestJson(c, options.pairing, secureSessionsByTokenHash, WorkspaceTailscaleServeRequestSchema);
|
|
1323
|
+
if (!parsed.success) return secureJson(c, options.pairing, secureSessionsByTokenHash, validationError(parsed.error), 400);
|
|
1324
|
+
try {
|
|
1325
|
+
const serve = await (options.tailscaleServeForPreviewUrl ?? startTailscaleServeForPreviewUrl)({ url: parsed.data.url });
|
|
1326
|
+
const response = WorkspaceTailscaleServeResponseSchema.parse(serve);
|
|
1327
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, response);
|
|
1328
|
+
} catch (error) {
|
|
1329
|
+
const status = error instanceof TailscaleServeInvalidUrlError ? 400 : 502;
|
|
1330
|
+
const code = error instanceof TailscaleServeInvalidUrlError ? "invalid_tailscale_preview_url" : "tailscale_serve_failed";
|
|
1331
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError(code, errorMessage(error)), status);
|
|
1332
|
+
}
|
|
1333
|
+
});
|
|
1225
1334
|
app.get("/v1/workspace/terminal/sessions/:sessionId/output", async (c) => {
|
|
1226
1335
|
const session = workspaceTerminalSessions.get(c.req.param("sessionId"));
|
|
1227
1336
|
if (!session) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("workspace_terminal_not_found", "Terminal session was not found."), 404);
|
|
@@ -5532,8 +5641,8 @@ async function git(cwd, args) {
|
|
|
5532
5641
|
function createWorkspaceTerminalSession(input) {
|
|
5533
5642
|
const sessionId = randomUUID();
|
|
5534
5643
|
const startedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
5535
|
-
const shell =
|
|
5536
|
-
const child = pty.spawn(shell, [
|
|
5644
|
+
const shell = resolveWorkspaceTerminalShell();
|
|
5645
|
+
const child = pty.spawn(shell.command, [...shell.args], {
|
|
5537
5646
|
cols: input.cols,
|
|
5538
5647
|
cwd: input.cwd,
|
|
5539
5648
|
env: {
|
package/package.json
CHANGED
package/src/api-schema.ts
CHANGED
|
@@ -464,6 +464,15 @@ export const WorkspaceTerminalResizeRequestSchema = z.object({
|
|
|
464
464
|
rows: z.number().int().min(2).max(120),
|
|
465
465
|
});
|
|
466
466
|
|
|
467
|
+
export const WorkspaceTailscaleServeRequestSchema = z.object({
|
|
468
|
+
url: z.string().url(),
|
|
469
|
+
});
|
|
470
|
+
|
|
471
|
+
export const WorkspaceTailscaleServeResponseSchema = z.object({
|
|
472
|
+
port: z.number().int().positive(),
|
|
473
|
+
url: z.string().url(),
|
|
474
|
+
});
|
|
475
|
+
|
|
467
476
|
export const PairRequestSchema = z.object({
|
|
468
477
|
clientSessionId: z.string().trim().min(1).max(120).optional(),
|
|
469
478
|
clientName: z.string().trim().min(1).max(80).optional(),
|
|
@@ -762,6 +771,8 @@ export type WorkspaceTerminalSessionResponse = z.infer<
|
|
|
762
771
|
export type WorkspaceTerminalOutputResponse = z.infer<typeof WorkspaceTerminalOutputResponseSchema>;
|
|
763
772
|
export type WorkspaceTerminalInputRequest = z.infer<typeof WorkspaceTerminalInputRequestSchema>;
|
|
764
773
|
export type WorkspaceTerminalResizeRequest = z.infer<typeof WorkspaceTerminalResizeRequestSchema>;
|
|
774
|
+
export type WorkspaceTailscaleServeRequest = z.infer<typeof WorkspaceTailscaleServeRequestSchema>;
|
|
775
|
+
export type WorkspaceTailscaleServeResponse = z.infer<typeof WorkspaceTailscaleServeResponseSchema>;
|
|
765
776
|
export type WebPreviewTarget = z.infer<typeof WebPreviewTargetSchema>;
|
|
766
777
|
export type PairRequest = z.infer<typeof PairRequestSchema>;
|
|
767
778
|
export type PairResponse = z.infer<typeof PairResponseSchema>;
|
|
@@ -1024,6 +1035,7 @@ export const apiPaths = {
|
|
|
1024
1035
|
`/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/output/stream`,
|
|
1025
1036
|
workspaceTerminalResize: (sessionId: string) =>
|
|
1026
1037
|
`/v1/workspace/terminal/sessions/${encodeURIComponent(sessionId)}/resize`,
|
|
1038
|
+
workspaceTailscaleServe: "/v1/workspace/tailscale/serve",
|
|
1027
1039
|
imageAttachments: "/v1/attachments/images",
|
|
1028
1040
|
imageAttachment: (attachmentId: string) =>
|
|
1029
1041
|
`/v1/attachments/images/${encodeURIComponent(attachmentId)}`,
|
|
@@ -1170,6 +1182,17 @@ export function createOpenApiDocument() {
|
|
|
1170
1182
|
},
|
|
1171
1183
|
},
|
|
1172
1184
|
},
|
|
1185
|
+
"/v1/workspace/tailscale/serve": {
|
|
1186
|
+
post: {
|
|
1187
|
+
summary: "Start Tailscale Serve for a workspace preview URL",
|
|
1188
|
+
requestBody: jsonRequest("WorkspaceTailscaleServeRequest"),
|
|
1189
|
+
responses: {
|
|
1190
|
+
"200": jsonResponse("WorkspaceTailscaleServeResponse"),
|
|
1191
|
+
"400": jsonResponse("ErrorResponse"),
|
|
1192
|
+
"502": jsonResponse("ErrorResponse"),
|
|
1193
|
+
},
|
|
1194
|
+
},
|
|
1195
|
+
},
|
|
1173
1196
|
"/v1/threads/{threadId}/runs": {
|
|
1174
1197
|
post: {
|
|
1175
1198
|
summary: "Run a prompt on a Codex thread",
|
|
@@ -1528,6 +1551,21 @@ export function createOpenApiDocument() {
|
|
|
1528
1551
|
workspacePath: { type: "string" },
|
|
1529
1552
|
},
|
|
1530
1553
|
},
|
|
1554
|
+
WorkspaceTailscaleServeRequest: {
|
|
1555
|
+
type: "object",
|
|
1556
|
+
required: ["url"],
|
|
1557
|
+
properties: {
|
|
1558
|
+
url: { type: "string", format: "uri" },
|
|
1559
|
+
},
|
|
1560
|
+
},
|
|
1561
|
+
WorkspaceTailscaleServeResponse: {
|
|
1562
|
+
type: "object",
|
|
1563
|
+
required: ["url", "port"],
|
|
1564
|
+
properties: {
|
|
1565
|
+
url: { type: "string", format: "uri" },
|
|
1566
|
+
port: { type: "integer", minimum: 1 },
|
|
1567
|
+
},
|
|
1568
|
+
},
|
|
1531
1569
|
CreateThreadRequest: {
|
|
1532
1570
|
type: "object",
|
|
1533
1571
|
properties: {
|