codex-relay 1.4.0 → 1.4.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/src.js +83 -45
- package/package.json +1 -1
package/dist/src.js
CHANGED
|
@@ -1418,6 +1418,7 @@ function createApp(options = {}) {
|
|
|
1418
1418
|
const pendingApprovals = /* @__PURE__ */ new Map();
|
|
1419
1419
|
const resolvedApprovals = /* @__PURE__ */ new Map();
|
|
1420
1420
|
const queuedInputsByThreadId = /* @__PURE__ */ new Map();
|
|
1421
|
+
const threadOperationTails = /* @__PURE__ */ new Map();
|
|
1421
1422
|
const workspaceTerminalSessions = /* @__PURE__ */ new Map();
|
|
1422
1423
|
const activeAppServerTurnIdsByThreadId = /* @__PURE__ */ new Map();
|
|
1423
1424
|
const appServerHistoryLoadsByThreadId = /* @__PURE__ */ new Map();
|
|
@@ -1425,6 +1426,15 @@ function createApp(options = {}) {
|
|
|
1425
1426
|
const secureSessionsByTokenHash = /* @__PURE__ */ new Map();
|
|
1426
1427
|
const activeStreamControllers = /* @__PURE__ */ new Set();
|
|
1427
1428
|
const threadOptions = { workingDirectory: workspacePath };
|
|
1429
|
+
function runThreadOperation(threadId, operation) {
|
|
1430
|
+
const result = (threadOperationTails.get(threadId) ?? Promise.resolve()).then(operation, operation);
|
|
1431
|
+
const tail = result.then(() => void 0, () => void 0);
|
|
1432
|
+
threadOperationTails.set(threadId, tail);
|
|
1433
|
+
tail.finally(() => {
|
|
1434
|
+
if (threadOperationTails.get(threadId) === tail) threadOperationTails.delete(threadId);
|
|
1435
|
+
});
|
|
1436
|
+
return result;
|
|
1437
|
+
}
|
|
1428
1438
|
const pushNotificationDispatcher = options.pairing ? createPushNotificationDispatcher({
|
|
1429
1439
|
sender: options.pushNotificationSender ?? createExpoPushNotificationSender(),
|
|
1430
1440
|
sessions: options.pairing.sessions
|
|
@@ -2392,44 +2402,46 @@ function createApp(options = {}) {
|
|
|
2392
2402
|
});
|
|
2393
2403
|
app.post("/v1/threads/:threadId/input", async (c) => {
|
|
2394
2404
|
const threadId = c.req.param("threadId");
|
|
2395
|
-
|
|
2396
|
-
|
|
2397
|
-
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
2429
|
-
|
|
2430
|
-
|
|
2405
|
+
return runThreadOperation(threadId, async () => {
|
|
2406
|
+
const knownThread = await ensureKnownThread({
|
|
2407
|
+
appServer,
|
|
2408
|
+
threadId,
|
|
2409
|
+
messagesByThreadId,
|
|
2410
|
+
threads
|
|
2411
|
+
});
|
|
2412
|
+
if (!knownThread) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("not_found", `Thread ${threadId} is not known to this server.`), 404);
|
|
2413
|
+
if (!appServer) return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("unsupported", "Running-thread input requires the Codex app-server."), 409);
|
|
2414
|
+
if (knownThread.state !== "running") return secureJson(c, options.pairing, secureSessionsByTokenHash, apiError("thread_not_running", `Thread ${threadId} is not currently running.`), 409);
|
|
2415
|
+
const parsed = await parseRequestJson(c, options.pairing, secureSessionsByTokenHash, RunThreadRequestSchema);
|
|
2416
|
+
if (!parsed.success) return secureJson(c, options.pairing, secureSessionsByTokenHash, validationError(parsed.error), 400);
|
|
2417
|
+
const runOptions = withRuntimePreferences(await preferences.read(knownThread.cwd ?? workspacePath), parsed.data);
|
|
2418
|
+
const skills = runOptions.skills ?? [];
|
|
2419
|
+
const prompt = runOptions.prompt;
|
|
2420
|
+
const queuedInputs = queuedInputsByThreadId.get(threadId) ?? [];
|
|
2421
|
+
const queuedInput = {
|
|
2422
|
+
attachments: runOptions.attachments ?? [],
|
|
2423
|
+
id: randomUUID(),
|
|
2424
|
+
prompt,
|
|
2425
|
+
runOptions,
|
|
2426
|
+
skills,
|
|
2427
|
+
workspacePath: knownThread.cwd ?? workspacePath
|
|
2428
|
+
};
|
|
2429
|
+
queuedInputs.push(queuedInput);
|
|
2430
|
+
queuedInputsByThreadId.set(threadId, queuedInputs);
|
|
2431
|
+
const thread = updateThread(threads, messagesByThreadId, threadId, {
|
|
2432
|
+
state: "running",
|
|
2433
|
+
lastPrompt: promptWithAttachmentReferences(prompt, runOptions.attachments ?? []),
|
|
2434
|
+
lastError: void 0,
|
|
2435
|
+
...runtimeMetadataFromOptions(runOptions)
|
|
2436
|
+
});
|
|
2437
|
+
const response = SubmitThreadInputResponseSchema.parse({
|
|
2438
|
+
acceptedAs: "queued",
|
|
2439
|
+
input: queuedThreadInputSummary(queuedInput),
|
|
2440
|
+
queueLength: queuedInputsByThreadId.get(threadId)?.length ?? 0,
|
|
2441
|
+
thread
|
|
2442
|
+
});
|
|
2443
|
+
return secureJson(c, options.pairing, secureSessionsByTokenHash, response, 202);
|
|
2431
2444
|
});
|
|
2432
|
-
return secureJson(c, options.pairing, secureSessionsByTokenHash, response, 202);
|
|
2433
2445
|
});
|
|
2434
2446
|
app.delete("/v1/threads/:threadId/input/:inputId", async (c) => {
|
|
2435
2447
|
const threadId = c.req.param("threadId");
|
|
@@ -2650,6 +2662,7 @@ function createApp(options = {}) {
|
|
|
2650
2662
|
messagesByThreadId,
|
|
2651
2663
|
pendingApprovals,
|
|
2652
2664
|
queuedInputsByThreadId,
|
|
2665
|
+
runThreadOperation,
|
|
2653
2666
|
prompt: rawPrompt,
|
|
2654
2667
|
attachments: runOptions.attachments ?? [],
|
|
2655
2668
|
secureSession,
|
|
@@ -2862,6 +2875,7 @@ async function runPromptStreamed(input) {
|
|
|
2862
2875
|
messagesByThreadId: input.messagesByThreadId,
|
|
2863
2876
|
pendingApprovals: input.pendingApprovals,
|
|
2864
2877
|
queuedInputsByThreadId: input.queuedInputsByThreadId,
|
|
2878
|
+
runThreadOperation: input.runThreadOperation,
|
|
2865
2879
|
prompt: input.prompt,
|
|
2866
2880
|
runOptions: input.runOptions,
|
|
2867
2881
|
secureSession: input.secureSession,
|
|
@@ -3693,11 +3707,16 @@ async function runAppServerPromptStreamed(input) {
|
|
|
3693
3707
|
case "turn/failed": {
|
|
3694
3708
|
const state = terminalTurnState(notification.method, params);
|
|
3695
3709
|
const terminalTurnId = firstString(params, ["turnId"]) ?? turnIdFromParams(params) ?? activeTurnId;
|
|
3696
|
-
|
|
3697
|
-
|
|
3698
|
-
|
|
3699
|
-
|
|
3700
|
-
|
|
3710
|
+
input.runThreadOperation(activeThreadId, async () => {
|
|
3711
|
+
finishTerminalTurn({
|
|
3712
|
+
lastError: state === "failed" ? turnErrorMessage(params) : void 0,
|
|
3713
|
+
method: notification.method,
|
|
3714
|
+
state,
|
|
3715
|
+
turnId: terminalTurnId
|
|
3716
|
+
});
|
|
3717
|
+
}).catch((error) => {
|
|
3718
|
+
cleanupNotificationHandler();
|
|
3719
|
+
rejectCompleted(error);
|
|
3701
3720
|
});
|
|
3702
3721
|
return;
|
|
3703
3722
|
}
|
|
@@ -5721,10 +5740,14 @@ function isApprovalServerRequest(method) {
|
|
|
5721
5740
|
}
|
|
5722
5741
|
function observeAppServerPushNotifications(appServer, dispatcher) {
|
|
5723
5742
|
const dispatchedEventIds = /* @__PURE__ */ new Set();
|
|
5724
|
-
const
|
|
5725
|
-
|
|
5743
|
+
const subagentThreadIds = /* @__PURE__ */ new Set();
|
|
5744
|
+
const rememberEventId = (eventId) => {
|
|
5726
5745
|
if (dispatchedEventIds.size >= 1e3) dispatchedEventIds.clear();
|
|
5727
5746
|
dispatchedEventIds.add(eventId);
|
|
5747
|
+
};
|
|
5748
|
+
const dispatch = (event, eventId) => {
|
|
5749
|
+
if (dispatchedEventIds.has(eventId)) return;
|
|
5750
|
+
rememberEventId(eventId);
|
|
5728
5751
|
dispatcher.dispatch(event).catch((error) => {
|
|
5729
5752
|
relayDebugLog("push_notification.dispatch_failed", {
|
|
5730
5753
|
error: errorMessage(error),
|
|
@@ -5735,9 +5758,15 @@ function observeAppServerPushNotifications(appServer, dispatcher) {
|
|
|
5735
5758
|
});
|
|
5736
5759
|
};
|
|
5737
5760
|
appServer.onNotification((notification) => {
|
|
5761
|
+
rememberSubagentThreadIds(notification, subagentThreadIds);
|
|
5738
5762
|
const event = pushNotificationEventFromTerminalNotification(notification);
|
|
5739
5763
|
if (!event) return;
|
|
5740
|
-
|
|
5764
|
+
const eventId = `${event.intent}:${event.threadId}:${event.turnId ?? ""}`;
|
|
5765
|
+
if (subagentThreadIds.delete(event.threadId)) {
|
|
5766
|
+
rememberEventId(eventId);
|
|
5767
|
+
return;
|
|
5768
|
+
}
|
|
5769
|
+
dispatch(event, eventId);
|
|
5741
5770
|
});
|
|
5742
5771
|
appServer.onRequest((request) => {
|
|
5743
5772
|
const event = pushNotificationEventFromApprovalRequest(request);
|
|
@@ -5745,6 +5774,15 @@ function observeAppServerPushNotifications(appServer, dispatcher) {
|
|
|
5745
5774
|
dispatch(event, `${event.intent}:${event.threadId}:${event.turnId ?? ""}:${request.id}`);
|
|
5746
5775
|
});
|
|
5747
5776
|
}
|
|
5777
|
+
function rememberSubagentThreadIds(notification, subagentThreadIds) {
|
|
5778
|
+
const item = objectRecord(recordParams(notification)?.item);
|
|
5779
|
+
if (item?.type !== "collabAgentToolCall" || ![
|
|
5780
|
+
"spawnAgent",
|
|
5781
|
+
"sendInput",
|
|
5782
|
+
"resumeAgent"
|
|
5783
|
+
].includes(String(item.tool))) return;
|
|
5784
|
+
for (const threadId of stringArray(item.receiverThreadIds)) subagentThreadIds.add(threadId);
|
|
5785
|
+
}
|
|
5748
5786
|
function pushNotificationEventFromTerminalNotification(notification) {
|
|
5749
5787
|
if (notification.method !== "turn/completed" && notification.method !== "turn/failed") return;
|
|
5750
5788
|
const params = recordParams(notification);
|