@opengeni/api-router 2.5.0 → 2.6.4
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/app.js +1 -1
- package/dist/auth/managed-auth-attempt-context.d.ts +5 -1
- package/dist/auth/managed-auth.d.ts +24 -1
- package/dist/{chunk-QESX7HDK.js → chunk-XTLI3CBH.js} +2236 -387
- package/dist/chunk-XTLI3CBH.js.map +1 -0
- package/dist/http/sse.d.ts +9 -0
- package/dist/index.js +104 -4
- package/dist/index.js.map +1 -1
- package/dist/interaction-metrics.d.ts +2 -0
- package/dist/mcp/company-brain-governed-writes.d.ts +1 -1
- package/dist/mcp/company-profile-agent-admin.d.ts +6 -6
- package/dist/mcp/remember.d.ts +2 -2
- package/dist/mcp/server.d.ts +1 -0
- package/dist/mcp/session-view.d.ts +1 -0
- package/dist/mcp/session-wait.d.ts +19 -0
- package/dist/routes/api-keys.d.ts +2 -0
- package/dist/routes/browser-sessions.d.ts +1 -0
- package/dist/routes/computer-sessions.d.ts +12 -0
- package/dist/routes/managed-auth-session-sets.d.ts +7 -0
- package/dist/routes/workspaces.d.ts +1 -1
- package/dist/sandbox/metrics-ingestion.d.ts +16 -0
- package/dist/workspace-delete-observability.d.ts +10 -0
- package/package.json +15 -15
- package/src/app.ts +172 -20
- package/src/auth/managed-auth-attempt-context.ts +40 -3
- package/src/auth/managed-auth-session-adapter.ts +1 -0
- package/src/auth/managed-auth.ts +164 -4
- package/src/http/sse.ts +279 -45
- package/src/integrations/oauth-client.ts +8 -1
- package/src/integrations/provider-oauth.ts +12 -2
- package/src/interaction-metrics.ts +30 -0
- package/src/mcp/company-brain-governed-writes.ts +38 -23
- package/src/mcp/company-profile-agent-admin.ts +7 -7
- package/src/mcp/remember.ts +19 -8
- package/src/mcp/server.ts +318 -26
- package/src/mcp/session-wait.ts +56 -8
- package/src/routes/api-integrations.ts +2 -2
- package/src/routes/api-keys.ts +149 -7
- package/src/routes/browser-sessions.ts +10 -2
- package/src/routes/capabilities.ts +3 -3
- package/src/routes/codex.ts +483 -74
- package/src/routes/company-profile.ts +64 -0
- package/src/routes/computer-sessions.ts +103 -1
- package/src/routes/integration-facets.ts +8 -5
- package/src/routes/interaction-resources.ts +7 -1
- package/src/routes/managed-auth-session-sets.ts +199 -2
- package/src/routes/organization-memberships.ts +28 -8
- package/src/routes/packs.ts +5 -5
- package/src/routes/plugins.ts +2 -2
- package/src/routes/scheduled-tasks.ts +9 -0
- package/src/routes/sessions.ts +3 -6
- package/src/routes/skills.ts +3 -3
- package/src/routes/workspaces.ts +293 -54
- package/src/sandbox/channel-a.ts +10 -4
- package/src/sandbox/machines.ts +13 -6
- package/src/sandbox/metrics-ingestion.ts +157 -3
- package/src/sandbox/viewer.ts +20 -1
- package/src/workspace-delete-observability.ts +75 -0
- package/dist/chunk-QESX7HDK.js.map +0 -1
package/dist/http/sse.d.ts
CHANGED
|
@@ -5,6 +5,8 @@ import type { Observability } from "@opengeni/observability";
|
|
|
5
5
|
export declare const SSE_QUEUED_FRAME_MAX_COUNT = 1;
|
|
6
6
|
export declare const SSE_WRITE_STALL_TIMEOUT_MS = 30000;
|
|
7
7
|
export declare const SSE_HEARTBEAT_INTERVAL_MS = 15000;
|
|
8
|
+
export declare const HTTP1_BROWSER_SSE_BATCH_MAX_BYTES: number;
|
|
9
|
+
export declare const HTTP1_BROWSER_SSE_BATCH_CONTENT_TYPE = "application/vnd.opengeni.sse-batch";
|
|
8
10
|
export type SseDeliveryBoundObservation = {
|
|
9
11
|
reason: "desired_size_non_positive" | "stall_timeout" | "frame_too_large";
|
|
10
12
|
desiredSize: number | null;
|
|
@@ -12,6 +14,7 @@ export type SseDeliveryBoundObservation = {
|
|
|
12
14
|
queuedBytes: number;
|
|
13
15
|
};
|
|
14
16
|
export type ByteBoundedSseStreamOptions = {
|
|
17
|
+
connectionLifetimeMs?: number | undefined;
|
|
15
18
|
maxQueuedBytes?: number;
|
|
16
19
|
stallTimeoutMs?: number;
|
|
17
20
|
onStop?: () => void;
|
|
@@ -76,6 +79,11 @@ export declare function sseWorkspaceLiveStream(db: Database, bus: EventBus, acco
|
|
|
76
79
|
*/
|
|
77
80
|
export declare function sseWorkspaceInteractionRevisionStream(db: Database, accountId: string, workspaceId: string, after: number, signal: AbortSignal, options?: WorkspaceInteractionSseOptions): Promise<Response>;
|
|
78
81
|
export type SseDeliveryOptions = {
|
|
82
|
+
connectionLifetimeMs?: number | undefined;
|
|
83
|
+
/** Return a known-length batch instead of a chunked response. HTTP/1 only. */
|
|
84
|
+
finiteResponseMaxBytes?: number | undefined;
|
|
85
|
+
/** Browser transport classification for a finite response. */
|
|
86
|
+
finiteResponseMediaType?: "event-stream" | "http1-browser-batch" | undefined;
|
|
79
87
|
maxQueuedBytes?: number;
|
|
80
88
|
stallTimeoutMs?: number;
|
|
81
89
|
heartbeatIntervalMs?: number;
|
|
@@ -87,4 +95,5 @@ export type SseDeliveryOptions = {
|
|
|
87
95
|
/** Exact selected actor emitted on the stream response for cross-tab fencing. */
|
|
88
96
|
actorEpoch?: string | undefined;
|
|
89
97
|
};
|
|
98
|
+
export declare function browserSseDeliveryOptions(transport: string | undefined): Pick<SseDeliveryOptions, "connectionLifetimeMs" | "finiteResponseMaxBytes" | "finiteResponseMediaType">;
|
|
90
99
|
export type SessionSseDeliveryOptions = SseDeliveryOptions;
|
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
createOpenGeniSlackBotInteractionClient,
|
|
7
7
|
startSlackInteractionPump,
|
|
8
8
|
startTemporalScheduleCleanupPump
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-XTLI3CBH.js";
|
|
10
10
|
|
|
11
11
|
// src/index.ts
|
|
12
12
|
import {
|
|
@@ -233,6 +233,94 @@ import {
|
|
|
233
233
|
} from "@opengeni/agent-proto";
|
|
234
234
|
var AGENT_EVENTS_SUBJECT = "agent.*.*.connection.*.events";
|
|
235
235
|
var AGENT_HELLO_SUBJECT = "agent.*.*.connection.*.hello";
|
|
236
|
+
function payloadIsHeartbeat(payload) {
|
|
237
|
+
try {
|
|
238
|
+
return AgentEvent.decode(payload).event?.$case === "heartbeat";
|
|
239
|
+
} catch {
|
|
240
|
+
return false;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
function createAgentEventIngestionScheduler(handler, options = {}) {
|
|
244
|
+
const maxConcurrentSubjects = options.maxConcurrentSubjects ?? 32;
|
|
245
|
+
if (!Number.isSafeInteger(maxConcurrentSubjects) || maxConcurrentSubjects <= 0) {
|
|
246
|
+
throw new RangeError("maxConcurrentSubjects must be a positive safe integer");
|
|
247
|
+
}
|
|
248
|
+
const states = /* @__PURE__ */ new Map();
|
|
249
|
+
const readySubjects = [];
|
|
250
|
+
const idleWaiters = /* @__PURE__ */ new Set();
|
|
251
|
+
let accepting = true;
|
|
252
|
+
let activeSubjects = 0;
|
|
253
|
+
const resolveIdleWaiters = () => {
|
|
254
|
+
if (states.size !== 0) return;
|
|
255
|
+
for (const resolve of idleWaiters) resolve();
|
|
256
|
+
idleWaiters.clear();
|
|
257
|
+
};
|
|
258
|
+
async function drain(subject, state) {
|
|
259
|
+
while (true) {
|
|
260
|
+
const event = state.pending.shift();
|
|
261
|
+
if (!event) break;
|
|
262
|
+
try {
|
|
263
|
+
await handler(event.payload, event.subject);
|
|
264
|
+
} catch {
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
activeSubjects -= 1;
|
|
268
|
+
state.scheduled = false;
|
|
269
|
+
if (state.pending.length > 0) {
|
|
270
|
+
schedule(subject, state);
|
|
271
|
+
} else {
|
|
272
|
+
if (states.get(subject) === state) states.delete(subject);
|
|
273
|
+
resolveIdleWaiters();
|
|
274
|
+
}
|
|
275
|
+
pump();
|
|
276
|
+
}
|
|
277
|
+
function pump() {
|
|
278
|
+
while (activeSubjects < maxConcurrentSubjects) {
|
|
279
|
+
const next = readySubjects.shift();
|
|
280
|
+
if (!next) return;
|
|
281
|
+
if (states.get(next.subject) !== next.state || !next.state.scheduled) continue;
|
|
282
|
+
activeSubjects += 1;
|
|
283
|
+
void drain(next.subject, next.state);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function schedule(subject, state) {
|
|
287
|
+
if (state.scheduled) return;
|
|
288
|
+
state.scheduled = true;
|
|
289
|
+
readySubjects.push({ subject, state });
|
|
290
|
+
pump();
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
enqueue(payload, subject) {
|
|
294
|
+
if (!accepting) return;
|
|
295
|
+
const heartbeat = payloadIsHeartbeat(payload);
|
|
296
|
+
let state = states.get(subject);
|
|
297
|
+
if (!state) {
|
|
298
|
+
state = { scheduled: false, pending: [] };
|
|
299
|
+
states.set(subject, state);
|
|
300
|
+
}
|
|
301
|
+
const queued = { payload, subject, heartbeat };
|
|
302
|
+
const lastIndex = state.pending.length - 1;
|
|
303
|
+
if (heartbeat && lastIndex >= 0 && state.pending[lastIndex].heartbeat) {
|
|
304
|
+
state.pending[lastIndex] = queued;
|
|
305
|
+
options.onHeartbeatCoalesced?.();
|
|
306
|
+
} else {
|
|
307
|
+
state.pending.push(queued);
|
|
308
|
+
}
|
|
309
|
+
schedule(subject, state);
|
|
310
|
+
},
|
|
311
|
+
async whenIdle() {
|
|
312
|
+
if (states.size === 0) return;
|
|
313
|
+
await new Promise((resolve) => idleWaiters.add(resolve));
|
|
314
|
+
},
|
|
315
|
+
close() {
|
|
316
|
+
accepting = false;
|
|
317
|
+
for (const state of states.values()) {
|
|
318
|
+
state.pending.length = 0;
|
|
319
|
+
}
|
|
320
|
+
resolveIdleWaiters();
|
|
321
|
+
}
|
|
322
|
+
};
|
|
323
|
+
}
|
|
236
324
|
function parseAgentSubject(subject, tail) {
|
|
237
325
|
const parts = subject.split(".");
|
|
238
326
|
if (parts.length !== 6 || parts[0] !== "agent" || parts[3] !== "connection" || !parts[4] || parts[5] !== tail) {
|
|
@@ -545,10 +633,22 @@ async function handleAgentEventPayload(db, observability, payload, subject, bus)
|
|
|
545
633
|
}
|
|
546
634
|
}
|
|
547
635
|
function startMetricsIngestion(deps) {
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
636
|
+
const scheduler = createAgentEventIngestionScheduler(
|
|
637
|
+
(payload, subject) => handleAgentEventPayload(deps.db, deps.observability, payload, subject, deps.bus),
|
|
638
|
+
{
|
|
639
|
+
onHeartbeatCoalesced: () => deps.observability?.incrementCounter({
|
|
640
|
+
name: "opengeni_machine_heartbeat_coalesced_total",
|
|
641
|
+
help: "Connected Machine heartbeats collapsed while an exact runner event queue was busy."
|
|
642
|
+
})
|
|
643
|
+
}
|
|
551
644
|
);
|
|
645
|
+
const unsubscribe = deps.bus.subscribeAgentEvents(AGENT_EVENTS_SUBJECT, (payload, subject) => {
|
|
646
|
+
scheduler.enqueue(payload, subject);
|
|
647
|
+
});
|
|
648
|
+
return () => {
|
|
649
|
+
unsubscribe();
|
|
650
|
+
scheduler.close();
|
|
651
|
+
};
|
|
552
652
|
}
|
|
553
653
|
function helloReportsDisplay(hello) {
|
|
554
654
|
const caps = hello.capabilities;
|