codex-relay 1.1.0 → 1.2.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/README.md +10 -0
- package/dist/api-schema.js +2 -2
- package/dist/api-schema2.js +132 -4
- package/dist/cli.js +1 -1
- package/dist/src.js +197 -25
- package/package.json +2 -2
- package/src/api-schema.ts +120 -1
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Codex Relay runs a local bridge server for the Codex Relay mobile app. Keep Codex on your computer, then use your phone to pair with that local session, send prompts, watch streamed output, and respond to approval requests.
|
|
4
4
|
|
|
5
|
+
Codex Relay is an independent project. It is not affiliated with, endorsed by, or sponsored by OpenAI or the OpenAI Codex team.
|
|
6
|
+
|
|
5
7
|
## Requirements
|
|
6
8
|
|
|
7
9
|
- Node.js 22.14 or newer
|
|
@@ -145,3 +147,11 @@ kill -TERM <pid>
|
|
|
145
147
|
```
|
|
146
148
|
|
|
147
149
|
If the mobile app cannot connect, confirm that the phone can reach the printed `Mobile:` URL and that the chosen port is not blocked by a firewall.
|
|
150
|
+
|
|
151
|
+
Connection checklist:
|
|
152
|
+
|
|
153
|
+
- Are the phone and computer on the same Wi-Fi or LAN?
|
|
154
|
+
- If keeping the same network is difficult, are both devices connected through Tailscale or another reachable private network?
|
|
155
|
+
- Can the phone open the exact `Mobile:` URL printed by the relay?
|
|
156
|
+
- Does the computer firewall allow inbound traffic on the relay port, usually `8787`?
|
|
157
|
+
- If the printed URL is not reachable, did you set `CODEX_RELAY_PUBLIC_URL` to a reachable LAN, Tailscale, or tunnel URL?
|
package/dist/api-schema.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as SandboxModeSchema, A as PairResponseSchema, At as
|
|
2
|
-
export { AgentSkillSchema, AgentSkillSourceSchema, ApprovalDecisionSchema, ApprovalModeSchema, ArchiveThreadResponseSchema, ChatMessageKindSchema, ChatMessagePromptDetailsSchema, ChatMessageRoleSchema, ChatMessageSchema, ChatMessageStateSchema, CheckoutWorkspaceBranchRequestSchema, CodexModelSchema, CommitPushWorkspaceRequestSchema, ContextWindowUsageSchema, CreateThreadRequestSchema, CreateThreadResponseSchema, EncryptedPayloadSchema, ErrorResponseSchema, ImageAttachmentUploadResponseSchema, InterruptThreadRunResponseSchema, IsoDateTimeSchema, ListModelsResponseSchema, ListQueuedThreadInputsResponseSchema, ListSkillsResponseSchema, ListThreadsResponseSchema, ListWorkspaceDirectoriesResponseSchema, ListWorkspaceFilesResponseSchema, PairEncryptedPayloadSchema, PairRequestSchema, PairResponseSchema, PendingInputRequestOptionSchema, PendingInputRequestQuestionSchema, PendingInputRequestSchema, PromptAttachmentSchema, PromptAttachmentSummarySchema, PromptContextInputSchema, PromptContextSchema, PromptSkillSchema, QueuedThreadInputActionResponseSchema, QueuedThreadInputSchema, RateLimitBucketSchema, RateLimitWindowSchema, RateLimitsResponseSchema, ReasoningEffortSchema, ResolveApprovalRequestSchema, ResolveApprovalResponseSchema, RunThreadRequestSchema, RunThreadResponseSchema, RuntimeModeSchema, RuntimePreferencesByWorkspacePathSchema, RuntimePreferencesResponseSchema, RuntimePreferencesSchema, SandboxModeSchema, StatusResponseSchema, StreamThreadRunEventSchema, StreamThreadRunRequestSchema, SubmitThreadInputResponseSchema, ThreadCollaborationModeSchema, ThreadContextWindowResponseSchema, ThreadDetailResponseSchema, ThreadMessageDetailFieldSchema, ThreadMessageDetailResponseSchema, ThreadRunOptionsSchema, ThreadStateSchema, ThreadSummarySchema, UpdateRuntimePreferencesRequestSchema, UpdateWorkspaceFileContentRequestSchema, VersionResponseSchema, WORKSPACE_PREVIEW_OPEN_PROTOCOL, WORKSPACE_PREVIEW_TAB_VALUES, WebPreviewTargetSchema, WorkspaceChangesResponseSchema, WorkspaceDirectoryEntrySchema, WorkspaceFileContentResponseSchema, WorkspaceFileMentionSchema, WorkspaceGitActionResponseSchema, WorkspaceMarkdownPreviewTargetSchema, WorkspacePreviewNavigationRequestSchema, WorkspacePreviewTabSchema, WorkspaceSelectionRequestSchema, WorkspaceTerminalInputRequestSchema, WorkspaceTerminalOutputChunkSchema, WorkspaceTerminalOutputResponseSchema, WorkspaceTerminalResizeRequestSchema, WorkspaceTerminalSessionResponseSchema, WorkspaceTerminalStartRequestSchema, apiPaths, chatMessageDetailsFromPromptContext, createOpenApiDocument, isPromptSkillMarkdownMention, normalizePromptContext, promptMarkdownWithSkills, promptSkillDisplayName, promptSkillMentionLabel, promptSkillMentionMarkdown, promptSkillMentionTextCandidates, stripPromptSkillMentions };
|
|
1
|
+
import { $ as SandboxModeSchema, A as PairResponseSchema, At as WorkspaceSelectionRequestSchema, B as QueuedThreadInputSchema, Bt as isPromptSkillMarkdownMention, C as ListQueuedThreadInputsResponseSchema, Ct as WorkspaceDirectoryEntrySchema, D as ListWorkspaceFilesResponseSchema, Dt as WorkspaceMarkdownPreviewTargetSchema, E as ListWorkspaceDirectoriesResponseSchema, Et as WorkspaceGitActionResponseSchema, F as PromptAttachmentSummarySchema, Ft as WorkspaceTerminalSessionResponseSchema, G as ResolveApprovalRequestSchema, Gt as promptSkillMentionMarkdown, H as RateLimitWindowSchema, Ht as promptMarkdownWithSkills, I as PromptContextInputSchema, It as WorkspaceTerminalStartRequestSchema, J as RunThreadResponseSchema, K as ResolveApprovalResponseSchema, Kt as promptSkillMentionTextCandidates, L as PromptContextSchema, Lt as apiPaths, M as PendingInputRequestQuestionSchema, Mt as WorkspaceTerminalOutputChunkSchema, N as PendingInputRequestSchema, Nt as WorkspaceTerminalOutputResponseSchema, O as PairEncryptedPayloadSchema, Ot as WorkspacePreviewNavigationRequestSchema, P as PromptAttachmentSchema, Pt as WorkspaceTerminalResizeRequestSchema, Q as RuntimePreferencesSchema, R as PromptSkillSchema, Rt as chatMessageDetailsFromPromptContext, S as ListModelsResponseSchema, St as WorkspaceChangesResponseSchema, T as ListThreadsResponseSchema, Tt as WorkspaceFileMentionSchema, U as RateLimitsResponseSchema, Ut as promptSkillDisplayName, V as RateLimitBucketSchema, Vt as normalizePromptContext, W as ReasoningEffortSchema, Wt as promptSkillMentionLabel, X as RuntimePreferencesByWorkspacePathSchema, Y as RuntimeModeSchema, Z as RuntimePreferencesResponseSchema, _ as EncryptedPayloadSchema, _t as UpdateWorkspaceFileContentRequestSchema, a as ArchiveThreadResponseSchema, at as ThreadContextWindowResponseSchema, b as InterruptThreadRunResponseSchema, bt as WORKSPACE_PREVIEW_TAB_VALUES, c as ChatMessageRoleSchema, ct as ThreadGoalSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as ThreadMessageDetailResponseSchema, et as StatusResponseSchema, f as CodexModelSchema, ft as ThreadRunOptionsSchema, g as CreateThreadResponseSchema, gt as UpdateThreadGoalRequestSchema, h as CreateThreadRequestSchema, ht as UpdateRuntimePreferencesRequestSchema, i as ApprovalModeSchema, it as ThreadCollaborationModeSchema, j as PendingInputRequestOptionSchema, jt as WorkspaceTerminalInputRequestSchema, k as PairRequestSchema, kt as WorkspacePreviewTabSchema, l as ChatMessageSchema, lt as ThreadGoalStatusSchema, m as ContextWindowUsageSchema, mt as ThreadSummarySchema, n as AgentSkillSourceSchema, nt as StreamThreadRunRequestSchema, o as ChatMessageKindSchema, ot as ThreadDetailResponseSchema, p as CommitPushWorkspaceRequestSchema, pt as ThreadStateSchema, q as RunThreadRequestSchema, qt as stripPromptSkillMentions, r as ApprovalDecisionSchema, rt as SubmitThreadInputResponseSchema, s as ChatMessagePromptDetailsSchema, st as ThreadGoalResponseSchema, t as AgentSkillSchema, tt as StreamThreadRunEventSchema, u as ChatMessageStateSchema, ut as ThreadMessageDetailFieldSchema, v as ErrorResponseSchema, vt as VersionResponseSchema, w as ListSkillsResponseSchema, wt as WorkspaceFileContentResponseSchema, x as IsoDateTimeSchema, xt as WebPreviewTargetSchema, y as ImageAttachmentUploadResponseSchema, yt as WORKSPACE_PREVIEW_OPEN_PROTOCOL, z as QueuedThreadInputActionResponseSchema, zt as createOpenApiDocument } from "./api-schema2.js";
|
|
2
|
+
export { AgentSkillSchema, AgentSkillSourceSchema, ApprovalDecisionSchema, ApprovalModeSchema, ArchiveThreadResponseSchema, ChatMessageKindSchema, ChatMessagePromptDetailsSchema, ChatMessageRoleSchema, ChatMessageSchema, ChatMessageStateSchema, CheckoutWorkspaceBranchRequestSchema, CodexModelSchema, CommitPushWorkspaceRequestSchema, ContextWindowUsageSchema, CreateThreadRequestSchema, CreateThreadResponseSchema, EncryptedPayloadSchema, ErrorResponseSchema, ImageAttachmentUploadResponseSchema, InterruptThreadRunResponseSchema, IsoDateTimeSchema, ListModelsResponseSchema, ListQueuedThreadInputsResponseSchema, ListSkillsResponseSchema, ListThreadsResponseSchema, ListWorkspaceDirectoriesResponseSchema, ListWorkspaceFilesResponseSchema, PairEncryptedPayloadSchema, PairRequestSchema, PairResponseSchema, PendingInputRequestOptionSchema, PendingInputRequestQuestionSchema, PendingInputRequestSchema, PromptAttachmentSchema, PromptAttachmentSummarySchema, PromptContextInputSchema, PromptContextSchema, PromptSkillSchema, QueuedThreadInputActionResponseSchema, QueuedThreadInputSchema, RateLimitBucketSchema, RateLimitWindowSchema, RateLimitsResponseSchema, ReasoningEffortSchema, ResolveApprovalRequestSchema, ResolveApprovalResponseSchema, RunThreadRequestSchema, RunThreadResponseSchema, RuntimeModeSchema, RuntimePreferencesByWorkspacePathSchema, RuntimePreferencesResponseSchema, RuntimePreferencesSchema, SandboxModeSchema, StatusResponseSchema, StreamThreadRunEventSchema, StreamThreadRunRequestSchema, SubmitThreadInputResponseSchema, ThreadCollaborationModeSchema, ThreadContextWindowResponseSchema, ThreadDetailResponseSchema, ThreadGoalResponseSchema, ThreadGoalSchema, ThreadGoalStatusSchema, ThreadMessageDetailFieldSchema, ThreadMessageDetailResponseSchema, ThreadRunOptionsSchema, ThreadStateSchema, ThreadSummarySchema, UpdateRuntimePreferencesRequestSchema, UpdateThreadGoalRequestSchema, UpdateWorkspaceFileContentRequestSchema, VersionResponseSchema, WORKSPACE_PREVIEW_OPEN_PROTOCOL, WORKSPACE_PREVIEW_TAB_VALUES, WebPreviewTargetSchema, WorkspaceChangesResponseSchema, WorkspaceDirectoryEntrySchema, WorkspaceFileContentResponseSchema, WorkspaceFileMentionSchema, WorkspaceGitActionResponseSchema, WorkspaceMarkdownPreviewTargetSchema, WorkspacePreviewNavigationRequestSchema, WorkspacePreviewTabSchema, WorkspaceSelectionRequestSchema, WorkspaceTerminalInputRequestSchema, WorkspaceTerminalOutputChunkSchema, WorkspaceTerminalOutputResponseSchema, WorkspaceTerminalResizeRequestSchema, WorkspaceTerminalSessionResponseSchema, WorkspaceTerminalStartRequestSchema, apiPaths, chatMessageDetailsFromPromptContext, createOpenApiDocument, isPromptSkillMarkdownMention, normalizePromptContext, promptMarkdownWithSkills, promptSkillDisplayName, promptSkillMentionLabel, promptSkillMentionMarkdown, promptSkillMentionTextCandidates, stripPromptSkillMentions };
|
package/dist/api-schema2.js
CHANGED
|
@@ -57,6 +57,14 @@ const ReasoningEffortSchema = z.enum([
|
|
|
57
57
|
"xhigh"
|
|
58
58
|
]);
|
|
59
59
|
const ThreadCollaborationModeSchema = z.enum(["default", "plan"]);
|
|
60
|
+
const ThreadGoalStatusSchema = z.enum([
|
|
61
|
+
"active",
|
|
62
|
+
"paused",
|
|
63
|
+
"blocked",
|
|
64
|
+
"usageLimited",
|
|
65
|
+
"budgetLimited",
|
|
66
|
+
"complete"
|
|
67
|
+
]);
|
|
60
68
|
const VersionResponseSchema = z.object({
|
|
61
69
|
ok: z.boolean(),
|
|
62
70
|
service: z.literal("codex-relay-server"),
|
|
@@ -145,6 +153,16 @@ const ThreadContextWindowResponseSchema = z.object({
|
|
|
145
153
|
usage: ContextWindowUsageSchema.nullable(),
|
|
146
154
|
rolloutPath: z.string().nullable().optional()
|
|
147
155
|
});
|
|
156
|
+
const ThreadGoalSchema = z.object({
|
|
157
|
+
threadId: z.string().min(1),
|
|
158
|
+
objective: z.string().trim().min(1),
|
|
159
|
+
status: ThreadGoalStatusSchema,
|
|
160
|
+
tokenBudget: z.number().int().positive().nullable(),
|
|
161
|
+
tokensUsed: z.number().int().nonnegative(),
|
|
162
|
+
timeUsedSeconds: z.number().int().nonnegative(),
|
|
163
|
+
createdAt: IsoDateTimeSchema,
|
|
164
|
+
updatedAt: IsoDateTimeSchema
|
|
165
|
+
});
|
|
148
166
|
const PromptAttachmentBaseSchema = z.object({
|
|
149
167
|
type: z.literal("image"),
|
|
150
168
|
mimeType: z.string().trim().startsWith("image/").optional(),
|
|
@@ -247,7 +265,8 @@ const ThreadSummarySchema = z.object({
|
|
|
247
265
|
lastActivityAt: IsoDateTimeSchema.optional(),
|
|
248
266
|
lastPrompt: z.string().optional(),
|
|
249
267
|
lastResult: z.string().optional(),
|
|
250
|
-
lastError: z.string().optional()
|
|
268
|
+
lastError: z.string().optional(),
|
|
269
|
+
goal: ThreadGoalSchema.nullable().optional()
|
|
251
270
|
});
|
|
252
271
|
const StatusResponseSchema = z.object({
|
|
253
272
|
ok: z.boolean(),
|
|
@@ -473,6 +492,15 @@ const QueuedThreadInputActionResponseSchema = z.object({
|
|
|
473
492
|
queueLength: z.number().int().nonnegative(),
|
|
474
493
|
thread: ThreadSummarySchema
|
|
475
494
|
});
|
|
495
|
+
const UpdateThreadGoalRequestSchema = z.object({
|
|
496
|
+
objective: z.string().trim().min(1).optional(),
|
|
497
|
+
status: ThreadGoalStatusSchema.optional(),
|
|
498
|
+
tokenBudget: z.number().int().positive().nullable().optional()
|
|
499
|
+
}).refine((input) => input.objective || input.status || input.tokenBudget !== void 0, { message: "At least one goal field is required." });
|
|
500
|
+
const ThreadGoalResponseSchema = z.object({
|
|
501
|
+
goal: ThreadGoalSchema.nullable(),
|
|
502
|
+
thread: ThreadSummarySchema
|
|
503
|
+
});
|
|
476
504
|
const InterruptThreadRunResponseSchema = z.object({ thread: ThreadSummarySchema });
|
|
477
505
|
const ListQueuedThreadInputsResponseSchema = z.object({
|
|
478
506
|
inputs: z.array(QueuedThreadInputSchema),
|
|
@@ -533,6 +561,11 @@ const StreamThreadRunEventSchema = z.discriminatedUnion("type", [
|
|
|
533
561
|
type: z.literal("thread.state.changed"),
|
|
534
562
|
thread: ThreadSummarySchema
|
|
535
563
|
}),
|
|
564
|
+
z.object({
|
|
565
|
+
type: z.literal("thread.goal.updated"),
|
|
566
|
+
thread: ThreadSummarySchema,
|
|
567
|
+
goal: ThreadGoalSchema.nullable()
|
|
568
|
+
}),
|
|
536
569
|
z.object({
|
|
537
570
|
type: z.literal("thread.error"),
|
|
538
571
|
thread: ThreadSummarySchema.optional(),
|
|
@@ -697,6 +730,7 @@ const apiPaths = {
|
|
|
697
730
|
thread: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}`,
|
|
698
731
|
threadArchive: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}`,
|
|
699
732
|
threadContextWindow: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}/context-window`,
|
|
733
|
+
threadGoal: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}/goal`,
|
|
700
734
|
threadMessageDetail: (threadId, messageId, field) => `/v1/threads/${encodeURIComponent(threadId)}/messages/${encodeURIComponent(messageId)}/details/${encodeURIComponent(field)}`,
|
|
701
735
|
approval: (approvalId) => `/v1/approvals/${encodeURIComponent(approvalId)}`,
|
|
702
736
|
threadInput: (threadId) => `/v1/threads/${encodeURIComponent(threadId)}/input`,
|
|
@@ -711,7 +745,7 @@ function createOpenApiDocument() {
|
|
|
711
745
|
openapi: "3.1.0",
|
|
712
746
|
info: {
|
|
713
747
|
title: "Codex Relay Local Codex API",
|
|
714
|
-
version: "
|
|
748
|
+
version: "1.2.0"
|
|
715
749
|
},
|
|
716
750
|
paths: {
|
|
717
751
|
"/version": { get: {
|
|
@@ -838,6 +872,36 @@ function createOpenApiDocument() {
|
|
|
838
872
|
"409": jsonResponse("ErrorResponse")
|
|
839
873
|
}
|
|
840
874
|
} },
|
|
875
|
+
"/v1/threads/{threadId}/goal": {
|
|
876
|
+
get: {
|
|
877
|
+
summary: "Read the active goal for a Codex app-server thread",
|
|
878
|
+
responses: {
|
|
879
|
+
"200": jsonResponse("ThreadGoalResponse"),
|
|
880
|
+
"404": jsonResponse("ErrorResponse"),
|
|
881
|
+
"502": jsonResponse("ErrorResponse")
|
|
882
|
+
}
|
|
883
|
+
},
|
|
884
|
+
post: {
|
|
885
|
+
summary: "Update the active goal for a Codex app-server thread",
|
|
886
|
+
requestBody: jsonRequest("UpdateThreadGoalRequest"),
|
|
887
|
+
responses: {
|
|
888
|
+
"200": jsonResponse("ThreadGoalResponse"),
|
|
889
|
+
"400": jsonResponse("ErrorResponse"),
|
|
890
|
+
"404": jsonResponse("ErrorResponse"),
|
|
891
|
+
"409": jsonResponse("ErrorResponse"),
|
|
892
|
+
"502": jsonResponse("ErrorResponse")
|
|
893
|
+
}
|
|
894
|
+
},
|
|
895
|
+
delete: {
|
|
896
|
+
summary: "Clear the active goal for a Codex app-server thread",
|
|
897
|
+
responses: {
|
|
898
|
+
"200": jsonResponse("ThreadGoalResponse"),
|
|
899
|
+
"404": jsonResponse("ErrorResponse"),
|
|
900
|
+
"409": jsonResponse("ErrorResponse"),
|
|
901
|
+
"502": jsonResponse("ErrorResponse")
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
},
|
|
841
905
|
"/v1/threads/{threadId}/input": {
|
|
842
906
|
post: {
|
|
843
907
|
summary: "Submit input to an already-running Codex thread",
|
|
@@ -970,7 +1034,71 @@ function createOpenApiDocument() {
|
|
|
970
1034
|
},
|
|
971
1035
|
lastPrompt: { type: "string" },
|
|
972
1036
|
lastResult: { type: "string" },
|
|
973
|
-
lastError: { type: "string" }
|
|
1037
|
+
lastError: { type: "string" },
|
|
1038
|
+
goal: { anyOf: [{ $ref: "#/components/schemas/ThreadGoal" }, { type: "null" }] }
|
|
1039
|
+
}
|
|
1040
|
+
},
|
|
1041
|
+
ThreadGoal: {
|
|
1042
|
+
type: "object",
|
|
1043
|
+
required: [
|
|
1044
|
+
"threadId",
|
|
1045
|
+
"objective",
|
|
1046
|
+
"status",
|
|
1047
|
+
"tokenBudget",
|
|
1048
|
+
"tokensUsed",
|
|
1049
|
+
"timeUsedSeconds",
|
|
1050
|
+
"createdAt",
|
|
1051
|
+
"updatedAt"
|
|
1052
|
+
],
|
|
1053
|
+
properties: {
|
|
1054
|
+
threadId: { type: "string" },
|
|
1055
|
+
objective: { type: "string" },
|
|
1056
|
+
status: {
|
|
1057
|
+
type: "string",
|
|
1058
|
+
enum: ThreadGoalStatusSchema.options
|
|
1059
|
+
},
|
|
1060
|
+
tokenBudget: { anyOf: [{
|
|
1061
|
+
type: "integer",
|
|
1062
|
+
minimum: 1
|
|
1063
|
+
}, { type: "null" }] },
|
|
1064
|
+
tokensUsed: {
|
|
1065
|
+
type: "integer",
|
|
1066
|
+
minimum: 0
|
|
1067
|
+
},
|
|
1068
|
+
timeUsedSeconds: {
|
|
1069
|
+
type: "integer",
|
|
1070
|
+
minimum: 0
|
|
1071
|
+
},
|
|
1072
|
+
createdAt: {
|
|
1073
|
+
type: "string",
|
|
1074
|
+
format: "date-time"
|
|
1075
|
+
},
|
|
1076
|
+
updatedAt: {
|
|
1077
|
+
type: "string",
|
|
1078
|
+
format: "date-time"
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
},
|
|
1082
|
+
UpdateThreadGoalRequest: {
|
|
1083
|
+
type: "object",
|
|
1084
|
+
properties: {
|
|
1085
|
+
objective: { type: "string" },
|
|
1086
|
+
status: {
|
|
1087
|
+
type: "string",
|
|
1088
|
+
enum: ThreadGoalStatusSchema.options
|
|
1089
|
+
},
|
|
1090
|
+
tokenBudget: { anyOf: [{
|
|
1091
|
+
type: "integer",
|
|
1092
|
+
minimum: 1
|
|
1093
|
+
}, { type: "null" }] }
|
|
1094
|
+
}
|
|
1095
|
+
},
|
|
1096
|
+
ThreadGoalResponse: {
|
|
1097
|
+
type: "object",
|
|
1098
|
+
required: ["goal", "thread"],
|
|
1099
|
+
properties: {
|
|
1100
|
+
goal: { anyOf: [{ $ref: "#/components/schemas/ThreadGoal" }, { type: "null" }] },
|
|
1101
|
+
thread: { $ref: "#/components/schemas/ThreadSummary" }
|
|
974
1102
|
}
|
|
975
1103
|
},
|
|
976
1104
|
StatusResponse: {
|
|
@@ -1561,4 +1689,4 @@ function jsonResponse(schemaName) {
|
|
|
1561
1689
|
};
|
|
1562
1690
|
}
|
|
1563
1691
|
//#endregion
|
|
1564
|
-
export { SandboxModeSchema as $, PairResponseSchema as A,
|
|
1692
|
+
export { SandboxModeSchema as $, PairResponseSchema as A, WorkspaceSelectionRequestSchema as At, QueuedThreadInputSchema as B, isPromptSkillMarkdownMention as Bt, ListQueuedThreadInputsResponseSchema as C, WorkspaceDirectoryEntrySchema as Ct, ListWorkspaceFilesResponseSchema as D, WorkspaceMarkdownPreviewTargetSchema as Dt, ListWorkspaceDirectoriesResponseSchema as E, WorkspaceGitActionResponseSchema as Et, PromptAttachmentSummarySchema as F, WorkspaceTerminalSessionResponseSchema as Ft, ResolveApprovalRequestSchema as G, promptSkillMentionMarkdown as Gt, RateLimitWindowSchema as H, promptMarkdownWithSkills as Ht, PromptContextInputSchema as I, WorkspaceTerminalStartRequestSchema as It, RunThreadResponseSchema as J, ResolveApprovalResponseSchema as K, promptSkillMentionTextCandidates as Kt, PromptContextSchema as L, apiPaths as Lt, PendingInputRequestQuestionSchema as M, WorkspaceTerminalOutputChunkSchema as Mt, PendingInputRequestSchema as N, WorkspaceTerminalOutputResponseSchema as Nt, PairEncryptedPayloadSchema as O, WorkspacePreviewNavigationRequestSchema as Ot, PromptAttachmentSchema as P, WorkspaceTerminalResizeRequestSchema as Pt, RuntimePreferencesSchema as Q, PromptSkillSchema as R, chatMessageDetailsFromPromptContext as Rt, ListModelsResponseSchema as S, WorkspaceChangesResponseSchema as St, ListThreadsResponseSchema as T, WorkspaceFileMentionSchema as Tt, RateLimitsResponseSchema as U, promptSkillDisplayName as Ut, RateLimitBucketSchema as V, normalizePromptContext as Vt, ReasoningEffortSchema as W, promptSkillMentionLabel as Wt, RuntimePreferencesByWorkspacePathSchema as X, RuntimeModeSchema as Y, RuntimePreferencesResponseSchema as Z, EncryptedPayloadSchema as _, UpdateWorkspaceFileContentRequestSchema as _t, ArchiveThreadResponseSchema as a, ThreadContextWindowResponseSchema as at, InterruptThreadRunResponseSchema as b, WORKSPACE_PREVIEW_TAB_VALUES as bt, ChatMessageRoleSchema as c, ThreadGoalSchema as ct, CheckoutWorkspaceBranchRequestSchema as d, ThreadMessageDetailResponseSchema as dt, StatusResponseSchema as et, CodexModelSchema as f, ThreadRunOptionsSchema as ft, CreateThreadResponseSchema as g, UpdateThreadGoalRequestSchema as gt, CreateThreadRequestSchema as h, UpdateRuntimePreferencesRequestSchema as ht, ApprovalModeSchema as i, ThreadCollaborationModeSchema as it, PendingInputRequestOptionSchema as j, WorkspaceTerminalInputRequestSchema as jt, PairRequestSchema as k, WorkspacePreviewTabSchema as kt, ChatMessageSchema as l, ThreadGoalStatusSchema as lt, ContextWindowUsageSchema as m, ThreadSummarySchema as mt, AgentSkillSourceSchema as n, StreamThreadRunRequestSchema as nt, ChatMessageKindSchema as o, ThreadDetailResponseSchema as ot, CommitPushWorkspaceRequestSchema as p, ThreadStateSchema as pt, RunThreadRequestSchema as q, stripPromptSkillMentions as qt, ApprovalDecisionSchema as r, SubmitThreadInputResponseSchema as rt, ChatMessagePromptDetailsSchema as s, ThreadGoalResponseSchema as st, AgentSkillSchema as t, StreamThreadRunEventSchema as tt, ChatMessageStateSchema as u, ThreadMessageDetailFieldSchema as ut, ErrorResponseSchema as v, VersionResponseSchema as vt, ListSkillsResponseSchema as w, WorkspaceFileContentResponseSchema as wt, IsoDateTimeSchema as x, WebPreviewTargetSchema as xt, ImageAttachmentUploadResponseSchema as y, WORKSPACE_PREVIEW_OPEN_PROTOCOL as yt, QueuedThreadInputActionResponseSchema as z, createOpenApiDocument as zt };
|
package/dist/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
2
|
+
import { Lt as apiPaths } from "./api-schema2.js";
|
|
3
3
|
import { n as codexRelayHome, o as getConnectUrlGuidance, r as legacyCodexRelayDataPath, s as createTursoPairingSessionStore, t as codexRelayDataPath } from "./paths.js";
|
|
4
4
|
import { Command } from "@commander-js/extra-typings";
|
|
5
5
|
import qrcode from "qrcode-terminal";
|
package/dist/src.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as PairResponseSchema,
|
|
1
|
+
import { A as PairResponseSchema, C as ListQueuedThreadInputsResponseSchema, D as ListWorkspaceFilesResponseSchema, E as ListWorkspaceDirectoriesResponseSchema, Et as WorkspaceGitActionResponseSchema, Ft as WorkspaceTerminalSessionResponseSchema, G as ResolveApprovalRequestSchema, Ht as promptMarkdownWithSkills, It as WorkspaceTerminalStartRequestSchema, K as ResolveApprovalResponseSchema, Lt as apiPaths, Nt as WorkspaceTerminalOutputResponseSchema, Pt as WorkspaceTerminalResizeRequestSchema, Q as RuntimePreferencesSchema, Rt as chatMessageDetailsFromPromptContext, S as ListModelsResponseSchema, St as WorkspaceChangesResponseSchema, T as ListThreadsResponseSchema, U as RateLimitsResponseSchema, Vt as normalizePromptContext, X as RuntimePreferencesByWorkspacePathSchema, Z as RuntimePreferencesResponseSchema, _ as EncryptedPayloadSchema, _t as UpdateWorkspaceFileContentRequestSchema, a as ArchiveThreadResponseSchema, at as ThreadContextWindowResponseSchema, b as InterruptThreadRunResponseSchema, ct as ThreadGoalSchema, d as CheckoutWorkspaceBranchRequestSchema, dt as ThreadMessageDetailResponseSchema, et as StatusResponseSchema, gt as UpdateThreadGoalRequestSchema, h as CreateThreadRequestSchema, ht as UpdateRuntimePreferencesRequestSchema, jt as WorkspaceTerminalInputRequestSchema, k as PairRequestSchema, l as ChatMessageSchema, lt as ThreadGoalStatusSchema, m as ContextWindowUsageSchema, mt as ThreadSummarySchema, nt as StreamThreadRunRequestSchema, ot as ThreadDetailResponseSchema, p as CommitPushWorkspaceRequestSchema, q as RunThreadRequestSchema, qt as stripPromptSkillMentions, rt as SubmitThreadInputResponseSchema, st as ThreadGoalResponseSchema, tt as StreamThreadRunEventSchema, ut as ThreadMessageDetailFieldSchema, vt as VersionResponseSchema, w as ListSkillsResponseSchema, wt as WorkspaceFileContentResponseSchema, y as ImageAttachmentUploadResponseSchema, z as QueuedThreadInputActionResponseSchema, zt as createOpenApiDocument } from "./api-schema2.js";
|
|
2
2
|
import { a as getConnectUrlCandidates, i as createPairingQrPayload, o as getConnectUrlGuidance, r as legacyCodexRelayDataPath, s as createTursoPairingSessionStore, t as codexRelayDataPath } from "./paths.js";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import qrcode from "qrcode-terminal";
|
|
@@ -73,6 +73,15 @@ var CodexAppServerClient = class {
|
|
|
73
73
|
async archiveThread(params) {
|
|
74
74
|
await this.request("thread/archive", params);
|
|
75
75
|
}
|
|
76
|
+
async getThreadGoal(params) {
|
|
77
|
+
return (await this.request("thread/goal/get", params)).goal;
|
|
78
|
+
}
|
|
79
|
+
async setThreadGoal(params) {
|
|
80
|
+
return (await this.request("thread/goal/set", params)).goal;
|
|
81
|
+
}
|
|
82
|
+
async clearThreadGoal(params) {
|
|
83
|
+
await this.request("thread/goal/clear", params);
|
|
84
|
+
}
|
|
76
85
|
onNotification(handler) {
|
|
77
86
|
this.notificationHandlers.add(handler);
|
|
78
87
|
return () => this.notificationHandlers.delete(handler);
|
|
@@ -155,7 +164,7 @@ var CodexAppServerClient = class {
|
|
|
155
164
|
clientInfo: {
|
|
156
165
|
name: "codex-relay",
|
|
157
166
|
title: "Codex Relay Mobile Server",
|
|
158
|
-
version: "
|
|
167
|
+
version: "1.2.0"
|
|
159
168
|
},
|
|
160
169
|
capabilities: { experimentalApi: true }
|
|
161
170
|
}).then(() => void 0);
|
|
@@ -822,6 +831,16 @@ const defaultWebPreviewPorts = [
|
|
|
822
831
|
19006
|
|
823
832
|
];
|
|
824
833
|
const PairApproveRequestSchema = z.object({ approvalCode: z.string().trim().min(1) });
|
|
834
|
+
const AppServerThreadGoalPayloadSchema = z.object({
|
|
835
|
+
threadId: z.string().min(1),
|
|
836
|
+
objective: z.string().trim().min(1),
|
|
837
|
+
status: ThreadGoalStatusSchema,
|
|
838
|
+
tokenBudget: z.number().int().positive().nullable(),
|
|
839
|
+
tokensUsed: z.number().int().nonnegative(),
|
|
840
|
+
timeUsedSeconds: z.number().int().nonnegative(),
|
|
841
|
+
createdAt: z.number(),
|
|
842
|
+
updatedAt: z.number()
|
|
843
|
+
});
|
|
825
844
|
const maxResolvedApprovals = 100;
|
|
826
845
|
const maxWorkspaceTerminalOutputChunks = 2e3;
|
|
827
846
|
function createApp(options = {}) {
|
|
@@ -1570,6 +1589,72 @@ function createApp(options = {}) {
|
|
|
1570
1589
|
usage: result.usage
|
|
1571
1590
|
}));
|
|
1572
1591
|
});
|
|
1592
|
+
app.get("/v1/threads/:threadId/goal", async (c) => {
|
|
1593
|
+
const threadId = c.req.param("threadId");
|
|
1594
|
+
if (!appServer) {
|
|
1595
|
+
const thread = threads.get(threadId);
|
|
1596
|
+
if (!thread) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("not_found", `Thread ${threadId} is not known to this server.`), 404);
|
|
1597
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, ThreadGoalResponseSchema.parse({
|
|
1598
|
+
goal: thread.goal ?? null,
|
|
1599
|
+
thread
|
|
1600
|
+
}));
|
|
1601
|
+
}
|
|
1602
|
+
try {
|
|
1603
|
+
const thread = rememberAppServerThread(threads, await appServer.readThread(threadId, { includeTurns: false }));
|
|
1604
|
+
const goal = mapAppServerThreadGoal(await appServer.getThreadGoal({ threadId }));
|
|
1605
|
+
const threadWithGoal = rememberThreadGoal(threads, thread, goal);
|
|
1606
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, ThreadGoalResponseSchema.parse({
|
|
1607
|
+
goal,
|
|
1608
|
+
thread: threadWithGoal
|
|
1609
|
+
}));
|
|
1610
|
+
} catch (error) {
|
|
1611
|
+
const message = errorMessage(error);
|
|
1612
|
+
const status = /not found|no rollout found/i.test(message) ? 404 : 502;
|
|
1613
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError(status === 404 ? "not_found" : "goal_unavailable", message), status);
|
|
1614
|
+
}
|
|
1615
|
+
});
|
|
1616
|
+
app.post("/v1/threads/:threadId/goal", async (c) => {
|
|
1617
|
+
const threadId = c.req.param("threadId");
|
|
1618
|
+
if (!appServer) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("unsupported", "Thread goals require the Codex app-server."), 409);
|
|
1619
|
+
const parsed = await parseRequestJson(c, options.pairing, secureSessionsByTokenHash, UpdateThreadGoalRequestSchema);
|
|
1620
|
+
if (!parsed.success) return secureJson(c, options.pairing, secureSessionsByTokenHash, validationError(parsed.error), 400);
|
|
1621
|
+
try {
|
|
1622
|
+
const body = parsed.data;
|
|
1623
|
+
const thread = rememberAppServerThread(threads, await appServer.readThread(threadId, { includeTurns: false }));
|
|
1624
|
+
const goal = mapAppServerThreadGoal(await appServer.setThreadGoal({
|
|
1625
|
+
threadId,
|
|
1626
|
+
objective: body.objective,
|
|
1627
|
+
status: body.status,
|
|
1628
|
+
tokenBudget: body.tokenBudget
|
|
1629
|
+
}));
|
|
1630
|
+
const threadWithGoal = rememberThreadGoal(threads, thread, goal);
|
|
1631
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, ThreadGoalResponseSchema.parse({
|
|
1632
|
+
goal,
|
|
1633
|
+
thread: threadWithGoal
|
|
1634
|
+
}));
|
|
1635
|
+
} catch (error) {
|
|
1636
|
+
const message = errorMessage(error);
|
|
1637
|
+
const status = /not found|no rollout found/i.test(message) ? 404 : 502;
|
|
1638
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError(status === 404 ? "not_found" : "goal_unavailable", message), status);
|
|
1639
|
+
}
|
|
1640
|
+
});
|
|
1641
|
+
app.delete("/v1/threads/:threadId/goal", async (c) => {
|
|
1642
|
+
const threadId = c.req.param("threadId");
|
|
1643
|
+
if (!appServer) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("unsupported", "Thread goals require the Codex app-server."), 409);
|
|
1644
|
+
try {
|
|
1645
|
+
const thread = rememberAppServerThread(threads, await appServer.readThread(threadId, { includeTurns: false }));
|
|
1646
|
+
await appServer.clearThreadGoal({ threadId });
|
|
1647
|
+
const threadWithoutGoal = rememberThreadGoal(threads, thread, null);
|
|
1648
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, ThreadGoalResponseSchema.parse({
|
|
1649
|
+
goal: null,
|
|
1650
|
+
thread: threadWithoutGoal
|
|
1651
|
+
}));
|
|
1652
|
+
} catch (error) {
|
|
1653
|
+
const message = errorMessage(error);
|
|
1654
|
+
const status = /not found|no rollout found/i.test(message) ? 404 : 502;
|
|
1655
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError(status === 404 ? "not_found" : "goal_unavailable", message), status);
|
|
1656
|
+
}
|
|
1657
|
+
});
|
|
1573
1658
|
app.get("/openapi.json", (c) => secureJson(c, options.pairing, secureSessionsByTokenHash, createOpenApiDocument()));
|
|
1574
1659
|
app.post("/v1/approvals/:approvalId", async (c) => {
|
|
1575
1660
|
const approvalId = c.req.param("approvalId");
|
|
@@ -2229,16 +2314,17 @@ async function runPromptStreamed(input) {
|
|
|
2229
2314
|
if (kind === "error") throw new Error(text ?? "Codex run failed.");
|
|
2230
2315
|
if (!text) continue;
|
|
2231
2316
|
if (kind === "assistant") {
|
|
2232
|
-
|
|
2317
|
+
const assistantPatch = appendMessageDelta(input.messagesByThreadId, activeThreadId, assistantMessage.id, text);
|
|
2318
|
+
assistantMessage = assistantPatch.message;
|
|
2233
2319
|
updateThread(input.threads, input.messagesByThreadId, activeThreadId, {
|
|
2234
2320
|
state: "running",
|
|
2235
2321
|
lastResult: assistantMessage.content
|
|
2236
2322
|
});
|
|
2237
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
2323
|
+
if (assistantPatch.delta) sendSse(input.controller, input.encoder, input.secureSession, {
|
|
2238
2324
|
type: "thread.message.delta",
|
|
2239
2325
|
threadId: activeThreadId,
|
|
2240
2326
|
messageId: assistantMessage.id,
|
|
2241
|
-
delta:
|
|
2327
|
+
delta: assistantPatch.delta
|
|
2242
2328
|
});
|
|
2243
2329
|
} else {
|
|
2244
2330
|
const structured = structuredStreamMessage(kind, event, text);
|
|
@@ -2459,6 +2545,19 @@ async function streamRunningAppServerThread(input) {
|
|
|
2459
2545
|
}
|
|
2460
2546
|
return;
|
|
2461
2547
|
}
|
|
2548
|
+
case "thread/goal/updated":
|
|
2549
|
+
case "thread/goal/cleared": {
|
|
2550
|
+
const goal = notification.method === "thread/goal/updated" ? mapAppServerThreadGoal(appServerThreadGoalFromParams(params)) : null;
|
|
2551
|
+
const currentThreadSummary = threadSummary ?? input.threads.get(input.threadId);
|
|
2552
|
+
if (!currentThreadSummary) return;
|
|
2553
|
+
threadSummary = rememberThreadGoal(input.threads, currentThreadSummary, goal);
|
|
2554
|
+
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
2555
|
+
type: "thread.goal.updated",
|
|
2556
|
+
thread: threadSummary,
|
|
2557
|
+
goal
|
|
2558
|
+
});
|
|
2559
|
+
return;
|
|
2560
|
+
}
|
|
2462
2561
|
case "turn/started":
|
|
2463
2562
|
observedTurnActivity = true;
|
|
2464
2563
|
activeTurnId = firstString(params, ["turnId"]) ?? turnIdFromParams(params);
|
|
@@ -2494,16 +2593,17 @@ async function streamRunningAppServerThread(input) {
|
|
|
2494
2593
|
turnId: firstString(params, ["turnId"]) ?? activeTurnId
|
|
2495
2594
|
});
|
|
2496
2595
|
assistantMessageId = itemId;
|
|
2497
|
-
const
|
|
2596
|
+
const patch = appendMessageDelta(input.messagesByThreadId, input.threadId, itemId, delta);
|
|
2597
|
+
const message = patch.message;
|
|
2498
2598
|
updateThread(input.threads, input.messagesByThreadId, input.threadId, {
|
|
2499
2599
|
state: "running",
|
|
2500
2600
|
lastResult: message.content
|
|
2501
2601
|
});
|
|
2502
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
2602
|
+
if (patch.delta) sendSse(input.controller, input.encoder, input.secureSession, {
|
|
2503
2603
|
type: "thread.message.delta",
|
|
2504
2604
|
threadId: input.threadId,
|
|
2505
2605
|
messageId: itemId,
|
|
2506
|
-
delta
|
|
2606
|
+
delta: patch.delta
|
|
2507
2607
|
});
|
|
2508
2608
|
return;
|
|
2509
2609
|
}
|
|
@@ -2697,6 +2797,17 @@ async function runAppServerPromptStreamed(input) {
|
|
|
2697
2797
|
});
|
|
2698
2798
|
return;
|
|
2699
2799
|
}
|
|
2800
|
+
case "thread/goal/updated":
|
|
2801
|
+
case "thread/goal/cleared": {
|
|
2802
|
+
const goal = notification.method === "thread/goal/updated" ? mapAppServerThreadGoal(appServerThreadGoalFromParams(params)) : null;
|
|
2803
|
+
threadSummary = rememberThreadGoal(input.threads, threadSummary, goal);
|
|
2804
|
+
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
2805
|
+
type: "thread.goal.updated",
|
|
2806
|
+
thread: threadSummary,
|
|
2807
|
+
goal
|
|
2808
|
+
});
|
|
2809
|
+
return;
|
|
2810
|
+
}
|
|
2700
2811
|
case "turn/started":
|
|
2701
2812
|
activeTurnId = firstString(params, ["turnId"]) ?? turnIdFromParams(params);
|
|
2702
2813
|
if (activeTurnId) input.activeAppServerTurnIdsByThreadId.set(activeThreadId, activeTurnId);
|
|
@@ -2705,7 +2816,7 @@ async function runAppServerPromptStreamed(input) {
|
|
|
2705
2816
|
case "item/completed": {
|
|
2706
2817
|
const item = params?.item;
|
|
2707
2818
|
if (!item || typeof item !== "object") return;
|
|
2708
|
-
const canonicalUserMessage = replaceDuplicateInitialUserMessage(input.messagesByThreadId, activeThreadId, firstString(params, ["turnId"]) ?? activeTurnId, item, userMessage.id,
|
|
2819
|
+
const canonicalUserMessage = replaceDuplicateInitialUserMessage(input.messagesByThreadId, activeThreadId, firstString(params, ["turnId"]) ?? activeTurnId, item, userMessage.id, displayPrompt);
|
|
2709
2820
|
if (canonicalUserMessage) {
|
|
2710
2821
|
userMessage = canonicalUserMessage;
|
|
2711
2822
|
return;
|
|
@@ -2737,17 +2848,18 @@ async function runAppServerPromptStreamed(input) {
|
|
|
2737
2848
|
turnId: firstString(params, ["turnId"]) ?? activeTurnId
|
|
2738
2849
|
});
|
|
2739
2850
|
assistantMessageId = itemId;
|
|
2740
|
-
const
|
|
2851
|
+
const patch = appendMessageDelta(input.messagesByThreadId, activeThreadId, itemId, delta);
|
|
2852
|
+
const message = patch.message;
|
|
2741
2853
|
producedTurnOutput = true;
|
|
2742
2854
|
updateThread(input.threads, input.messagesByThreadId, activeThreadId, {
|
|
2743
2855
|
state: "running",
|
|
2744
2856
|
lastResult: message.content
|
|
2745
2857
|
});
|
|
2746
|
-
sendSse(input.controller, input.encoder, input.secureSession, {
|
|
2858
|
+
if (patch.delta) sendSse(input.controller, input.encoder, input.secureSession, {
|
|
2747
2859
|
type: "thread.message.delta",
|
|
2748
2860
|
threadId: activeThreadId,
|
|
2749
2861
|
messageId: itemId,
|
|
2750
|
-
delta
|
|
2862
|
+
delta: patch.delta
|
|
2751
2863
|
});
|
|
2752
2864
|
return;
|
|
2753
2865
|
}
|
|
@@ -3269,8 +3381,9 @@ function isDuplicateInitialUserMessage(messagesByThreadId, threadId, item, local
|
|
|
3269
3381
|
if (item.type !== "userMessage" || !("content" in item) || !Array.isArray(item.content)) return false;
|
|
3270
3382
|
const localMessage = messagesByThreadId.get(threadId)?.find((message) => message.id === localMessageId);
|
|
3271
3383
|
const skills = appServerUserMessageSkills(item);
|
|
3272
|
-
const
|
|
3273
|
-
|
|
3384
|
+
const normalizeContent = (content) => stripPromptSkillMentions(normalizeImageMessageContent(content), skills);
|
|
3385
|
+
const normalizedPrompt = normalizeContent(prompt);
|
|
3386
|
+
return normalizeContent(localMessage?.content ?? "") === normalizedPrompt && normalizeContent(appServerUserMessageText(item)) === normalizedPrompt;
|
|
3274
3387
|
}
|
|
3275
3388
|
function messageWithReplacementDetail(message, replacesMessageId) {
|
|
3276
3389
|
return ChatMessageSchema.parse({
|
|
@@ -3526,10 +3639,18 @@ function isAppServerSkillInput(input) {
|
|
|
3526
3639
|
}
|
|
3527
3640
|
function appendMessageDelta(messagesByThreadId, threadId, messageId, delta) {
|
|
3528
3641
|
const existing = messagesByThreadId.get(threadId)?.find((message) => message.id === messageId);
|
|
3529
|
-
|
|
3530
|
-
|
|
3531
|
-
|
|
3532
|
-
|
|
3642
|
+
const normalizedDelta = normalizeStreamDelta(existing?.content ?? "", delta);
|
|
3643
|
+
return {
|
|
3644
|
+
delta: normalizedDelta,
|
|
3645
|
+
message: updateMessage(messagesByThreadId, threadId, messageId, {
|
|
3646
|
+
content: `${existing?.content ?? ""}${normalizedDelta}`,
|
|
3647
|
+
state: "streaming"
|
|
3648
|
+
})
|
|
3649
|
+
};
|
|
3650
|
+
}
|
|
3651
|
+
function normalizeStreamDelta(existingContent, incomingDelta) {
|
|
3652
|
+
if (!existingContent || !incomingDelta.startsWith(existingContent)) return incomingDelta;
|
|
3653
|
+
return incomingDelta.slice(existingContent.length);
|
|
3533
3654
|
}
|
|
3534
3655
|
function markApprovalMessageResolved(messagesByThreadId, threadId, messageId, decision) {
|
|
3535
3656
|
const message = (messagesByThreadId.get(threadId) ?? []).find((candidate) => candidate.id === messageId);
|
|
@@ -3932,12 +4053,33 @@ function rememberAppServerThread(threads, thread) {
|
|
|
3932
4053
|
const mappedThread = mapAppServerThread(thread, existingThread?.messageCount);
|
|
3933
4054
|
const threadWithLocalRuntime = ThreadSummarySchema.parse({
|
|
3934
4055
|
...mappedThread,
|
|
4056
|
+
goal: existingThread?.goal ?? mappedThread.goal,
|
|
3935
4057
|
...runtimeMetadataFromOptions(existingThread ?? {}),
|
|
3936
4058
|
model: existingThread?.model ?? mappedThread.model
|
|
3937
4059
|
});
|
|
3938
4060
|
threads.set(threadWithLocalRuntime.id, threadWithLocalRuntime);
|
|
3939
4061
|
return threadWithLocalRuntime;
|
|
3940
4062
|
}
|
|
4063
|
+
function mapAppServerThreadGoal(goal) {
|
|
4064
|
+
if (!goal) return null;
|
|
4065
|
+
return ThreadGoalSchema.parse({
|
|
4066
|
+
...goal,
|
|
4067
|
+
createdAt: fromUnixSeconds(goal.createdAt),
|
|
4068
|
+
updatedAt: fromUnixSeconds(goal.updatedAt)
|
|
4069
|
+
});
|
|
4070
|
+
}
|
|
4071
|
+
function appServerThreadGoalFromParams(params) {
|
|
4072
|
+
const parsed = AppServerThreadGoalPayloadSchema.safeParse(params?.goal);
|
|
4073
|
+
return parsed.success ? parsed.data : null;
|
|
4074
|
+
}
|
|
4075
|
+
function rememberThreadGoal(threads, thread, goal) {
|
|
4076
|
+
const next = ThreadSummarySchema.parse({
|
|
4077
|
+
...thread,
|
|
4078
|
+
goal
|
|
4079
|
+
});
|
|
4080
|
+
threads.set(next.id, next);
|
|
4081
|
+
return next;
|
|
4082
|
+
}
|
|
3941
4083
|
function preserveKnownRunningThreadState(thread, wasKnownRunning) {
|
|
3942
4084
|
if (!wasKnownRunning || thread.state === "running") return thread;
|
|
3943
4085
|
return ThreadSummarySchema.parse({
|
|
@@ -4092,6 +4234,7 @@ function readRolloutThreadMessages(threadId, workspacePath = defaultWorkspacePat
|
|
|
4092
4234
|
};
|
|
4093
4235
|
const collected = [];
|
|
4094
4236
|
const applyPatchInputs = /* @__PURE__ */ new Map();
|
|
4237
|
+
const handledApplyPatchCallIds = /* @__PURE__ */ new Set();
|
|
4095
4238
|
const pendingApplyPatchChanges = [];
|
|
4096
4239
|
const lines = readFileSync(rolloutPath, "utf8").split("\n");
|
|
4097
4240
|
for (let index = 0; index < lines.length; index += 1) {
|
|
@@ -4102,7 +4245,7 @@ function readRolloutThreadMessages(threadId, workspacePath = defaultWorkspacePat
|
|
|
4102
4245
|
try {
|
|
4103
4246
|
const record = JSON.parse(line);
|
|
4104
4247
|
rememberRolloutApplyPatchInput(record, applyPatchInputs);
|
|
4105
|
-
collectRolloutApplyPatchOutput(record, workspacePath, applyPatchInputs, pendingApplyPatchChanges);
|
|
4248
|
+
collectRolloutApplyPatchOutput(record, workspacePath, applyPatchInputs, handledApplyPatchCallIds, pendingApplyPatchChanges);
|
|
4106
4249
|
if (isRolloutTaskComplete(record) && pendingApplyPatchChanges.length > 0) {
|
|
4107
4250
|
collected.push(rolloutApplyPatchSummaryMessage(threadId, record, `rollout:${lineNumber}:apply_patch`, pendingApplyPatchChanges));
|
|
4108
4251
|
pendingApplyPatchChanges.length = 0;
|
|
@@ -4111,6 +4254,11 @@ function readRolloutThreadMessages(threadId, workspacePath = defaultWorkspacePat
|
|
|
4111
4254
|
const message = rolloutRecordMessage(threadId, record, `rollout:${lineNumber}`, workspacePath);
|
|
4112
4255
|
if (!message) continue;
|
|
4113
4256
|
collected.push(message);
|
|
4257
|
+
const patchApplyEndCallId = rolloutPatchApplyEndCallId(record);
|
|
4258
|
+
if (patchApplyEndCallId) {
|
|
4259
|
+
handledApplyPatchCallIds.add(patchApplyEndCallId);
|
|
4260
|
+
pendingApplyPatchChanges.splice(0, pendingApplyPatchChanges.length, ...pendingApplyPatchChanges.filter((change) => change.callId !== patchApplyEndCallId));
|
|
4261
|
+
}
|
|
4114
4262
|
} catch {}
|
|
4115
4263
|
}
|
|
4116
4264
|
return {
|
|
@@ -4172,7 +4320,7 @@ function rolloutRecordMessage(threadId, record, messageKey, workspacePath = defa
|
|
|
4172
4320
|
if (record.type === "event_msg" && payload.type === "patch_apply_end") {
|
|
4173
4321
|
const changes = rolloutPatchApplyChanges(payload.changes, workspacePath);
|
|
4174
4322
|
if (changes.length === 0) return;
|
|
4175
|
-
const patchPreview = largeTextPreview(changes
|
|
4323
|
+
const patchPreview = largeTextPreview(rolloutPatchPreview(changes));
|
|
4176
4324
|
return ChatMessageSchema.parse({
|
|
4177
4325
|
id: `${messageKey}:patch:${firstString(payload, ["call_id"]) ?? ""}`,
|
|
4178
4326
|
threadId,
|
|
@@ -4182,7 +4330,7 @@ function rolloutRecordMessage(threadId, record, messageKey, workspacePath = defa
|
|
|
4182
4330
|
createdAt: timestamp,
|
|
4183
4331
|
state: "completed",
|
|
4184
4332
|
details: {
|
|
4185
|
-
changes: changes.map(
|
|
4333
|
+
changes: changes.map(publicRolloutPatchChange),
|
|
4186
4334
|
patch: patchPreview?.text,
|
|
4187
4335
|
patchOriginalLength: patchPreview?.originalLength,
|
|
4188
4336
|
patchTruncated: patchPreview?.truncated
|
|
@@ -4250,15 +4398,16 @@ function rememberRolloutApplyPatchInput(record, applyPatchInputs) {
|
|
|
4250
4398
|
const input = firstString(payload, ["input"]);
|
|
4251
4399
|
if (callId && input) applyPatchInputs.set(callId, input);
|
|
4252
4400
|
}
|
|
4253
|
-
function collectRolloutApplyPatchOutput(record, workspacePath, applyPatchInputs, pendingApplyPatchChanges) {
|
|
4401
|
+
function collectRolloutApplyPatchOutput(record, workspacePath, applyPatchInputs, handledApplyPatchCallIds, pendingApplyPatchChanges) {
|
|
4254
4402
|
const payload = record.payload;
|
|
4255
|
-
|
|
4403
|
+
const callId = firstString(payload, ["call_id"]);
|
|
4404
|
+
if (record.type !== "response_item" || payload?.type !== "custom_tool_call_output" || !callId || handledApplyPatchCallIds.has(callId)) return;
|
|
4256
4405
|
const changes = rolloutApplyPatchOutputChanges(rolloutCustomToolOutputText(payload), workspacePath);
|
|
4257
4406
|
if (changes.length === 0) return;
|
|
4258
|
-
const callId = firstString(payload, ["call_id"]);
|
|
4259
4407
|
const patch = callId ? applyPatchInputs.get(callId) : void 0;
|
|
4260
4408
|
for (const change of changes) pendingApplyPatchChanges.push({
|
|
4261
4409
|
...change,
|
|
4410
|
+
callId,
|
|
4262
4411
|
patch
|
|
4263
4412
|
});
|
|
4264
4413
|
}
|
|
@@ -4274,13 +4423,36 @@ function rolloutApplyPatchSummaryMessage(threadId, record, messageKey, pendingAp
|
|
|
4274
4423
|
createdAt: timestamp,
|
|
4275
4424
|
state: "completed",
|
|
4276
4425
|
details: {
|
|
4277
|
-
changes: pendingApplyPatchChanges.map(
|
|
4426
|
+
changes: pendingApplyPatchChanges.map(publicRolloutPatchChange),
|
|
4278
4427
|
patch: patchPreview?.text,
|
|
4279
4428
|
patchOriginalLength: patchPreview?.originalLength,
|
|
4280
4429
|
patchTruncated: patchPreview?.truncated
|
|
4281
4430
|
}
|
|
4282
4431
|
});
|
|
4283
4432
|
}
|
|
4433
|
+
function rolloutPatchApplyEndCallId(record) {
|
|
4434
|
+
if (record.type !== "event_msg" || record.payload?.type !== "patch_apply_end") return;
|
|
4435
|
+
return firstString(record.payload, ["call_id"]);
|
|
4436
|
+
}
|
|
4437
|
+
function publicRolloutPatchChange(change) {
|
|
4438
|
+
const { callId: _callId, patch: _patch, ...publicChange } = change;
|
|
4439
|
+
return publicChange;
|
|
4440
|
+
}
|
|
4441
|
+
function rolloutPatchPreview(changes) {
|
|
4442
|
+
return changes.flatMap((change) => {
|
|
4443
|
+
if (!change.patch) return [];
|
|
4444
|
+
if (hasPatchFileHeader(change.patch)) return [change.patch];
|
|
4445
|
+
return [`*** ${patchHeaderChangeKind(change.kind)} File: ${change.path}\n${change.patch}`];
|
|
4446
|
+
}).join("\n");
|
|
4447
|
+
}
|
|
4448
|
+
function hasPatchFileHeader(patch) {
|
|
4449
|
+
return /^(?:diff --git |\*\*\* (?:Add|Update|Delete) File: )/m.test(patch);
|
|
4450
|
+
}
|
|
4451
|
+
function patchHeaderChangeKind(kind) {
|
|
4452
|
+
if (kind === "added") return "Add";
|
|
4453
|
+
if (kind === "deleted") return "Delete";
|
|
4454
|
+
return "Update";
|
|
4455
|
+
}
|
|
4284
4456
|
function rolloutCustomToolOutputText(payload) {
|
|
4285
4457
|
const rawOutput = firstString(payload, ["output"]);
|
|
4286
4458
|
if (!rawOutput) return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-relay",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.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": "
|
|
43
|
+
"@openai/codex-sdk": "0.137.0",
|
|
44
44
|
"@tursodatabase/database": "^0.5.3",
|
|
45
45
|
"base64-js": "1.5.1",
|
|
46
46
|
"commander": "^14.0.3",
|
package/src/api-schema.ts
CHANGED
|
@@ -32,6 +32,14 @@ export const RuntimeModeSchema = z.enum(["default", "auto", "full-access", "on-r
|
|
|
32
32
|
export const SandboxModeSchema = z.enum(["workspace-write", "danger-full-access", "read-only"]);
|
|
33
33
|
export const ReasoningEffortSchema = z.enum(["minimal", "low", "medium", "high", "xhigh"]);
|
|
34
34
|
export const ThreadCollaborationModeSchema = z.enum(["default", "plan"]);
|
|
35
|
+
export const ThreadGoalStatusSchema = z.enum([
|
|
36
|
+
"active",
|
|
37
|
+
"paused",
|
|
38
|
+
"blocked",
|
|
39
|
+
"usageLimited",
|
|
40
|
+
"budgetLimited",
|
|
41
|
+
"complete",
|
|
42
|
+
]);
|
|
35
43
|
|
|
36
44
|
export const VersionResponseSchema = z.object({
|
|
37
45
|
ok: z.boolean(),
|
|
@@ -139,6 +147,17 @@ export const ThreadContextWindowResponseSchema = z.object({
|
|
|
139
147
|
rolloutPath: z.string().nullable().optional(),
|
|
140
148
|
});
|
|
141
149
|
|
|
150
|
+
export const ThreadGoalSchema = z.object({
|
|
151
|
+
threadId: z.string().min(1),
|
|
152
|
+
objective: z.string().trim().min(1),
|
|
153
|
+
status: ThreadGoalStatusSchema,
|
|
154
|
+
tokenBudget: z.number().int().positive().nullable(),
|
|
155
|
+
tokensUsed: z.number().int().nonnegative(),
|
|
156
|
+
timeUsedSeconds: z.number().int().nonnegative(),
|
|
157
|
+
createdAt: IsoDateTimeSchema,
|
|
158
|
+
updatedAt: IsoDateTimeSchema,
|
|
159
|
+
});
|
|
160
|
+
|
|
142
161
|
const PromptAttachmentBaseSchema = z.object({
|
|
143
162
|
type: z.literal("image"),
|
|
144
163
|
mimeType: z.string().trim().startsWith("image/").optional(),
|
|
@@ -266,6 +285,7 @@ export const ThreadSummarySchema = z.object({
|
|
|
266
285
|
lastPrompt: z.string().optional(),
|
|
267
286
|
lastResult: z.string().optional(),
|
|
268
287
|
lastError: z.string().optional(),
|
|
288
|
+
goal: ThreadGoalSchema.nullable().optional(),
|
|
269
289
|
});
|
|
270
290
|
|
|
271
291
|
export const StatusResponseSchema = z.object({
|
|
@@ -567,6 +587,21 @@ export const QueuedThreadInputActionResponseSchema = z.object({
|
|
|
567
587
|
thread: ThreadSummarySchema,
|
|
568
588
|
});
|
|
569
589
|
|
|
590
|
+
export const UpdateThreadGoalRequestSchema = z
|
|
591
|
+
.object({
|
|
592
|
+
objective: z.string().trim().min(1).optional(),
|
|
593
|
+
status: ThreadGoalStatusSchema.optional(),
|
|
594
|
+
tokenBudget: z.number().int().positive().nullable().optional(),
|
|
595
|
+
})
|
|
596
|
+
.refine((input) => input.objective || input.status || input.tokenBudget !== undefined, {
|
|
597
|
+
message: "At least one goal field is required.",
|
|
598
|
+
});
|
|
599
|
+
|
|
600
|
+
export const ThreadGoalResponseSchema = z.object({
|
|
601
|
+
goal: ThreadGoalSchema.nullable(),
|
|
602
|
+
thread: ThreadSummarySchema,
|
|
603
|
+
});
|
|
604
|
+
|
|
570
605
|
export const InterruptThreadRunResponseSchema = z.object({
|
|
571
606
|
thread: ThreadSummarySchema,
|
|
572
607
|
});
|
|
@@ -642,6 +677,11 @@ export const StreamThreadRunEventSchema = z.discriminatedUnion("type", [
|
|
|
642
677
|
type: z.literal("thread.state.changed"),
|
|
643
678
|
thread: ThreadSummarySchema,
|
|
644
679
|
}),
|
|
680
|
+
z.object({
|
|
681
|
+
type: z.literal("thread.goal.updated"),
|
|
682
|
+
thread: ThreadSummarySchema,
|
|
683
|
+
goal: ThreadGoalSchema.nullable(),
|
|
684
|
+
}),
|
|
645
685
|
z.object({
|
|
646
686
|
type: z.literal("thread.error"),
|
|
647
687
|
thread: ThreadSummarySchema.optional(),
|
|
@@ -691,6 +731,9 @@ export type RateLimitBucket = z.infer<typeof RateLimitBucketSchema>;
|
|
|
691
731
|
export type RateLimitWindow = z.infer<typeof RateLimitWindowSchema>;
|
|
692
732
|
export type RateLimitsResponse = z.infer<typeof RateLimitsResponseSchema>;
|
|
693
733
|
export type ThreadContextWindowResponse = z.infer<typeof ThreadContextWindowResponseSchema>;
|
|
734
|
+
export type ThreadGoal = z.infer<typeof ThreadGoalSchema>;
|
|
735
|
+
export type ThreadGoalResponse = z.infer<typeof ThreadGoalResponseSchema>;
|
|
736
|
+
export type ThreadGoalStatus = z.infer<typeof ThreadGoalStatusSchema>;
|
|
694
737
|
export type PromptAttachment = z.infer<typeof PromptAttachmentSchema>;
|
|
695
738
|
export type PendingInputRequest = z.infer<typeof PendingInputRequestSchema>;
|
|
696
739
|
export type PendingInputRequestQuestion = z.infer<typeof PendingInputRequestQuestionSchema>;
|
|
@@ -734,6 +777,7 @@ export type ImageAttachmentUploadResponse = z.infer<typeof ImageAttachmentUpload
|
|
|
734
777
|
export type QueuedThreadInput = z.infer<typeof QueuedThreadInputSchema>;
|
|
735
778
|
export type SubmitThreadInputResponse = z.infer<typeof SubmitThreadInputResponseSchema>;
|
|
736
779
|
export type QueuedThreadInputActionResponse = z.infer<typeof QueuedThreadInputActionResponseSchema>;
|
|
780
|
+
export type UpdateThreadGoalRequest = z.infer<typeof UpdateThreadGoalRequestSchema>;
|
|
737
781
|
export type InterruptThreadRunResponse = z.infer<typeof InterruptThreadRunResponseSchema>;
|
|
738
782
|
export type ListQueuedThreadInputsResponse = z.infer<typeof ListQueuedThreadInputsResponseSchema>;
|
|
739
783
|
export type ApprovalDecision = z.infer<typeof ApprovalDecisionSchema>;
|
|
@@ -988,6 +1032,7 @@ export const apiPaths = {
|
|
|
988
1032
|
threadArchive: (threadId: string) => `/v1/threads/${encodeURIComponent(threadId)}`,
|
|
989
1033
|
threadContextWindow: (threadId: string) =>
|
|
990
1034
|
`/v1/threads/${encodeURIComponent(threadId)}/context-window`,
|
|
1035
|
+
threadGoal: (threadId: string) => `/v1/threads/${encodeURIComponent(threadId)}/goal`,
|
|
991
1036
|
threadMessageDetail: (threadId: string, messageId: string, field: ThreadMessageDetailField) =>
|
|
992
1037
|
`/v1/threads/${encodeURIComponent(threadId)}/messages/${encodeURIComponent(messageId)}/details/${encodeURIComponent(field)}`,
|
|
993
1038
|
approval: (approvalId: string) => `/v1/approvals/${encodeURIComponent(approvalId)}`,
|
|
@@ -1007,7 +1052,7 @@ export function createOpenApiDocument() {
|
|
|
1007
1052
|
openapi: "3.1.0",
|
|
1008
1053
|
info: {
|
|
1009
1054
|
title: "Codex Relay Local Codex API",
|
|
1010
|
-
version: "
|
|
1055
|
+
version: "1.2.0",
|
|
1011
1056
|
},
|
|
1012
1057
|
paths: {
|
|
1013
1058
|
"/version": {
|
|
@@ -1162,6 +1207,36 @@ export function createOpenApiDocument() {
|
|
|
1162
1207
|
},
|
|
1163
1208
|
},
|
|
1164
1209
|
},
|
|
1210
|
+
"/v1/threads/{threadId}/goal": {
|
|
1211
|
+
get: {
|
|
1212
|
+
summary: "Read the active goal for a Codex app-server thread",
|
|
1213
|
+
responses: {
|
|
1214
|
+
"200": jsonResponse("ThreadGoalResponse"),
|
|
1215
|
+
"404": jsonResponse("ErrorResponse"),
|
|
1216
|
+
"502": jsonResponse("ErrorResponse"),
|
|
1217
|
+
},
|
|
1218
|
+
},
|
|
1219
|
+
post: {
|
|
1220
|
+
summary: "Update the active goal for a Codex app-server thread",
|
|
1221
|
+
requestBody: jsonRequest("UpdateThreadGoalRequest"),
|
|
1222
|
+
responses: {
|
|
1223
|
+
"200": jsonResponse("ThreadGoalResponse"),
|
|
1224
|
+
"400": jsonResponse("ErrorResponse"),
|
|
1225
|
+
"404": jsonResponse("ErrorResponse"),
|
|
1226
|
+
"409": jsonResponse("ErrorResponse"),
|
|
1227
|
+
"502": jsonResponse("ErrorResponse"),
|
|
1228
|
+
},
|
|
1229
|
+
},
|
|
1230
|
+
delete: {
|
|
1231
|
+
summary: "Clear the active goal for a Codex app-server thread",
|
|
1232
|
+
responses: {
|
|
1233
|
+
"200": jsonResponse("ThreadGoalResponse"),
|
|
1234
|
+
"404": jsonResponse("ErrorResponse"),
|
|
1235
|
+
"409": jsonResponse("ErrorResponse"),
|
|
1236
|
+
"502": jsonResponse("ErrorResponse"),
|
|
1237
|
+
},
|
|
1238
|
+
},
|
|
1239
|
+
},
|
|
1165
1240
|
"/v1/threads/{threadId}/input": {
|
|
1166
1241
|
post: {
|
|
1167
1242
|
summary: "Submit input to an already-running Codex thread",
|
|
@@ -1245,6 +1320,50 @@ export function createOpenApiDocument() {
|
|
|
1245
1320
|
lastPrompt: { type: "string" },
|
|
1246
1321
|
lastResult: { type: "string" },
|
|
1247
1322
|
lastError: { type: "string" },
|
|
1323
|
+
goal: {
|
|
1324
|
+
anyOf: [{ $ref: "#/components/schemas/ThreadGoal" }, { type: "null" }],
|
|
1325
|
+
},
|
|
1326
|
+
},
|
|
1327
|
+
},
|
|
1328
|
+
ThreadGoal: {
|
|
1329
|
+
type: "object",
|
|
1330
|
+
required: [
|
|
1331
|
+
"threadId",
|
|
1332
|
+
"objective",
|
|
1333
|
+
"status",
|
|
1334
|
+
"tokenBudget",
|
|
1335
|
+
"tokensUsed",
|
|
1336
|
+
"timeUsedSeconds",
|
|
1337
|
+
"createdAt",
|
|
1338
|
+
"updatedAt",
|
|
1339
|
+
],
|
|
1340
|
+
properties: {
|
|
1341
|
+
threadId: { type: "string" },
|
|
1342
|
+
objective: { type: "string" },
|
|
1343
|
+
status: { type: "string", enum: ThreadGoalStatusSchema.options },
|
|
1344
|
+
tokenBudget: { anyOf: [{ type: "integer", minimum: 1 }, { type: "null" }] },
|
|
1345
|
+
tokensUsed: { type: "integer", minimum: 0 },
|
|
1346
|
+
timeUsedSeconds: { type: "integer", minimum: 0 },
|
|
1347
|
+
createdAt: { type: "string", format: "date-time" },
|
|
1348
|
+
updatedAt: { type: "string", format: "date-time" },
|
|
1349
|
+
},
|
|
1350
|
+
},
|
|
1351
|
+
UpdateThreadGoalRequest: {
|
|
1352
|
+
type: "object",
|
|
1353
|
+
properties: {
|
|
1354
|
+
objective: { type: "string" },
|
|
1355
|
+
status: { type: "string", enum: ThreadGoalStatusSchema.options },
|
|
1356
|
+
tokenBudget: { anyOf: [{ type: "integer", minimum: 1 }, { type: "null" }] },
|
|
1357
|
+
},
|
|
1358
|
+
},
|
|
1359
|
+
ThreadGoalResponse: {
|
|
1360
|
+
type: "object",
|
|
1361
|
+
required: ["goal", "thread"],
|
|
1362
|
+
properties: {
|
|
1363
|
+
goal: {
|
|
1364
|
+
anyOf: [{ $ref: "#/components/schemas/ThreadGoal" }, { type: "null" }],
|
|
1365
|
+
},
|
|
1366
|
+
thread: { $ref: "#/components/schemas/ThreadSummary" },
|
|
1248
1367
|
},
|
|
1249
1368
|
},
|
|
1250
1369
|
StatusResponse: {
|