orkestrator 2.26.3-beta → 2.27.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 +393 -95
- package/dist/main.js +11370 -8204
- package/package.json +3 -3
- package/resources/claude-bridge/dist/index.js +97 -16
- package/resources/codex-bridge/dist/index.js +43 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "orkestrator",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.27.0-beta",
|
|
4
4
|
"description": "Run the Orkestrator backend service without the desktop application",
|
|
5
5
|
"homepage": "https://orkestrator.dev",
|
|
6
6
|
"repository": {
|
|
@@ -39,8 +39,8 @@
|
|
|
39
39
|
"sharp": "0.35.5"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"@orkestrator/protocol": "2.
|
|
43
|
-
"@orkestrator/toolchain": "2.
|
|
42
|
+
"@orkestrator/protocol": "2.27.0-beta",
|
|
43
|
+
"@orkestrator/toolchain": "2.27.0-beta"
|
|
44
44
|
},
|
|
45
45
|
"engines": {
|
|
46
46
|
"bun": ">=1.4.3"
|
|
@@ -4243,6 +4243,7 @@ var NATIVE_AGENT_APPROVAL_MODES = Object.freeze({
|
|
|
4243
4243
|
]
|
|
4244
4244
|
});
|
|
4245
4245
|
var DISPATCH_OUTCOME_LOST_KIND = "dispatch-outcome-lost";
|
|
4246
|
+
var NATIVE_AGENT_RETIRED_DISPATCH_TTL_MS = 24 * 60 * 60 * 1000;
|
|
4246
4247
|
var SUPPRESSED_COMPOSER_PARAMETERS = Object.freeze({
|
|
4247
4248
|
claude: Object.freeze(["parameter:thinking", "parameter:context1m"]),
|
|
4248
4249
|
codex: Object.freeze(["parameter:summary"]),
|
|
@@ -4358,6 +4359,7 @@ var PROJECTION_FIELD_SET = new Set([
|
|
|
4358
4359
|
"runtimeHealthAuthoritative",
|
|
4359
4360
|
"notices",
|
|
4360
4361
|
"recoverableDispatch",
|
|
4362
|
+
"retiredDispatch",
|
|
4361
4363
|
"backgroundTasks",
|
|
4362
4364
|
"suggestedPrompt",
|
|
4363
4365
|
"completionBlockedByBackgroundTasks",
|
|
@@ -4381,6 +4383,7 @@ var OPTIONAL_PROJECTION_FIELD_SET = new Set([
|
|
|
4381
4383
|
"runtimeHealthAuthoritative",
|
|
4382
4384
|
"notices",
|
|
4383
4385
|
"recoverableDispatch",
|
|
4386
|
+
"retiredDispatch",
|
|
4384
4387
|
"backgroundTasks",
|
|
4385
4388
|
"suggestedPrompt",
|
|
4386
4389
|
"completionBlockedByBackgroundTasks",
|
|
@@ -5160,7 +5163,15 @@ async function stopBackgroundTask(sessionId, taskId) {
|
|
|
5160
5163
|
}
|
|
5161
5164
|
return { ok: true };
|
|
5162
5165
|
}
|
|
5166
|
+
var backgroundTaskRevisions = new WeakMap;
|
|
5167
|
+
function noteBackgroundTasksChanged(session) {
|
|
5168
|
+
backgroundTaskRevisions.set(session, (backgroundTaskRevisions.get(session) ?? 0) + 1);
|
|
5169
|
+
}
|
|
5170
|
+
function backgroundTaskRevision(session) {
|
|
5171
|
+
return backgroundTaskRevisions.get(session) ?? 0;
|
|
5172
|
+
}
|
|
5163
5173
|
function emitBackgroundTaskSnapshot(session) {
|
|
5174
|
+
noteBackgroundTasksChanged(session);
|
|
5164
5175
|
eventEmitter.emit({
|
|
5165
5176
|
type: "session.updated",
|
|
5166
5177
|
sessionId: session.id,
|
|
@@ -6771,6 +6782,34 @@ function getPromptDispatchState(sessionId, requestId) {
|
|
|
6771
6782
|
}
|
|
6772
6783
|
return "new";
|
|
6773
6784
|
}
|
|
6785
|
+
function idleSteerUserMessageId(requestId) {
|
|
6786
|
+
return `idle-steer:${requestId}`;
|
|
6787
|
+
}
|
|
6788
|
+
function restoredDispatchClaimLost(session, requestId) {
|
|
6789
|
+
if (!session?.restoredDispatchedRequestIds?.has(requestId))
|
|
6790
|
+
return false;
|
|
6791
|
+
const localReplyId = idleSteerUserMessageId(requestId);
|
|
6792
|
+
return !session.localTranscript?.some((message) => message.id === localReplyId);
|
|
6793
|
+
}
|
|
6794
|
+
async function persistedDispatchClaimLost(sessionId, requestId) {
|
|
6795
|
+
if (sessions.has(sessionId))
|
|
6796
|
+
return false;
|
|
6797
|
+
const sdkSessionId = sdkSessionIdFromBridgeId(sessionId);
|
|
6798
|
+
if (!sdkSessionId)
|
|
6799
|
+
return false;
|
|
6800
|
+
let preferences;
|
|
6801
|
+
try {
|
|
6802
|
+
preferences = await readSessionPreferences(sdkSessionId);
|
|
6803
|
+
} catch {
|
|
6804
|
+
return false;
|
|
6805
|
+
}
|
|
6806
|
+
if (!preferences || sessionPreferencesUnavailable(preferences))
|
|
6807
|
+
return false;
|
|
6808
|
+
if (!preferences.dispatchedRequestIds?.includes(requestId))
|
|
6809
|
+
return false;
|
|
6810
|
+
const localReplyId = idleSteerUserMessageId(requestId);
|
|
6811
|
+
return !preferences.localTranscript?.some((entry) => entry.id === localReplyId);
|
|
6812
|
+
}
|
|
6774
6813
|
async function claimPromptDispatch(sessionId, requestId, startDispatch, testHooks) {
|
|
6775
6814
|
const session = sessions.get(sessionId);
|
|
6776
6815
|
if (!session)
|
|
@@ -12179,7 +12218,7 @@ function displayCommandName(name) {
|
|
|
12179
12218
|
function normalizeAvailability(value) {
|
|
12180
12219
|
if (!isRecord(value))
|
|
12181
12220
|
return;
|
|
12182
|
-
if (
|
|
12221
|
+
if (typeof value.state !== "string")
|
|
12183
12222
|
return;
|
|
12184
12223
|
const reason = typeof value.reason === "string" && UNAVAILABLE_REASONS.has(value.reason) ? value.reason : undefined;
|
|
12185
12224
|
const message = boundedText(value.message, COMMAND_CATALOGUE_LIMITS.maxAvailabilityMessageBytes);
|
|
@@ -12696,7 +12735,10 @@ function idleSteerMessageIds(requestId) {
|
|
|
12696
12735
|
if (!requestId) {
|
|
12697
12736
|
return { userId: generateMessageId(), assistantId: generateMessageId() };
|
|
12698
12737
|
}
|
|
12699
|
-
return {
|
|
12738
|
+
return {
|
|
12739
|
+
userId: idleSteerUserMessageId(requestId),
|
|
12740
|
+
assistantId: `idle-steer-reply:${requestId}`
|
|
12741
|
+
};
|
|
12700
12742
|
}
|
|
12701
12743
|
async function answerIdleSteerPrompt(session, prompt, requestId) {
|
|
12702
12744
|
const reply = idleSteerPromptReply(prompt, "Claude");
|
|
@@ -15405,6 +15447,7 @@ async function handleResultMessage(turn, message) {
|
|
|
15405
15447
|
|
|
15406
15448
|
// ../../bridges/claude-bridge/src/services/session-manager-prompt-handlers/system-tasks.ts
|
|
15407
15449
|
function emitBackgroundTasks(turn) {
|
|
15450
|
+
noteBackgroundTasksChanged(turn.session);
|
|
15408
15451
|
eventEmitter.emit({
|
|
15409
15452
|
type: "session.updated",
|
|
15410
15453
|
sessionId: turn.sessionId,
|
|
@@ -16871,7 +16914,9 @@ var MCP_MANAGEMENT_LIMITS = {
|
|
|
16871
16914
|
operationStoreMaxBytes: 4 * 1024 * 1024,
|
|
16872
16915
|
runtimesPerOperation: 64,
|
|
16873
16916
|
runtimesTrackedPerOperation: 256,
|
|
16874
|
-
queuedApplyTargets: 32
|
|
16917
|
+
queuedApplyTargets: 32,
|
|
16918
|
+
overlayRecordMaxBytes: 3 * 1024 * 1024,
|
|
16919
|
+
containerPathProbesMax: 32
|
|
16875
16920
|
};
|
|
16876
16921
|
var MCP_SCOPE_LABELS = Object.freeze({
|
|
16877
16922
|
"backend-user": "Backend user",
|
|
@@ -17015,6 +17060,7 @@ var SESSION_ACTIVITY_BATCH_LIMITS = {
|
|
|
17015
17060
|
maxResponseBytes: 512 * 1024,
|
|
17016
17061
|
maxAsyncQuestionItemIds: 64,
|
|
17017
17062
|
maxAsyncQuestionItemIdLength: 2048,
|
|
17063
|
+
maxContentRevisionLength: 256,
|
|
17018
17064
|
readConcurrency: 4
|
|
17019
17065
|
};
|
|
17020
17066
|
var SESSION_ACTIVITY_STATES = new Set(["idle", "working", "waiting", "missing"]);
|
|
@@ -17029,6 +17075,7 @@ function parseSessionActivityObservation(value) {
|
|
|
17029
17075
|
if (!isRecord3(value))
|
|
17030
17076
|
return;
|
|
17031
17077
|
const { activity, readyForInput, completionPending, asyncQuestionItemIds, closing } = value;
|
|
17078
|
+
const { contentRevision } = value;
|
|
17032
17079
|
if (typeof activity !== "string" || !SESSION_ACTIVITY_STATES.has(activity))
|
|
17033
17080
|
return;
|
|
17034
17081
|
if (readyForInput !== undefined && typeof readyForInput !== "boolean")
|
|
@@ -17037,6 +17084,8 @@ function parseSessionActivityObservation(value) {
|
|
|
17037
17084
|
return;
|
|
17038
17085
|
if (closing !== undefined && typeof closing !== "boolean")
|
|
17039
17086
|
return;
|
|
17087
|
+
if (contentRevision !== undefined && !isContentRevision(contentRevision))
|
|
17088
|
+
return;
|
|
17040
17089
|
let itemIds;
|
|
17041
17090
|
if (asyncQuestionItemIds !== undefined) {
|
|
17042
17091
|
if (!Array.isArray(asyncQuestionItemIds) || asyncQuestionItemIds.length > SESSION_ACTIVITY_BATCH_LIMITS.maxAsyncQuestionItemIds || !asyncQuestionItemIds.every((itemId) => typeof itemId === "string" && itemId.length > 0 && itemId.length <= SESSION_ACTIVITY_BATCH_LIMITS.maxAsyncQuestionItemIdLength)) {
|
|
@@ -17049,9 +17098,13 @@ function parseSessionActivityObservation(value) {
|
|
|
17049
17098
|
...readyForInput !== undefined ? { readyForInput } : {},
|
|
17050
17099
|
...completionPending !== undefined ? { completionPending } : {},
|
|
17051
17100
|
...itemIds !== undefined ? { asyncQuestionItemIds: itemIds } : {},
|
|
17052
|
-
...closing !== undefined ? { closing } : {}
|
|
17101
|
+
...closing !== undefined ? { closing } : {},
|
|
17102
|
+
...contentRevision !== undefined ? { contentRevision } : {}
|
|
17053
17103
|
};
|
|
17054
17104
|
}
|
|
17105
|
+
function isContentRevision(value) {
|
|
17106
|
+
return typeof value === "string" && value.length > 0 && value.length <= SESSION_ACTIVITY_BATCH_LIMITS.maxContentRevisionLength;
|
|
17107
|
+
}
|
|
17055
17108
|
function parseSessionActivityBatchRequest(value) {
|
|
17056
17109
|
if (!isRecord3(value))
|
|
17057
17110
|
return { ok: false, error: "Expected a JSON object" };
|
|
@@ -17176,9 +17229,23 @@ async function readSessionActivityObservation(sessionId) {
|
|
|
17176
17229
|
const completionPending = resident ? sessionCompletionPending(resident) : undefined;
|
|
17177
17230
|
return {
|
|
17178
17231
|
activity: activity === "idle" && completionPending ? "working" : activity,
|
|
17179
|
-
...resident?.status === "idle" ? { readyForInput: true, completionPending } : {}
|
|
17232
|
+
...resident?.status === "idle" ? { readyForInput: true, completionPending } : {},
|
|
17233
|
+
...activity === "missing" ? {} : contentRevisionField(resident)
|
|
17180
17234
|
};
|
|
17181
17235
|
}
|
|
17236
|
+
function contentRevisionField(resident) {
|
|
17237
|
+
try {
|
|
17238
|
+
return { contentRevision: sessionContentRevision(resident) };
|
|
17239
|
+
} catch {
|
|
17240
|
+
return {};
|
|
17241
|
+
}
|
|
17242
|
+
}
|
|
17243
|
+
function sessionContentRevision(resident) {
|
|
17244
|
+
if (!resident)
|
|
17245
|
+
return eventEmitter.generation;
|
|
17246
|
+
const transcript = readTranscriptVersion(resident);
|
|
17247
|
+
return `${eventEmitter.generation}:${transcript.epoch}.${transcript.revision}:${backgroundTaskRevision(resident)}`;
|
|
17248
|
+
}
|
|
17182
17249
|
var sessionActivityBatch = new Hono2;
|
|
17183
17250
|
sessionActivityBatch.post(SESSION_ACTIVITY_BATCH_PATH, async (c) => {
|
|
17184
17251
|
const answer = await answerSessionActivityBatch(c.req.raw.body, readSessionActivityObservation, {
|
|
@@ -18449,13 +18516,20 @@ session.get("/:id/activity", async (c) => {
|
|
|
18449
18516
|
session.get("/:id/runtime-health", (c) => {
|
|
18450
18517
|
return c.json(sessionRuntimeHealthBody(peekSession(c.req.param("id"))));
|
|
18451
18518
|
});
|
|
18452
|
-
session.get("/:id/dispatch", (c) => {
|
|
18519
|
+
session.get("/:id/dispatch", async (c) => {
|
|
18520
|
+
const answer = (dispatch) => c.json({ dispatch });
|
|
18453
18521
|
const requestId = c.req.query("requestId")?.trim();
|
|
18454
18522
|
if (!requestId)
|
|
18455
|
-
return
|
|
18456
|
-
const
|
|
18457
|
-
const
|
|
18458
|
-
|
|
18523
|
+
return answer("unknown");
|
|
18524
|
+
const id = c.req.param("id");
|
|
18525
|
+
const state = getPromptDispatchState(id, requestId);
|
|
18526
|
+
if (state === "processing" || state === "already-processed")
|
|
18527
|
+
return answer("dispatched");
|
|
18528
|
+
if (state === "new") {
|
|
18529
|
+
return answer(restoredDispatchClaimLost(peekSession(id), requestId) ? "lost" : "unknown");
|
|
18530
|
+
}
|
|
18531
|
+
const lost = await persistedDispatchClaimLost(id, requestId).catch(() => false);
|
|
18532
|
+
return answer(lost ? "lost" : "unknown");
|
|
18459
18533
|
});
|
|
18460
18534
|
session.get("/:id/questions", (c) => {
|
|
18461
18535
|
const id = c.req.param("id");
|
|
@@ -18869,6 +18943,9 @@ function serializeEventData(event) {
|
|
|
18869
18943
|
}
|
|
18870
18944
|
var MAX_PENDING_SSE_FRAMES = 1000;
|
|
18871
18945
|
var MAX_PENDING_SSE_BYTES = 16 * 1024 * 1024;
|
|
18946
|
+
function observationFrameData(sessionId) {
|
|
18947
|
+
return JSON.stringify(sessionId === undefined ? {} : { sessionId });
|
|
18948
|
+
}
|
|
18872
18949
|
var MAX_REPLAY_SSE_FRAMES = 512;
|
|
18873
18950
|
var MAX_REPLAY_SSE_BYTES = 4 * 1024 * 1024;
|
|
18874
18951
|
var REPLAY_IDLE_RETENTION_MS = 60000;
|
|
@@ -18885,7 +18962,8 @@ function createReplayBuffer(limits = {}) {
|
|
|
18885
18962
|
id: `${generation}:${revision}`,
|
|
18886
18963
|
event: event.type,
|
|
18887
18964
|
data,
|
|
18888
|
-
bytes: Buffer.byteLength(data) + Buffer.byteLength(event.type)
|
|
18965
|
+
bytes: Buffer.byteLength(data) + Buffer.byteLength(event.type),
|
|
18966
|
+
...event.sessionId === undefined ? {} : { sessionId: event.sessionId }
|
|
18889
18967
|
};
|
|
18890
18968
|
frames.push(frame);
|
|
18891
18969
|
bytes += frame.bytes;
|
|
@@ -19063,6 +19141,7 @@ function createEventsRouter(limits = {}) {
|
|
|
19063
19141
|
if (!isOpen)
|
|
19064
19142
|
throw new Error("SSE request aborted");
|
|
19065
19143
|
}, () => closeConnection("write backlog exceeded its cap"), { maxPendingFrames, maxPendingBytes });
|
|
19144
|
+
const observe = c.req.query("observe") === "1";
|
|
19066
19145
|
const requestedCursorValue = c.req.header("last-event-id") ?? c.req.query("since");
|
|
19067
19146
|
const requestedCursor = parseReplayCursor(requestedCursorValue);
|
|
19068
19147
|
const cursorWasSupplied = requestedCursorValue !== undefined;
|
|
@@ -19071,12 +19150,12 @@ function createEventsRouter(limits = {}) {
|
|
|
19071
19150
|
let replaying = true;
|
|
19072
19151
|
let keepaliveInterval;
|
|
19073
19152
|
let unsubscribe = () => {};
|
|
19074
|
-
const releaseReplayRetention = replayRetention.acquire();
|
|
19153
|
+
const releaseReplayRetention = observe ? () => {} : replayRetention.acquire();
|
|
19075
19154
|
try {
|
|
19076
19155
|
unsubscribe = eventEmitter.subscribe((event, revision) => {
|
|
19077
19156
|
if (!isOpen)
|
|
19078
19157
|
return;
|
|
19079
|
-
const data = serializeEventData(event);
|
|
19158
|
+
const data = observe ? observationFrameData(event.sessionId) : serializeEventData(event);
|
|
19080
19159
|
const frame = {
|
|
19081
19160
|
revision,
|
|
19082
19161
|
id: formatReplayCursor(revision),
|
|
@@ -19113,7 +19192,8 @@ function createEventsRouter(limits = {}) {
|
|
|
19113
19192
|
status: "connected",
|
|
19114
19193
|
timestamp: connectedAt,
|
|
19115
19194
|
replayed: replay.frames.length,
|
|
19116
|
-
resetRequired: replay.resetRequired
|
|
19195
|
+
resetRequired: replay.resetRequired,
|
|
19196
|
+
...observe ? { observe: true } : {}
|
|
19117
19197
|
})
|
|
19118
19198
|
});
|
|
19119
19199
|
if (replay.resetRequired) {
|
|
@@ -19123,8 +19203,9 @@ function createEventsRouter(limits = {}) {
|
|
|
19123
19203
|
data: JSON.stringify({ through: formatReplayCursor(replayCeiling) })
|
|
19124
19204
|
});
|
|
19125
19205
|
} else {
|
|
19126
|
-
for (const frame of replay.frames)
|
|
19127
|
-
await writeFrame(frame);
|
|
19206
|
+
for (const frame of replay.frames) {
|
|
19207
|
+
await writeFrame(observe ? { ...frame, data: observationFrameData(frame.sessionId) } : frame);
|
|
19208
|
+
}
|
|
19128
19209
|
}
|
|
19129
19210
|
const drained = pendingLiveFrames.splice(0);
|
|
19130
19211
|
pendingLiveBytes = 0;
|
|
@@ -4060,6 +4060,7 @@ var NATIVE_AGENT_APPROVAL_MODES = Object.freeze({
|
|
|
4060
4060
|
}
|
|
4061
4061
|
]
|
|
4062
4062
|
});
|
|
4063
|
+
var NATIVE_AGENT_RETIRED_DISPATCH_TTL_MS = 24 * 60 * 60 * 1000;
|
|
4063
4064
|
var SUPPRESSED_COMPOSER_PARAMETERS = Object.freeze({
|
|
4064
4065
|
claude: Object.freeze(["parameter:thinking", "parameter:context1m"]),
|
|
4065
4066
|
codex: Object.freeze(["parameter:summary"]),
|
|
@@ -4191,6 +4192,7 @@ var PROJECTION_FIELD_SET = new Set([
|
|
|
4191
4192
|
"runtimeHealthAuthoritative",
|
|
4192
4193
|
"notices",
|
|
4193
4194
|
"recoverableDispatch",
|
|
4195
|
+
"retiredDispatch",
|
|
4194
4196
|
"backgroundTasks",
|
|
4195
4197
|
"suggestedPrompt",
|
|
4196
4198
|
"completionBlockedByBackgroundTasks",
|
|
@@ -4214,6 +4216,7 @@ var OPTIONAL_PROJECTION_FIELD_SET = new Set([
|
|
|
4214
4216
|
"runtimeHealthAuthoritative",
|
|
4215
4217
|
"notices",
|
|
4216
4218
|
"recoverableDispatch",
|
|
4219
|
+
"retiredDispatch",
|
|
4217
4220
|
"backgroundTasks",
|
|
4218
4221
|
"suggestedPrompt",
|
|
4219
4222
|
"completionBlockedByBackgroundTasks",
|
|
@@ -5089,6 +5092,7 @@ var SESSION_ACTIVITY_BATCH_LIMITS = {
|
|
|
5089
5092
|
maxResponseBytes: 512 * 1024,
|
|
5090
5093
|
maxAsyncQuestionItemIds: 64,
|
|
5091
5094
|
maxAsyncQuestionItemIdLength: 2048,
|
|
5095
|
+
maxContentRevisionLength: 256,
|
|
5092
5096
|
readConcurrency: 4
|
|
5093
5097
|
};
|
|
5094
5098
|
var SESSION_ACTIVITY_STATES = new Set(["idle", "working", "waiting", "missing"]);
|
|
@@ -5103,6 +5107,7 @@ function parseSessionActivityObservation(value) {
|
|
|
5103
5107
|
if (!isRecord(value))
|
|
5104
5108
|
return;
|
|
5105
5109
|
const { activity, readyForInput, completionPending, asyncQuestionItemIds, closing } = value;
|
|
5110
|
+
const { contentRevision } = value;
|
|
5106
5111
|
if (typeof activity !== "string" || !SESSION_ACTIVITY_STATES.has(activity))
|
|
5107
5112
|
return;
|
|
5108
5113
|
if (readyForInput !== undefined && typeof readyForInput !== "boolean")
|
|
@@ -5111,6 +5116,8 @@ function parseSessionActivityObservation(value) {
|
|
|
5111
5116
|
return;
|
|
5112
5117
|
if (closing !== undefined && typeof closing !== "boolean")
|
|
5113
5118
|
return;
|
|
5119
|
+
if (contentRevision !== undefined && !isContentRevision(contentRevision))
|
|
5120
|
+
return;
|
|
5114
5121
|
let itemIds;
|
|
5115
5122
|
if (asyncQuestionItemIds !== undefined) {
|
|
5116
5123
|
if (!Array.isArray(asyncQuestionItemIds) || asyncQuestionItemIds.length > SESSION_ACTIVITY_BATCH_LIMITS.maxAsyncQuestionItemIds || !asyncQuestionItemIds.every((itemId) => typeof itemId === "string" && itemId.length > 0 && itemId.length <= SESSION_ACTIVITY_BATCH_LIMITS.maxAsyncQuestionItemIdLength)) {
|
|
@@ -5123,9 +5130,13 @@ function parseSessionActivityObservation(value) {
|
|
|
5123
5130
|
...readyForInput !== undefined ? { readyForInput } : {},
|
|
5124
5131
|
...completionPending !== undefined ? { completionPending } : {},
|
|
5125
5132
|
...itemIds !== undefined ? { asyncQuestionItemIds: itemIds } : {},
|
|
5126
|
-
...closing !== undefined ? { closing } : {}
|
|
5133
|
+
...closing !== undefined ? { closing } : {},
|
|
5134
|
+
...contentRevision !== undefined ? { contentRevision } : {}
|
|
5127
5135
|
};
|
|
5128
5136
|
}
|
|
5137
|
+
function isContentRevision(value) {
|
|
5138
|
+
return typeof value === "string" && value.length > 0 && value.length <= SESSION_ACTIVITY_BATCH_LIMITS.maxContentRevisionLength;
|
|
5139
|
+
}
|
|
5129
5140
|
function parseSessionActivityBatchRequest(value) {
|
|
5130
5141
|
if (!isRecord(value))
|
|
5131
5142
|
return { ok: false, error: "Expected a JSON object" };
|
|
@@ -14024,7 +14035,7 @@ async function publishAssistantRows(context, state, turn, options) {
|
|
|
14024
14035
|
}
|
|
14025
14036
|
|
|
14026
14037
|
// ../../bridges/codex-bridge/src/app-server-runtime-sessions.ts
|
|
14027
|
-
import { createHash as createHash9 } from "node:crypto";
|
|
14038
|
+
import { createHash as createHash9, randomUUID as randomUUID6 } from "node:crypto";
|
|
14028
14039
|
|
|
14029
14040
|
// ../protocol/src/agent-mail.ts
|
|
14030
14041
|
var AGENT_MAIL_MAX_BODY_BYTES = 32 * 1024;
|
|
@@ -20092,6 +20103,7 @@ class ThreadRegistry {
|
|
|
20092
20103
|
|
|
20093
20104
|
// ../../bridges/codex-bridge/src/app-server-runtime-sessions.ts
|
|
20094
20105
|
var SESSION_CLOSING_ERROR = "Session is closing";
|
|
20106
|
+
var ACTIVITY_PROCESS = randomUUID6();
|
|
20095
20107
|
|
|
20096
20108
|
class CodexRuntimeSessions {
|
|
20097
20109
|
ctx;
|
|
@@ -20949,7 +20961,8 @@ class CodexRuntimeSessions {
|
|
|
20949
20961
|
return { activity: "missing" };
|
|
20950
20962
|
return {
|
|
20951
20963
|
activity,
|
|
20952
|
-
...session.asyncQuestionItemIds.length > 0 ? { asyncQuestionItemIds: [...session.asyncQuestionItemIds] } : {}
|
|
20964
|
+
...session.asyncQuestionItemIds.length > 0 ? { asyncQuestionItemIds: [...session.asyncQuestionItemIds] } : {},
|
|
20965
|
+
contentRevision: `${ACTIVITY_PROCESS}:${session.contentEpoch}.${session.messageRevision}:${session.asyncQuestionItemIds.length}`
|
|
20953
20966
|
};
|
|
20954
20967
|
}
|
|
20955
20968
|
hasParkedInput(session) {
|
|
@@ -26082,6 +26095,21 @@ var codexPathOverride = process.env.CODEX_PATH || "codex";
|
|
|
26082
26095
|
var BRIDGE_VERSION = "1.0.0";
|
|
26083
26096
|
var execFile4 = promisify2(execFileCallback2);
|
|
26084
26097
|
var subscribers = new Set;
|
|
26098
|
+
var observers = new Set;
|
|
26099
|
+
function observationFrameData(sessionId) {
|
|
26100
|
+
return JSON.stringify(sessionId === undefined ? {} : { sessionId });
|
|
26101
|
+
}
|
|
26102
|
+
function notifyObservers(event, revision) {
|
|
26103
|
+
for (const observer of observers) {
|
|
26104
|
+
try {
|
|
26105
|
+
Promise.resolve(observer(event, revision, "{}")).catch((error) => {
|
|
26106
|
+
console.error("[codex-bridge] Failed to notify SSE observer:", error);
|
|
26107
|
+
});
|
|
26108
|
+
} catch (error) {
|
|
26109
|
+
console.error("[codex-bridge] Failed to notify SSE observer:", error);
|
|
26110
|
+
}
|
|
26111
|
+
}
|
|
26112
|
+
}
|
|
26085
26113
|
var MAX_REPLAY_SSE_BYTES = 4 * 1024 * 1024;
|
|
26086
26114
|
var REPLAY_IDLE_RETENTION_MS = 60000;
|
|
26087
26115
|
var SUPERSEDED_FRAME_BYTES = 64;
|
|
@@ -26349,7 +26377,7 @@ function retainedMessageId(type, payload) {
|
|
|
26349
26377
|
}
|
|
26350
26378
|
function emit(event) {
|
|
26351
26379
|
if (!replayRetentionEnabled) {
|
|
26352
|
-
eventRing.advance();
|
|
26380
|
+
notifyObservers(event, eventRing.advance());
|
|
26353
26381
|
return;
|
|
26354
26382
|
}
|
|
26355
26383
|
const sessionId = event.sessionId;
|
|
@@ -26376,6 +26404,7 @@ function emit(event) {
|
|
|
26376
26404
|
serialize: () => eager ?? serializeSseEventData({ sessionId, data: payload }),
|
|
26377
26405
|
bytes
|
|
26378
26406
|
});
|
|
26407
|
+
notifyObservers(event, revision);
|
|
26379
26408
|
for (const subscriber of subscribers) {
|
|
26380
26409
|
try {
|
|
26381
26410
|
Promise.resolve(subscriber(event, revision, eager ?? "{}")).catch((error) => {
|
|
@@ -26704,7 +26733,7 @@ app.get("/global/health", (c) => {
|
|
|
26704
26733
|
notificationDepth: health.notificationQueueDepth,
|
|
26705
26734
|
notificationHighWaterMark: health.notificationQueueHighWaterMark
|
|
26706
26735
|
},
|
|
26707
|
-
events: { ...eventRing.getStats(), subscribers: subscribers.size }
|
|
26736
|
+
events: { ...eventRing.getStats(), subscribers: subscribers.size, observers: observers.size }
|
|
26708
26737
|
}, terminal ? 503 : 200);
|
|
26709
26738
|
});
|
|
26710
26739
|
app.get("/global/auth-check", (c) => {
|
|
@@ -27219,6 +27248,7 @@ app.delete("/session/:id", async (c) => {
|
|
|
27219
27248
|
app.get("/event/subscribe", (c) => {
|
|
27220
27249
|
const cursor = parseEventCursor(c.req.query("since")) ?? parseEventCursor(c.req.header("last-event-id"));
|
|
27221
27250
|
const sessionFilter = c.req.query("sessionId")?.trim() || null;
|
|
27251
|
+
const observe = c.req.query("observe") === "1";
|
|
27222
27252
|
return streamSSE(c, async (stream) => {
|
|
27223
27253
|
let open = true;
|
|
27224
27254
|
let resolveConnectionClosed;
|
|
@@ -27244,10 +27274,10 @@ app.get("/event/subscribe", (c) => {
|
|
|
27244
27274
|
return {
|
|
27245
27275
|
event: event.type,
|
|
27246
27276
|
id: String(revision),
|
|
27247
|
-
data: serializeData()
|
|
27277
|
+
data: observe ? observationFrameData(event.sessionId) : serializeData()
|
|
27248
27278
|
};
|
|
27249
27279
|
};
|
|
27250
|
-
const releaseReplayRetention = acquireReplayRetention();
|
|
27280
|
+
const releaseReplayRetention = observe ? () => {} : acquireReplayRetention();
|
|
27251
27281
|
const anchorRevision = cursor ?? eventRing.latestRevision;
|
|
27252
27282
|
let buffered = [];
|
|
27253
27283
|
let highestSent = anchorRevision;
|
|
@@ -27269,7 +27299,7 @@ app.get("/event/subscribe", (c) => {
|
|
|
27269
27299
|
highestSent = revision;
|
|
27270
27300
|
await writeWhileOpen(frameFor(event, revision, () => serializedData));
|
|
27271
27301
|
};
|
|
27272
|
-
subscribers.add(listener);
|
|
27302
|
+
(observe ? observers : subscribers).add(listener);
|
|
27273
27303
|
let keepalive;
|
|
27274
27304
|
try {
|
|
27275
27305
|
if (sseRouteTestHooks?.afterSubscriberRegistered) {
|
|
@@ -27283,7 +27313,8 @@ app.get("/event/subscribe", (c) => {
|
|
|
27283
27313
|
status: "connected",
|
|
27284
27314
|
timestamp: new Date().toISOString(),
|
|
27285
27315
|
revision: replay?.latestRevision ?? anchorRevision,
|
|
27286
|
-
replayed: replay?.complete === true ? replay.events.length : 0
|
|
27316
|
+
replayed: replay?.complete === true ? replay.events.length : 0,
|
|
27317
|
+
...observe ? { observe: true } : {}
|
|
27287
27318
|
})
|
|
27288
27319
|
});
|
|
27289
27320
|
if (replay && !replay.complete) {
|
|
@@ -27329,6 +27360,8 @@ app.get("/event/subscribe", (c) => {
|
|
|
27329
27360
|
}
|
|
27330
27361
|
buffered = null;
|
|
27331
27362
|
keepalive = startSseKeepalive(writeWhileOpen, 5000, () => {
|
|
27363
|
+
if (observe)
|
|
27364
|
+
return false;
|
|
27332
27365
|
if (!sessionFilter)
|
|
27333
27366
|
return true;
|
|
27334
27367
|
const activity = appServerRuntime.getActivity(sessionFilter);
|
|
@@ -27348,6 +27381,7 @@ app.get("/event/subscribe", (c) => {
|
|
|
27348
27381
|
if (keepalive)
|
|
27349
27382
|
clearInterval(keepalive);
|
|
27350
27383
|
subscribers.delete(listener);
|
|
27384
|
+
observers.delete(listener);
|
|
27351
27385
|
releaseReplayRetention();
|
|
27352
27386
|
}
|
|
27353
27387
|
});
|