codex-relay 1.2.4 → 1.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api-schema.js +2 -2
- package/dist/api-schema2.js +16 -17
- package/dist/cli.js +43 -17
- package/dist/paths.js +98 -11
- package/dist/src.js +268 -131
- package/package.json +5 -3
- 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/paths.js
CHANGED
|
@@ -1,9 +1,96 @@
|
|
|
1
1
|
import { execFileSync } from "node:child_process";
|
|
2
2
|
import { mkdir } from "node:fs/promises";
|
|
3
3
|
import { dirname, join, resolve } from "node:path";
|
|
4
|
-
import {
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
5
|
import { fromByteArray, toByteArray } from "base64-js";
|
|
6
|
+
import { createClient } from "@libsql/client/node";
|
|
6
7
|
import { homedir, networkInterfaces, platform } from "node:os";
|
|
8
|
+
//#region src/libsql-database.ts
|
|
9
|
+
function connect(path) {
|
|
10
|
+
const client = createClient({
|
|
11
|
+
intMode: "number",
|
|
12
|
+
url: databaseUrl(path)
|
|
13
|
+
});
|
|
14
|
+
const lock = createExclusiveLock();
|
|
15
|
+
return {
|
|
16
|
+
...createQueryableDatabase(path === ":memory:" ? { execute(statement) {
|
|
17
|
+
return lock(() => client.execute(statement));
|
|
18
|
+
} } : client),
|
|
19
|
+
exec(sql) {
|
|
20
|
+
return path === ":memory:" ? lock(() => client.executeMultiple(sql)) : client.executeMultiple(sql);
|
|
21
|
+
},
|
|
22
|
+
transaction(callback) {
|
|
23
|
+
if (path === ":memory:") {
|
|
24
|
+
const transactionDatabase = createQueryableDatabase(client);
|
|
25
|
+
return () => lock(async () => {
|
|
26
|
+
await client.execute("BEGIN IMMEDIATE");
|
|
27
|
+
try {
|
|
28
|
+
const result = await callback(transactionDatabase);
|
|
29
|
+
await client.execute("COMMIT");
|
|
30
|
+
return result;
|
|
31
|
+
} catch (error) {
|
|
32
|
+
await client.execute("ROLLBACK");
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return async () => {
|
|
38
|
+
const transaction = await client.transaction("write");
|
|
39
|
+
try {
|
|
40
|
+
const result = await callback(createQueryableDatabase(transaction));
|
|
41
|
+
await transaction.commit();
|
|
42
|
+
return result;
|
|
43
|
+
} finally {
|
|
44
|
+
transaction.close();
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function databaseUrl(path) {
|
|
51
|
+
return path === ":memory:" ? path : pathToFileURL(resolve(path)).href;
|
|
52
|
+
}
|
|
53
|
+
function createExclusiveLock() {
|
|
54
|
+
let tail = Promise.resolve();
|
|
55
|
+
return async function withLock(callback) {
|
|
56
|
+
const previous = tail;
|
|
57
|
+
let release;
|
|
58
|
+
tail = new Promise((resolve) => {
|
|
59
|
+
release = resolve;
|
|
60
|
+
});
|
|
61
|
+
await previous;
|
|
62
|
+
try {
|
|
63
|
+
return await callback();
|
|
64
|
+
} finally {
|
|
65
|
+
release();
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function createQueryableDatabase(executor) {
|
|
70
|
+
return { prepare(sql) {
|
|
71
|
+
return {
|
|
72
|
+
async all(...args) {
|
|
73
|
+
return (await executor.execute({
|
|
74
|
+
sql,
|
|
75
|
+
args
|
|
76
|
+
})).rows;
|
|
77
|
+
},
|
|
78
|
+
async get(...args) {
|
|
79
|
+
return (await executor.execute({
|
|
80
|
+
sql,
|
|
81
|
+
args
|
|
82
|
+
})).rows[0];
|
|
83
|
+
},
|
|
84
|
+
run(...args) {
|
|
85
|
+
return executor.execute({
|
|
86
|
+
sql,
|
|
87
|
+
args
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
} };
|
|
92
|
+
}
|
|
93
|
+
//#endregion
|
|
7
94
|
//#region src/pairing-store.ts
|
|
8
95
|
async function createTursoPairingSessionStore(path) {
|
|
9
96
|
if (path !== ":memory:") await mkdir(dirname(path), { recursive: true });
|
|
@@ -86,11 +173,11 @@ async function createTursoPairingSessionStore(path) {
|
|
|
86
173
|
};
|
|
87
174
|
},
|
|
88
175
|
async clearAll() {
|
|
89
|
-
return await db.transaction(async () => {
|
|
90
|
-
const sessionRow = await
|
|
91
|
-
const pendingRow = await
|
|
92
|
-
await
|
|
93
|
-
await
|
|
176
|
+
return await db.transaction(async (transaction) => {
|
|
177
|
+
const sessionRow = await transaction.prepare("SELECT COUNT(*) AS count FROM pairing_sessions").get();
|
|
178
|
+
const pendingRow = await transaction.prepare("SELECT COUNT(*) AS count FROM pending_pairings").get();
|
|
179
|
+
await transaction.prepare("DELETE FROM pairing_sessions").run();
|
|
180
|
+
await transaction.prepare("DELETE FROM pending_pairings").run();
|
|
94
181
|
return {
|
|
95
182
|
pendingPairingsCleared: Number(pendingRow?.count ?? 0),
|
|
96
183
|
sessionsCleared: Number(sessionRow?.count ?? 0)
|
|
@@ -171,13 +258,13 @@ async function createTursoPairingSessionStore(path) {
|
|
|
171
258
|
async rotateSession(oldTokenHash, newTokenHash, session) {
|
|
172
259
|
const now = Date.now();
|
|
173
260
|
const secure = encodeSecureSession(session.secureSession);
|
|
174
|
-
await db.transaction(async () => {
|
|
175
|
-
await
|
|
261
|
+
await db.transaction(async (transaction) => {
|
|
262
|
+
await transaction.prepare("DELETE FROM pairing_sessions WHERE token_hash = ?").run(oldTokenHash);
|
|
176
263
|
if (session.clientSessionId) {
|
|
177
|
-
await
|
|
178
|
-
if (session.clientName) await
|
|
264
|
+
await transaction.prepare("DELETE FROM pairing_sessions WHERE client_session_id = ?").run(session.clientSessionId);
|
|
265
|
+
if (session.clientName) await transaction.prepare("DELETE FROM pairing_sessions WHERE client_session_id IS NULL AND client_name = ?").run(session.clientName);
|
|
179
266
|
}
|
|
180
|
-
await
|
|
267
|
+
await transaction.prepare(`INSERT INTO pairing_sessions (
|
|
181
268
|
token_hash,
|
|
182
269
|
client_session_id,
|
|
183
270
|
client_name,
|
package/dist/src.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
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";
|
|
@@ -8,6 +8,7 @@ import { access, appendFile, copyFile, mkdir, open, readFile, readdir, realpath,
|
|
|
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,7 +732,7 @@ 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 = [];
|
|
@@ -887,6 +895,9 @@ function compareSkills(a, b) {
|
|
|
887
895
|
};
|
|
888
896
|
return sourceOrder[a.source] - sourceOrder[b.source] || a.displayName.localeCompare(b.displayName, void 0, { sensitivity: "base" });
|
|
889
897
|
}
|
|
898
|
+
function skillIdentityKey(skill) {
|
|
899
|
+
return [skill.source, skill.name].join("\n");
|
|
900
|
+
}
|
|
890
901
|
function dedupe(items, keyFor) {
|
|
891
902
|
const seen = /* @__PURE__ */ new Set();
|
|
892
903
|
return items.filter((item) => {
|
|
@@ -2671,7 +2682,9 @@ function queuedThreadInputSummary(input) {
|
|
|
2671
2682
|
async function streamRunningAppServerThread(input) {
|
|
2672
2683
|
let activeTurnId;
|
|
2673
2684
|
let assistantMessageId;
|
|
2685
|
+
let observedInputRequest = false;
|
|
2674
2686
|
let observedTurnActivity = false;
|
|
2687
|
+
let producedTurnOutput = false;
|
|
2675
2688
|
let threadSummary = input.threads.get(input.threadId);
|
|
2676
2689
|
const cleanupRequestHandler = input.appServer.onRequest((request) => {
|
|
2677
2690
|
if (!isApprovalServerRequest(request.method)) {
|
|
@@ -2683,6 +2696,7 @@ async function streamRunningAppServerThread(input) {
|
|
|
2683
2696
|
input.appServer.rejectRequest(request.id, -32602, "Approval request is malformed.");
|
|
2684
2697
|
return;
|
|
2685
2698
|
}
|
|
2699
|
+
observedInputRequest = true;
|
|
2686
2700
|
if (approval.kind === "structuredUserInput") {
|
|
2687
2701
|
const pending = {
|
|
2688
2702
|
appServer: input.appServer,
|
|
@@ -2771,6 +2785,7 @@ async function streamRunningAppServerThread(input) {
|
|
|
2771
2785
|
if (!item || typeof item !== "object") return;
|
|
2772
2786
|
const message = upsertAppServerItemMessage(input.messagesByThreadId, input.threadId, firstString(params, ["turnId"]) ?? activeTurnId, item);
|
|
2773
2787
|
if (!message) return;
|
|
2788
|
+
if (message.role !== "user") producedTurnOutput = true;
|
|
2774
2789
|
if (message.role === "assistant") assistantMessageId = message.id;
|
|
2775
2790
|
threadSummary = updateThread(input.threads, input.messagesByThreadId, input.threadId, {
|
|
2776
2791
|
state: "running",
|
|
@@ -2795,6 +2810,7 @@ async function streamRunningAppServerThread(input) {
|
|
|
2795
2810
|
turnId: firstString(params, ["turnId"]) ?? activeTurnId
|
|
2796
2811
|
});
|
|
2797
2812
|
assistantMessageId = itemId;
|
|
2813
|
+
producedTurnOutput = true;
|
|
2798
2814
|
const patch = appendMessageDelta(input.messagesByThreadId, input.threadId, itemId, delta);
|
|
2799
2815
|
const message = patch.message;
|
|
2800
2816
|
updateThread(input.threads, input.messagesByThreadId, input.threadId, {
|
|
@@ -2811,6 +2827,7 @@ async function streamRunningAppServerThread(input) {
|
|
|
2811
2827
|
}
|
|
2812
2828
|
case "turn/plan/updated": {
|
|
2813
2829
|
observedTurnActivity = true;
|
|
2830
|
+
producedTurnOutput = true;
|
|
2814
2831
|
const content = planContentFromRecord(params);
|
|
2815
2832
|
const message = appendMessage(input.messagesByThreadId, input.threadId, {
|
|
2816
2833
|
role: "status",
|
|
@@ -2840,6 +2857,20 @@ async function streamRunningAppServerThread(input) {
|
|
|
2840
2857
|
threadId: input.threadId,
|
|
2841
2858
|
turnId: firstString(params, ["turnId"]) ?? activeTurnId
|
|
2842
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
|
+
}
|
|
2843
2874
|
if (assistantMessageId) {
|
|
2844
2875
|
const completedMessage = updateMessage(input.messagesByThreadId, input.threadId, assistantMessageId, { state: "completed" });
|
|
2845
2876
|
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
@@ -2856,11 +2887,25 @@ async function streamRunningAppServerThread(input) {
|
|
|
2856
2887
|
type: "thread.state.changed",
|
|
2857
2888
|
thread: threadSummary
|
|
2858
2889
|
});
|
|
2859
|
-
if (state === "failed")
|
|
2860
|
-
|
|
2861
|
-
|
|
2862
|
-
|
|
2863
|
-
|
|
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
|
+
}
|
|
2864
2909
|
cleanupNotificationHandler();
|
|
2865
2910
|
resolve();
|
|
2866
2911
|
return;
|
|
@@ -2905,6 +2950,7 @@ async function runAppServerPromptStreamed(input) {
|
|
|
2905
2950
|
const displayPrompt = promptMarkdownWithSkills(promptWithAttachmentReferences(input.prompt, input.attachments), input.skills);
|
|
2906
2951
|
const prompt = input.prompt;
|
|
2907
2952
|
let handedOffToQueuedTurn = false;
|
|
2953
|
+
let observedInputRequest = false;
|
|
2908
2954
|
let producedTurnOutput = false;
|
|
2909
2955
|
let userMessage = appendMessage(input.messagesByThreadId, activeThreadId, {
|
|
2910
2956
|
role: "user",
|
|
@@ -2938,6 +2984,7 @@ async function runAppServerPromptStreamed(input) {
|
|
|
2938
2984
|
input.appServer.rejectRequest(request.id, -32602, "Approval request is malformed.");
|
|
2939
2985
|
return;
|
|
2940
2986
|
}
|
|
2987
|
+
observedInputRequest = true;
|
|
2941
2988
|
if (approval.kind === "structuredUserInput") {
|
|
2942
2989
|
const pending = {
|
|
2943
2990
|
appServer: input.appServer,
|
|
@@ -2981,7 +3028,141 @@ async function runAppServerPromptStreamed(input) {
|
|
|
2981
3028
|
});
|
|
2982
3029
|
});
|
|
2983
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
|
+
}
|
|
2984
3163
|
const completed = new Promise((resolve, reject) => {
|
|
3164
|
+
resolveCompleted = resolve;
|
|
3165
|
+
rejectCompleted = reject;
|
|
2985
3166
|
cleanupNotificationHandler = input.appServer.onNotification((notification) => {
|
|
2986
3167
|
const params = recordParams(notification);
|
|
2987
3168
|
const threadId = firstString(params, ["threadId"]);
|
|
@@ -3026,7 +3207,7 @@ async function runAppServerPromptStreamed(input) {
|
|
|
3026
3207
|
const turnId = firstString(params, ["turnId"]) ?? activeTurnId;
|
|
3027
3208
|
const message = upsertAppServerItemMessage(input.messagesByThreadId, activeThreadId, turnId, item);
|
|
3028
3209
|
if (!message) return;
|
|
3029
|
-
producedTurnOutput = true;
|
|
3210
|
+
if (message.role !== "user") producedTurnOutput = true;
|
|
3030
3211
|
if (message.role === "assistant") assistantMessageId = message.id;
|
|
3031
3212
|
threadSummary = updateThread(input.threads, input.messagesByThreadId, activeThreadId, {
|
|
3032
3213
|
state: "running",
|
|
@@ -3089,69 +3270,13 @@ async function runAppServerPromptStreamed(input) {
|
|
|
3089
3270
|
case "turn/completed":
|
|
3090
3271
|
case "turn/failed": {
|
|
3091
3272
|
const state = terminalTurnState(notification.method, params);
|
|
3092
|
-
|
|
3273
|
+
const terminalTurnId = firstString(params, ["turnId"]) ?? turnIdFromParams(params) ?? activeTurnId;
|
|
3274
|
+
finishTerminalTurn({
|
|
3275
|
+
lastError: state === "failed" ? turnErrorMessage(params) : void 0,
|
|
3093
3276
|
method: notification.method,
|
|
3094
3277
|
state,
|
|
3095
|
-
|
|
3096
|
-
turnId: firstString(params, ["turnId"]) ?? activeTurnId
|
|
3097
|
-
});
|
|
3098
|
-
input.activeAppServerTurnIdsByThreadId.delete(activeThreadId);
|
|
3099
|
-
if (assistantMessageId) {
|
|
3100
|
-
const completedMessage = updateMessage(input.messagesByThreadId, activeThreadId, assistantMessageId, { state: "completed" });
|
|
3101
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3102
|
-
type: "thread.message.completed",
|
|
3103
|
-
thread: threadSummary,
|
|
3104
|
-
message: completedMessage
|
|
3105
|
-
});
|
|
3106
|
-
}
|
|
3107
|
-
const lastError = state === "failed" ? turnErrorMessage(params) : void 0;
|
|
3108
|
-
const nextQueuedInput = state === "completed" ? shiftQueuedInput(input.queuedInputsByThreadId, activeThreadId) : void 0;
|
|
3109
|
-
threadSummary = updateThread(input.threads, input.messagesByThreadId, activeThreadId, {
|
|
3110
|
-
state: nextQueuedInput ? "running" : state,
|
|
3111
|
-
lastError: nextQueuedInput ? void 0 : lastError,
|
|
3112
|
-
...nextQueuedInput ? {
|
|
3113
|
-
lastPrompt: promptWithAttachmentReferences(nextQueuedInput.prompt, nextQueuedInput.attachments),
|
|
3114
|
-
...runtimeMetadataFromOptions(nextQueuedInput.runOptions)
|
|
3115
|
-
} : {}
|
|
3278
|
+
turnId: terminalTurnId
|
|
3116
3279
|
});
|
|
3117
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3118
|
-
type: "thread.state.changed",
|
|
3119
|
-
thread: threadSummary
|
|
3120
|
-
});
|
|
3121
|
-
if (state === "failed") {
|
|
3122
|
-
const errorBody = apiError("codex_run_failed", lastError ?? "Codex turn did not complete.");
|
|
3123
|
-
appendMessage(input.messagesByThreadId, activeThreadId, {
|
|
3124
|
-
role: "error",
|
|
3125
|
-
content: errorBody.error.message,
|
|
3126
|
-
state: "failed",
|
|
3127
|
-
turnId: activeTurnId
|
|
3128
|
-
});
|
|
3129
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3130
|
-
type: "thread.error",
|
|
3131
|
-
thread: threadSummary,
|
|
3132
|
-
error: errorBody.error
|
|
3133
|
-
});
|
|
3134
|
-
input.steeringThreads.delete(activeThreadId);
|
|
3135
|
-
cleanupNotificationHandler();
|
|
3136
|
-
resolve();
|
|
3137
|
-
return;
|
|
3138
|
-
}
|
|
3139
|
-
if (nextQueuedInput) {
|
|
3140
|
-
handedOffToQueuedTurn = true;
|
|
3141
|
-
assistantMessageId = void 0;
|
|
3142
|
-
input.steeringThreads.add(activeThreadId);
|
|
3143
|
-
startAppServerTurn(input.appServer, activeThreadId, nextQueuedInput).then((turn) => {
|
|
3144
|
-
activeTurnId = turn.id;
|
|
3145
|
-
input.activeAppServerTurnIdsByThreadId.set(activeThreadId, activeTurnId);
|
|
3146
|
-
}).catch((error) => {
|
|
3147
|
-
cleanupNotificationHandler();
|
|
3148
|
-
reject(error);
|
|
3149
|
-
});
|
|
3150
|
-
return;
|
|
3151
|
-
}
|
|
3152
|
-
input.steeringThreads.delete(activeThreadId);
|
|
3153
|
-
cleanupNotificationHandler();
|
|
3154
|
-
resolve();
|
|
3155
3280
|
return;
|
|
3156
3281
|
}
|
|
3157
3282
|
}
|
|
@@ -3251,56 +3376,8 @@ async function runAppServerPromptStreamed(input) {
|
|
|
3251
3376
|
workspacePath: input.workspacePath
|
|
3252
3377
|
});
|
|
3253
3378
|
}
|
|
3254
|
-
|
|
3255
|
-
|
|
3256
|
-
debugStream("start turn complete", activeThreadId, activeTurnId);
|
|
3257
|
-
let streamedReturnedItem = false;
|
|
3258
|
-
for (const item of turn.items) {
|
|
3259
|
-
const canonicalUserMessage = replaceDuplicateInitialUserMessage(input.messagesByThreadId, activeThreadId, activeTurnId, item, userMessage.id, displayPrompt);
|
|
3260
|
-
if (canonicalUserMessage) {
|
|
3261
|
-
userMessage = canonicalUserMessage;
|
|
3262
|
-
continue;
|
|
3263
|
-
}
|
|
3264
|
-
const message = upsertAppServerItemMessage(input.messagesByThreadId, activeThreadId, activeTurnId, item);
|
|
3265
|
-
if (!message) continue;
|
|
3266
|
-
streamedReturnedItem = true;
|
|
3267
|
-
producedTurnOutput = true;
|
|
3268
|
-
if (message.role === "assistant") assistantMessageId = message.id;
|
|
3269
|
-
threadSummary = updateThread(input.threads, input.messagesByThreadId, activeThreadId, {
|
|
3270
|
-
state: "running",
|
|
3271
|
-
lastResult: message.role === "assistant" ? message.content : void 0
|
|
3272
|
-
});
|
|
3273
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3274
|
-
type: message.role === "assistant" ? "thread.message.completed" : "thread.message.created",
|
|
3275
|
-
thread: threadSummary,
|
|
3276
|
-
message
|
|
3277
|
-
});
|
|
3278
|
-
}
|
|
3279
|
-
const returnedState = mapAppServerThreadState(turn.status);
|
|
3280
|
-
if (returnedState !== "running") {
|
|
3281
|
-
if (!streamedReturnedItem && !producedTurnOutput) {
|
|
3282
|
-
sendEmptyAppServerTurnError({
|
|
3283
|
-
activeTurnId,
|
|
3284
|
-
controller: input.controller,
|
|
3285
|
-
encoder: input.encoder,
|
|
3286
|
-
messagesByThreadId: input.messagesByThreadId,
|
|
3287
|
-
secureSession: input.secureSession,
|
|
3288
|
-
threadId: activeThreadId,
|
|
3289
|
-
threads: input.threads
|
|
3290
|
-
});
|
|
3291
|
-
input.steeringThreads.delete(activeThreadId);
|
|
3292
|
-
cleanupNotificationHandler();
|
|
3293
|
-
return;
|
|
3294
|
-
}
|
|
3295
|
-
threadSummary = updateThread(input.threads, input.messagesByThreadId, activeThreadId, { state: returnedState });
|
|
3296
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
3297
|
-
type: "thread.state.changed",
|
|
3298
|
-
thread: threadSummary
|
|
3299
|
-
});
|
|
3300
|
-
input.steeringThreads.delete(activeThreadId);
|
|
3301
|
-
cleanupNotificationHandler();
|
|
3302
|
-
return;
|
|
3303
|
-
}
|
|
3379
|
+
debugStream("start turn complete", activeThreadId, turn.id);
|
|
3380
|
+
processReturnedTurn(turn);
|
|
3304
3381
|
await completed;
|
|
3305
3382
|
} catch (error) {
|
|
3306
3383
|
debugStream(`failed ${errorMessage(error)}`, activeThreadId, activeTurnId);
|
|
@@ -4154,11 +4231,12 @@ function appServerCollaborationMode(options) {
|
|
|
4154
4231
|
}
|
|
4155
4232
|
function buildThreadOptions(base, options) {
|
|
4156
4233
|
const runtime = resolveRuntimeOptions(options.runtimeMode);
|
|
4234
|
+
const reasoningEffort = KnownReasoningEffortSchema.safeParse(options.reasoningEffort);
|
|
4157
4235
|
return {
|
|
4158
4236
|
...base,
|
|
4159
4237
|
...runtime,
|
|
4160
4238
|
...options.model ? { model: options.model } : {},
|
|
4161
|
-
...
|
|
4239
|
+
...reasoningEffort.success ? { modelReasoningEffort: reasoningEffort.data } : {},
|
|
4162
4240
|
...options.approvalPolicy ? { approvalPolicy: options.approvalPolicy } : {},
|
|
4163
4241
|
...options.sandboxMode ? { sandboxMode: options.sandboxMode } : {}
|
|
4164
4242
|
};
|
|
@@ -4878,6 +4956,41 @@ function mapAppServerItem(threadId, turn, item) {
|
|
|
4878
4956
|
}
|
|
4879
4957
|
});
|
|
4880
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
|
+
}
|
|
4881
4994
|
case "webSearch": {
|
|
4882
4995
|
const searchItem = item;
|
|
4883
4996
|
return ChatMessageSchema.parse({
|
|
@@ -4894,6 +5007,17 @@ function mapAppServerItem(threadId, turn, item) {
|
|
|
4894
5007
|
default: return mapUnknownAppServerItem(threadId, turn, item);
|
|
4895
5008
|
}
|
|
4896
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
|
+
}
|
|
4897
5021
|
function mapUnknownAppServerItem(threadId, turn, item) {
|
|
4898
5022
|
const timestamp = fromUnixSeconds(turn.startedAt ?? turn.completedAt ?? Date.now() / 1e3);
|
|
4899
5023
|
const type = "type" in item ? String(item.type) : "unknown";
|
|
@@ -4923,6 +5047,14 @@ function appServerTurnShell(turnId) {
|
|
|
4923
5047
|
};
|
|
4924
5048
|
}
|
|
4925
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);
|
|
4926
5058
|
const serviceTiers = model.serviceTiers ?? model.additionalSpeedTiers?.map((tier) => ({
|
|
4927
5059
|
id: tier,
|
|
4928
5060
|
name: tier === "fast" ? "Fast" : tier,
|
|
@@ -4934,8 +5066,9 @@ function mapAppServerModel(model) {
|
|
|
4934
5066
|
displayName: model.displayName,
|
|
4935
5067
|
description: model.description,
|
|
4936
5068
|
isDefault: Boolean(model.isDefault),
|
|
4937
|
-
defaultReasoningEffort:
|
|
4938
|
-
supportedReasoningEfforts:
|
|
5069
|
+
defaultReasoningEffort: defaultReasoningEffort.success ? defaultReasoningEffort.data : void 0,
|
|
5070
|
+
supportedReasoningEfforts: reasoningEffortOptions.map((effort) => effort.reasoningEffort),
|
|
5071
|
+
reasoningEffortOptions,
|
|
4939
5072
|
serviceTiers
|
|
4940
5073
|
};
|
|
4941
5074
|
}
|
|
@@ -5396,7 +5529,11 @@ function kindFromProtocolType(type) {
|
|
|
5396
5529
|
case "approval_request":
|
|
5397
5530
|
case "approvalRequest": return "approvalRequest";
|
|
5398
5531
|
case "subagent_action":
|
|
5399
|
-
case "subagentAction":
|
|
5532
|
+
case "subagentAction":
|
|
5533
|
+
case "collab_agent_tool_call":
|
|
5534
|
+
case "collabAgentToolCall":
|
|
5535
|
+
case "sub_agent_activity":
|
|
5536
|
+
case "subAgentActivity": return "subagentAction";
|
|
5400
5537
|
default: return;
|
|
5401
5538
|
}
|
|
5402
5539
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-relay",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "Local Codex Relay CLI bridge for the Codex Relay mobile app.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -35,19 +35,21 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@commander-js/extra-typings": "^14.0.0",
|
|
37
37
|
"@hono/node-server": "^1.19.6",
|
|
38
|
+
"@libsql/client": "0.17.4",
|
|
38
39
|
"@lydell/node-pty": "1.2.0-beta.12",
|
|
39
40
|
"@modelcontextprotocol/sdk": "^1.24.0",
|
|
40
41
|
"@noble/ciphers": "2.2.0",
|
|
41
42
|
"@noble/curves": "2.2.0",
|
|
42
43
|
"@noble/hashes": "2.2.0",
|
|
43
|
-
"@openai/codex-sdk": "0.
|
|
44
|
-
"@tursodatabase/database": "^0.5.3",
|
|
44
|
+
"@openai/codex-sdk": "0.144.1",
|
|
45
45
|
"base64-js": "1.5.1",
|
|
46
46
|
"commander": "^14.0.3",
|
|
47
47
|
"es-git": "^0.6.0",
|
|
48
48
|
"hono": "^4.10.7",
|
|
49
|
+
"libsql": "0.5.29",
|
|
49
50
|
"picocolors": "^1.1.1",
|
|
50
51
|
"qrcode-terminal": "^0.12.0",
|
|
52
|
+
"ws": "8.21.0",
|
|
51
53
|
"zod": "^4.1.12"
|
|
52
54
|
},
|
|
53
55
|
"devDependencies": {
|
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
|
},
|