orkestrator 2.29.0-beta → 2.30.0-beta
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/client.js +956 -335
- package/dist/main.js +172332 -153863
- package/package.json +5 -5
- package/resources/claude-bridge/dist/index.js +264 -195
- package/resources/codex-bridge/dist/index.js +343 -60
|
@@ -4161,7 +4161,8 @@ var NATIVE_AGENT_COMMAND_CATALOGUE_ERROR_CODES = [
|
|
|
4161
4161
|
"rejected",
|
|
4162
4162
|
"malformed",
|
|
4163
4163
|
"too-large",
|
|
4164
|
-
"provider-error"
|
|
4164
|
+
"provider-error",
|
|
4165
|
+
"outdated-bridge"
|
|
4165
4166
|
];
|
|
4166
4167
|
var DEFAULT_NATIVE_AGENT_LIVE_WINDOW = {
|
|
4167
4168
|
messages: 100,
|
|
@@ -10805,18 +10806,11 @@ async function deriveTranscriptSubagentPartsForTurn({
|
|
|
10805
10806
|
}
|
|
10806
10807
|
|
|
10807
10808
|
// ../../bridges/codex-bridge/src/history/rollout.ts
|
|
10809
|
+
import { createHash as createHash7 } from "node:crypto";
|
|
10808
10810
|
import { readFile as readFile4, readdir, stat as stat4 } from "node:fs/promises";
|
|
10809
10811
|
import { homedir } from "node:os";
|
|
10810
10812
|
import { basename, join as join8 } from "node:path";
|
|
10811
10813
|
|
|
10812
|
-
// ../../bridges/codex-bridge/src/messages/types.ts
|
|
10813
|
-
function createMessageId() {
|
|
10814
|
-
return `msg-${crypto.randomUUID()}`;
|
|
10815
|
-
}
|
|
10816
|
-
function createSessionId() {
|
|
10817
|
-
return `session-${crypto.randomUUID()}`;
|
|
10818
|
-
}
|
|
10819
|
-
|
|
10820
10814
|
// ../../bridges/codex-bridge/src/sessions/refused-cell-tail.ts
|
|
10821
10815
|
import { open as open2, stat as stat3 } from "node:fs/promises";
|
|
10822
10816
|
var STRONG_REFUSAL_MARKERS = [
|
|
@@ -11415,6 +11409,7 @@ class TurnAccumulator {
|
|
|
11415
11409
|
turnId;
|
|
11416
11410
|
phase = "starting";
|
|
11417
11411
|
cancelRequested = false;
|
|
11412
|
+
stoppedByShutdown = false;
|
|
11418
11413
|
error;
|
|
11419
11414
|
finalDiff;
|
|
11420
11415
|
completedAt;
|
|
@@ -11427,9 +11422,15 @@ class TurnAccumulator {
|
|
|
11427
11422
|
changedFrozenRows = new Set;
|
|
11428
11423
|
steerFloor = 0;
|
|
11429
11424
|
modelToolCalled = false;
|
|
11425
|
+
pendingResponseBoundaries = 0;
|
|
11430
11426
|
noteModelToolCall() {
|
|
11431
11427
|
this.modelToolCalled = true;
|
|
11432
11428
|
}
|
|
11429
|
+
noteModelResponseCompleted() {
|
|
11430
|
+
if (this.isTerminal())
|
|
11431
|
+
return;
|
|
11432
|
+
this.pendingResponseBoundaries += 1;
|
|
11433
|
+
}
|
|
11433
11434
|
clientToolItemStartedBetween(fromMs, toMs) {
|
|
11434
11435
|
for (const accumulator of this.items.values()) {
|
|
11435
11436
|
const item = accumulator.item;
|
|
@@ -11767,6 +11768,7 @@ class TurnAccumulator {
|
|
|
11767
11768
|
startAssistantSegment(assistantMessageId, boundary, startedAt = new Date().toISOString()) {
|
|
11768
11769
|
this.assistantMessageId = assistantMessageId;
|
|
11769
11770
|
this.modelToolCalled = false;
|
|
11771
|
+
this.pendingResponseBoundaries = Math.max(0, this.pendingResponseBoundaries - 1);
|
|
11770
11772
|
const segment = {
|
|
11771
11773
|
assistantMessageId,
|
|
11772
11774
|
startIndex: boundary,
|
|
@@ -11779,11 +11781,13 @@ class TurnAccumulator {
|
|
|
11779
11781
|
opensModelStep(event) {
|
|
11780
11782
|
let itemId;
|
|
11781
11783
|
let type;
|
|
11784
|
+
let toolCall = false;
|
|
11782
11785
|
switch (event.kind) {
|
|
11783
11786
|
case "item.started":
|
|
11784
11787
|
case "item.completed":
|
|
11785
11788
|
itemId = event.item.id;
|
|
11786
11789
|
type = event.item.type;
|
|
11790
|
+
toolCall = isClientToolCall(event.item) && !isCodeModeCell(event.item);
|
|
11787
11791
|
break;
|
|
11788
11792
|
case "item.text.delta":
|
|
11789
11793
|
itemId = event.itemId;
|
|
@@ -11796,7 +11800,8 @@ class TurnAccumulator {
|
|
|
11796
11800
|
default:
|
|
11797
11801
|
return false;
|
|
11798
11802
|
}
|
|
11799
|
-
|
|
11803
|
+
const opensResponse = type === "reasoning" || type === "agent_message";
|
|
11804
|
+
if (!opensResponse && !(toolCall && this.pendingResponseBoundaries > 0))
|
|
11800
11805
|
return false;
|
|
11801
11806
|
if (this.items.has(itemId) || this.isTerminal())
|
|
11802
11807
|
return false;
|
|
@@ -12975,6 +12980,10 @@ var NON_TOOL_TURN_ITEM_TYPES = new Set([
|
|
|
12975
12980
|
"Plan"
|
|
12976
12981
|
]);
|
|
12977
12982
|
var MAX_OPEN_CODE_MODE_CELLS = 256;
|
|
12983
|
+
function replayedRowId(threadId, scope, kind, ordinal) {
|
|
12984
|
+
const digest = createHash7("sha256").update(`${threadId}\x00${scope}\x00${kind}\x00${ordinal}`).digest("hex");
|
|
12985
|
+
return `msg-r-${digest.slice(0, 32)}`;
|
|
12986
|
+
}
|
|
12978
12987
|
async function replayPersistedRollout(threadId, snapshot, meta, structuredTurns) {
|
|
12979
12988
|
const finalAssistantRecordByTurn = new Map;
|
|
12980
12989
|
if (structuredTurns.size > 0) {
|
|
@@ -13002,19 +13011,29 @@ async function replayPersistedRollout(threadId, snapshot, meta, structuredTurns)
|
|
|
13002
13011
|
let currentTurnModel;
|
|
13003
13012
|
let currentAssistantMessage;
|
|
13004
13013
|
let currentRowCalledTool = false;
|
|
13014
|
+
let responseCompletedInRow = false;
|
|
13005
13015
|
let nextRowStartedAt;
|
|
13006
13016
|
let lastTimestamp;
|
|
13007
13017
|
let unreadableRun;
|
|
13018
|
+
const rowOrdinals = new Map;
|
|
13019
|
+
const nextRowId = (kind) => {
|
|
13020
|
+
const scope = currentTurnId ?? "";
|
|
13021
|
+
const key = `${kind}\x00${scope}`;
|
|
13022
|
+
const ordinal = rowOrdinals.get(key) ?? 0;
|
|
13023
|
+
rowOrdinals.set(key, ordinal + 1);
|
|
13024
|
+
return replayedRowId(threadId, scope, kind, ordinal);
|
|
13025
|
+
};
|
|
13008
13026
|
const closeAssistantRow = () => {
|
|
13009
13027
|
currentAssistantMessage = undefined;
|
|
13010
13028
|
currentRowCalledTool = false;
|
|
13029
|
+
responseCompletedInRow = false;
|
|
13011
13030
|
nextRowStartedAt = undefined;
|
|
13012
13031
|
};
|
|
13013
13032
|
const ensureAssistantMessage = (timestamp) => {
|
|
13014
13033
|
if (currentAssistantMessage)
|
|
13015
13034
|
return currentAssistantMessage;
|
|
13016
13035
|
currentAssistantMessage = {
|
|
13017
|
-
id:
|
|
13036
|
+
id: nextRowId("assistant"),
|
|
13018
13037
|
role: "assistant",
|
|
13019
13038
|
content: "",
|
|
13020
13039
|
parts: [],
|
|
@@ -13161,7 +13180,7 @@ async function replayPersistedRollout(threadId, snapshot, meta, structuredTurns)
|
|
|
13161
13180
|
} else {
|
|
13162
13181
|
unreadableRun = {
|
|
13163
13182
|
message: {
|
|
13164
|
-
id:
|
|
13183
|
+
id: replayedRowId(threadId, currentTurnId ?? "", "unreadable", unreadable.offset),
|
|
13165
13184
|
role: "assistant",
|
|
13166
13185
|
content: "",
|
|
13167
13186
|
parts: [],
|
|
@@ -13200,11 +13219,16 @@ async function replayPersistedRollout(threadId, snapshot, meta, structuredTurns)
|
|
|
13200
13219
|
visitCompletedItem(record.payload.item, timestamp);
|
|
13201
13220
|
return;
|
|
13202
13221
|
}
|
|
13222
|
+
if (record.type === "token_usage_record" || record.type === "event_msg" && record.payload?.type === "token_count") {
|
|
13223
|
+
if (currentRowCalledTool)
|
|
13224
|
+
responseCompletedInRow = true;
|
|
13225
|
+
return;
|
|
13226
|
+
}
|
|
13203
13227
|
if (record.type !== "response_item" || !record.payload) {
|
|
13204
13228
|
return;
|
|
13205
13229
|
}
|
|
13206
13230
|
const payload = record.payload;
|
|
13207
|
-
if (currentRowCalledTool && (payload.type === "reasoning" || payload.type === "message" && payload.role === "assistant")) {
|
|
13231
|
+
if (currentRowCalledTool && (payload.type === "reasoning" || payload.type === "message" && payload.role === "assistant" || responseCompletedInRow && ROLLOUT_TOOL_CALL_TYPES.has(String(payload.type)))) {
|
|
13208
13232
|
closeAssistantRow();
|
|
13209
13233
|
nextRowStartedAt = timestamp;
|
|
13210
13234
|
}
|
|
@@ -13273,7 +13297,7 @@ async function replayPersistedRollout(threadId, snapshot, meta, structuredTurns)
|
|
|
13273
13297
|
}
|
|
13274
13298
|
closeAssistantRow();
|
|
13275
13299
|
messages.push({
|
|
13276
|
-
id:
|
|
13300
|
+
id: nextRowId("user"),
|
|
13277
13301
|
role,
|
|
13278
13302
|
content: text,
|
|
13279
13303
|
parts: [...text ? [{ type: "text", content: text }] : [], ...attachments],
|
|
@@ -13798,6 +13822,14 @@ async function renderTurn(turn, options) {
|
|
|
13798
13822
|
};
|
|
13799
13823
|
}
|
|
13800
13824
|
|
|
13825
|
+
// ../../bridges/codex-bridge/src/messages/types.ts
|
|
13826
|
+
function createMessageId() {
|
|
13827
|
+
return `msg-${crypto.randomUUID()}`;
|
|
13828
|
+
}
|
|
13829
|
+
function createSessionId() {
|
|
13830
|
+
return `session-${crypto.randomUUID()}`;
|
|
13831
|
+
}
|
|
13832
|
+
|
|
13801
13833
|
// ../../bridges/codex-bridge/src/app-server-runtime-rows.ts
|
|
13802
13834
|
function patchCommandChangePart(part, itemId, change) {
|
|
13803
13835
|
if (part.type === "tool-invocation" && part.toolUseId === itemId) {
|
|
@@ -14076,7 +14108,7 @@ async function publishAssistantRows(context, state, turn, options) {
|
|
|
14076
14108
|
}
|
|
14077
14109
|
|
|
14078
14110
|
// ../../bridges/codex-bridge/src/app-server-runtime-sessions.ts
|
|
14079
|
-
import { createHash as
|
|
14111
|
+
import { createHash as createHash10, randomUUID as randomUUID6 } from "node:crypto";
|
|
14080
14112
|
|
|
14081
14113
|
// ../protocol/src/agent-mail.ts
|
|
14082
14114
|
var AGENT_MAIL_MAX_BODY_BYTES = 32 * 1024;
|
|
@@ -14140,7 +14172,7 @@ var ORKESTRATOR_ARTIFACT_MCP_PATH = "/artifact-mcp";
|
|
|
14140
14172
|
|
|
14141
14173
|
// ../../bridges/codex-bridge/src/engine/app-server-engine.ts
|
|
14142
14174
|
import { open as open6 } from "node:fs/promises";
|
|
14143
|
-
import { createHash as
|
|
14175
|
+
import { createHash as createHash9 } from "node:crypto";
|
|
14144
14176
|
import { isAbsolute as isAbsolute7, join as join13 } from "node:path";
|
|
14145
14177
|
|
|
14146
14178
|
// ../../bridges/codex-bridge/src/app-server/process-supervisor.ts
|
|
@@ -16780,8 +16812,6 @@ var IGNORED_METHODS = new Set([
|
|
|
16780
16812
|
"autoApprovalReview/strictReviewRequired",
|
|
16781
16813
|
"mcpServer/event/stream/notification",
|
|
16782
16814
|
"thread/reverted",
|
|
16783
|
-
"modelProvider/authRecoveryStarted",
|
|
16784
|
-
"modelProvider/authRecoveryCompleted",
|
|
16785
16815
|
"thread/status/changed",
|
|
16786
16816
|
"thread/archived",
|
|
16787
16817
|
"thread/unarchived",
|
|
@@ -16853,6 +16883,25 @@ function reduceNotification(notification, generation, handle) {
|
|
|
16853
16883
|
]
|
|
16854
16884
|
};
|
|
16855
16885
|
}
|
|
16886
|
+
case "modelProvider/authRecoveryStarted":
|
|
16887
|
+
case "modelProvider/authRecoveryCompleted": {
|
|
16888
|
+
if (!threadId || !isRecord9(params))
|
|
16889
|
+
return { events: [] };
|
|
16890
|
+
const message = str3(params.message)?.trim().slice(0, 300);
|
|
16891
|
+
const provider = str3(params.provider)?.trim().slice(0, 64);
|
|
16892
|
+
return {
|
|
16893
|
+
events: [
|
|
16894
|
+
{
|
|
16895
|
+
kind: "thread.authRecovery",
|
|
16896
|
+
threadId,
|
|
16897
|
+
phase: notification.method === "modelProvider/authRecoveryStarted" ? "started" : "completed",
|
|
16898
|
+
...message ? { message } : {},
|
|
16899
|
+
...provider ? { provider } : {},
|
|
16900
|
+
...base
|
|
16901
|
+
}
|
|
16902
|
+
]
|
|
16903
|
+
};
|
|
16904
|
+
}
|
|
16856
16905
|
case "thread/tokenUsage/updated": {
|
|
16857
16906
|
if (!isRecord9(params) || !threadId || !turnId || !isRecord9(params.tokenUsage)) {
|
|
16858
16907
|
return { events: [] };
|
|
@@ -16895,7 +16944,8 @@ function reduceNotification(notification, generation, handle) {
|
|
|
16895
16944
|
updatedAt: new Date().toISOString()
|
|
16896
16945
|
},
|
|
16897
16946
|
...base
|
|
16898
|
-
}
|
|
16947
|
+
},
|
|
16948
|
+
{ kind: "model.response.completed", threadId, turnId, ...base }
|
|
16899
16949
|
]
|
|
16900
16950
|
};
|
|
16901
16951
|
}
|
|
@@ -17289,7 +17339,7 @@ import { mkdir as mkdir7, open as open4, rename as rename5, rm as rm7, writeFile
|
|
|
17289
17339
|
import { join as join12 } from "node:path";
|
|
17290
17340
|
|
|
17291
17341
|
// ../../bridges/codex-bridge/src/sessions/persistence.ts
|
|
17292
|
-
import { createHash as
|
|
17342
|
+
import { createHash as createHash8, randomUUID as randomUUID5 } from "node:crypto";
|
|
17293
17343
|
import {
|
|
17294
17344
|
chmod,
|
|
17295
17345
|
link as link2,
|
|
@@ -17383,7 +17433,7 @@ function isPersistedSessionTombstone(value) {
|
|
|
17383
17433
|
return tombstone.deleted === true && typeof tombstone.bridgeSessionId === "string" && tombstone.bridgeSessionId.length > 0 && typeof tombstone.deletedAt === "string" && Number.isFinite(Date.parse(tombstone.deletedAt));
|
|
17384
17434
|
}
|
|
17385
17435
|
function hashCwd(cwd) {
|
|
17386
|
-
return
|
|
17436
|
+
return createHash8("sha256").update(cwd).digest("hex").slice(0, 16);
|
|
17387
17437
|
}
|
|
17388
17438
|
var DEFAULT_RETENTION_MS = 7 * 24 * 60 * 60 * 1000;
|
|
17389
17439
|
var TEMP_FILE_GRACE_MS = 60 * 60 * 1000;
|
|
@@ -17412,7 +17462,7 @@ class BridgeSessionStore {
|
|
|
17412
17462
|
return join11(this.dir(), `bridge-sessions-${this.cwdHash}`);
|
|
17413
17463
|
}
|
|
17414
17464
|
recordKey(bridgeSessionId) {
|
|
17415
|
-
return
|
|
17465
|
+
return createHash8("sha256").update(bridgeSessionId).digest("hex");
|
|
17416
17466
|
}
|
|
17417
17467
|
recordPath(bridgeSessionId) {
|
|
17418
17468
|
return join11(this.recordsDir(), `${this.recordKey(bridgeSessionId)}.json`);
|
|
@@ -18808,7 +18858,7 @@ async function readStoredLoginFingerprint(codexHome) {
|
|
|
18808
18858
|
const apiKey = typeof root.OPENAI_API_KEY === "string" ? root.OPENAI_API_KEY : "";
|
|
18809
18859
|
if (!refreshToken && !apiKey)
|
|
18810
18860
|
return;
|
|
18811
|
-
return
|
|
18861
|
+
return createHash9("sha256").update(JSON.stringify([refreshToken, apiKey])).digest("hex");
|
|
18812
18862
|
} catch {
|
|
18813
18863
|
return;
|
|
18814
18864
|
}
|
|
@@ -18863,7 +18913,9 @@ class AppServerEngine {
|
|
|
18863
18913
|
pendingSignIn = null;
|
|
18864
18914
|
pendingSignInTimer;
|
|
18865
18915
|
completedLoginId = null;
|
|
18916
|
+
activeLoginId = null;
|
|
18866
18917
|
loginSequence = 0;
|
|
18918
|
+
loginStart;
|
|
18867
18919
|
accountServingGeneration;
|
|
18868
18920
|
notificationSequence = 0;
|
|
18869
18921
|
accountProofInvalidatedSequence = 0;
|
|
@@ -18907,7 +18959,7 @@ class AppServerEngine {
|
|
|
18907
18959
|
}),
|
|
18908
18960
|
onGenerationReady: (generation, previous) => this.handleGenerationChange(generation, previous),
|
|
18909
18961
|
onGenerationExit: (generation) => {
|
|
18910
|
-
this.
|
|
18962
|
+
this.forgetSignIn();
|
|
18911
18963
|
this.loginSequence++;
|
|
18912
18964
|
this.hostedNetworkLockVerifiedGeneration = null;
|
|
18913
18965
|
this.toolHistoryLockVerifiedGeneration = null;
|
|
@@ -18975,7 +19027,7 @@ class AppServerEngine {
|
|
|
18975
19027
|
return this.info();
|
|
18976
19028
|
}
|
|
18977
19029
|
async stop() {
|
|
18978
|
-
this.
|
|
19030
|
+
this.forgetSignIn();
|
|
18979
19031
|
await this.supervisor.stop();
|
|
18980
19032
|
this.bindings.clear();
|
|
18981
19033
|
this.rejectAllWaiters();
|
|
@@ -19059,6 +19111,8 @@ class AppServerEngine {
|
|
|
19059
19111
|
this.completedLoginId = loginId;
|
|
19060
19112
|
if (this.pendingSignIn?.loginId === loginId)
|
|
19061
19113
|
this.clearPendingSignIn();
|
|
19114
|
+
if (this.activeLoginId === loginId)
|
|
19115
|
+
this.activeLoginId = null;
|
|
19062
19116
|
}
|
|
19063
19117
|
}
|
|
19064
19118
|
if (notification.method === "account/login/completed" && objectRecord(notification.params).success === true || notification.method === "account/updated") {
|
|
@@ -19603,6 +19657,10 @@ class AppServerEngine {
|
|
|
19603
19657
|
this.pendingSignInTimer = undefined;
|
|
19604
19658
|
this.pendingSignIn = null;
|
|
19605
19659
|
}
|
|
19660
|
+
forgetSignIn() {
|
|
19661
|
+
this.clearPendingSignIn();
|
|
19662
|
+
this.activeLoginId = null;
|
|
19663
|
+
}
|
|
19606
19664
|
async readAccount() {
|
|
19607
19665
|
const sequence = ++this.accountCheckSequence;
|
|
19608
19666
|
const generation = this.supervisor.getGeneration();
|
|
@@ -19612,7 +19670,7 @@ class AppServerEngine {
|
|
|
19612
19670
|
console.warn("[codex-bridge] Account connector recovery failed:", redactSecrets(error instanceof Error ? error.message : String(error)));
|
|
19613
19671
|
});
|
|
19614
19672
|
if (loginSequence === this.loginSequence && objectRecord(response).account)
|
|
19615
|
-
this.
|
|
19673
|
+
this.forgetSignIn();
|
|
19616
19674
|
const pendingSignIn = normalizePendingSignIn(this.pendingSignIn?.display);
|
|
19617
19675
|
if (!pendingSignIn)
|
|
19618
19676
|
this.clearPendingSignIn();
|
|
@@ -19628,15 +19686,26 @@ class AppServerEngine {
|
|
|
19628
19686
|
}
|
|
19629
19687
|
async beginAccountLogin(method = "browser") {
|
|
19630
19688
|
const sequence = ++this.loginSequence;
|
|
19631
|
-
this.
|
|
19632
|
-
const
|
|
19689
|
+
this.forgetSignIn();
|
|
19690
|
+
const start = this.supervisor.requestWithGeneration("account/login/start", method === "device-code" ? {
|
|
19633
19691
|
type: "chatgptDeviceCode"
|
|
19634
19692
|
} : {
|
|
19635
19693
|
type: "chatgpt",
|
|
19636
19694
|
codexStreamlinedLogin: true,
|
|
19637
19695
|
useHostedLoginSuccessPage: true
|
|
19638
19696
|
});
|
|
19697
|
+
this.loginStart = start;
|
|
19698
|
+
let response;
|
|
19699
|
+
try {
|
|
19700
|
+
response = (await start).result;
|
|
19701
|
+
} finally {
|
|
19702
|
+
if (this.loginStart === start)
|
|
19703
|
+
this.loginStart = undefined;
|
|
19704
|
+
}
|
|
19639
19705
|
const raw = objectRecord(response);
|
|
19706
|
+
if (sequence === this.loginSequence && typeof raw.loginId === "string" && raw.loginId.length > 0 && raw.loginId.length <= 512 && raw.loginId !== this.completedLoginId) {
|
|
19707
|
+
this.activeLoginId = raw.loginId;
|
|
19708
|
+
}
|
|
19640
19709
|
const display = normalizePendingSignIn({
|
|
19641
19710
|
url: raw.verificationUrl,
|
|
19642
19711
|
code: raw.userCode,
|
|
@@ -19644,13 +19713,46 @@ class AppServerEngine {
|
|
|
19644
19713
|
});
|
|
19645
19714
|
if (sequence === this.loginSequence && typeof raw.loginId === "string" && raw.loginId.length > 0 && raw.loginId.length <= 512 && raw.loginId !== this.completedLoginId && display) {
|
|
19646
19715
|
this.pendingSignIn = { loginId: raw.loginId, display };
|
|
19647
|
-
this.pendingSignInTimer = setTimeout(() => this.
|
|
19716
|
+
this.pendingSignInTimer = setTimeout(() => void this.cancelAccountLogin().catch(() => {
|
|
19717
|
+
return;
|
|
19718
|
+
}), Math.max(0, display.expiresAt - Date.now()));
|
|
19648
19719
|
this.pendingSignInTimer.unref?.();
|
|
19649
19720
|
}
|
|
19650
19721
|
return response;
|
|
19651
19722
|
}
|
|
19723
|
+
async cancelAccountLogin() {
|
|
19724
|
+
let loginId = this.activeLoginId;
|
|
19725
|
+
const start = this.loginStart;
|
|
19726
|
+
let generation = this.supervisor.getGeneration();
|
|
19727
|
+
const sequence = ++this.loginSequence;
|
|
19728
|
+
if (!loginId && start) {
|
|
19729
|
+
const started = await start;
|
|
19730
|
+
generation = started.generation;
|
|
19731
|
+
if (generation !== this.supervisor.getGeneration())
|
|
19732
|
+
return "none";
|
|
19733
|
+
const raw = objectRecord(started.result);
|
|
19734
|
+
if (typeof raw.loginId === "string" && raw.loginId.length > 0 && raw.loginId.length <= 512 && raw.loginId !== this.completedLoginId) {
|
|
19735
|
+
loginId = raw.loginId;
|
|
19736
|
+
if (sequence === this.loginSequence) {
|
|
19737
|
+
this.activeLoginId = loginId;
|
|
19738
|
+
this.pendingSignInTimer = setTimeout(() => void this.cancelAccountLogin().catch(() => {
|
|
19739
|
+
return;
|
|
19740
|
+
}), NATIVE_AGENT_PENDING_SIGN_IN_TTL_MS);
|
|
19741
|
+
this.pendingSignInTimer.unref?.();
|
|
19742
|
+
}
|
|
19743
|
+
}
|
|
19744
|
+
}
|
|
19745
|
+
if (!loginId)
|
|
19746
|
+
return "none";
|
|
19747
|
+
const response = await this.supervisor.requestOnGeneration(generation, "account/login/cancel", {
|
|
19748
|
+
loginId
|
|
19749
|
+
});
|
|
19750
|
+
if (sequence === this.loginSequence && this.activeLoginId === loginId && generation === this.supervisor.getGeneration())
|
|
19751
|
+
this.forgetSignIn();
|
|
19752
|
+
return objectRecord(response).status === "canceled" ? "canceled" : "none";
|
|
19753
|
+
}
|
|
19652
19754
|
async logoutAccount() {
|
|
19653
|
-
this.
|
|
19755
|
+
this.forgetSignIn();
|
|
19654
19756
|
this.loginSequence++;
|
|
19655
19757
|
await this.supervisor.request("account/logout", undefined);
|
|
19656
19758
|
}
|
|
@@ -20319,7 +20421,7 @@ class CodexRuntimeSessions {
|
|
|
20319
20421
|
}
|
|
20320
20422
|
createSession(body) {
|
|
20321
20423
|
const clientSessionKey = typeof body.clientSessionKey === "string" && body.clientSessionKey.trim().length > 0 && body.clientSessionKey.length <= 512 ? body.clientSessionKey : undefined;
|
|
20322
|
-
const sessionId = clientSessionKey ? `session-client-${
|
|
20424
|
+
const sessionId = clientSessionKey ? `session-client-${createHash10("sha256").update(this.ctx.options.cwd).update("\x00").update(clientSessionKey).digest("hex").slice(0, 32)}` : createSessionId();
|
|
20323
20425
|
const existing = this.ctx.registry.getSession(sessionId);
|
|
20324
20426
|
if (existing) {
|
|
20325
20427
|
this.ctx.registry.touch(sessionId);
|
|
@@ -20605,7 +20707,7 @@ class CodexRuntimeSessions {
|
|
|
20605
20707
|
return "not-found";
|
|
20606
20708
|
if (this.sessionAdmissionClosed(session))
|
|
20607
20709
|
return "closing";
|
|
20608
|
-
const inputDigest =
|
|
20710
|
+
const inputDigest = createHash10("sha256").update(input).digest("hex");
|
|
20609
20711
|
const previous = this.ctx.steerRequests.get(requestId);
|
|
20610
20712
|
if (previous) {
|
|
20611
20713
|
if (previous.threadId !== session.threadId || previous.turnId !== expectedTurnId || previous.inputDigest !== inputDigest) {
|
|
@@ -20922,6 +21024,9 @@ class CodexRuntimeSessions {
|
|
|
20922
21024
|
logoutAuth() {
|
|
20923
21025
|
return this.ctx.options.engine.logoutAccount();
|
|
20924
21026
|
}
|
|
21027
|
+
cancelAuthLogin() {
|
|
21028
|
+
return this.ctx.options.engine.cancelAccountLogin();
|
|
21029
|
+
}
|
|
20925
21030
|
async rewindMessages(sessionId, messageId) {
|
|
20926
21031
|
const session = this.ctx.registry.getSession(sessionId);
|
|
20927
21032
|
if (!session)
|
|
@@ -21133,6 +21238,7 @@ class CodexRuntimeSessions {
|
|
|
21133
21238
|
messageRevision: session.messageRevision,
|
|
21134
21239
|
contentEpoch: session.contentEpoch,
|
|
21135
21240
|
...this.ctx.commandCatalogue.revision > 0 ? { commandRevision: this.ctx.commandCatalogue.revision } : {},
|
|
21241
|
+
...context?.authNotice ? { authNotice: context.authNotice } : {},
|
|
21136
21242
|
...this.ctx.options.engine.isAccountSignInRequired() ? {
|
|
21137
21243
|
readiness: {
|
|
21138
21244
|
state: "authentication-required",
|
|
@@ -21653,7 +21759,7 @@ function parseCommandToken(text, sigils = ["/"]) {
|
|
|
21653
21759
|
}
|
|
21654
21760
|
|
|
21655
21761
|
// ../../bridges/codex-bridge/src/prompts/template-discovery.ts
|
|
21656
|
-
import { createHash as
|
|
21762
|
+
import { createHash as createHash11 } from "node:crypto";
|
|
21657
21763
|
import { open as open7, readdir as readdir3, stat as stat7 } from "node:fs/promises";
|
|
21658
21764
|
import { join as join14 } from "node:path";
|
|
21659
21765
|
|
|
@@ -21794,7 +21900,7 @@ function templateBindingRevision(origin, relativePath) {
|
|
|
21794
21900
|
return commandBindingRevision(["template", origin, relativePath]);
|
|
21795
21901
|
}
|
|
21796
21902
|
function fingerprintOf(bytes) {
|
|
21797
|
-
return
|
|
21903
|
+
return createHash11("sha256").update(bytes).digest("hex").slice(0, 32);
|
|
21798
21904
|
}
|
|
21799
21905
|
function nameFromRelativePath(relativePath) {
|
|
21800
21906
|
return `/${relativePath.replace(/\.md$/i, "")}`;
|
|
@@ -22061,7 +22167,9 @@ var SKILL_INVENTORY_LIMITS = Object.freeze({
|
|
|
22061
22167
|
maxSkills: 512,
|
|
22062
22168
|
maxDescriptionBytes: 1000,
|
|
22063
22169
|
ttlMs: 30000,
|
|
22064
|
-
refreshDebounceMs: 250
|
|
22170
|
+
refreshDebounceMs: 250,
|
|
22171
|
+
coldSettleMs: 1000,
|
|
22172
|
+
maxSettleReads: 5
|
|
22065
22173
|
});
|
|
22066
22174
|
var SKILL_ID_PREFIX = "codex-skill:";
|
|
22067
22175
|
var SKILL_ALIAS_PREFIX = "/skill:";
|
|
@@ -22149,6 +22257,10 @@ function normalizeSkillsList(raw, context) {
|
|
|
22149
22257
|
fetchedAt: context.now
|
|
22150
22258
|
};
|
|
22151
22259
|
}
|
|
22260
|
+
function snapshotSignature(snapshot) {
|
|
22261
|
+
return snapshot.bindings.map((binding) => `${binding.bindingRevision}:${binding.enabled}:${binding.ambiguous}`).join(`
|
|
22262
|
+
`);
|
|
22263
|
+
}
|
|
22152
22264
|
function skillUnavailability(binding, projectResources = true) {
|
|
22153
22265
|
if (!projectResources && !["user", "system", "admin"].includes(binding.scope)) {
|
|
22154
22266
|
return {
|
|
@@ -22195,8 +22307,12 @@ class SkillInventory {
|
|
|
22195
22307
|
invalidationSerial = 0;
|
|
22196
22308
|
inflight = null;
|
|
22197
22309
|
refreshTimer = null;
|
|
22310
|
+
settledGeneration = null;
|
|
22311
|
+
settling = null;
|
|
22312
|
+
answeredGeneration = null;
|
|
22313
|
+
settleTimer = null;
|
|
22198
22314
|
disposed = false;
|
|
22199
|
-
stats = { invalidations: 0, reads: 0, scheduledRefreshes: 0 };
|
|
22315
|
+
stats = { invalidations: 0, reads: 0, scheduledRefreshes: 0, settlingReads: 0 };
|
|
22200
22316
|
constructor(deps) {
|
|
22201
22317
|
this.deps = deps;
|
|
22202
22318
|
}
|
|
@@ -22228,7 +22344,7 @@ class SkillInventory {
|
|
|
22228
22344
|
const snapshot = this.current();
|
|
22229
22345
|
const ttl = this.deps.ttlMs ?? SKILL_INVENTORY_LIMITS.ttlMs;
|
|
22230
22346
|
if (!options.forceReload && snapshot && !this.dirty && this.deps.now() - snapshot.fetchedAt < ttl) {
|
|
22231
|
-
return { snapshot, fresh: !snapshot.partial };
|
|
22347
|
+
return { snapshot, fresh: !snapshot.partial, settled: this.isSettled(snapshot.generation) };
|
|
22232
22348
|
}
|
|
22233
22349
|
if (this.inflight && (this.inflight.forced || !options.forceReload)) {
|
|
22234
22350
|
return this.inflight.promise;
|
|
@@ -22243,7 +22359,8 @@ class SkillInventory {
|
|
|
22243
22359
|
}
|
|
22244
22360
|
async refresh(forceReload) {
|
|
22245
22361
|
const read = await this.fetch(forceReload);
|
|
22246
|
-
this.
|
|
22362
|
+
if (!this.disposed)
|
|
22363
|
+
this.deps.onRefreshed?.(read);
|
|
22247
22364
|
return read;
|
|
22248
22365
|
}
|
|
22249
22366
|
async fetch(forceReload) {
|
|
@@ -22263,18 +22380,93 @@ class SkillInventory {
|
|
|
22263
22380
|
this.dirty = this.invalidationSerial !== serial;
|
|
22264
22381
|
const live = this.current();
|
|
22265
22382
|
if (!live)
|
|
22266
|
-
return {
|
|
22267
|
-
|
|
22383
|
+
return {
|
|
22384
|
+
snapshot: null,
|
|
22385
|
+
fresh: false,
|
|
22386
|
+
settled: false,
|
|
22387
|
+
error: "Codex restarted while listing skills"
|
|
22388
|
+
};
|
|
22389
|
+
this.noteSettlingAnswer(live, serial);
|
|
22390
|
+
this.noteAnswer(live);
|
|
22391
|
+
return { snapshot: live, fresh: !live.partial, settled: this.isSettled(live.generation) };
|
|
22268
22392
|
} catch {
|
|
22269
22393
|
this.dirty = true;
|
|
22270
|
-
|
|
22394
|
+
const retained = this.current();
|
|
22395
|
+
return {
|
|
22396
|
+
snapshot: retained,
|
|
22397
|
+
fresh: false,
|
|
22398
|
+
settled: retained ? this.isSettled(retained.generation) : false,
|
|
22399
|
+
error: "Codex skills could not be listed"
|
|
22400
|
+
};
|
|
22401
|
+
}
|
|
22402
|
+
}
|
|
22403
|
+
isSettled(generation) {
|
|
22404
|
+
return this.coldSettleMs() <= 0 || this.settledGeneration === generation;
|
|
22405
|
+
}
|
|
22406
|
+
coldSettleMs() {
|
|
22407
|
+
return this.deps.coldSettleMs ?? SKILL_INVENTORY_LIMITS.coldSettleMs;
|
|
22408
|
+
}
|
|
22409
|
+
noteAnswer(snapshot) {
|
|
22410
|
+
const { generation } = snapshot;
|
|
22411
|
+
if (this.isSettled(generation) || this.answeredGeneration === generation || this.disposed) {
|
|
22412
|
+
return;
|
|
22271
22413
|
}
|
|
22414
|
+
this.answeredGeneration = generation;
|
|
22415
|
+
this.armSettle(snapshot, 1);
|
|
22416
|
+
}
|
|
22417
|
+
noteSettlingAnswer(live, serial) {
|
|
22418
|
+
const settling = this.settling;
|
|
22419
|
+
if (!settling || settling.generation !== live.generation || serial < settling.serial)
|
|
22420
|
+
return;
|
|
22421
|
+
this.settling = null;
|
|
22422
|
+
if (settling.round >= 2 && snapshotSignature(live) === settling.baseline || settling.round >= SKILL_INVENTORY_LIMITS.maxSettleReads) {
|
|
22423
|
+
this.settledGeneration = live.generation;
|
|
22424
|
+
return;
|
|
22425
|
+
}
|
|
22426
|
+
this.armSettle(live, settling.round + 1);
|
|
22427
|
+
}
|
|
22428
|
+
armSettle(snapshot, round) {
|
|
22429
|
+
const { generation } = snapshot;
|
|
22430
|
+
const baseline = snapshotSignature(snapshot);
|
|
22431
|
+
if (this.settleTimer)
|
|
22432
|
+
clearTimeout(this.settleTimer);
|
|
22433
|
+
this.settleTimer = setTimeout(() => {
|
|
22434
|
+
this.settleTimer = null;
|
|
22435
|
+
if (this.disposed || this.deps.generation() !== generation)
|
|
22436
|
+
return;
|
|
22437
|
+
this.invalidationSerial += 1;
|
|
22438
|
+
this.dirty = true;
|
|
22439
|
+
const settling = {
|
|
22440
|
+
generation,
|
|
22441
|
+
serial: this.invalidationSerial,
|
|
22442
|
+
round,
|
|
22443
|
+
baseline
|
|
22444
|
+
};
|
|
22445
|
+
this.settling = settling;
|
|
22446
|
+
this.stats.settlingReads += 1;
|
|
22447
|
+
const pending = this.inflight?.promise.catch(() => {
|
|
22448
|
+
return;
|
|
22449
|
+
});
|
|
22450
|
+
const read = () => {
|
|
22451
|
+
if (this.disposed || this.deps.generation() !== generation || this.settling !== settling)
|
|
22452
|
+
return;
|
|
22453
|
+
return this.read();
|
|
22454
|
+
};
|
|
22455
|
+
(pending ? pending.then(read) : read())?.catch(() => {
|
|
22456
|
+
return;
|
|
22457
|
+
});
|
|
22458
|
+
}, this.coldSettleMs());
|
|
22459
|
+
this.settleTimer.unref?.();
|
|
22272
22460
|
}
|
|
22273
22461
|
dispose() {
|
|
22274
22462
|
this.disposed = true;
|
|
22275
22463
|
if (this.refreshTimer)
|
|
22276
22464
|
clearTimeout(this.refreshTimer);
|
|
22277
22465
|
this.refreshTimer = null;
|
|
22466
|
+
if (this.settleTimer)
|
|
22467
|
+
clearTimeout(this.settleTimer);
|
|
22468
|
+
this.settleTimer = null;
|
|
22469
|
+
this.settling = null;
|
|
22278
22470
|
}
|
|
22279
22471
|
}
|
|
22280
22472
|
|
|
@@ -22362,9 +22554,11 @@ class CodexCommandCatalogue {
|
|
|
22362
22554
|
now: options.now,
|
|
22363
22555
|
...options.skillTtlMs !== undefined ? { ttlMs: options.skillTtlMs } : {},
|
|
22364
22556
|
...options.skillRefreshDebounceMs !== undefined ? { refreshDebounceMs: options.skillRefreshDebounceMs } : {},
|
|
22557
|
+
...options.skillColdSettleMs !== undefined ? { coldSettleMs: options.skillColdSettleMs } : {},
|
|
22365
22558
|
onRefreshed: (read) => {
|
|
22366
22559
|
this.skillsDigest = commandBindingRevision([
|
|
22367
22560
|
String(read.fresh),
|
|
22561
|
+
String(read.settled),
|
|
22368
22562
|
read.snapshot ? JSON.stringify([
|
|
22369
22563
|
read.snapshot.truncated,
|
|
22370
22564
|
read.snapshot.bindings.map((binding) => skillCommandRow(binding))
|
|
@@ -22411,10 +22605,6 @@ class CodexCommandCatalogue {
|
|
|
22411
22605
|
this.bumpIfChanged();
|
|
22412
22606
|
return scan;
|
|
22413
22607
|
}
|
|
22414
|
-
async listTemplateAndBuiltinRows() {
|
|
22415
|
-
const templates = await this.scanTemplates();
|
|
22416
|
-
return [...BUILTINS.map(builtinRow), ...templates.effective.map(templateCommandRow)];
|
|
22417
|
-
}
|
|
22418
22608
|
async collect(projectResources = true) {
|
|
22419
22609
|
this.deferredBumps += 1;
|
|
22420
22610
|
let templates;
|
|
@@ -22444,7 +22634,7 @@ class CodexCommandCatalogue {
|
|
|
22444
22634
|
}
|
|
22445
22635
|
return {
|
|
22446
22636
|
commands,
|
|
22447
|
-
status: skillRead.fresh ? "ready" : "stale",
|
|
22637
|
+
status: skillRead.fresh && skillRead.settled ? "ready" : "stale",
|
|
22448
22638
|
truncated,
|
|
22449
22639
|
templates,
|
|
22450
22640
|
skills: skillRead.snapshot
|
|
@@ -22752,7 +22942,8 @@ class CodexRuntimeContext {
|
|
|
22752
22942
|
cwd: options.cwd,
|
|
22753
22943
|
now: this.now,
|
|
22754
22944
|
...options.skillInventoryTtlMs !== undefined ? { skillTtlMs: options.skillInventoryTtlMs } : {},
|
|
22755
|
-
...options.skillRefreshDebounceMs !== undefined ? { skillRefreshDebounceMs: options.skillRefreshDebounceMs } : {}
|
|
22945
|
+
...options.skillRefreshDebounceMs !== undefined ? { skillRefreshDebounceMs: options.skillRefreshDebounceMs } : {},
|
|
22946
|
+
...options.skillColdSettleMs !== undefined ? { skillColdSettleMs: options.skillColdSettleMs } : {}
|
|
22756
22947
|
});
|
|
22757
22948
|
}
|
|
22758
22949
|
getRevisedRowsOverflowVersion(sessionId) {
|
|
@@ -22792,6 +22983,30 @@ function promptThreadConfig(config) {
|
|
|
22792
22983
|
]);
|
|
22793
22984
|
}
|
|
22794
22985
|
|
|
22986
|
+
// ../../bridges/codex-bridge/src/sessions/auth-recovery-notice.ts
|
|
22987
|
+
var RENEWAL_FAILED = /\b(fail(?:ed|ure)?|could ?n[o']t|unable|unrecoverable|log ?(?:in|out) again|sign ?(?:in|out) again)\b/i;
|
|
22988
|
+
var CODEX_LOGIN_RENEWING_MESSAGE = "Codex's login stopped working during this turn, and Codex is renewing it.";
|
|
22989
|
+
var CODEX_LOGIN_RENEWAL_FAILED_SUFFIX = "Sign in to Codex again to keep working.";
|
|
22990
|
+
function nextThreadAuthNotice(current, event, newOccurrenceId) {
|
|
22991
|
+
if (event.phase === "started") {
|
|
22992
|
+
if (current?.state === "expired")
|
|
22993
|
+
return current;
|
|
22994
|
+
return {
|
|
22995
|
+
state: "expired",
|
|
22996
|
+
message: event.message ?? CODEX_LOGIN_RENEWING_MESSAGE,
|
|
22997
|
+
occurrenceId: newOccurrenceId()
|
|
22998
|
+
};
|
|
22999
|
+
}
|
|
23000
|
+
if (event.message && RENEWAL_FAILED.test(event.message)) {
|
|
23001
|
+
return {
|
|
23002
|
+
state: "needs-auth",
|
|
23003
|
+
message: `${event.message.replace(/[.\s]*$/, "")}. ${CODEX_LOGIN_RENEWAL_FAILED_SUFFIX}`,
|
|
23004
|
+
occurrenceId: current?.state === "needs-auth" ? current.occurrenceId : newOccurrenceId()
|
|
23005
|
+
};
|
|
23006
|
+
}
|
|
23007
|
+
return;
|
|
23008
|
+
}
|
|
23009
|
+
|
|
22795
23010
|
// ../../bridges/codex-bridge/src/messages/coalescer.ts
|
|
22796
23011
|
var DEFAULT_COALESCE_INTERVAL_MS = 100;
|
|
22797
23012
|
|
|
@@ -23480,6 +23695,9 @@ class CodexRuntimeLifecycle {
|
|
|
23480
23695
|
case "turn.model.updated":
|
|
23481
23696
|
this.applyConfirmedModel(context, event.model, event.turnId);
|
|
23482
23697
|
return;
|
|
23698
|
+
case "thread.authRecovery":
|
|
23699
|
+
this.setThreadAuthNotice(context, nextThreadAuthNotice(context.authNotice, event, () => crypto.randomUUID()));
|
|
23700
|
+
return;
|
|
23483
23701
|
case "turn.configuration.updated": {
|
|
23484
23702
|
const turn = context.activeTurn;
|
|
23485
23703
|
if (!turn || !turn.accepts(event))
|
|
@@ -23531,6 +23749,12 @@ class CodexRuntimeLifecycle {
|
|
|
23531
23749
|
turn.noteModelToolCall();
|
|
23532
23750
|
return;
|
|
23533
23751
|
}
|
|
23752
|
+
case "model.response.completed": {
|
|
23753
|
+
const turn = context.activeTurn;
|
|
23754
|
+
if (turn?.accepts(event))
|
|
23755
|
+
turn.noteModelResponseCompleted();
|
|
23756
|
+
return;
|
|
23757
|
+
}
|
|
23534
23758
|
case "item.started":
|
|
23535
23759
|
case "item.updated":
|
|
23536
23760
|
case "item.completed": {
|
|
@@ -23649,8 +23873,13 @@ class CodexRuntimeLifecycle {
|
|
|
23649
23873
|
const turn = context.activeTurn;
|
|
23650
23874
|
if (!turn || !turn.accepts(event))
|
|
23651
23875
|
return;
|
|
23876
|
+
if (event.status === "completed")
|
|
23877
|
+
this.setThreadAuthNotice(context, undefined);
|
|
23652
23878
|
this.discardOutlivingCommandWindows(turn);
|
|
23653
|
-
turn.
|
|
23879
|
+
if (turn.stoppedByShutdown && event.status === "interrupted")
|
|
23880
|
+
this.completeRecoveredTurn(turn, event.status);
|
|
23881
|
+
else
|
|
23882
|
+
turn.complete(event.status, event.error);
|
|
23654
23883
|
this.ctx.options.changeEvidence?.turn(this.evidenceSource(context, turn), event.status);
|
|
23655
23884
|
const finalize = () => this.runFinalization(context, turn).catch((error) => {
|
|
23656
23885
|
console.error(`[codex-bridge] Failed to finalize turn ${turn.turnId}:`, error instanceof Error ? error.message : error);
|
|
@@ -23944,6 +24173,18 @@ class CodexRuntimeLifecycle {
|
|
|
23944
24173
|
bytes: patchable ? estimateOrderedEventBytes(changedParts) : normalizedMessageSnapshotChars(target) * 2
|
|
23945
24174
|
});
|
|
23946
24175
|
}
|
|
24176
|
+
setThreadAuthNotice(context, notice) {
|
|
24177
|
+
if (context.authNotice === notice)
|
|
24178
|
+
return;
|
|
24179
|
+
context.authNotice = notice;
|
|
24180
|
+
for (const session of this.ctx.registry.boundSessionsForThread(context.threadId)) {
|
|
24181
|
+
this.ctx.options.emit({
|
|
24182
|
+
type: "session.updated",
|
|
24183
|
+
sessionId: session.id,
|
|
24184
|
+
data: { authNotice: notice ?? null }
|
|
24185
|
+
});
|
|
24186
|
+
}
|
|
24187
|
+
}
|
|
23947
24188
|
applyConfirmedModel(context, model, turnId) {
|
|
23948
24189
|
if (!turnId)
|
|
23949
24190
|
context.modelId = model;
|
|
@@ -25313,9 +25554,6 @@ class CodexRuntimePrompt {
|
|
|
25313
25554
|
}
|
|
25314
25555
|
return this.ctx.commandCatalogue.refresh();
|
|
25315
25556
|
}
|
|
25316
|
-
async listGlobalCommandRows() {
|
|
25317
|
-
return this.ctx.commandCatalogue.listTemplateAndBuiltinRows();
|
|
25318
|
-
}
|
|
25319
25557
|
async modelsListText(session) {
|
|
25320
25558
|
const { models } = await this.ctx.callbacks.listModels();
|
|
25321
25559
|
const current = session.config.model || models[0]?.id || "UNCONFIRMED";
|
|
@@ -25466,6 +25704,32 @@ class CodexRuntimeTail {
|
|
|
25466
25704
|
this.lifecycle = lifecycle;
|
|
25467
25705
|
this.sessions = sessions;
|
|
25468
25706
|
}
|
|
25707
|
+
async interruptForParentExit(budgetMs) {
|
|
25708
|
+
const stopping = [];
|
|
25709
|
+
for (const context of this.ctx.registry.listThreads()) {
|
|
25710
|
+
const turn = context.activeTurn;
|
|
25711
|
+
if (!turn || turn.isTerminal() || turn.isUnconfirmed())
|
|
25712
|
+
continue;
|
|
25713
|
+
turn.stoppedByShutdown = true;
|
|
25714
|
+
const { engineHandle } = context;
|
|
25715
|
+
stopping.push(this.ctx.options.engine.interruptTurn(engineHandle, turn.turnId).then(() => this.ctx.options.engine.waitForTurnTerminal(engineHandle, turn.turnId, {
|
|
25716
|
+
timeoutMs: budgetMs
|
|
25717
|
+
})).catch(() => {
|
|
25718
|
+
return;
|
|
25719
|
+
}));
|
|
25720
|
+
}
|
|
25721
|
+
if (stopping.length === 0)
|
|
25722
|
+
return 0;
|
|
25723
|
+
let timer;
|
|
25724
|
+
await Promise.race([
|
|
25725
|
+
Promise.allSettled(stopping),
|
|
25726
|
+
new Promise((resolve) => {
|
|
25727
|
+
timer = setTimeout(resolve, budgetMs);
|
|
25728
|
+
})
|
|
25729
|
+
]);
|
|
25730
|
+
clearTimeout(timer);
|
|
25731
|
+
return stopping.length;
|
|
25732
|
+
}
|
|
25469
25733
|
async abort(sessionId) {
|
|
25470
25734
|
const session = this.ctx.registry.getSession(sessionId);
|
|
25471
25735
|
if (!session)
|
|
@@ -25776,6 +26040,9 @@ class AppServerRuntime {
|
|
|
25776
26040
|
logoutAuth(...args) {
|
|
25777
26041
|
return this.sessions.logoutAuth(...args);
|
|
25778
26042
|
}
|
|
26043
|
+
cancelAuthLogin(...args) {
|
|
26044
|
+
return this.sessions.cancelAuthLogin(...args);
|
|
26045
|
+
}
|
|
25779
26046
|
rewindMessages(...args) {
|
|
25780
26047
|
return this.sessions.rewindMessages(...args);
|
|
25781
26048
|
}
|
|
@@ -25824,15 +26091,15 @@ class AppServerRuntime {
|
|
|
25824
26091
|
refreshCommandCatalogue(...args) {
|
|
25825
26092
|
return this.prompts.refreshCommandCatalogue(...args);
|
|
25826
26093
|
}
|
|
25827
|
-
listGlobalCommandRows(...args) {
|
|
25828
|
-
return this.prompts.listGlobalCommandRows(...args);
|
|
25829
|
-
}
|
|
25830
26094
|
get closeStopBudgetMs() {
|
|
25831
26095
|
return this.tail.closeStopBudgetMs;
|
|
25832
26096
|
}
|
|
25833
26097
|
set closeStopBudgetMs(value) {
|
|
25834
26098
|
this.tail.closeStopBudgetMs = value;
|
|
25835
26099
|
}
|
|
26100
|
+
interruptForParentExit(...args) {
|
|
26101
|
+
return this.tail.interruptForParentExit(...args);
|
|
26102
|
+
}
|
|
25836
26103
|
abort(...args) {
|
|
25837
26104
|
return this.tail.abort(...args);
|
|
25838
26105
|
}
|
|
@@ -26028,7 +26295,8 @@ function parseEventCursor(raw) {
|
|
|
26028
26295
|
|
|
26029
26296
|
// ../protocol/src/parent-watchdog.ts
|
|
26030
26297
|
var PARENT_PID_ENV = "ORKESTRATOR_PARENT_PID";
|
|
26031
|
-
var
|
|
26298
|
+
var PARENT_WATCH_INTERVAL_MS = 1000;
|
|
26299
|
+
var DEFAULT_POLL_INTERVAL_MS = PARENT_WATCH_INTERVAL_MS;
|
|
26032
26300
|
function parseParentPid(value) {
|
|
26033
26301
|
if (!value)
|
|
26034
26302
|
return null;
|
|
@@ -26460,6 +26728,19 @@ function createShutdownHandler(timer, clearTimer = clearInterval, exit = (code)
|
|
|
26460
26728
|
]).finally(() => exit(0));
|
|
26461
26729
|
};
|
|
26462
26730
|
}
|
|
26731
|
+
function createParentExitHandler(interrupt, shutdown, report = (turns, ms) => {
|
|
26732
|
+
console.error(`[codex-bridge] Stopped ${turns} running turn(s) in ${ms} ms`);
|
|
26733
|
+
}) {
|
|
26734
|
+
return async () => {
|
|
26735
|
+
const detectedAt = performance.now();
|
|
26736
|
+
try {
|
|
26737
|
+
const turns = await interrupt(PARENT_EXIT_INTERRUPT_BUDGET_MS).catch(() => 0);
|
|
26738
|
+
report(turns, Math.round(performance.now() - detectedAt));
|
|
26739
|
+
} finally {
|
|
26740
|
+
shutdown();
|
|
26741
|
+
}
|
|
26742
|
+
};
|
|
26743
|
+
}
|
|
26463
26744
|
var FALLBACK_MODELS = [
|
|
26464
26745
|
{
|
|
26465
26746
|
id: "gpt-5.4",
|
|
@@ -26756,6 +27037,7 @@ var __testing = {
|
|
|
26756
27037
|
createCodexProcessDiagnosticsForTesting: createCodexProcessDiagnostics,
|
|
26757
27038
|
createSharedTranscriptMetaLoaderForTesting: createSharedTranscriptMetaLoader,
|
|
26758
27039
|
createShutdownHandlerForTesting: createShutdownHandler,
|
|
27040
|
+
createParentExitHandlerForTesting: createParentExitHandler,
|
|
26759
27041
|
emitForTesting: emit,
|
|
26760
27042
|
eventRingForTesting: () => eventRing,
|
|
26761
27043
|
withIsolatedEventRingForTesting: () => {
|
|
@@ -26971,6 +27253,10 @@ app.post("/global/auth/login", async (c) => {
|
|
|
26971
27253
|
...raw.userCode ? { code: raw.userCode } : {}
|
|
26972
27254
|
});
|
|
26973
27255
|
});
|
|
27256
|
+
app.post("/global/auth/login/cancel", async (c) => {
|
|
27257
|
+
const status = await appServerRuntime.cancelAuthLogin();
|
|
27258
|
+
return c.json({ cancelled: status === "canceled" });
|
|
27259
|
+
});
|
|
26974
27260
|
app.post("/global/auth/logout", async (c) => {
|
|
26975
27261
|
await appServerRuntime.logoutAuth();
|
|
26976
27262
|
return c.json({ ok: true });
|
|
@@ -26982,10 +27268,6 @@ app.get("/global/usage", async (c) => {
|
|
|
26982
27268
|
const account = await appServerRuntime.readPlanUsage();
|
|
26983
27269
|
return c.json({ account: account ?? null });
|
|
26984
27270
|
});
|
|
26985
|
-
app.get("/global/slash-commands", async (c) => {
|
|
26986
|
-
const cwd = getWorkingDirectory();
|
|
26987
|
-
return c.json({ commands: await appServerRuntime.listGlobalCommandRows(), cwd });
|
|
26988
|
-
});
|
|
26989
27271
|
app.get("/session/:id/commands", async (c) => {
|
|
26990
27272
|
return c.json(await appServerRuntime.getCommandCatalogue(c.req.param("id")));
|
|
26991
27273
|
});
|
|
@@ -27602,13 +27884,14 @@ for (const signal of ["SIGTERM", "SIGINT"]) {
|
|
|
27602
27884
|
process.on(signal, shutdownHandler);
|
|
27603
27885
|
}
|
|
27604
27886
|
installFatalRejectionGuard({ label: "[codex-bridge]" });
|
|
27887
|
+
var PARENT_EXIT_INTERRUPT_BUDGET_MS = 2000;
|
|
27605
27888
|
var parentPid = parseParentPid(process.env[PARENT_PID_ENV]);
|
|
27606
27889
|
if (parentPid !== null) {
|
|
27607
27890
|
startParentWatchdog({
|
|
27608
27891
|
parentPid,
|
|
27609
27892
|
onParentExit: () => {
|
|
27610
27893
|
console.error(`[codex-bridge] Backend process ${parentPid} is gone; shutting down`);
|
|
27611
|
-
shutdownHandler();
|
|
27894
|
+
createParentExitHandler((budgetMs) => appServerRuntime.interruptForParentExit(budgetMs), shutdownHandler)();
|
|
27612
27895
|
}
|
|
27613
27896
|
});
|
|
27614
27897
|
}
|