codex-relay 1.2.3 → 1.3.0
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/dist/api-schema.js +2 -2
- package/dist/api-schema2.js +16 -17
- package/dist/cli.js +43 -17
- package/dist/src.js +344 -138
- package/package.json +2 -2
- package/src/api-schema.ts +22 -3
package/dist/api-schema.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ 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, WorkspaceTailscaleServeRequestSchema, WorkspaceTailscaleServeResponseSchema, WorkspaceTerminalInputRequestSchema, WorkspaceTerminalOutputChunkSchema, WorkspaceTerminalOutputResponseSchema, WorkspaceTerminalResizeRequestSchema, WorkspaceTerminalSessionResponseSchema, WorkspaceTerminalStartRequestSchema, apiPaths, chatMessageDetailsFromPromptContext, createOpenApiDocument, isPromptSkillMarkdownMention, normalizePromptContext, promptMarkdownWithSkills, promptSkillDisplayName, promptSkillMentionLabel, promptSkillMentionMarkdown, promptSkillMentionTextCandidates, stripPromptSkillMentions };
|
|
1
|
+
import { $ as RuntimePreferencesSchema, A as PairRequestSchema, At as WorkspacePreviewTabSchema, B as QueuedThreadInputActionResponseSchema, Bt as apiPaths, C as ListModelsResponseSchema, Ct as WorkspaceChangesResponseSchema, D as ListWorkspaceDirectoriesResponseSchema, Dt as WorkspaceGitActionResponseSchema, E as ListThreadsResponseSchema, Et as WorkspaceFileMentionSchema, F as PromptAttachmentSchema, Ft as WorkspaceTerminalOutputChunkSchema, G as ReasoningEffortSchema, Gt as promptMarkdownWithSkills, H as RateLimitBucketSchema, Ht as createOpenApiDocument, I as PromptAttachmentSummarySchema, It as WorkspaceTerminalOutputResponseSchema, J as RunThreadRequestSchema, Jt as promptSkillMentionMarkdown, K as ResolveApprovalRequestSchema, Kt as promptSkillDisplayName, L as PromptContextInputSchema, Lt as WorkspaceTerminalResizeRequestSchema, M as PendingInputRequestOptionSchema, Mt as WorkspaceTailscaleServeRequestSchema, N as PendingInputRequestQuestionSchema, Nt as WorkspaceTailscaleServeResponseSchema, O as ListWorkspaceFilesResponseSchema, Ot as WorkspaceMarkdownPreviewTargetSchema, P as PendingInputRequestSchema, Pt as WorkspaceTerminalInputRequestSchema, Q as RuntimePreferencesResponseSchema, R as PromptContextSchema, Rt as WorkspaceTerminalSessionResponseSchema, S as KnownReasoningEffortSchema, St as WebPreviewTargetSchema, T as ListSkillsResponseSchema, Tt as WorkspaceFileContentResponseSchema, U as RateLimitWindowSchema, Ut as isPromptSkillMarkdownMention, V as QueuedThreadInputSchema, Vt as chatMessageDetailsFromPromptContext, W as RateLimitsResponseSchema, Wt as normalizePromptContext, X as RuntimeModeSchema, Xt as stripPromptSkillMentions, Y as RunThreadResponseSchema, Yt as promptSkillMentionTextCandidates, Z as RuntimePreferencesByWorkspacePathSchema, _ as EncryptedPayloadSchema, _t as UpdateThreadGoalRequestSchema, a as ArchiveThreadResponseSchema, at as ThreadCollaborationModeSchema, b as InterruptThreadRunResponseSchema, bt as WORKSPACE_PREVIEW_OPEN_PROTOCOL, c as ChatMessageRoleSchema, ct as ThreadGoalResponseSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as ThreadMessageDetailFieldSchema, et as SandboxModeSchema, f as CodexModelSchema, ft as ThreadMessageDetailResponseSchema, g as CreateThreadResponseSchema, gt as UpdateRuntimePreferencesRequestSchema, h as CreateThreadRequestSchema, ht as ThreadSummarySchema, i as ApprovalModeSchema, it as SubmitThreadInputResponseSchema, j as PairResponseSchema, jt as WorkspaceSelectionRequestSchema, k as PairEncryptedPayloadSchema, kt as WorkspacePreviewNavigationRequestSchema, l as ChatMessageSchema, lt as ThreadGoalSchema, m as ContextWindowUsageSchema, mt as ThreadStateSchema, n as AgentSkillSourceSchema, nt as StreamThreadRunEventSchema, o as ChatMessageKindSchema, ot as ThreadContextWindowResponseSchema, p as CommitPushWorkspaceRequestSchema, pt as ThreadRunOptionsSchema, q as ResolveApprovalResponseSchema, qt as promptSkillMentionLabel, r as ApprovalDecisionSchema, rt as StreamThreadRunRequestSchema, s as ChatMessagePromptDetailsSchema, st as ThreadDetailResponseSchema, t as AgentSkillSchema, tt as StatusResponseSchema, u as ChatMessageStateSchema, ut as ThreadGoalStatusSchema, v as ErrorResponseSchema, vt as UpdateWorkspaceFileContentRequestSchema, w as ListQueuedThreadInputsResponseSchema, wt as WorkspaceDirectoryEntrySchema, x as IsoDateTimeSchema, xt as WORKSPACE_PREVIEW_TAB_VALUES, y as ImageAttachmentUploadResponseSchema, yt as VersionResponseSchema, z as PromptSkillSchema, zt as WorkspaceTerminalStartRequestSchema } from "./api-schema2.js";
|
|
2
|
+
export { AgentSkillSchema, AgentSkillSourceSchema, ApprovalDecisionSchema, ApprovalModeSchema, ArchiveThreadResponseSchema, ChatMessageKindSchema, ChatMessagePromptDetailsSchema, ChatMessageRoleSchema, ChatMessageSchema, ChatMessageStateSchema, CheckoutWorkspaceBranchRequestSchema, CodexModelSchema, CommitPushWorkspaceRequestSchema, ContextWindowUsageSchema, CreateThreadRequestSchema, CreateThreadResponseSchema, EncryptedPayloadSchema, ErrorResponseSchema, ImageAttachmentUploadResponseSchema, InterruptThreadRunResponseSchema, IsoDateTimeSchema, KnownReasoningEffortSchema, ListModelsResponseSchema, ListQueuedThreadInputsResponseSchema, ListSkillsResponseSchema, ListThreadsResponseSchema, ListWorkspaceDirectoriesResponseSchema, ListWorkspaceFilesResponseSchema, PairEncryptedPayloadSchema, PairRequestSchema, PairResponseSchema, PendingInputRequestOptionSchema, PendingInputRequestQuestionSchema, PendingInputRequestSchema, PromptAttachmentSchema, PromptAttachmentSummarySchema, PromptContextInputSchema, PromptContextSchema, PromptSkillSchema, 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
|
@@ -49,13 +49,16 @@ const SandboxModeSchema = z.enum([
|
|
|
49
49
|
"danger-full-access",
|
|
50
50
|
"read-only"
|
|
51
51
|
]);
|
|
52
|
-
const
|
|
52
|
+
const KnownReasoningEffortSchema = z.enum([
|
|
53
53
|
"minimal",
|
|
54
54
|
"low",
|
|
55
55
|
"medium",
|
|
56
56
|
"high",
|
|
57
|
-
"xhigh"
|
|
57
|
+
"xhigh",
|
|
58
|
+
"max",
|
|
59
|
+
"ultra"
|
|
58
60
|
]);
|
|
61
|
+
const ReasoningEffortSchema = z.string().trim().min(1);
|
|
59
62
|
const ThreadCollaborationModeSchema = z.enum(["default", "plan"]);
|
|
60
63
|
const ThreadGoalStatusSchema = z.enum([
|
|
61
64
|
"active",
|
|
@@ -109,6 +112,10 @@ const CodexModelSchema = z.object({
|
|
|
109
112
|
isDefault: z.boolean().default(false),
|
|
110
113
|
defaultReasoningEffort: ReasoningEffortSchema.optional(),
|
|
111
114
|
supportedReasoningEfforts: z.array(ReasoningEffortSchema).default([]),
|
|
115
|
+
reasoningEffortOptions: z.array(z.object({
|
|
116
|
+
reasoningEffort: ReasoningEffortSchema,
|
|
117
|
+
description: z.string().optional()
|
|
118
|
+
})).default([]),
|
|
112
119
|
serviceTiers: z.array(z.object({
|
|
113
120
|
id: z.string().min(1),
|
|
114
121
|
name: z.string().min(1),
|
|
@@ -954,6 +961,10 @@ function createOpenApiDocument() {
|
|
|
954
961
|
type: "string",
|
|
955
962
|
enum: ThreadStateSchema.options
|
|
956
963
|
},
|
|
964
|
+
ReasoningEffort: {
|
|
965
|
+
type: "string",
|
|
966
|
+
minLength: 1
|
|
967
|
+
},
|
|
957
968
|
ChatMessage: {
|
|
958
969
|
type: "object",
|
|
959
970
|
required: [
|
|
@@ -1186,13 +1197,7 @@ function createOpenApiDocument() {
|
|
|
1186
1197
|
},
|
|
1187
1198
|
reasoningEffort: {
|
|
1188
1199
|
type: "string",
|
|
1189
|
-
|
|
1190
|
-
"minimal",
|
|
1191
|
-
"low",
|
|
1192
|
-
"medium",
|
|
1193
|
-
"high",
|
|
1194
|
-
"xhigh"
|
|
1195
|
-
]
|
|
1200
|
+
minLength: 1
|
|
1196
1201
|
}
|
|
1197
1202
|
}
|
|
1198
1203
|
},
|
|
@@ -1220,13 +1225,7 @@ function createOpenApiDocument() {
|
|
|
1220
1225
|
},
|
|
1221
1226
|
reasoningEffort: {
|
|
1222
1227
|
type: "string",
|
|
1223
|
-
|
|
1224
|
-
"minimal",
|
|
1225
|
-
"low",
|
|
1226
|
-
"medium",
|
|
1227
|
-
"high",
|
|
1228
|
-
"xhigh"
|
|
1229
|
-
],
|
|
1228
|
+
minLength: 1,
|
|
1230
1229
|
nullable: true
|
|
1231
1230
|
}
|
|
1232
1231
|
}
|
|
@@ -1726,4 +1725,4 @@ function jsonResponse(schemaName) {
|
|
|
1726
1725
|
};
|
|
1727
1726
|
}
|
|
1728
1727
|
//#endregion
|
|
1729
|
-
export {
|
|
1728
|
+
export { RuntimePreferencesSchema as $, PairRequestSchema as A, WorkspacePreviewTabSchema as At, QueuedThreadInputActionResponseSchema as B, apiPaths as Bt, ListModelsResponseSchema as C, WorkspaceChangesResponseSchema as Ct, ListWorkspaceDirectoriesResponseSchema as D, WorkspaceGitActionResponseSchema as Dt, ListThreadsResponseSchema as E, WorkspaceFileMentionSchema as Et, PromptAttachmentSchema as F, WorkspaceTerminalOutputChunkSchema as Ft, ReasoningEffortSchema as G, promptMarkdownWithSkills as Gt, RateLimitBucketSchema as H, createOpenApiDocument as Ht, PromptAttachmentSummarySchema as I, WorkspaceTerminalOutputResponseSchema as It, RunThreadRequestSchema as J, promptSkillMentionMarkdown as Jt, ResolveApprovalRequestSchema as K, promptSkillDisplayName as Kt, PromptContextInputSchema as L, WorkspaceTerminalResizeRequestSchema as Lt, PendingInputRequestOptionSchema as M, WorkspaceTailscaleServeRequestSchema as Mt, PendingInputRequestQuestionSchema as N, WorkspaceTailscaleServeResponseSchema as Nt, ListWorkspaceFilesResponseSchema as O, WorkspaceMarkdownPreviewTargetSchema as Ot, PendingInputRequestSchema as P, WorkspaceTerminalInputRequestSchema as Pt, RuntimePreferencesResponseSchema as Q, PromptContextSchema as R, WorkspaceTerminalSessionResponseSchema as Rt, KnownReasoningEffortSchema as S, WebPreviewTargetSchema as St, ListSkillsResponseSchema as T, WorkspaceFileContentResponseSchema as Tt, RateLimitWindowSchema as U, isPromptSkillMarkdownMention as Ut, QueuedThreadInputSchema as V, chatMessageDetailsFromPromptContext as Vt, RateLimitsResponseSchema as W, normalizePromptContext as Wt, RuntimeModeSchema as X, stripPromptSkillMentions as Xt, RunThreadResponseSchema as Y, promptSkillMentionTextCandidates as Yt, RuntimePreferencesByWorkspacePathSchema as Z, EncryptedPayloadSchema as _, UpdateThreadGoalRequestSchema as _t, ArchiveThreadResponseSchema as a, ThreadCollaborationModeSchema as at, InterruptThreadRunResponseSchema as b, WORKSPACE_PREVIEW_OPEN_PROTOCOL as bt, ChatMessageRoleSchema as c, ThreadGoalResponseSchema as ct, CheckoutWorkspaceBranchRequestSchema as d, ThreadMessageDetailFieldSchema as dt, SandboxModeSchema as et, CodexModelSchema as f, ThreadMessageDetailResponseSchema as ft, CreateThreadResponseSchema as g, UpdateRuntimePreferencesRequestSchema as gt, CreateThreadRequestSchema as h, ThreadSummarySchema as ht, ApprovalModeSchema as i, SubmitThreadInputResponseSchema as it, PairResponseSchema as j, WorkspaceSelectionRequestSchema as jt, PairEncryptedPayloadSchema as k, WorkspacePreviewNavigationRequestSchema as kt, ChatMessageSchema as l, ThreadGoalSchema as lt, ContextWindowUsageSchema as m, ThreadStateSchema as mt, AgentSkillSourceSchema as n, StreamThreadRunEventSchema as nt, ChatMessageKindSchema as o, ThreadContextWindowResponseSchema as ot, CommitPushWorkspaceRequestSchema as p, ThreadRunOptionsSchema as pt, ResolveApprovalResponseSchema as q, promptSkillMentionLabel as qt, ApprovalDecisionSchema as r, StreamThreadRunRequestSchema as rt, ChatMessagePromptDetailsSchema as s, ThreadDetailResponseSchema as st, AgentSkillSchema as t, StatusResponseSchema as tt, ChatMessageStateSchema as u, ThreadGoalStatusSchema as ut, ErrorResponseSchema as v, UpdateWorkspaceFileContentRequestSchema as vt, ListQueuedThreadInputsResponseSchema as w, WorkspaceDirectoryEntrySchema as wt, IsoDateTimeSchema as x, WORKSPACE_PREVIEW_TAB_VALUES as xt, ImageAttachmentUploadResponseSchema as y, VersionResponseSchema as yt, PromptSkillSchema as z, WorkspaceTerminalStartRequestSchema as zt };
|
package/dist/cli.js
CHANGED
|
@@ -1,14 +1,51 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { Bt 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";
|
|
6
|
-
import { spawn } from "node:child_process";
|
|
6
|
+
import { execFile, spawn } from "node:child_process";
|
|
7
7
|
import { closeSync, openSync } from "node:fs";
|
|
8
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";
|
|
12
|
+
import { promisify } from "node:util";
|
|
13
|
+
//#region src/background-process.ts
|
|
14
|
+
const execFileAsync = promisify(execFile);
|
|
15
|
+
async function readRunningRelayPid(pidPath, options = {}) {
|
|
16
|
+
const value = await readFile(pidPath, "utf8").catch(() => void 0);
|
|
17
|
+
const pid = value ? Number(value.trim()) : NaN;
|
|
18
|
+
if (!Number.isInteger(pid) || pid <= 0) return;
|
|
19
|
+
if (!(options.isProcessAlive ?? defaultIsProcessAlive)(pid)) return;
|
|
20
|
+
const command = await (options.commandReader ?? readProcessCommand)(pid);
|
|
21
|
+
return command && isRelayProcessCommand(command) ? pid : void 0;
|
|
22
|
+
}
|
|
23
|
+
function defaultIsProcessAlive(pid) {
|
|
24
|
+
try {
|
|
25
|
+
process.kill(pid, 0);
|
|
26
|
+
return true;
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function readProcessCommand(pid) {
|
|
32
|
+
try {
|
|
33
|
+
const { stdout } = await execFileAsync("ps", [
|
|
34
|
+
"-p",
|
|
35
|
+
String(pid),
|
|
36
|
+
"-o",
|
|
37
|
+
"command="
|
|
38
|
+
]);
|
|
39
|
+
return stdout.trim() || void 0;
|
|
40
|
+
} catch {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
function isRelayProcessCommand(command) {
|
|
45
|
+
const normalized = command.replaceAll("\\", "/");
|
|
46
|
+
return normalized.includes("codex-relay") || normalized.includes("/src/cli.ts") || normalized.includes(" src/cli.ts");
|
|
47
|
+
}
|
|
48
|
+
//#endregion
|
|
12
49
|
//#region src/cli.ts
|
|
13
50
|
const npxCommand = "npx codex-relay@latest";
|
|
14
51
|
const program = new Command().name("codex-relay").description("Run and approve the codex-relay local CLI bridge.").option("--bg", "run the Codex Relay server in the background").option("--debug", "write verbose relay diagnostics to debug.log").option("--dangerously-auto-approve", "automatically approve mobile pairing requests without a local approval command").addHelpText("after", `
|
|
@@ -42,7 +79,7 @@ async function startBackgroundServer() {
|
|
|
42
79
|
const debugLogPath = codexRelayDataPath("debug.log");
|
|
43
80
|
const pidPath = codexRelayDataPath("server.pid");
|
|
44
81
|
await mkdir(dirname(logPath), { recursive: true });
|
|
45
|
-
const existingPid = await
|
|
82
|
+
const existingPid = await readRunningRelayPid(pidPath);
|
|
46
83
|
if (existingPid) {
|
|
47
84
|
console.log(`codex-relay is already running in the background (pid ${existingPid}).`);
|
|
48
85
|
console.log(`Logs: ${logPath}`);
|
|
@@ -86,17 +123,6 @@ async function startBackgroundServer() {
|
|
|
86
123
|
if (process.env.CODEX_RELAY_DEBUG === "1") console.log(`Debug logs: ${debugLogPath}`);
|
|
87
124
|
console.log(`Print the pairing QR later with: ${npxCommand} qr`);
|
|
88
125
|
}
|
|
89
|
-
async function readRunningPid(pidPath) {
|
|
90
|
-
const value = await readFile(pidPath, "utf8").catch(() => void 0);
|
|
91
|
-
const pid = value ? Number(value.trim()) : NaN;
|
|
92
|
-
if (!Number.isInteger(pid) || pid <= 0) return;
|
|
93
|
-
try {
|
|
94
|
-
process.kill(pid, 0);
|
|
95
|
-
return pid;
|
|
96
|
-
} catch {
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
126
|
function backgroundArgs() {
|
|
101
127
|
return process.argv.slice(2).filter((arg) => arg !== "--bg");
|
|
102
128
|
}
|
|
@@ -106,7 +132,7 @@ async function waitForBackgroundPid(child, pidPath) {
|
|
|
106
132
|
childExited = true;
|
|
107
133
|
});
|
|
108
134
|
for (let attempt = 0; attempt < 50; attempt += 1) {
|
|
109
|
-
const pid = await
|
|
135
|
+
const pid = await readRunningRelayPid(pidPath);
|
|
110
136
|
if (pid) return pid;
|
|
111
137
|
if (childExited) return;
|
|
112
138
|
await setTimeout(100);
|
|
@@ -192,7 +218,7 @@ async function clearDebugLogs() {
|
|
|
192
218
|
return removed;
|
|
193
219
|
}
|
|
194
220
|
async function hasRunningBackgroundServer() {
|
|
195
|
-
return Boolean(await
|
|
221
|
+
return Boolean(await readRunningRelayPid(codexRelayDataPath("server.pid")));
|
|
196
222
|
}
|
|
197
223
|
async function pathExists(path) {
|
|
198
224
|
return access(path).then(() => true, () => false);
|
|
@@ -238,7 +264,7 @@ async function handleServerStartError(error) {
|
|
|
238
264
|
if (!isDatabaseLockError(error)) throw error;
|
|
239
265
|
const pidPath = codexRelayDataPath("server.pid");
|
|
240
266
|
const logPath = codexRelayDataPath("server.log");
|
|
241
|
-
const existingPid = await
|
|
267
|
+
const existingPid = await readRunningRelayPid(pidPath);
|
|
242
268
|
const storedState = await readServerState();
|
|
243
269
|
const state = storedState?.pairingPayload ? storedState : await readServerLogState();
|
|
244
270
|
console.error("Codex Relay is already using its local pairing database.");
|
package/dist/src.js
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { $ as RuntimePreferencesSchema, A as PairRequestSchema, B as QueuedThreadInputActionResponseSchema, Bt as apiPaths, C as ListModelsResponseSchema, Ct as WorkspaceChangesResponseSchema, D as ListWorkspaceDirectoriesResponseSchema, Dt as WorkspaceGitActionResponseSchema, E as ListThreadsResponseSchema, G as ReasoningEffortSchema, Gt as promptMarkdownWithSkills, Ht as createOpenApiDocument, It as WorkspaceTerminalOutputResponseSchema, J as RunThreadRequestSchema, K as ResolveApprovalRequestSchema, Lt as WorkspaceTerminalResizeRequestSchema, Mt as WorkspaceTailscaleServeRequestSchema, Nt as WorkspaceTailscaleServeResponseSchema, O as ListWorkspaceFilesResponseSchema, Pt as WorkspaceTerminalInputRequestSchema, Q as RuntimePreferencesResponseSchema, Rt as WorkspaceTerminalSessionResponseSchema, S as KnownReasoningEffortSchema, T as ListSkillsResponseSchema, Tt as WorkspaceFileContentResponseSchema, Vt as chatMessageDetailsFromPromptContext, W as RateLimitsResponseSchema, Wt as normalizePromptContext, Xt as stripPromptSkillMentions, _ as EncryptedPayloadSchema, _t as UpdateThreadGoalRequestSchema, a as ArchiveThreadResponseSchema, b as InterruptThreadRunResponseSchema, ct as ThreadGoalResponseSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as ThreadMessageDetailFieldSchema, ft as ThreadMessageDetailResponseSchema, gt as UpdateRuntimePreferencesRequestSchema, h as CreateThreadRequestSchema, ht as ThreadSummarySchema, it as SubmitThreadInputResponseSchema, j as PairResponseSchema, l as ChatMessageSchema, lt as ThreadGoalSchema, m as ContextWindowUsageSchema, nt as StreamThreadRunEventSchema, ot as ThreadContextWindowResponseSchema, p as CommitPushWorkspaceRequestSchema, q as ResolveApprovalResponseSchema, rt as StreamThreadRunRequestSchema, st as ThreadDetailResponseSchema, tt as StatusResponseSchema, ut as ThreadGoalStatusSchema, vt as UpdateWorkspaceFileContentRequestSchema, w as ListQueuedThreadInputsResponseSchema, y as ImageAttachmentUploadResponseSchema, yt as VersionResponseSchema, zt as WorkspaceTerminalStartRequestSchema } 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";
|
|
5
5
|
import { execFile, spawn } from "node:child_process";
|
|
6
6
|
import fs, { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFileSync } from "node:fs";
|
|
7
|
-
import { access, appendFile, copyFile, mkdir, open, readFile, readdir, stat, writeFile } from "node:fs/promises";
|
|
7
|
+
import { access, appendFile, copyFile, mkdir, open, readFile, readdir, realpath, stat, writeFile } from "node:fs/promises";
|
|
8
8
|
import path, { basename, dirname, extname, isAbsolute, join, relative, resolve } from "node:path";
|
|
9
9
|
import { fileURLToPath } from "node:url";
|
|
10
10
|
import { z } from "zod";
|
|
11
|
+
import { promisify } from "node:util";
|
|
11
12
|
import { fromByteArray, toByteArray } from "base64-js";
|
|
12
13
|
import os, { homedir, hostname, platform } from "node:os";
|
|
13
14
|
import { serve } from "@hono/node-server";
|
|
@@ -16,7 +17,6 @@ import pc from "picocolors";
|
|
|
16
17
|
import { openRepository } from "es-git";
|
|
17
18
|
import { Hono } from "hono";
|
|
18
19
|
import { cors } from "hono/cors";
|
|
19
|
-
import { promisify } from "node:util";
|
|
20
20
|
import * as pty from "@lydell/node-pty";
|
|
21
21
|
import { createInterface } from "node:readline";
|
|
22
22
|
import { Codex } from "@openai/codex-sdk";
|
|
@@ -500,9 +500,10 @@ function formatDebugValue(value) {
|
|
|
500
500
|
//#endregion
|
|
501
501
|
//#region src/preferences-store.ts
|
|
502
502
|
const defaultRuntimePreferences = { runtimeMode: "default" };
|
|
503
|
+
const PersistedRuntimePreferencesSchema = RuntimePreferencesSchema;
|
|
503
504
|
const RuntimePreferencesFileSchema = z.object({
|
|
504
|
-
preferences:
|
|
505
|
-
runtimePreferencesByWorkspacePath:
|
|
505
|
+
preferences: PersistedRuntimePreferencesSchema.default(defaultRuntimePreferences),
|
|
506
|
+
runtimePreferencesByWorkspacePath: z.record(z.string().trim().min(1), PersistedRuntimePreferencesSchema).default({})
|
|
506
507
|
});
|
|
507
508
|
function createMemoryRuntimePreferencesStore(initial = defaultRuntimePreferences) {
|
|
508
509
|
let current = {
|
|
@@ -523,6 +524,7 @@ function createMemoryRuntimePreferencesStore(initial = defaultRuntimePreferences
|
|
|
523
524
|
};
|
|
524
525
|
}
|
|
525
526
|
function createFileRuntimePreferencesStore(path) {
|
|
527
|
+
let updateQueue = Promise.resolve();
|
|
526
528
|
async function readPreferences() {
|
|
527
529
|
try {
|
|
528
530
|
return parseRuntimePreferencesFile(JSON.parse(await readFile(path, "utf8")));
|
|
@@ -532,17 +534,23 @@ function createFileRuntimePreferencesStore(path) {
|
|
|
532
534
|
}
|
|
533
535
|
return {
|
|
534
536
|
async read(workspacePath) {
|
|
537
|
+
await updateQueue;
|
|
535
538
|
const current = await readPreferences();
|
|
536
539
|
return workspacePath ? current.runtimePreferencesByWorkspacePath[workspacePath] ?? current.preferences : current.preferences;
|
|
537
540
|
},
|
|
538
541
|
async readByWorkspacePath() {
|
|
542
|
+
await updateQueue;
|
|
539
543
|
return (await readPreferences()).runtimePreferencesByWorkspacePath;
|
|
540
544
|
},
|
|
541
|
-
|
|
542
|
-
const
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
545
|
+
update(preferences, workspacePath) {
|
|
546
|
+
const operation = updateQueue.then(async () => {
|
|
547
|
+
const next = updatePreferencesFile(await readPreferences(), preferences, workspacePath);
|
|
548
|
+
await mkdir(dirname(path), { recursive: true });
|
|
549
|
+
await writeFile(path, `${JSON.stringify(next, null, 2)}\n`, { mode: 384 });
|
|
550
|
+
return workspacePath ? next.runtimePreferencesByWorkspacePath[workspacePath] ?? next.preferences : next.preferences;
|
|
551
|
+
});
|
|
552
|
+
updateQueue = operation.then(() => void 0, () => void 0);
|
|
553
|
+
return operation;
|
|
546
554
|
}
|
|
547
555
|
};
|
|
548
556
|
}
|
|
@@ -551,7 +559,7 @@ function parseRuntimePreferencesFile(payload) {
|
|
|
551
559
|
const record = payload;
|
|
552
560
|
if ("preferences" in record || "runtimePreferencesByWorkspacePath" in record) return RuntimePreferencesFileSchema.parse(payload);
|
|
553
561
|
}
|
|
554
|
-
const legacyPreferences =
|
|
562
|
+
const legacyPreferences = PersistedRuntimePreferencesSchema.safeParse(payload);
|
|
555
563
|
if (legacyPreferences.success) return RuntimePreferencesFileSchema.parse({
|
|
556
564
|
preferences: legacyPreferences.data,
|
|
557
565
|
runtimePreferencesByWorkspacePath: {}
|
|
@@ -724,12 +732,21 @@ async function listAvailableSkills(options) {
|
|
|
724
732
|
}
|
|
725
733
|
];
|
|
726
734
|
const skillPaths = dedupe((await Promise.all(roots.map((root) => findSkillFiles(root)))).flat(), (entry) => entry.path);
|
|
727
|
-
return (await Promise.all(skillPaths.map(readSkill))).filter((skill) => Boolean(skill)).sort(compareSkills);
|
|
735
|
+
return dedupe((await Promise.all(skillPaths.map(readSkill))).filter((skill) => Boolean(skill)).sort(compareSkills), skillIdentityKey);
|
|
728
736
|
}
|
|
729
737
|
async function findSkillFiles(root) {
|
|
730
738
|
const found = [];
|
|
739
|
+
const visitedDirectories = /* @__PURE__ */ new Set();
|
|
731
740
|
async function walk(path, depth) {
|
|
732
741
|
if (depth < 0) return;
|
|
742
|
+
let realDirectoryPath;
|
|
743
|
+
try {
|
|
744
|
+
realDirectoryPath = await realpath(path);
|
|
745
|
+
} catch {
|
|
746
|
+
return;
|
|
747
|
+
}
|
|
748
|
+
if (visitedDirectories.has(realDirectoryPath)) return;
|
|
749
|
+
visitedDirectories.add(realDirectoryPath);
|
|
733
750
|
let entries;
|
|
734
751
|
try {
|
|
735
752
|
entries = await readdir(path, { withFileTypes: true });
|
|
@@ -738,20 +755,34 @@ async function findSkillFiles(root) {
|
|
|
738
755
|
}
|
|
739
756
|
for (const entry of entries) {
|
|
740
757
|
const entryPath = join(path, entry.name);
|
|
741
|
-
|
|
758
|
+
const kind = await directoryEntryKind(entry, entryPath);
|
|
759
|
+
if (kind === "file" && entry.name === "SKILL.md") {
|
|
742
760
|
found.push({
|
|
743
761
|
...root,
|
|
744
762
|
path: entryPath
|
|
745
763
|
});
|
|
746
764
|
continue;
|
|
747
765
|
}
|
|
748
|
-
if (
|
|
766
|
+
if (kind !== "directory" || entry.name === "node_modules") continue;
|
|
749
767
|
await walk(entryPath, depth - 1);
|
|
750
768
|
}
|
|
751
769
|
}
|
|
752
770
|
await walk(root.path, root.maxDepth);
|
|
753
771
|
return found;
|
|
754
772
|
}
|
|
773
|
+
async function directoryEntryKind(entry, entryPath) {
|
|
774
|
+
if (entry.isFile()) return "file";
|
|
775
|
+
if (entry.isDirectory()) return "directory";
|
|
776
|
+
if (!entry.isSymbolicLink()) return null;
|
|
777
|
+
try {
|
|
778
|
+
const target = await stat(entryPath);
|
|
779
|
+
if (target.isFile()) return "file";
|
|
780
|
+
if (target.isDirectory()) return "directory";
|
|
781
|
+
} catch {
|
|
782
|
+
return null;
|
|
783
|
+
}
|
|
784
|
+
return null;
|
|
785
|
+
}
|
|
755
786
|
async function readSkill(entry) {
|
|
756
787
|
let markdown;
|
|
757
788
|
try {
|
|
@@ -777,7 +808,7 @@ async function readSkill(entry) {
|
|
|
777
808
|
}
|
|
778
809
|
function parseSkillMarkdown(markdown) {
|
|
779
810
|
const frontmatter = parseFrontmatter(markdown);
|
|
780
|
-
const heading =
|
|
811
|
+
const heading = firstMarkdownHeading(markdownBody(markdown));
|
|
781
812
|
return {
|
|
782
813
|
description: frontmatter.description,
|
|
783
814
|
displayName: heading ? cleanHeading(heading) : void 0,
|
|
@@ -789,13 +820,59 @@ function parseFrontmatter(markdown) {
|
|
|
789
820
|
const end = markdown.indexOf("\n---", 4);
|
|
790
821
|
if (end < 0) return {};
|
|
791
822
|
const fields = {};
|
|
792
|
-
|
|
793
|
-
|
|
823
|
+
const lines = markdown.slice(4, end).split("\n");
|
|
824
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
825
|
+
const match = lines[index].match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
|
794
826
|
if (!match) continue;
|
|
795
|
-
|
|
827
|
+
const key = match[1];
|
|
828
|
+
const value = match[2].trim();
|
|
829
|
+
if (isBlockScalar(value)) {
|
|
830
|
+
const blockLines = [];
|
|
831
|
+
while (index + 1 < lines.length && (lines[index + 1].trim() === "" || /^\s/.test(lines[index + 1]))) {
|
|
832
|
+
index += 1;
|
|
833
|
+
blockLines.push(lines[index].replace(/^\s+/, ""));
|
|
834
|
+
}
|
|
835
|
+
fields[key] = formatBlockScalar(value, blockLines);
|
|
836
|
+
continue;
|
|
837
|
+
}
|
|
838
|
+
fields[key] = unquoteYamlScalar(value);
|
|
796
839
|
}
|
|
797
840
|
return fields;
|
|
798
841
|
}
|
|
842
|
+
function isBlockScalar(value) {
|
|
843
|
+
return [
|
|
844
|
+
"|",
|
|
845
|
+
"|-",
|
|
846
|
+
"|+",
|
|
847
|
+
">",
|
|
848
|
+
">-",
|
|
849
|
+
">+"
|
|
850
|
+
].includes(value);
|
|
851
|
+
}
|
|
852
|
+
function formatBlockScalar(marker, lines) {
|
|
853
|
+
const trimmedLines = lines.map((line) => line.trimEnd());
|
|
854
|
+
if (marker.startsWith("|")) return trimmedLines.join("\n").trim();
|
|
855
|
+
return trimmedLines.map((line) => line.trim()).filter(Boolean).join(" ");
|
|
856
|
+
}
|
|
857
|
+
function markdownBody(markdown) {
|
|
858
|
+
if (!markdown.startsWith("---\n")) return markdown;
|
|
859
|
+
const end = markdown.indexOf("\n---", 4);
|
|
860
|
+
if (end < 0) return markdown;
|
|
861
|
+
return markdown.slice(end + 4).replace(/^\r?\n/, "");
|
|
862
|
+
}
|
|
863
|
+
function firstMarkdownHeading(markdown) {
|
|
864
|
+
let fence;
|
|
865
|
+
for (const line of markdown.split("\n")) {
|
|
866
|
+
const fenceMatch = line.match(/^\s*(```|~~~)/);
|
|
867
|
+
if (fenceMatch) {
|
|
868
|
+
fence = fence ? void 0 : fenceMatch[1];
|
|
869
|
+
continue;
|
|
870
|
+
}
|
|
871
|
+
if (fence) continue;
|
|
872
|
+
const heading = line.match(/^#\s+(.+)$/)?.[1]?.trim();
|
|
873
|
+
if (heading) return heading;
|
|
874
|
+
}
|
|
875
|
+
}
|
|
799
876
|
function unquoteYamlScalar(value) {
|
|
800
877
|
if (value.startsWith("\"") && value.endsWith("\"") || value.startsWith("'") && value.endsWith("'")) return value.slice(1, -1);
|
|
801
878
|
return value;
|
|
@@ -818,6 +895,9 @@ function compareSkills(a, b) {
|
|
|
818
895
|
};
|
|
819
896
|
return sourceOrder[a.source] - sourceOrder[b.source] || a.displayName.localeCompare(b.displayName, void 0, { sensitivity: "base" });
|
|
820
897
|
}
|
|
898
|
+
function skillIdentityKey(skill) {
|
|
899
|
+
return [skill.source, skill.name].join("\n");
|
|
900
|
+
}
|
|
821
901
|
function dedupe(items, keyFor) {
|
|
822
902
|
const seen = /* @__PURE__ */ new Set();
|
|
823
903
|
return items.filter((item) => {
|
|
@@ -2602,7 +2682,9 @@ function queuedThreadInputSummary(input) {
|
|
|
2602
2682
|
async function streamRunningAppServerThread(input) {
|
|
2603
2683
|
let activeTurnId;
|
|
2604
2684
|
let assistantMessageId;
|
|
2685
|
+
let observedInputRequest = false;
|
|
2605
2686
|
let observedTurnActivity = false;
|
|
2687
|
+
let producedTurnOutput = false;
|
|
2606
2688
|
let threadSummary = input.threads.get(input.threadId);
|
|
2607
2689
|
const cleanupRequestHandler = input.appServer.onRequest((request) => {
|
|
2608
2690
|
if (!isApprovalServerRequest(request.method)) {
|
|
@@ -2614,6 +2696,7 @@ async function streamRunningAppServerThread(input) {
|
|
|
2614
2696
|
input.appServer.rejectRequest(request.id, -32602, "Approval request is malformed.");
|
|
2615
2697
|
return;
|
|
2616
2698
|
}
|
|
2699
|
+
observedInputRequest = true;
|
|
2617
2700
|
if (approval.kind === "structuredUserInput") {
|
|
2618
2701
|
const pending = {
|
|
2619
2702
|
appServer: input.appServer,
|
|
@@ -2702,6 +2785,7 @@ async function streamRunningAppServerThread(input) {
|
|
|
2702
2785
|
if (!item || typeof item !== "object") return;
|
|
2703
2786
|
const message = upsertAppServerItemMessage(input.messagesByThreadId, input.threadId, firstString(params, ["turnId"]) ?? activeTurnId, item);
|
|
2704
2787
|
if (!message) return;
|
|
2788
|
+
if (message.role !== "user") producedTurnOutput = true;
|
|
2705
2789
|
if (message.role === "assistant") assistantMessageId = message.id;
|
|
2706
2790
|
threadSummary = updateThread(input.threads, input.messagesByThreadId, input.threadId, {
|
|
2707
2791
|
state: "running",
|
|
@@ -2726,6 +2810,7 @@ async function streamRunningAppServerThread(input) {
|
|
|
2726
2810
|
turnId: firstString(params, ["turnId"]) ?? activeTurnId
|
|
2727
2811
|
});
|
|
2728
2812
|
assistantMessageId = itemId;
|
|
2813
|
+
producedTurnOutput = true;
|
|
2729
2814
|
const patch = appendMessageDelta(input.messagesByThreadId, input.threadId, itemId, delta);
|
|
2730
2815
|
const message = patch.message;
|
|
2731
2816
|
updateThread(input.threads, input.messagesByThreadId, input.threadId, {
|
|
@@ -2742,6 +2827,7 @@ async function streamRunningAppServerThread(input) {
|
|
|
2742
2827
|
}
|
|
2743
2828
|
case "turn/plan/updated": {
|
|
2744
2829
|
observedTurnActivity = true;
|
|
2830
|
+
producedTurnOutput = true;
|
|
2745
2831
|
const content = planContentFromRecord(params);
|
|
2746
2832
|
const message = appendMessage(input.messagesByThreadId, input.threadId, {
|
|
2747
2833
|
role: "status",
|
|
@@ -2771,6 +2857,20 @@ async function streamRunningAppServerThread(input) {
|
|
|
2771
2857
|
threadId: input.threadId,
|
|
2772
2858
|
turnId: firstString(params, ["turnId"]) ?? activeTurnId
|
|
2773
2859
|
});
|
|
2860
|
+
if (state === "completed" && !producedTurnOutput && !observedInputRequest) {
|
|
2861
|
+
sendEmptyAppServerTurnError({
|
|
2862
|
+
activeTurnId,
|
|
2863
|
+
controller: input.controller,
|
|
2864
|
+
encoder: input.encoder,
|
|
2865
|
+
messagesByThreadId: input.messagesByThreadId,
|
|
2866
|
+
secureSession: input.secureSession,
|
|
2867
|
+
threadId: input.threadId,
|
|
2868
|
+
threads: input.threads
|
|
2869
|
+
});
|
|
2870
|
+
cleanupNotificationHandler();
|
|
2871
|
+
resolve();
|
|
2872
|
+
return;
|
|
2873
|
+
}
|
|
2774
2874
|
if (assistantMessageId) {
|
|
2775
2875
|
const completedMessage = updateMessage(input.messagesByThreadId, input.threadId, assistantMessageId, { state: "completed" });
|
|
2776
2876
|
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
@@ -2787,11 +2887,25 @@ async function streamRunningAppServerThread(input) {
|
|
|
2787
2887
|
type: "thread.state.changed",
|
|
2788
2888
|
thread: threadSummary
|
|
2789
2889
|
});
|
|
2790
|
-
if (state === "failed")
|
|
2791
|
-
|
|
2792
|
-
|
|
2793
|
-
|
|
2794
|
-
|
|
2890
|
+
if (state === "failed") {
|
|
2891
|
+
const errorBody = apiError("codex_run_failed", threadSummary.lastError ?? "Codex turn did not complete.");
|
|
2892
|
+
const message = appendMessage(input.messagesByThreadId, input.threadId, {
|
|
2893
|
+
role: "error",
|
|
2894
|
+
content: errorBody.error.message,
|
|
2895
|
+
state: "failed",
|
|
2896
|
+
turnId: activeTurnId
|
|
2897
|
+
});
|
|
2898
|
+
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
2899
|
+
type: "thread.message.created",
|
|
2900
|
+
thread: threadSummary,
|
|
2901
|
+
message
|
|
2902
|
+
});
|
|
2903
|
+
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
2904
|
+
type: "thread.error",
|
|
2905
|
+
thread: threadSummary,
|
|
2906
|
+
error: errorBody.error
|
|
2907
|
+
});
|
|
2908
|
+
}
|
|
2795
2909
|
cleanupNotificationHandler();
|
|
2796
2910
|
resolve();
|
|
2797
2911
|
return;
|
|
@@ -2836,6 +2950,7 @@ async function runAppServerPromptStreamed(input) {
|
|
|
2836
2950
|
const displayPrompt = promptMarkdownWithSkills(promptWithAttachmentReferences(input.prompt, input.attachments), input.skills);
|
|
2837
2951
|
const prompt = input.prompt;
|
|
2838
2952
|
let handedOffToQueuedTurn = false;
|
|
2953
|
+
let observedInputRequest = false;
|
|
2839
2954
|
let producedTurnOutput = false;
|
|
2840
2955
|
let userMessage = appendMessage(input.messagesByThreadId, activeThreadId, {
|
|
2841
2956
|
role: "user",
|
|
@@ -2869,6 +2984,7 @@ async function runAppServerPromptStreamed(input) {
|
|
|
2869
2984
|
input.appServer.rejectRequest(request.id, -32602, "Approval request is malformed.");
|
|
2870
2985
|
return;
|
|
2871
2986
|
}
|
|
2987
|
+
observedInputRequest = true;
|
|
2872
2988
|
if (approval.kind === "structuredUserInput") {
|
|
2873
2989
|
const pending = {
|
|
2874
2990
|
appServer: input.appServer,
|
|
@@ -2912,7 +3028,141 @@ async function runAppServerPromptStreamed(input) {
|
|
|
2912
3028
|
});
|
|
2913
3029
|
});
|
|
2914
3030
|
let cleanupNotificationHandler = () => void 0;
|
|
3031
|
+
let resolveCompleted = () => void 0;
|
|
3032
|
+
let rejectCompleted = (_error) => void 0;
|
|
3033
|
+
const finalizedTurnIds = /* @__PURE__ */ new Set();
|
|
3034
|
+
function resetTurnTracking() {
|
|
3035
|
+
activeTurnId = void 0;
|
|
3036
|
+
assistantMessageId = void 0;
|
|
3037
|
+
observedInputRequest = false;
|
|
3038
|
+
producedTurnOutput = false;
|
|
3039
|
+
}
|
|
3040
|
+
function finishTerminalTurn(options) {
|
|
3041
|
+
const terminalTurnId = options.turnId ?? activeTurnId;
|
|
3042
|
+
if (terminalTurnId && finalizedTurnIds.has(terminalTurnId)) return;
|
|
3043
|
+
if (terminalTurnId) {
|
|
3044
|
+
finalizedTurnIds.add(terminalTurnId);
|
|
3045
|
+
activeTurnId = terminalTurnId;
|
|
3046
|
+
}
|
|
3047
|
+
relayDebugLog("app_server.turn.terminal", {
|
|
3048
|
+
method: options.method,
|
|
3049
|
+
state: options.state,
|
|
3050
|
+
threadId: activeThreadId,
|
|
3051
|
+
turnId: terminalTurnId
|
|
3052
|
+
});
|
|
3053
|
+
input.activeAppServerTurnIdsByThreadId.delete(activeThreadId);
|
|
3054
|
+
const hasQueuedInput = (input.queuedInputsByThreadId.get(activeThreadId)?.length ?? 0) > 0;
|
|
3055
|
+
if (options.state === "completed" && !producedTurnOutput && !observedInputRequest && !hasQueuedInput) {
|
|
3056
|
+
sendEmptyAppServerTurnError({
|
|
3057
|
+
activeTurnId: terminalTurnId,
|
|
3058
|
+
controller: input.controller,
|
|
3059
|
+
encoder: input.encoder,
|
|
3060
|
+
messagesByThreadId: input.messagesByThreadId,
|
|
3061
|
+
secureSession: input.secureSession,
|
|
3062
|
+
threadId: activeThreadId,
|
|
3063
|
+
threads: input.threads
|
|
3064
|
+
});
|
|
3065
|
+
input.steeringThreads.delete(activeThreadId);
|
|
3066
|
+
cleanupNotificationHandler();
|
|
3067
|
+
resolveCompleted();
|
|
3068
|
+
return;
|
|
3069
|
+
}
|
|
3070
|
+
if (assistantMessageId) {
|
|
3071
|
+
const completedMessage = updateMessage(input.messagesByThreadId, activeThreadId, assistantMessageId, { state: "completed" });
|
|
3072
|
+
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3073
|
+
type: "thread.message.completed",
|
|
3074
|
+
thread: threadSummary,
|
|
3075
|
+
message: completedMessage
|
|
3076
|
+
});
|
|
3077
|
+
}
|
|
3078
|
+
const nextQueuedInput = options.state === "completed" ? shiftQueuedInput(input.queuedInputsByThreadId, activeThreadId) : void 0;
|
|
3079
|
+
threadSummary = updateThread(input.threads, input.messagesByThreadId, activeThreadId, {
|
|
3080
|
+
state: nextQueuedInput ? "running" : options.state,
|
|
3081
|
+
lastError: nextQueuedInput ? void 0 : options.lastError,
|
|
3082
|
+
...nextQueuedInput ? {
|
|
3083
|
+
lastPrompt: promptWithAttachmentReferences(nextQueuedInput.prompt, nextQueuedInput.attachments),
|
|
3084
|
+
...runtimeMetadataFromOptions(nextQueuedInput.runOptions)
|
|
3085
|
+
} : {}
|
|
3086
|
+
});
|
|
3087
|
+
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3088
|
+
type: "thread.state.changed",
|
|
3089
|
+
thread: threadSummary
|
|
3090
|
+
});
|
|
3091
|
+
if (options.state === "failed") {
|
|
3092
|
+
const errorBody = apiError("codex_run_failed", options.lastError ?? "Codex turn did not complete.");
|
|
3093
|
+
const message = appendMessage(input.messagesByThreadId, activeThreadId, {
|
|
3094
|
+
role: "error",
|
|
3095
|
+
content: errorBody.error.message,
|
|
3096
|
+
state: "failed",
|
|
3097
|
+
turnId: terminalTurnId
|
|
3098
|
+
});
|
|
3099
|
+
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3100
|
+
type: "thread.message.created",
|
|
3101
|
+
thread: threadSummary,
|
|
3102
|
+
message
|
|
3103
|
+
});
|
|
3104
|
+
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3105
|
+
type: "thread.error",
|
|
3106
|
+
thread: threadSummary,
|
|
3107
|
+
error: errorBody.error
|
|
3108
|
+
});
|
|
3109
|
+
input.steeringThreads.delete(activeThreadId);
|
|
3110
|
+
cleanupNotificationHandler();
|
|
3111
|
+
resolveCompleted();
|
|
3112
|
+
return;
|
|
3113
|
+
}
|
|
3114
|
+
if (nextQueuedInput) {
|
|
3115
|
+
handedOffToQueuedTurn = true;
|
|
3116
|
+
resetTurnTracking();
|
|
3117
|
+
input.steeringThreads.add(activeThreadId);
|
|
3118
|
+
startAppServerTurn(input.appServer, activeThreadId, nextQueuedInput).then(processReturnedTurn).catch((error) => {
|
|
3119
|
+
cleanupNotificationHandler();
|
|
3120
|
+
rejectCompleted(error);
|
|
3121
|
+
});
|
|
3122
|
+
return;
|
|
3123
|
+
}
|
|
3124
|
+
input.steeringThreads.delete(activeThreadId);
|
|
3125
|
+
cleanupNotificationHandler();
|
|
3126
|
+
resolveCompleted();
|
|
3127
|
+
}
|
|
3128
|
+
function processReturnedTurn(turn) {
|
|
3129
|
+
if (finalizedTurnIds.has(turn.id)) return;
|
|
3130
|
+
activeTurnId = turn.id;
|
|
3131
|
+
input.activeAppServerTurnIdsByThreadId.set(activeThreadId, turn.id);
|
|
3132
|
+
const turnIsRunning = isAppServerTurnRunning(turn);
|
|
3133
|
+
for (const item of turn.items) {
|
|
3134
|
+
const canonicalUserMessage = replaceDuplicateInitialUserMessage(input.messagesByThreadId, activeThreadId, turn.id, item, userMessage.id, displayPrompt);
|
|
3135
|
+
if (canonicalUserMessage) {
|
|
3136
|
+
userMessage = canonicalUserMessage;
|
|
3137
|
+
continue;
|
|
3138
|
+
}
|
|
3139
|
+
const message = upsertAppServerItemMessage(input.messagesByThreadId, activeThreadId, turn.id, item);
|
|
3140
|
+
if (!message) continue;
|
|
3141
|
+
if (message.role !== "user") producedTurnOutput = true;
|
|
3142
|
+
if (message.role === "assistant" && turnIsRunning) assistantMessageId = message.id;
|
|
3143
|
+
threadSummary = updateThread(input.threads, input.messagesByThreadId, activeThreadId, {
|
|
3144
|
+
state: "running",
|
|
3145
|
+
lastResult: message.role === "assistant" ? message.content : void 0
|
|
3146
|
+
});
|
|
3147
|
+
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3148
|
+
type: message.role === "assistant" ? "thread.message.completed" : "thread.message.created",
|
|
3149
|
+
thread: threadSummary,
|
|
3150
|
+
message
|
|
3151
|
+
});
|
|
3152
|
+
}
|
|
3153
|
+
if (turnIsRunning) return;
|
|
3154
|
+
const params = { turn };
|
|
3155
|
+
const state = terminalTurnState("turn/completed", params);
|
|
3156
|
+
finishTerminalTurn({
|
|
3157
|
+
lastError: state === "failed" ? turnErrorMessage(params) : void 0,
|
|
3158
|
+
method: "turn/returned",
|
|
3159
|
+
state,
|
|
3160
|
+
turnId: turn.id
|
|
3161
|
+
});
|
|
3162
|
+
}
|
|
2915
3163
|
const completed = new Promise((resolve, reject) => {
|
|
3164
|
+
resolveCompleted = resolve;
|
|
3165
|
+
rejectCompleted = reject;
|
|
2916
3166
|
cleanupNotificationHandler = input.appServer.onNotification((notification) => {
|
|
2917
3167
|
const params = recordParams(notification);
|
|
2918
3168
|
const threadId = firstString(params, ["threadId"]);
|
|
@@ -2957,7 +3207,7 @@ async function runAppServerPromptStreamed(input) {
|
|
|
2957
3207
|
const turnId = firstString(params, ["turnId"]) ?? activeTurnId;
|
|
2958
3208
|
const message = upsertAppServerItemMessage(input.messagesByThreadId, activeThreadId, turnId, item);
|
|
2959
3209
|
if (!message) return;
|
|
2960
|
-
producedTurnOutput = true;
|
|
3210
|
+
if (message.role !== "user") producedTurnOutput = true;
|
|
2961
3211
|
if (message.role === "assistant") assistantMessageId = message.id;
|
|
2962
3212
|
threadSummary = updateThread(input.threads, input.messagesByThreadId, activeThreadId, {
|
|
2963
3213
|
state: "running",
|
|
@@ -3020,69 +3270,13 @@ async function runAppServerPromptStreamed(input) {
|
|
|
3020
3270
|
case "turn/completed":
|
|
3021
3271
|
case "turn/failed": {
|
|
3022
3272
|
const state = terminalTurnState(notification.method, params);
|
|
3023
|
-
|
|
3273
|
+
const terminalTurnId = firstString(params, ["turnId"]) ?? turnIdFromParams(params) ?? activeTurnId;
|
|
3274
|
+
finishTerminalTurn({
|
|
3275
|
+
lastError: state === "failed" ? turnErrorMessage(params) : void 0,
|
|
3024
3276
|
method: notification.method,
|
|
3025
3277
|
state,
|
|
3026
|
-
|
|
3027
|
-
turnId: firstString(params, ["turnId"]) ?? activeTurnId
|
|
3028
|
-
});
|
|
3029
|
-
input.activeAppServerTurnIdsByThreadId.delete(activeThreadId);
|
|
3030
|
-
if (assistantMessageId) {
|
|
3031
|
-
const completedMessage = updateMessage(input.messagesByThreadId, activeThreadId, assistantMessageId, { state: "completed" });
|
|
3032
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3033
|
-
type: "thread.message.completed",
|
|
3034
|
-
thread: threadSummary,
|
|
3035
|
-
message: completedMessage
|
|
3036
|
-
});
|
|
3037
|
-
}
|
|
3038
|
-
const lastError = state === "failed" ? turnErrorMessage(params) : void 0;
|
|
3039
|
-
const nextQueuedInput = state === "completed" ? shiftQueuedInput(input.queuedInputsByThreadId, activeThreadId) : void 0;
|
|
3040
|
-
threadSummary = updateThread(input.threads, input.messagesByThreadId, activeThreadId, {
|
|
3041
|
-
state: nextQueuedInput ? "running" : state,
|
|
3042
|
-
lastError: nextQueuedInput ? void 0 : lastError,
|
|
3043
|
-
...nextQueuedInput ? {
|
|
3044
|
-
lastPrompt: promptWithAttachmentReferences(nextQueuedInput.prompt, nextQueuedInput.attachments),
|
|
3045
|
-
...runtimeMetadataFromOptions(nextQueuedInput.runOptions)
|
|
3046
|
-
} : {}
|
|
3047
|
-
});
|
|
3048
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3049
|
-
type: "thread.state.changed",
|
|
3050
|
-
thread: threadSummary
|
|
3278
|
+
turnId: terminalTurnId
|
|
3051
3279
|
});
|
|
3052
|
-
if (state === "failed") {
|
|
3053
|
-
const errorBody = apiError("codex_run_failed", lastError ?? "Codex turn did not complete.");
|
|
3054
|
-
appendMessage(input.messagesByThreadId, activeThreadId, {
|
|
3055
|
-
role: "error",
|
|
3056
|
-
content: errorBody.error.message,
|
|
3057
|
-
state: "failed",
|
|
3058
|
-
turnId: activeTurnId
|
|
3059
|
-
});
|
|
3060
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3061
|
-
type: "thread.error",
|
|
3062
|
-
thread: threadSummary,
|
|
3063
|
-
error: errorBody.error
|
|
3064
|
-
});
|
|
3065
|
-
input.steeringThreads.delete(activeThreadId);
|
|
3066
|
-
cleanupNotificationHandler();
|
|
3067
|
-
resolve();
|
|
3068
|
-
return;
|
|
3069
|
-
}
|
|
3070
|
-
if (nextQueuedInput) {
|
|
3071
|
-
handedOffToQueuedTurn = true;
|
|
3072
|
-
assistantMessageId = void 0;
|
|
3073
|
-
input.steeringThreads.add(activeThreadId);
|
|
3074
|
-
startAppServerTurn(input.appServer, activeThreadId, nextQueuedInput).then((turn) => {
|
|
3075
|
-
activeTurnId = turn.id;
|
|
3076
|
-
input.activeAppServerTurnIdsByThreadId.set(activeThreadId, activeTurnId);
|
|
3077
|
-
}).catch((error) => {
|
|
3078
|
-
cleanupNotificationHandler();
|
|
3079
|
-
reject(error);
|
|
3080
|
-
});
|
|
3081
|
-
return;
|
|
3082
|
-
}
|
|
3083
|
-
input.steeringThreads.delete(activeThreadId);
|
|
3084
|
-
cleanupNotificationHandler();
|
|
3085
|
-
resolve();
|
|
3086
3280
|
return;
|
|
3087
3281
|
}
|
|
3088
3282
|
}
|
|
@@ -3182,56 +3376,8 @@ async function runAppServerPromptStreamed(input) {
|
|
|
3182
3376
|
workspacePath: input.workspacePath
|
|
3183
3377
|
});
|
|
3184
3378
|
}
|
|
3185
|
-
|
|
3186
|
-
|
|
3187
|
-
debugStream("start turn complete", activeThreadId, activeTurnId);
|
|
3188
|
-
let streamedReturnedItem = false;
|
|
3189
|
-
for (const item of turn.items) {
|
|
3190
|
-
const canonicalUserMessage = replaceDuplicateInitialUserMessage(input.messagesByThreadId, activeThreadId, activeTurnId, item, userMessage.id, displayPrompt);
|
|
3191
|
-
if (canonicalUserMessage) {
|
|
3192
|
-
userMessage = canonicalUserMessage;
|
|
3193
|
-
continue;
|
|
3194
|
-
}
|
|
3195
|
-
const message = upsertAppServerItemMessage(input.messagesByThreadId, activeThreadId, activeTurnId, item);
|
|
3196
|
-
if (!message) continue;
|
|
3197
|
-
streamedReturnedItem = true;
|
|
3198
|
-
producedTurnOutput = true;
|
|
3199
|
-
if (message.role === "assistant") assistantMessageId = message.id;
|
|
3200
|
-
threadSummary = updateThread(input.threads, input.messagesByThreadId, activeThreadId, {
|
|
3201
|
-
state: "running",
|
|
3202
|
-
lastResult: message.role === "assistant" ? message.content : void 0
|
|
3203
|
-
});
|
|
3204
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3205
|
-
type: message.role === "assistant" ? "thread.message.completed" : "thread.message.created",
|
|
3206
|
-
thread: threadSummary,
|
|
3207
|
-
message
|
|
3208
|
-
});
|
|
3209
|
-
}
|
|
3210
|
-
const returnedState = mapAppServerThreadState(turn.status);
|
|
3211
|
-
if (returnedState !== "running") {
|
|
3212
|
-
if (!streamedReturnedItem && !producedTurnOutput) {
|
|
3213
|
-
sendEmptyAppServerTurnError({
|
|
3214
|
-
activeTurnId,
|
|
3215
|
-
controller: input.controller,
|
|
3216
|
-
encoder: input.encoder,
|
|
3217
|
-
messagesByThreadId: input.messagesByThreadId,
|
|
3218
|
-
secureSession: input.secureSession,
|
|
3219
|
-
threadId: activeThreadId,
|
|
3220
|
-
threads: input.threads
|
|
3221
|
-
});
|
|
3222
|
-
input.steeringThreads.delete(activeThreadId);
|
|
3223
|
-
cleanupNotificationHandler();
|
|
3224
|
-
return;
|
|
3225
|
-
}
|
|
3226
|
-
threadSummary = updateThread(input.threads, input.messagesByThreadId, activeThreadId, { state: returnedState });
|
|
3227
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3228
|
-
type: "thread.state.changed",
|
|
3229
|
-
thread: threadSummary
|
|
3230
|
-
});
|
|
3231
|
-
input.steeringThreads.delete(activeThreadId);
|
|
3232
|
-
cleanupNotificationHandler();
|
|
3233
|
-
return;
|
|
3234
|
-
}
|
|
3379
|
+
debugStream("start turn complete", activeThreadId, turn.id);
|
|
3380
|
+
processReturnedTurn(turn);
|
|
3235
3381
|
await completed;
|
|
3236
3382
|
} catch (error) {
|
|
3237
3383
|
debugStream(`failed ${errorMessage(error)}`, activeThreadId, activeTurnId);
|
|
@@ -4085,11 +4231,12 @@ function appServerCollaborationMode(options) {
|
|
|
4085
4231
|
}
|
|
4086
4232
|
function buildThreadOptions(base, options) {
|
|
4087
4233
|
const runtime = resolveRuntimeOptions(options.runtimeMode);
|
|
4234
|
+
const reasoningEffort = KnownReasoningEffortSchema.safeParse(options.reasoningEffort);
|
|
4088
4235
|
return {
|
|
4089
4236
|
...base,
|
|
4090
4237
|
...runtime,
|
|
4091
4238
|
...options.model ? { model: options.model } : {},
|
|
4092
|
-
...
|
|
4239
|
+
...reasoningEffort.success ? { modelReasoningEffort: reasoningEffort.data } : {},
|
|
4093
4240
|
...options.approvalPolicy ? { approvalPolicy: options.approvalPolicy } : {},
|
|
4094
4241
|
...options.sandboxMode ? { sandboxMode: options.sandboxMode } : {}
|
|
4095
4242
|
};
|
|
@@ -4809,6 +4956,41 @@ function mapAppServerItem(threadId, turn, item) {
|
|
|
4809
4956
|
}
|
|
4810
4957
|
});
|
|
4811
4958
|
}
|
|
4959
|
+
case "collabAgentToolCall": {
|
|
4960
|
+
const collabItem = item;
|
|
4961
|
+
return ChatMessageSchema.parse({
|
|
4962
|
+
...base,
|
|
4963
|
+
role: "tool",
|
|
4964
|
+
kind: "subagentAction",
|
|
4965
|
+
content: appServerCollabAgentToolCallContent(collabItem),
|
|
4966
|
+
details: {
|
|
4967
|
+
type: collabItem.type,
|
|
4968
|
+
tool: collabItem.tool,
|
|
4969
|
+
status: collabItem.status,
|
|
4970
|
+
senderThreadId: collabItem.senderThreadId,
|
|
4971
|
+
receiverThreadIds: collabItem.receiverThreadIds,
|
|
4972
|
+
prompt: collabItem.prompt ?? void 0,
|
|
4973
|
+
model: collabItem.model ?? void 0,
|
|
4974
|
+
reasoningEffort: collabItem.reasoningEffort ?? void 0,
|
|
4975
|
+
agentsStates: collabItem.agentsStates
|
|
4976
|
+
}
|
|
4977
|
+
});
|
|
4978
|
+
}
|
|
4979
|
+
case "subAgentActivity": {
|
|
4980
|
+
const activityItem = item;
|
|
4981
|
+
return ChatMessageSchema.parse({
|
|
4982
|
+
...base,
|
|
4983
|
+
role: "status",
|
|
4984
|
+
kind: "subagentAction",
|
|
4985
|
+
content: `${activityItem.agentPath || activityItem.agentThreadId} ${activityItem.kind}`,
|
|
4986
|
+
details: {
|
|
4987
|
+
type: activityItem.type,
|
|
4988
|
+
activityKind: activityItem.kind,
|
|
4989
|
+
agentThreadId: activityItem.agentThreadId,
|
|
4990
|
+
agentPath: activityItem.agentPath
|
|
4991
|
+
}
|
|
4992
|
+
});
|
|
4993
|
+
}
|
|
4812
4994
|
case "webSearch": {
|
|
4813
4995
|
const searchItem = item;
|
|
4814
4996
|
return ChatMessageSchema.parse({
|
|
@@ -4825,6 +5007,17 @@ function mapAppServerItem(threadId, turn, item) {
|
|
|
4825
5007
|
default: return mapUnknownAppServerItem(threadId, turn, item);
|
|
4826
5008
|
}
|
|
4827
5009
|
}
|
|
5010
|
+
function appServerCollabAgentToolCallContent(item) {
|
|
5011
|
+
const targetCount = item.receiverThreadIds.length;
|
|
5012
|
+
const target = targetCount === 1 ? "subagent" : `${targetCount} subagents`;
|
|
5013
|
+
switch (item.tool) {
|
|
5014
|
+
case "spawnAgent": return targetCount > 0 ? `Spawned ${target}` : "Spawned subagent";
|
|
5015
|
+
case "sendInput": return `Sent input to ${target}`;
|
|
5016
|
+
case "resumeAgent": return `Resumed ${target}`;
|
|
5017
|
+
case "wait": return targetCount > 0 ? `Waited for ${target}` : "Waited for subagents";
|
|
5018
|
+
case "closeAgent": return `Closed ${target}`;
|
|
5019
|
+
}
|
|
5020
|
+
}
|
|
4828
5021
|
function mapUnknownAppServerItem(threadId, turn, item) {
|
|
4829
5022
|
const timestamp = fromUnixSeconds(turn.startedAt ?? turn.completedAt ?? Date.now() / 1e3);
|
|
4830
5023
|
const type = "type" in item ? String(item.type) : "unknown";
|
|
@@ -4854,6 +5047,14 @@ function appServerTurnShell(turnId) {
|
|
|
4854
5047
|
};
|
|
4855
5048
|
}
|
|
4856
5049
|
function mapAppServerModel(model) {
|
|
5050
|
+
const reasoningEffortOptions = model.supportedReasoningEfforts?.flatMap((effort) => {
|
|
5051
|
+
const parsed = ReasoningEffortSchema.safeParse(effort.reasoningEffort);
|
|
5052
|
+
return parsed.success ? [{
|
|
5053
|
+
reasoningEffort: parsed.data,
|
|
5054
|
+
description: effort.description
|
|
5055
|
+
}] : [];
|
|
5056
|
+
}) ?? [];
|
|
5057
|
+
const defaultReasoningEffort = ReasoningEffortSchema.safeParse(model.defaultReasoningEffort);
|
|
4857
5058
|
const serviceTiers = model.serviceTiers ?? model.additionalSpeedTiers?.map((tier) => ({
|
|
4858
5059
|
id: tier,
|
|
4859
5060
|
name: tier === "fast" ? "Fast" : tier,
|
|
@@ -4865,8 +5066,9 @@ function mapAppServerModel(model) {
|
|
|
4865
5066
|
displayName: model.displayName,
|
|
4866
5067
|
description: model.description,
|
|
4867
5068
|
isDefault: Boolean(model.isDefault),
|
|
4868
|
-
defaultReasoningEffort:
|
|
4869
|
-
supportedReasoningEfforts:
|
|
5069
|
+
defaultReasoningEffort: defaultReasoningEffort.success ? defaultReasoningEffort.data : void 0,
|
|
5070
|
+
supportedReasoningEfforts: reasoningEffortOptions.map((effort) => effort.reasoningEffort),
|
|
5071
|
+
reasoningEffortOptions,
|
|
4870
5072
|
serviceTiers
|
|
4871
5073
|
};
|
|
4872
5074
|
}
|
|
@@ -5327,7 +5529,11 @@ function kindFromProtocolType(type) {
|
|
|
5327
5529
|
case "approval_request":
|
|
5328
5530
|
case "approvalRequest": return "approvalRequest";
|
|
5329
5531
|
case "subagent_action":
|
|
5330
|
-
case "subagentAction":
|
|
5532
|
+
case "subagentAction":
|
|
5533
|
+
case "collab_agent_tool_call":
|
|
5534
|
+
case "collabAgentToolCall":
|
|
5535
|
+
case "sub_agent_activity":
|
|
5536
|
+
case "subAgentActivity": return "subagentAction";
|
|
5331
5537
|
default: return;
|
|
5332
5538
|
}
|
|
5333
5539
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-relay",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
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.
|
|
43
|
+
"@openai/codex-sdk": "0.144.1",
|
|
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
|
@@ -30,7 +30,16 @@ export const ChatMessageKindSchema = z.enum([
|
|
|
30
30
|
export const ApprovalModeSchema = z.enum(["on-request", "on-failure", "never"]);
|
|
31
31
|
export const RuntimeModeSchema = z.enum(["default", "auto", "full-access", "on-request"]);
|
|
32
32
|
export const SandboxModeSchema = z.enum(["workspace-write", "danger-full-access", "read-only"]);
|
|
33
|
-
export const
|
|
33
|
+
export const KnownReasoningEffortSchema = z.enum([
|
|
34
|
+
"minimal",
|
|
35
|
+
"low",
|
|
36
|
+
"medium",
|
|
37
|
+
"high",
|
|
38
|
+
"xhigh",
|
|
39
|
+
"max",
|
|
40
|
+
"ultra",
|
|
41
|
+
]);
|
|
42
|
+
export const ReasoningEffortSchema = z.string().trim().min(1);
|
|
34
43
|
export const ThreadCollaborationModeSchema = z.enum(["default", "plan"]);
|
|
35
44
|
export const ThreadGoalStatusSchema = z.enum([
|
|
36
45
|
"active",
|
|
@@ -94,6 +103,14 @@ export const CodexModelSchema = z.object({
|
|
|
94
103
|
isDefault: z.boolean().default(false),
|
|
95
104
|
defaultReasoningEffort: ReasoningEffortSchema.optional(),
|
|
96
105
|
supportedReasoningEfforts: z.array(ReasoningEffortSchema).default([]),
|
|
106
|
+
reasoningEffortOptions: z
|
|
107
|
+
.array(
|
|
108
|
+
z.object({
|
|
109
|
+
reasoningEffort: ReasoningEffortSchema,
|
|
110
|
+
description: z.string().optional(),
|
|
111
|
+
}),
|
|
112
|
+
)
|
|
113
|
+
.default([]),
|
|
97
114
|
serviceTiers: z
|
|
98
115
|
.array(
|
|
99
116
|
z.object({
|
|
@@ -718,6 +735,7 @@ export type ChatMessageRole = z.infer<typeof ChatMessageRoleSchema>;
|
|
|
718
735
|
export type ChatMessageState = z.infer<typeof ChatMessageStateSchema>;
|
|
719
736
|
export type ChatMessageKind = z.infer<typeof ChatMessageKindSchema>;
|
|
720
737
|
export type ApprovalMode = z.infer<typeof ApprovalModeSchema>;
|
|
738
|
+
export type KnownReasoningEffort = z.infer<typeof KnownReasoningEffortSchema>;
|
|
721
739
|
export type ReasoningEffort = z.infer<typeof ReasoningEffortSchema>;
|
|
722
740
|
export type RuntimeMode = z.infer<typeof RuntimeModeSchema>;
|
|
723
741
|
export type SandboxMode = z.infer<typeof SandboxModeSchema>;
|
|
@@ -1301,6 +1319,7 @@ export function createOpenApiDocument() {
|
|
|
1301
1319
|
components: {
|
|
1302
1320
|
schemas: {
|
|
1303
1321
|
ThreadState: { type: "string", enum: ThreadStateSchema.options },
|
|
1322
|
+
ReasoningEffort: { type: "string", minLength: 1 },
|
|
1304
1323
|
ChatMessage: {
|
|
1305
1324
|
type: "object",
|
|
1306
1325
|
required: ["id", "threadId", "role", "content", "createdAt"],
|
|
@@ -1437,7 +1456,7 @@ export function createOpenApiDocument() {
|
|
|
1437
1456
|
},
|
|
1438
1457
|
reasoningEffort: {
|
|
1439
1458
|
type: "string",
|
|
1440
|
-
|
|
1459
|
+
minLength: 1,
|
|
1441
1460
|
},
|
|
1442
1461
|
},
|
|
1443
1462
|
},
|
|
@@ -1454,7 +1473,7 @@ export function createOpenApiDocument() {
|
|
|
1454
1473
|
},
|
|
1455
1474
|
reasoningEffort: {
|
|
1456
1475
|
type: "string",
|
|
1457
|
-
|
|
1476
|
+
minLength: 1,
|
|
1458
1477
|
nullable: true,
|
|
1459
1478
|
},
|
|
1460
1479
|
},
|