@opengeni/api-router 0.5.4 → 0.5.6
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.d.ts +9 -1
- package/dist/app.js +7 -1
- package/dist/{chunk-DO2G3JSB.js → chunk-HBEJMWD3.js} +528 -270
- package/dist/chunk-HBEJMWD3.js.map +1 -0
- package/dist/index.js +8 -27
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
- package/src/app.ts +180 -31
- package/src/http/sse.ts +57 -2
- package/src/index.ts +8 -27
- package/src/mcp/server.ts +167 -85
- package/src/routes/sessions.ts +141 -109
- package/src/routes/workspaces.ts +30 -43
- package/dist/chunk-DO2G3JSB.js.map +0 -1
|
@@ -4,7 +4,12 @@ import {
|
|
|
4
4
|
configuredAllowedReasoningEfforts,
|
|
5
5
|
configuredModels
|
|
6
6
|
} from "@opengeni/config";
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
ClientConfig,
|
|
9
|
+
OPENGENI_API_CONTRACT_HEADER,
|
|
10
|
+
OPENGENI_API_CONTRACT_REVISION,
|
|
11
|
+
resolveWorkspaceMemoryEnabled
|
|
12
|
+
} from "@opengeni/contracts";
|
|
8
13
|
import {
|
|
9
14
|
createDocumentServices,
|
|
10
15
|
indexDocumentNow
|
|
@@ -14,6 +19,7 @@ import { createObservability } from "@opengeni/observability";
|
|
|
14
19
|
import { createObjectStorage } from "@opengeni/storage";
|
|
15
20
|
import { WebStandardStreamableHTTPServerTransport as WebStandardStreamableHTTPServerTransport2 } from "@modelcontextprotocol/sdk/server/webStandardStreamableHttp.js";
|
|
16
21
|
import { Hono } from "hono";
|
|
22
|
+
import { bodyLimit } from "hono/body-limit";
|
|
17
23
|
import { cors } from "hono/cors";
|
|
18
24
|
import { HTTPException as HTTPException24 } from "hono/http-exception";
|
|
19
25
|
import { hasPermission as hasPermission4, requireAccessGrant as requireAccessGrant17, requirePermission } from "@opengeni/core";
|
|
@@ -279,7 +285,6 @@ import {
|
|
|
279
285
|
UpdateScheduledTaskRequest
|
|
280
286
|
} from "@opengeni/contracts";
|
|
281
287
|
import {
|
|
282
|
-
addSessionSystemUpdate,
|
|
283
288
|
correctWorkspaceMemory,
|
|
284
289
|
countVariableSets,
|
|
285
290
|
beginRigChangeVerificationAttempt,
|
|
@@ -288,6 +293,7 @@ import {
|
|
|
288
293
|
encryptVariableSetValue,
|
|
289
294
|
getSession,
|
|
290
295
|
getSessionGoal,
|
|
296
|
+
getSessionQueueSnapshot,
|
|
291
297
|
getSessionTurn,
|
|
292
298
|
getVariableSet,
|
|
293
299
|
getVariableSetByName,
|
|
@@ -306,10 +312,8 @@ import {
|
|
|
306
312
|
requireFile,
|
|
307
313
|
requireScheduledTask,
|
|
308
314
|
requireSession,
|
|
309
|
-
requestSessionControl,
|
|
310
315
|
saveWorkspaceMemory,
|
|
311
316
|
searchWorkspaceMemories,
|
|
312
|
-
setSessionChildNotificationsMode,
|
|
313
317
|
setSessionGoalStatus,
|
|
314
318
|
setVariableSetVariable,
|
|
315
319
|
updateScheduledTask,
|
|
@@ -356,9 +360,12 @@ import {
|
|
|
356
360
|
} from "@opengeni/core";
|
|
357
361
|
import {
|
|
358
362
|
acceptSessionUserMessage,
|
|
363
|
+
controlAgentSessionWorkstream,
|
|
364
|
+
controlHumanSessionWorkstream,
|
|
359
365
|
createSessionForRequest,
|
|
360
|
-
|
|
361
|
-
|
|
366
|
+
sendAgentSessionMessage,
|
|
367
|
+
steerAgentSession,
|
|
368
|
+
updateSessionTitle
|
|
362
369
|
} from "@opengeni/core";
|
|
363
370
|
import {
|
|
364
371
|
buildFleetContextForSession,
|
|
@@ -545,24 +552,6 @@ function buildOpenGeniMcpServer(deps, grant, options = {}) {
|
|
|
545
552
|
}
|
|
546
553
|
);
|
|
547
554
|
}
|
|
548
|
-
if (sessionId !== null && !toolspaceMode && can("sessions:create")) {
|
|
549
|
-
server.registerTool(
|
|
550
|
-
"set_child_notifications_mode",
|
|
551
|
-
{
|
|
552
|
-
description: "Change how workers you spawn report back when they finish. This setting persists across turns and must not be re-applied as routine setup or recovery. 'digest' (default): completions arrive as a coalesced turn you process. 'passive': completions appear only as quiet cards and never queue a turn or model run. Call only when the desired mode differs from the mode already in effect.",
|
|
553
|
-
inputSchema: { mode: z4.enum(["digest", "passive"]) }
|
|
554
|
-
},
|
|
555
|
-
async ({ mode }) => {
|
|
556
|
-
const changed = await setSessionChildNotificationsMode(
|
|
557
|
-
deps.db,
|
|
558
|
-
grant.workspaceId,
|
|
559
|
-
sessionId,
|
|
560
|
-
mode
|
|
561
|
-
);
|
|
562
|
-
return json({ ok: true, changed, mode });
|
|
563
|
-
}
|
|
564
|
-
);
|
|
565
|
-
}
|
|
566
555
|
if (sessionId !== null && can("goals:manage")) {
|
|
567
556
|
registerGoalTools(server, deps, grant, sessionId, json);
|
|
568
557
|
}
|
|
@@ -575,7 +564,7 @@ function buildOpenGeniMcpServer(deps, grant, options = {}) {
|
|
|
575
564
|
if (!toolspaceMode) {
|
|
576
565
|
registerRigTools(server, deps, grant, can, sessionId, json);
|
|
577
566
|
}
|
|
578
|
-
registerWorkspaceOrchestrationTools(server, deps, grant, can, sessionId, json);
|
|
567
|
+
registerWorkspaceOrchestrationTools(server, deps, grant, can, sessionId, toolspaceMode, json);
|
|
579
568
|
registerVariableSetTools(server, deps, grant, can, json);
|
|
580
569
|
if (can("github:use")) {
|
|
581
570
|
registerGitHubConnectTool(server, deps, grant, options, json);
|
|
@@ -1445,7 +1434,23 @@ function registerRigTools(server, deps, grant, can, sessionId, json) {
|
|
|
1445
1434
|
);
|
|
1446
1435
|
}
|
|
1447
1436
|
}
|
|
1448
|
-
function
|
|
1437
|
+
function exactAgentCommandContext(grant, callerSessionId) {
|
|
1438
|
+
const turnId = grant.metadata?.["turnId"];
|
|
1439
|
+
const attemptId = grant.metadata?.["attemptId"];
|
|
1440
|
+
const executionGeneration = grant.metadata?.["executionGeneration"];
|
|
1441
|
+
if (typeof turnId !== "string" || typeof attemptId !== "string" || typeof executionGeneration !== "number" || !Number.isSafeInteger(executionGeneration) || executionGeneration < 1) {
|
|
1442
|
+
throw new Error("caller_attempt_claims_missing");
|
|
1443
|
+
}
|
|
1444
|
+
return {
|
|
1445
|
+
accountId: grant.accountId,
|
|
1446
|
+
workspaceId: grant.workspaceId,
|
|
1447
|
+
callerSessionId,
|
|
1448
|
+
callerTurnId: turnId,
|
|
1449
|
+
callerAttemptId: attemptId,
|
|
1450
|
+
callerExecutionGeneration: executionGeneration
|
|
1451
|
+
};
|
|
1452
|
+
}
|
|
1453
|
+
function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSessionId, toolspaceMode, json) {
|
|
1449
1454
|
if (can("sessions:read")) {
|
|
1450
1455
|
server.registerTool(
|
|
1451
1456
|
"sessions_list",
|
|
@@ -1466,7 +1471,11 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
|
|
|
1466
1471
|
if (!session) {
|
|
1467
1472
|
throw new Error("session not found");
|
|
1468
1473
|
}
|
|
1469
|
-
|
|
1474
|
+
const queue = await getSessionQueueSnapshot(deps.db, grant.workspaceId, sessionId);
|
|
1475
|
+
return json({
|
|
1476
|
+
...capSessionDetail(session),
|
|
1477
|
+
effectiveControl: queue?.effectiveControl ?? null
|
|
1478
|
+
});
|
|
1470
1479
|
}
|
|
1471
1480
|
);
|
|
1472
1481
|
server.registerTool(
|
|
@@ -1576,7 +1585,7 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
|
|
|
1576
1585
|
async (args) => json(await createSessionForRequest(deps, grant, grant.workspaceId, args))
|
|
1577
1586
|
);
|
|
1578
1587
|
}
|
|
1579
|
-
if (can("sessions:control")) {
|
|
1588
|
+
if (can("sessions:control") && !toolspaceMode) {
|
|
1580
1589
|
server.registerTool(
|
|
1581
1590
|
"session_send_message",
|
|
1582
1591
|
{
|
|
@@ -1584,50 +1593,30 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
|
|
|
1584
1593
|
inputSchema: {
|
|
1585
1594
|
sessionId: z4.string().uuid(),
|
|
1586
1595
|
text: z4.string().min(1),
|
|
1596
|
+
idempotencyKey: z4.string().uuid(),
|
|
1587
1597
|
// Header-value rotation only. URL/name/tool settings are immutable
|
|
1588
1598
|
// after create; core enforces mcp_servers:attach on this field.
|
|
1589
1599
|
mcpCredentialUpdates: z4.array(z4.unknown()).optional()
|
|
1590
1600
|
}
|
|
1591
1601
|
},
|
|
1592
|
-
async ({ sessionId: targetSessionId, text, mcpCredentialUpdates }) => {
|
|
1602
|
+
async ({ sessionId: targetSessionId, text, idempotencyKey, mcpCredentialUpdates }) => {
|
|
1593
1603
|
if (callerSessionId !== null) {
|
|
1594
1604
|
if ((mcpCredentialUpdates?.length ?? 0) > 0) {
|
|
1595
1605
|
throw new Error("internal session updates cannot change MCP credentials");
|
|
1596
1606
|
}
|
|
1597
|
-
const result = await
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
classification: "info",
|
|
1603
|
-
sourceId: callerSessionId,
|
|
1604
|
-
dedupeKey: `session-message:${callerSessionId}:${crypto.randomUUID()}`,
|
|
1605
|
-
summary: text,
|
|
1606
|
-
payload: { text },
|
|
1607
|
-
lineage: { sourceSessionId: callerSessionId, targetSessionId }
|
|
1608
|
-
});
|
|
1609
|
-
if (result.reason === "session_cancelled") {
|
|
1610
|
-
return json({ delivered: false, reason: result.reason });
|
|
1611
|
-
}
|
|
1612
|
-
if (result.added && result.events.length > 0) {
|
|
1613
|
-
await deps.bus.publish(grant.workspaceId, targetSessionId, result.events);
|
|
1614
|
-
}
|
|
1615
|
-
if (result.shouldWake) {
|
|
1616
|
-
if (result.workflowWakeRevision === null) {
|
|
1617
|
-
throw new Error("Internal update has no workflow wake revision");
|
|
1618
|
-
}
|
|
1619
|
-
await deps.workflowClient.wakeSessionWorkflow({
|
|
1620
|
-
accountId: grant.accountId,
|
|
1621
|
-
workspaceId: grant.workspaceId,
|
|
1622
|
-
sessionId: targetSessionId,
|
|
1623
|
-
workflowId: result.temporalWorkflowId ?? workflowIdForSession(targetSessionId),
|
|
1624
|
-
wakeRevision: result.workflowWakeRevision
|
|
1625
|
-
});
|
|
1626
|
-
}
|
|
1607
|
+
const result = await sendAgentSessionMessage(
|
|
1608
|
+
deps,
|
|
1609
|
+
exactAgentCommandContext(grant, callerSessionId),
|
|
1610
|
+
{ targetSessionId, text, idempotencyKey }
|
|
1611
|
+
);
|
|
1627
1612
|
return json({
|
|
1628
1613
|
delivered: true,
|
|
1629
|
-
updateId: result.
|
|
1630
|
-
delivery: "coalesced_internal_update"
|
|
1614
|
+
updateId: result.updateId,
|
|
1615
|
+
delivery: "coalesced_internal_update",
|
|
1616
|
+
effectiveState: result.effectiveState,
|
|
1617
|
+
wakeRequested: result.wakeRevision !== null,
|
|
1618
|
+
resumeRequired: result.effectiveState === "paused",
|
|
1619
|
+
replay: result.replay
|
|
1631
1620
|
});
|
|
1632
1621
|
}
|
|
1633
1622
|
const { accepted, turn } = await acceptSessionUserMessage(
|
|
@@ -1638,8 +1627,9 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
|
|
|
1638
1627
|
{
|
|
1639
1628
|
text,
|
|
1640
1629
|
toolsProvided: false,
|
|
1641
|
-
delivery: "
|
|
1630
|
+
delivery: "send",
|
|
1642
1631
|
origin: "operator",
|
|
1632
|
+
clientEventId: idempotencyKey,
|
|
1643
1633
|
mcpCredentialUpdates: (mcpCredentialUpdates ?? []).map(
|
|
1644
1634
|
(update) => SessionMcpCredentialUpdateInput.parse(update)
|
|
1645
1635
|
)
|
|
@@ -1653,39 +1643,122 @@ function registerWorkspaceOrchestrationTools(server, deps, grant, can, callerSes
|
|
|
1653
1643
|
{
|
|
1654
1644
|
description: "Pause this session. Waiting prompts stay saved and inert until Resume.",
|
|
1655
1645
|
inputSchema: {
|
|
1656
|
-
sessionId: z4.string().uuid()
|
|
1646
|
+
sessionId: z4.string().uuid(),
|
|
1647
|
+
idempotencyKey: z4.string().uuid(),
|
|
1648
|
+
reason: z4.string().min(1).max(500).optional()
|
|
1657
1649
|
}
|
|
1658
1650
|
},
|
|
1659
|
-
async ({ sessionId }) => {
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
sessionId,
|
|
1677
|
-
eventId: controlled.event.id,
|
|
1678
|
-
workflowId: workflowIdForSession(sessionId),
|
|
1679
|
-
workflowWakeRevision: controlled.workflowWakeRevision
|
|
1651
|
+
async ({ sessionId, idempotencyKey, reason }) => {
|
|
1652
|
+
if (callerSessionId !== null) {
|
|
1653
|
+
const controlled = await controlAgentSessionWorkstream(
|
|
1654
|
+
deps,
|
|
1655
|
+
exactAgentCommandContext(grant, callerSessionId),
|
|
1656
|
+
{
|
|
1657
|
+
targetSessionId: sessionId,
|
|
1658
|
+
action: "pause",
|
|
1659
|
+
idempotencyKey,
|
|
1660
|
+
reason: reason ?? "agent_mcp_pause"
|
|
1661
|
+
}
|
|
1662
|
+
);
|
|
1663
|
+
return json({
|
|
1664
|
+
receiptId: controlled.receipt.id,
|
|
1665
|
+
effectiveControl: controlled.control,
|
|
1666
|
+
interruptionCount: controlled.interruptionCount,
|
|
1667
|
+
replay: controlled.replay
|
|
1680
1668
|
});
|
|
1681
1669
|
}
|
|
1682
|
-
return json(
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1670
|
+
return json(
|
|
1671
|
+
await controlHumanSessionWorkstream(
|
|
1672
|
+
deps,
|
|
1673
|
+
{
|
|
1674
|
+
accountId: grant.accountId,
|
|
1675
|
+
workspaceId: grant.workspaceId,
|
|
1676
|
+
sessionId,
|
|
1677
|
+
subjectId: grant.subjectId
|
|
1678
|
+
},
|
|
1679
|
+
{
|
|
1680
|
+
action: "pause",
|
|
1681
|
+
clientEventId: idempotencyKey,
|
|
1682
|
+
...reason ? { reason } : {}
|
|
1683
|
+
}
|
|
1684
|
+
)
|
|
1685
|
+
);
|
|
1686
|
+
}
|
|
1687
|
+
);
|
|
1688
|
+
server.registerTool(
|
|
1689
|
+
"session_resume",
|
|
1690
|
+
{
|
|
1691
|
+
description: "Resume the selected session workstream through older parent/workspace pauses. This creates no message.",
|
|
1692
|
+
inputSchema: {
|
|
1693
|
+
sessionId: z4.string().uuid(),
|
|
1694
|
+
idempotencyKey: z4.string().uuid(),
|
|
1695
|
+
reason: z4.string().min(1).max(500).optional()
|
|
1696
|
+
}
|
|
1697
|
+
},
|
|
1698
|
+
async ({ sessionId, idempotencyKey, reason }) => {
|
|
1699
|
+
if (callerSessionId !== null) {
|
|
1700
|
+
const controlled = await controlAgentSessionWorkstream(
|
|
1701
|
+
deps,
|
|
1702
|
+
exactAgentCommandContext(grant, callerSessionId),
|
|
1703
|
+
{
|
|
1704
|
+
targetSessionId: sessionId,
|
|
1705
|
+
action: "resume",
|
|
1706
|
+
idempotencyKey,
|
|
1707
|
+
reason: reason ?? "agent_mcp_resume"
|
|
1708
|
+
}
|
|
1709
|
+
);
|
|
1710
|
+
return json({
|
|
1711
|
+
receiptId: controlled.receipt.id,
|
|
1712
|
+
effectiveControl: controlled.control,
|
|
1713
|
+
interruptionCount: controlled.interruptionCount,
|
|
1714
|
+
replay: controlled.replay
|
|
1715
|
+
});
|
|
1716
|
+
}
|
|
1717
|
+
return json(
|
|
1718
|
+
await controlHumanSessionWorkstream(
|
|
1719
|
+
deps,
|
|
1720
|
+
{
|
|
1721
|
+
accountId: grant.accountId,
|
|
1722
|
+
workspaceId: grant.workspaceId,
|
|
1723
|
+
sessionId,
|
|
1724
|
+
subjectId: grant.subjectId
|
|
1725
|
+
},
|
|
1726
|
+
{
|
|
1727
|
+
action: "resume",
|
|
1728
|
+
clientEventId: idempotencyKey,
|
|
1729
|
+
...reason ? { reason } : {}
|
|
1730
|
+
}
|
|
1731
|
+
)
|
|
1732
|
+
);
|
|
1687
1733
|
}
|
|
1688
1734
|
);
|
|
1735
|
+
if (callerSessionId !== null) {
|
|
1736
|
+
server.registerTool(
|
|
1737
|
+
"session_steer",
|
|
1738
|
+
{
|
|
1739
|
+
description: "Atomically replace another session's current direction and resume it. The instruction is an internal update, never a human queue row.",
|
|
1740
|
+
inputSchema: {
|
|
1741
|
+
sessionId: z4.string().uuid(),
|
|
1742
|
+
instruction: z4.string().min(1),
|
|
1743
|
+
idempotencyKey: z4.string().uuid()
|
|
1744
|
+
}
|
|
1745
|
+
},
|
|
1746
|
+
async ({ sessionId, instruction, idempotencyKey }) => {
|
|
1747
|
+
const result = await steerAgentSession(
|
|
1748
|
+
deps,
|
|
1749
|
+
exactAgentCommandContext(grant, callerSessionId),
|
|
1750
|
+
{ targetSessionId: sessionId, instruction, idempotencyKey }
|
|
1751
|
+
);
|
|
1752
|
+
return json({
|
|
1753
|
+
updateId: result.updateId,
|
|
1754
|
+
interruptionCount: result.interruptionCount,
|
|
1755
|
+
stoppingPreviousAttempt: result.interruptionCount > 0,
|
|
1756
|
+
effectiveState: result.effectiveState,
|
|
1757
|
+
replay: result.replay
|
|
1758
|
+
});
|
|
1759
|
+
}
|
|
1760
|
+
);
|
|
1761
|
+
}
|
|
1689
1762
|
server.registerTool(
|
|
1690
1763
|
"set_other_session_title",
|
|
1691
1764
|
{
|
|
@@ -7831,9 +7904,10 @@ import {
|
|
|
7831
7904
|
AcknowledgeStreamRequest,
|
|
7832
7905
|
AttachViewerRequest,
|
|
7833
7906
|
ClearSessionContextRequest,
|
|
7834
|
-
CancelSessionQueueItemRequest,
|
|
7835
7907
|
ClientSessionEvent,
|
|
7836
7908
|
CompactSessionContextRequest,
|
|
7909
|
+
DeleteSessionQueueItemRequest,
|
|
7910
|
+
EditSessionQueueItemRequest,
|
|
7837
7911
|
FsDeleteRequest,
|
|
7838
7912
|
FsListRequest,
|
|
7839
7913
|
FsMkdirRequest,
|
|
@@ -7844,11 +7918,14 @@ import {
|
|
|
7844
7918
|
GitLogRequest,
|
|
7845
7919
|
GitShowRequest,
|
|
7846
7920
|
GitStatusRequest,
|
|
7921
|
+
MoveSessionQueueItemRequest,
|
|
7847
7922
|
PtyCloseRequest,
|
|
7848
7923
|
PtyOpenRequest,
|
|
7849
7924
|
PtyResizeRequest,
|
|
7850
7925
|
PtyWriteRequest,
|
|
7851
7926
|
SessionControlRequest,
|
|
7927
|
+
SaveComposerDraftRequest,
|
|
7928
|
+
SteerSessionQueueItemRequest,
|
|
7852
7929
|
SteerSessionMessageRequest,
|
|
7853
7930
|
TerminalExecRequest,
|
|
7854
7931
|
UpdateSessionPinRequest,
|
|
@@ -7858,7 +7935,6 @@ import {
|
|
|
7858
7935
|
} from "@opengeni/contracts";
|
|
7859
7936
|
import { streamTokenDegraded } from "@opengeni/config";
|
|
7860
7937
|
import {
|
|
7861
|
-
cancelQueuedSessionTurnWithVersion,
|
|
7862
7938
|
acceptSessionApprovalDecision,
|
|
7863
7939
|
clearSessionGoal,
|
|
7864
7940
|
clearSessionContext,
|
|
@@ -7868,7 +7944,7 @@ import {
|
|
|
7868
7944
|
getSession as getSession4,
|
|
7869
7945
|
getSessionForSubject,
|
|
7870
7946
|
getSessionGoal as getSessionGoal2,
|
|
7871
|
-
getSessionQueueSnapshot,
|
|
7947
|
+
getSessionQueueSnapshot as getSessionQueueSnapshot2,
|
|
7872
7948
|
getStreamAcknowledgment,
|
|
7873
7949
|
insertPtySession,
|
|
7874
7950
|
listSessionEvents as listSessionEvents3,
|
|
@@ -7888,8 +7964,9 @@ import {
|
|
|
7888
7964
|
revokeViewer,
|
|
7889
7965
|
setSessionGoalStatus as setSessionGoalStatus2,
|
|
7890
7966
|
updatePtySessionActivity,
|
|
7891
|
-
|
|
7892
|
-
|
|
7967
|
+
QueueCommandConflictError,
|
|
7968
|
+
SessionCommandIdempotencyError,
|
|
7969
|
+
SessionControlConflictError,
|
|
7893
7970
|
SessionContextBusyError,
|
|
7894
7971
|
latestWorkspaceCapture,
|
|
7895
7972
|
workspaceCaptureAtRevision
|
|
@@ -8681,14 +8758,21 @@ function viewerIdAsUuid(rawViewerId) {
|
|
|
8681
8758
|
// src/routes/sessions.ts
|
|
8682
8759
|
import {
|
|
8683
8760
|
acceptSessionUserMessage as acceptSessionUserMessage2,
|
|
8761
|
+
controlHumanSessionWorkstream as controlHumanSessionWorkstream2,
|
|
8684
8762
|
createSessionForRequest as createSessionForRequest2,
|
|
8763
|
+
deleteHumanQueuePrompt,
|
|
8764
|
+
editHumanQueuePrompt,
|
|
8765
|
+
getHumanComposerDraft,
|
|
8766
|
+
moveHumanQueuePrompt,
|
|
8685
8767
|
readSessionLineage,
|
|
8768
|
+
saveHumanComposerDraft,
|
|
8769
|
+
steerHumanQueuePrompt,
|
|
8686
8770
|
updateSessionTitle as updateSessionTitle2,
|
|
8687
|
-
workflowIdForSession
|
|
8771
|
+
workflowIdForSession
|
|
8688
8772
|
} from "@opengeni/core";
|
|
8689
8773
|
|
|
8690
8774
|
// src/http/sse.ts
|
|
8691
|
-
import { listSessionEvents as listSessionEvents2 } from "@opengeni/db";
|
|
8775
|
+
import { listSessionEvents as listSessionEvents2, listWorkspaceControlEvents } from "@opengeni/db";
|
|
8692
8776
|
import { formatSse } from "@opengeni/events";
|
|
8693
8777
|
async function sseSessionStream(db, bus, workspaceId, sessionId, after, signal) {
|
|
8694
8778
|
const encoder = new TextEncoder();
|
|
@@ -8778,6 +8862,53 @@ async function replaySessionEvents(loadPage, send, after, pageSize = 1e3) {
|
|
|
8778
8862
|
}
|
|
8779
8863
|
}
|
|
8780
8864
|
}
|
|
8865
|
+
async function sseWorkspaceControlStream(db, bus, workspaceId, after, signal) {
|
|
8866
|
+
const encoder = new TextEncoder();
|
|
8867
|
+
let lastSent = after;
|
|
8868
|
+
let replaying = true;
|
|
8869
|
+
const buffered = [];
|
|
8870
|
+
let unsubscribe = null;
|
|
8871
|
+
const stream = new ReadableStream({
|
|
8872
|
+
start: async (controller) => {
|
|
8873
|
+
const send = (event) => {
|
|
8874
|
+
if (event.sequence <= lastSent) return;
|
|
8875
|
+
controller.enqueue(encoder.encode(formatSse(event)));
|
|
8876
|
+
lastSent = event.sequence;
|
|
8877
|
+
};
|
|
8878
|
+
unsubscribe = await bus.subscribeWorkspaceControl(workspaceId, async (event) => {
|
|
8879
|
+
if (replaying) {
|
|
8880
|
+
buffered.push(event);
|
|
8881
|
+
} else {
|
|
8882
|
+
send(event);
|
|
8883
|
+
}
|
|
8884
|
+
});
|
|
8885
|
+
let cursor = after;
|
|
8886
|
+
while (true) {
|
|
8887
|
+
const page = await listWorkspaceControlEvents(db, workspaceId, cursor, 1e3);
|
|
8888
|
+
for (const event of page) {
|
|
8889
|
+
send(event);
|
|
8890
|
+
cursor = Math.max(cursor, event.sequence);
|
|
8891
|
+
}
|
|
8892
|
+
if (page.length < 1e3) break;
|
|
8893
|
+
}
|
|
8894
|
+
replaying = false;
|
|
8895
|
+
for (const event of buffered.sort((left, right) => left.sequence - right.sequence)) {
|
|
8896
|
+
send(event);
|
|
8897
|
+
}
|
|
8898
|
+
buffered.length = 0;
|
|
8899
|
+
controller.enqueue(encoder.encode(": connected\n\n"));
|
|
8900
|
+
},
|
|
8901
|
+
cancel: () => unsubscribe?.()
|
|
8902
|
+
});
|
|
8903
|
+
signal.addEventListener("abort", () => unsubscribe?.(), { once: true });
|
|
8904
|
+
return new Response(stream, {
|
|
8905
|
+
headers: {
|
|
8906
|
+
"Content-Type": "text/event-stream; charset=utf-8",
|
|
8907
|
+
"Cache-Control": "no-cache, no-transform",
|
|
8908
|
+
Connection: "keep-alive"
|
|
8909
|
+
}
|
|
8910
|
+
});
|
|
8911
|
+
}
|
|
8781
8912
|
|
|
8782
8913
|
// src/routes/workspace-capture.ts
|
|
8783
8914
|
import {
|
|
@@ -9170,7 +9301,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
9170
9301
|
accountId: grant.accountId,
|
|
9171
9302
|
workspaceId,
|
|
9172
9303
|
sessionId,
|
|
9173
|
-
workflowId:
|
|
9304
|
+
workflowId: workflowIdForSession(sessionId),
|
|
9174
9305
|
wakeRevision: workflowWakeRevision
|
|
9175
9306
|
});
|
|
9176
9307
|
}
|
|
@@ -9288,111 +9419,133 @@ function registerSessionRoutes(app, deps) {
|
|
|
9288
9419
|
const workspaceId = c.req.param("workspaceId");
|
|
9289
9420
|
await requireAccessGrant14(c, deps, workspaceId, "sessions:read");
|
|
9290
9421
|
const sessionId = c.req.param("sessionId");
|
|
9291
|
-
const snapshot = await
|
|
9422
|
+
const snapshot = await getSessionQueueSnapshot2(db, workspaceId, sessionId);
|
|
9292
9423
|
if (!snapshot) throw new HTTPException21(404, { message: "session not found" });
|
|
9293
9424
|
return c.json(snapshot);
|
|
9294
9425
|
});
|
|
9295
|
-
app.post("/v1/workspaces/:workspaceId/sessions/:sessionId/queue/:turnId/
|
|
9426
|
+
app.post("/v1/workspaces/:workspaceId/sessions/:sessionId/queue/:turnId/move", async (c) => {
|
|
9296
9427
|
const workspaceId = c.req.param("workspaceId");
|
|
9297
9428
|
const grant = await requireAccessGrant14(c, deps, workspaceId, "sessions:control");
|
|
9298
9429
|
const sessionId = c.req.param("sessionId");
|
|
9299
9430
|
await assertSessionExists(db, workspaceId, sessionId);
|
|
9300
|
-
const payload =
|
|
9431
|
+
const payload = MoveSessionQueueItemRequest.parse(await c.req.json());
|
|
9301
9432
|
try {
|
|
9302
|
-
|
|
9303
|
-
|
|
9304
|
-
|
|
9305
|
-
|
|
9306
|
-
|
|
9307
|
-
|
|
9308
|
-
|
|
9309
|
-
grant.subjectId,
|
|
9310
|
-
payload.reason ?? null
|
|
9433
|
+
return c.json(
|
|
9434
|
+
await moveHumanQueuePrompt(
|
|
9435
|
+
{ db, bus },
|
|
9436
|
+
{ accountId: grant.accountId, workspaceId, sessionId, subjectId: grant.subjectId },
|
|
9437
|
+
c.req.param("turnId"),
|
|
9438
|
+
payload
|
|
9439
|
+
)
|
|
9311
9440
|
);
|
|
9312
|
-
await bus.publish(workspaceId, sessionId, result.events);
|
|
9313
|
-
if (result.shouldWake) {
|
|
9314
|
-
if (result.workflowWakeRevision === null) {
|
|
9315
|
-
throw new Error("Queue continuation has no workflow wake revision");
|
|
9316
|
-
}
|
|
9317
|
-
await workflowClient.wakeSessionWorkflow({
|
|
9318
|
-
accountId: grant.accountId,
|
|
9319
|
-
workspaceId,
|
|
9320
|
-
sessionId,
|
|
9321
|
-
workflowId: workflowIdForSession2(sessionId),
|
|
9322
|
-
wakeRevision: result.workflowWakeRevision
|
|
9323
|
-
});
|
|
9324
|
-
}
|
|
9325
|
-
return c.json(result);
|
|
9326
9441
|
} catch (error) {
|
|
9327
|
-
|
|
9442
|
+
return commandConflictResponse(c, error);
|
|
9328
9443
|
}
|
|
9329
9444
|
});
|
|
9330
|
-
app.post("/v1/workspaces/:workspaceId/sessions/:sessionId/
|
|
9445
|
+
app.post("/v1/workspaces/:workspaceId/sessions/:sessionId/queue/:turnId/edit", async (c) => {
|
|
9331
9446
|
const workspaceId = c.req.param("workspaceId");
|
|
9332
9447
|
const grant = await requireAccessGrant14(c, deps, workspaceId, "sessions:control");
|
|
9333
9448
|
const sessionId = c.req.param("sessionId");
|
|
9334
|
-
|
|
9335
|
-
|
|
9449
|
+
await assertSessionExists(db, workspaceId, sessionId);
|
|
9450
|
+
const payload = EditSessionQueueItemRequest.parse(await c.req.json());
|
|
9336
9451
|
try {
|
|
9337
|
-
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
|
|
9343
|
-
|
|
9344
|
-
|
|
9345
|
-
...payload.expectedControlState !== void 0 ? { expectedControlState: payload.expectedControlState } : {},
|
|
9346
|
-
...payload.expectedControlGeneration !== void 0 ? { expectedControlGeneration: payload.expectedControlGeneration } : {},
|
|
9347
|
-
...payload.expectedWorkspaceInferenceGeneration !== void 0 ? {
|
|
9348
|
-
expectedWorkspaceInferenceGeneration: payload.expectedWorkspaceInferenceGeneration
|
|
9349
|
-
} : {}
|
|
9350
|
-
});
|
|
9452
|
+
return c.json(
|
|
9453
|
+
await editHumanQueuePrompt(
|
|
9454
|
+
{ db, bus },
|
|
9455
|
+
{ accountId: grant.accountId, workspaceId, sessionId, subjectId: grant.subjectId },
|
|
9456
|
+
c.req.param("turnId"),
|
|
9457
|
+
payload
|
|
9458
|
+
)
|
|
9459
|
+
);
|
|
9351
9460
|
} catch (error) {
|
|
9352
|
-
|
|
9461
|
+
return commandConflictResponse(c, error);
|
|
9353
9462
|
}
|
|
9354
|
-
|
|
9355
|
-
|
|
9356
|
-
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
|
|
9367
|
-
|
|
9368
|
-
|
|
9369
|
-
|
|
9370
|
-
|
|
9371
|
-
|
|
9372
|
-
|
|
9463
|
+
});
|
|
9464
|
+
app.post("/v1/workspaces/:workspaceId/sessions/:sessionId/queue/:turnId/steer", async (c) => {
|
|
9465
|
+
const workspaceId = c.req.param("workspaceId");
|
|
9466
|
+
const grant = await requireAccessGrant14(c, deps, workspaceId, "sessions:control");
|
|
9467
|
+
const sessionId = c.req.param("sessionId");
|
|
9468
|
+
await assertSessionExists(db, workspaceId, sessionId);
|
|
9469
|
+
const payload = SteerSessionQueueItemRequest.parse(await c.req.json());
|
|
9470
|
+
try {
|
|
9471
|
+
return c.json(
|
|
9472
|
+
await steerHumanQueuePrompt(
|
|
9473
|
+
{ db, bus },
|
|
9474
|
+
{ accountId: grant.accountId, workspaceId, sessionId, subjectId: grant.subjectId },
|
|
9475
|
+
c.req.param("turnId"),
|
|
9476
|
+
payload
|
|
9477
|
+
)
|
|
9478
|
+
);
|
|
9479
|
+
} catch (error) {
|
|
9480
|
+
return commandConflictResponse(c, error);
|
|
9481
|
+
}
|
|
9482
|
+
});
|
|
9483
|
+
app.post("/v1/workspaces/:workspaceId/sessions/:sessionId/queue/:turnId/delete", async (c) => {
|
|
9484
|
+
const workspaceId = c.req.param("workspaceId");
|
|
9485
|
+
const grant = await requireAccessGrant14(c, deps, workspaceId, "sessions:control");
|
|
9486
|
+
const sessionId = c.req.param("sessionId");
|
|
9487
|
+
await assertSessionExists(db, workspaceId, sessionId);
|
|
9488
|
+
const payload = DeleteSessionQueueItemRequest.parse(await c.req.json());
|
|
9489
|
+
try {
|
|
9490
|
+
return c.json(
|
|
9491
|
+
await deleteHumanQueuePrompt(
|
|
9492
|
+
{ db, bus },
|
|
9493
|
+
{ accountId: grant.accountId, workspaceId, sessionId, subjectId: grant.subjectId },
|
|
9494
|
+
c.req.param("turnId"),
|
|
9495
|
+
payload
|
|
9496
|
+
)
|
|
9497
|
+
);
|
|
9498
|
+
} catch (error) {
|
|
9499
|
+
return commandConflictResponse(c, error);
|
|
9500
|
+
}
|
|
9501
|
+
});
|
|
9502
|
+
app.get("/v1/workspaces/:workspaceId/sessions/:sessionId/composer-draft", async (c) => {
|
|
9503
|
+
const workspaceId = c.req.param("workspaceId");
|
|
9504
|
+
const grant = await requireAccessGrant14(c, deps, workspaceId, "sessions:read");
|
|
9505
|
+
const sessionId = c.req.param("sessionId");
|
|
9506
|
+
return c.json(
|
|
9507
|
+
await getHumanComposerDraft(db, {
|
|
9373
9508
|
accountId: grant.accountId,
|
|
9374
9509
|
workspaceId,
|
|
9375
9510
|
sessionId,
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
});
|
|
9379
|
-
}
|
|
9380
|
-
return c.json(
|
|
9381
|
-
{
|
|
9382
|
-
operationId: result.operationId,
|
|
9383
|
-
event: result.event,
|
|
9384
|
-
controlState: result.controlState,
|
|
9385
|
-
controlGeneration: result.controlGeneration,
|
|
9386
|
-
expectedActiveTurnId: result.expectedActiveTurnId,
|
|
9387
|
-
expectedExecutionGeneration: result.expectedExecutionGeneration,
|
|
9388
|
-
expectedAttemptId: result.expectedAttemptId,
|
|
9389
|
-
deliveryEventId: result.deliveryEventId,
|
|
9390
|
-
shouldSignalControl: result.shouldSignalControl,
|
|
9391
|
-
shouldWake: result.shouldWake
|
|
9392
|
-
},
|
|
9393
|
-
202
|
|
9511
|
+
subjectId: grant.subjectId
|
|
9512
|
+
})
|
|
9394
9513
|
);
|
|
9395
9514
|
});
|
|
9515
|
+
app.put("/v1/workspaces/:workspaceId/sessions/:sessionId/composer-draft", async (c) => {
|
|
9516
|
+
const workspaceId = c.req.param("workspaceId");
|
|
9517
|
+
const grant = await requireAccessGrant14(c, deps, workspaceId, "sessions:control");
|
|
9518
|
+
const sessionId = c.req.param("sessionId");
|
|
9519
|
+
const payload = SaveComposerDraftRequest.parse(await c.req.json());
|
|
9520
|
+
try {
|
|
9521
|
+
return c.json(
|
|
9522
|
+
await saveHumanComposerDraft(
|
|
9523
|
+
db,
|
|
9524
|
+
{ accountId: grant.accountId, workspaceId, sessionId, subjectId: grant.subjectId },
|
|
9525
|
+
payload
|
|
9526
|
+
)
|
|
9527
|
+
);
|
|
9528
|
+
} catch (error) {
|
|
9529
|
+
return commandConflictResponse(c, error);
|
|
9530
|
+
}
|
|
9531
|
+
});
|
|
9532
|
+
app.post("/v1/workspaces/:workspaceId/sessions/:sessionId/control", async (c) => {
|
|
9533
|
+
const workspaceId = c.req.param("workspaceId");
|
|
9534
|
+
const grant = await requireAccessGrant14(c, deps, workspaceId, "sessions:control");
|
|
9535
|
+
const sessionId = c.req.param("sessionId");
|
|
9536
|
+
const payload = SessionControlRequest.parse(await c.req.json());
|
|
9537
|
+
try {
|
|
9538
|
+
return c.json(
|
|
9539
|
+
await controlHumanSessionWorkstream2(
|
|
9540
|
+
{ db, bus, workflowClient },
|
|
9541
|
+
{ accountId: grant.accountId, workspaceId, sessionId, subjectId: grant.subjectId },
|
|
9542
|
+
payload
|
|
9543
|
+
)
|
|
9544
|
+
);
|
|
9545
|
+
} catch (error) {
|
|
9546
|
+
return commandConflictResponse(c, error);
|
|
9547
|
+
}
|
|
9548
|
+
});
|
|
9396
9549
|
app.post("/v1/workspaces/:workspaceId/sessions/:sessionId/steer", async (c) => {
|
|
9397
9550
|
const workspaceId = c.req.param("workspaceId");
|
|
9398
9551
|
const grant = await requireAccessGrant14(c, deps, workspaceId, "sessions:control");
|
|
@@ -9410,10 +9563,8 @@ function registerSessionRoutes(app, deps) {
|
|
|
9410
9563
|
mcpCredentialUpdates: payload.mcpCredentialUpdates ?? [],
|
|
9411
9564
|
delivery: "steer",
|
|
9412
9565
|
origin: "human",
|
|
9413
|
-
...payload.
|
|
9414
|
-
...payload.
|
|
9415
|
-
expectedWorkspaceInferenceGeneration: payload.expectedWorkspaceInferenceGeneration
|
|
9416
|
-
} : {},
|
|
9566
|
+
...payload.controlEtag !== void 0 ? { controlEtag: payload.controlEtag } : {},
|
|
9567
|
+
...payload.expectedDraftRevision !== void 0 ? { expectedDraftRevision: payload.expectedDraftRevision } : {},
|
|
9417
9568
|
...payload.clientEventId ? { clientEventId: payload.clientEventId } : {}
|
|
9418
9569
|
});
|
|
9419
9570
|
return c.json(result, 202);
|
|
@@ -9433,6 +9584,8 @@ function registerSessionRoutes(app, deps) {
|
|
|
9433
9584
|
model: event.payload.model ?? null,
|
|
9434
9585
|
reasoningEffort: event.payload.reasoningEffort ?? null,
|
|
9435
9586
|
mcpCredentialUpdates: event.payload.mcpCredentialUpdates ?? [],
|
|
9587
|
+
...event.payload.controlEtag !== void 0 ? { controlEtag: event.payload.controlEtag } : {},
|
|
9588
|
+
...event.payload.expectedDraftRevision !== void 0 ? { expectedDraftRevision: event.payload.expectedDraftRevision } : {},
|
|
9436
9589
|
...event.clientEventId ? { clientEventId: event.clientEventId } : {}
|
|
9437
9590
|
});
|
|
9438
9591
|
return c.json(accepted, 202);
|
|
@@ -9451,7 +9604,7 @@ function registerSessionRoutes(app, deps) {
|
|
|
9451
9604
|
});
|
|
9452
9605
|
}
|
|
9453
9606
|
await publishDurableSessionEvents(bus, workspaceId, sessionId, accepted.events);
|
|
9454
|
-
const workflowId =
|
|
9607
|
+
const workflowId = workflowIdForSession(sessionId);
|
|
9455
9608
|
await workflowClient.signalApprovalDecision({
|
|
9456
9609
|
accountId: grant.accountId,
|
|
9457
9610
|
workspaceId,
|
|
@@ -10172,15 +10325,15 @@ function userMessagePayloadHasOwnProperty(value, key) {
|
|
|
10172
10325
|
const payload = value.payload;
|
|
10173
10326
|
return hasOwnProperty(payload, key);
|
|
10174
10327
|
}
|
|
10175
|
-
function
|
|
10176
|
-
if (error instanceof
|
|
10177
|
-
|
|
10178
|
-
|
|
10179
|
-
|
|
10180
|
-
|
|
10181
|
-
|
|
10182
|
-
|
|
10183
|
-
});
|
|
10328
|
+
function commandConflictResponse(c, error) {
|
|
10329
|
+
if (error instanceof QueueCommandConflictError) {
|
|
10330
|
+
return c.json({ code: error.code, message: error.message, current: error.current }, 409);
|
|
10331
|
+
}
|
|
10332
|
+
if (error instanceof SessionControlConflictError) {
|
|
10333
|
+
return c.json({ code: error.code, message: error.message }, 409);
|
|
10334
|
+
}
|
|
10335
|
+
if (error instanceof SessionCommandIdempotencyError) {
|
|
10336
|
+
return c.json({ code: error.code, message: error.message }, 409);
|
|
10184
10337
|
}
|
|
10185
10338
|
throw error;
|
|
10186
10339
|
}
|
|
@@ -10329,6 +10482,7 @@ import {
|
|
|
10329
10482
|
grantWorkspaceAccess,
|
|
10330
10483
|
listScheduledTasks as listScheduledTasks3,
|
|
10331
10484
|
listWorkspaceMembers,
|
|
10485
|
+
listWorkspaceControlEvents as listWorkspaceControlEvents2,
|
|
10332
10486
|
listWorkspacesForSubject,
|
|
10333
10487
|
removeWorkspaceMember,
|
|
10334
10488
|
requireWorkspace,
|
|
@@ -10336,8 +10490,7 @@ import {
|
|
|
10336
10490
|
setWorkspaceDefaultRig,
|
|
10337
10491
|
updateWorkspace,
|
|
10338
10492
|
updateWorkspaceSettings,
|
|
10339
|
-
upsertWorkspaceModelPolicy
|
|
10340
|
-
setWorkspaceInferenceControl
|
|
10493
|
+
upsertWorkspaceModelPolicy
|
|
10341
10494
|
} from "@opengeni/db";
|
|
10342
10495
|
import { HTTPException as HTTPException23 } from "hono/http-exception";
|
|
10343
10496
|
import { hasPermission as hasPermission3, requireAccessContext as requireAccessContext2, requireAccessGrant as requireAccessGrant16 } from "@opengeni/core";
|
|
@@ -10345,6 +10498,7 @@ import { requireLimit as requireLimit7 } from "@opengeni/core";
|
|
|
10345
10498
|
import {
|
|
10346
10499
|
assertWorkspaceDeletable,
|
|
10347
10500
|
assertWorkspaceMemberRemovable,
|
|
10501
|
+
controlHumanWorkspace,
|
|
10348
10502
|
resolveMemberSubjectId
|
|
10349
10503
|
} from "@opengeni/core";
|
|
10350
10504
|
function registerWorkspaceRoutes(app, deps) {
|
|
@@ -10448,51 +10602,33 @@ function registerWorkspaceRoutes(app, deps) {
|
|
|
10448
10602
|
const workspaceId = c.req.param("workspaceId");
|
|
10449
10603
|
const grant = await requireAccessGrant16(c, deps, workspaceId, "workspace:admin");
|
|
10450
10604
|
const payload = WorkspaceInferenceControlRequest.parse(await c.req.json());
|
|
10451
|
-
const result = await setWorkspaceInferenceControl(deps.db, {
|
|
10452
|
-
accountId: grant.accountId,
|
|
10453
|
-
workspaceId,
|
|
10454
|
-
actor: grant.subjectId,
|
|
10455
|
-
state: payload.state,
|
|
10456
|
-
reason: payload.reason,
|
|
10457
|
-
clientEventId: payload.clientEventId,
|
|
10458
|
-
expectedState: payload.expectedState,
|
|
10459
|
-
expectedGeneration: payload.expectedGeneration,
|
|
10460
|
-
exceptSessionIds: payload.exceptSessionIds
|
|
10461
|
-
});
|
|
10462
|
-
for (const broadcast of result.broadcasts) {
|
|
10463
|
-
await deps.bus.publish(workspaceId, broadcast.sessionId, broadcast.events);
|
|
10464
|
-
}
|
|
10465
|
-
for (const control of result.controls) {
|
|
10466
|
-
await deps.workflowClient.signalSessionControl({
|
|
10467
|
-
accountId: control.accountId,
|
|
10468
|
-
workspaceId,
|
|
10469
|
-
sessionId: control.sessionId,
|
|
10470
|
-
eventId: control.eventId,
|
|
10471
|
-
workflowId: control.workflowId,
|
|
10472
|
-
workflowWakeRevision: control.workflowWakeRevision
|
|
10473
|
-
});
|
|
10474
|
-
}
|
|
10475
|
-
for (const wake of result.wakeSessions) {
|
|
10476
|
-
await deps.workflowClient.wakeSessionWorkflow({
|
|
10477
|
-
accountId: wake.accountId,
|
|
10478
|
-
workspaceId,
|
|
10479
|
-
sessionId: wake.sessionId,
|
|
10480
|
-
workflowId: wake.workflowId,
|
|
10481
|
-
wakeRevision: wake.workflowWakeRevision
|
|
10482
|
-
});
|
|
10483
|
-
}
|
|
10484
10605
|
return c.json(
|
|
10485
|
-
|
|
10486
|
-
|
|
10487
|
-
|
|
10488
|
-
|
|
10489
|
-
|
|
10490
|
-
|
|
10491
|
-
|
|
10492
|
-
|
|
10493
|
-
|
|
10606
|
+
await controlHumanWorkspace(
|
|
10607
|
+
{ db: deps.db, bus: deps.bus, workflowClient: deps.workflowClient },
|
|
10608
|
+
{ accountId: grant.accountId, workspaceId, subjectId: grant.subjectId },
|
|
10609
|
+
payload
|
|
10610
|
+
)
|
|
10611
|
+
);
|
|
10612
|
+
});
|
|
10613
|
+
app.get("/v1/workspaces/:workspaceId/control-events", async (c) => {
|
|
10614
|
+
const workspaceId = c.req.param("workspaceId");
|
|
10615
|
+
await requireAccessGrant16(c, deps, workspaceId, "workspace:read");
|
|
10616
|
+
const after = Math.max(0, Number.parseInt(c.req.query("after") ?? "0", 10) || 0);
|
|
10617
|
+
return c.json(
|
|
10618
|
+
await listWorkspaceControlEvents2(
|
|
10619
|
+
deps.db,
|
|
10620
|
+
workspaceId,
|
|
10621
|
+
after,
|
|
10622
|
+
boundedLimit(c.req.query("limit"))
|
|
10623
|
+
)
|
|
10494
10624
|
);
|
|
10495
10625
|
});
|
|
10626
|
+
app.get("/v1/workspaces/:workspaceId/control-events/stream", async (c) => {
|
|
10627
|
+
const workspaceId = c.req.param("workspaceId");
|
|
10628
|
+
await requireAccessGrant16(c, deps, workspaceId, "workspace:read");
|
|
10629
|
+
const after = Math.max(0, Number.parseInt(c.req.query("after") ?? "0", 10) || 0);
|
|
10630
|
+
return await sseWorkspaceControlStream(deps.db, deps.bus, workspaceId, after, c.req.raw.signal);
|
|
10631
|
+
});
|
|
10496
10632
|
app.put("/v1/workspaces/:workspaceId/default-rig", async (c) => {
|
|
10497
10633
|
const workspaceId = c.req.param("workspaceId");
|
|
10498
10634
|
await requireAccessGrant16(c, deps, workspaceId, "rigs:manage");
|
|
@@ -10610,7 +10746,8 @@ import {
|
|
|
10610
10746
|
validateToolRefs,
|
|
10611
10747
|
withDefaultEnabledCapabilityMcpTools
|
|
10612
10748
|
} from "@opengeni/core";
|
|
10613
|
-
import { workflowIdForSession as
|
|
10749
|
+
import { workflowIdForSession as workflowIdForSession2 } from "@opengeni/core";
|
|
10750
|
+
var API_MAX_REQUEST_BODY_BYTES = 8 * 1024 * 1024;
|
|
10614
10751
|
function createApp(deps) {
|
|
10615
10752
|
const managedAuth = deps.managedAuth ?? createManagedAuth(deps.settings, deps.db);
|
|
10616
10753
|
const objectStorage = deps.objectStorage === void 0 ? createObjectStorage(deps.settings) : deps.objectStorage;
|
|
@@ -10626,7 +10763,9 @@ function createApp(deps) {
|
|
|
10626
10763
|
documentId
|
|
10627
10764
|
}) => {
|
|
10628
10765
|
if (!objectStorage) {
|
|
10629
|
-
throw new HTTPException24(503, {
|
|
10766
|
+
throw new HTTPException24(503, {
|
|
10767
|
+
message: "object storage is not configured"
|
|
10768
|
+
});
|
|
10630
10769
|
}
|
|
10631
10770
|
return await indexDocumentNow(
|
|
10632
10771
|
deps.db,
|
|
@@ -10665,6 +10804,15 @@ function createApp(deps) {
|
|
|
10665
10804
|
"*",
|
|
10666
10805
|
cors({
|
|
10667
10806
|
credentials: true,
|
|
10807
|
+
allowHeaders: [
|
|
10808
|
+
"Accept",
|
|
10809
|
+
"Authorization",
|
|
10810
|
+
"Content-Type",
|
|
10811
|
+
"X-OpenGeni-Access-Key",
|
|
10812
|
+
"X-OpenGeni-Api-Contract",
|
|
10813
|
+
"X-OpenGeni-Subject"
|
|
10814
|
+
],
|
|
10815
|
+
exposeHeaders: ["X-OpenGeni-Api-Contract"],
|
|
10668
10816
|
origin: (origin) => {
|
|
10669
10817
|
if (!origin) {
|
|
10670
10818
|
return null;
|
|
@@ -10673,6 +10821,13 @@ function createApp(deps) {
|
|
|
10673
10821
|
}
|
|
10674
10822
|
})
|
|
10675
10823
|
);
|
|
10824
|
+
app.use(
|
|
10825
|
+
"*",
|
|
10826
|
+
bodyLimit({
|
|
10827
|
+
maxSize: API_MAX_REQUEST_BODY_BYTES,
|
|
10828
|
+
onError: (c) => c.json({ code: "PAYLOAD_TOO_LARGE", message: "Request body is too large." }, 413)
|
|
10829
|
+
})
|
|
10830
|
+
);
|
|
10676
10831
|
app.use("*", async (c, next) => {
|
|
10677
10832
|
const url = new URL(c.req.url);
|
|
10678
10833
|
const route = routeLabel(url.pathname);
|
|
@@ -10686,7 +10841,12 @@ function createApp(deps) {
|
|
|
10686
10841
|
await next();
|
|
10687
10842
|
const status = c.res.status || 200;
|
|
10688
10843
|
const durationSeconds = (performance.now() - start) / 1e3;
|
|
10689
|
-
observability.recordHttpRequest({
|
|
10844
|
+
observability.recordHttpRequest({
|
|
10845
|
+
method: c.req.method,
|
|
10846
|
+
route,
|
|
10847
|
+
status,
|
|
10848
|
+
durationSeconds
|
|
10849
|
+
});
|
|
10690
10850
|
span.end({
|
|
10691
10851
|
attributes: {
|
|
10692
10852
|
"http.response.status_code": status,
|
|
@@ -10704,7 +10864,12 @@ function createApp(deps) {
|
|
|
10704
10864
|
} catch (error) {
|
|
10705
10865
|
const status = httpStatusForError(error);
|
|
10706
10866
|
const durationSeconds = (performance.now() - start) / 1e3;
|
|
10707
|
-
observability.recordHttpRequest({
|
|
10867
|
+
observability.recordHttpRequest({
|
|
10868
|
+
method: c.req.method,
|
|
10869
|
+
route,
|
|
10870
|
+
status,
|
|
10871
|
+
durationSeconds
|
|
10872
|
+
});
|
|
10708
10873
|
span.end({
|
|
10709
10874
|
attributes: {
|
|
10710
10875
|
"http.response.status_code": status,
|
|
@@ -10725,6 +10890,20 @@ function createApp(deps) {
|
|
|
10725
10890
|
}
|
|
10726
10891
|
});
|
|
10727
10892
|
app.use("*", requireAccessKey(deps.settings));
|
|
10893
|
+
app.use("/v1/*", async (c, next) => {
|
|
10894
|
+
c.header(OPENGENI_API_CONTRACT_HEADER, OPENGENI_API_CONTRACT_REVISION);
|
|
10895
|
+
if (deps.settings.environment !== "test" && isApiContractProtectedMutation(c.req.method, new URL(c.req.url).pathname) && c.req.header(OPENGENI_API_CONTRACT_HEADER) !== OPENGENI_API_CONTRACT_REVISION) {
|
|
10896
|
+
return c.json(
|
|
10897
|
+
{
|
|
10898
|
+
code: "API_CONTRACT_CHANGED",
|
|
10899
|
+
message: "OpenGeni updated. Reload this client before changing state.",
|
|
10900
|
+
apiContractRevision: OPENGENI_API_CONTRACT_REVISION
|
|
10901
|
+
},
|
|
10902
|
+
409
|
|
10903
|
+
);
|
|
10904
|
+
}
|
|
10905
|
+
await next();
|
|
10906
|
+
});
|
|
10728
10907
|
if (managedAuth) {
|
|
10729
10908
|
app.on(["GET", "POST"], "/v1/auth/*", (c) => managedAuth.handler(c.req.raw));
|
|
10730
10909
|
}
|
|
@@ -10748,11 +10927,12 @@ function createApp(deps) {
|
|
|
10748
10927
|
"content-type": "text/plain; version=0.0.4; charset=utf-8"
|
|
10749
10928
|
})
|
|
10750
10929
|
);
|
|
10751
|
-
app.get(
|
|
10752
|
-
"
|
|
10753
|
-
|
|
10930
|
+
app.get("/v1/config/client", (c) => {
|
|
10931
|
+
c.header("cache-control", "no-store");
|
|
10932
|
+
return c.json(
|
|
10754
10933
|
ClientConfig.parse({
|
|
10755
10934
|
deploymentRevision: deps.settings.deploymentRevision,
|
|
10935
|
+
apiContractRevision: OPENGENI_API_CONTRACT_REVISION,
|
|
10756
10936
|
...deps.settings.serverVersion ? { serverVersion: deps.settings.serverVersion } : {},
|
|
10757
10937
|
defaultModel: deps.settings.openaiModel,
|
|
10758
10938
|
allowedModels: configuredAllowedModels(deps.settings),
|
|
@@ -10785,15 +10965,17 @@ function createApp(deps) {
|
|
|
10785
10965
|
// Per-session availability is still negotiated on /stream-capabilities.
|
|
10786
10966
|
structuredServices: structuredServicesHint(deps.settings.sandboxBackend)
|
|
10787
10967
|
})
|
|
10788
|
-
)
|
|
10789
|
-
);
|
|
10968
|
+
);
|
|
10969
|
+
});
|
|
10790
10970
|
app.all("/v1/workspaces/:workspaceId/mcp", async (c) => {
|
|
10791
10971
|
const workspaceId = c.req.param("workspaceId");
|
|
10792
10972
|
const grant = await requireMcpAccessGrant(c, routeDeps, workspaceId);
|
|
10793
10973
|
const toolspace = isToolspaceGrant(routeDeps.settings, grant) ? await prepareToolspaceMcpSurface({ deps: routeDeps, grant }) : null;
|
|
10794
10974
|
const workspace = await getWorkspace2(routeDeps.db, workspaceId);
|
|
10795
10975
|
const workspaceMemoryEnabled = resolveWorkspaceMemoryEnabled(workspace?.settings);
|
|
10796
|
-
const transport = new WebStandardStreamableHTTPServerTransport2({
|
|
10976
|
+
const transport = new WebStandardStreamableHTTPServerTransport2({
|
|
10977
|
+
enableJsonResponse: true
|
|
10978
|
+
});
|
|
10797
10979
|
const mcp = buildOpenGeniMcpServer(routeDeps, grant, {
|
|
10798
10980
|
requestOrigin: new URL(c.req.url).origin,
|
|
10799
10981
|
toolspace,
|
|
@@ -10850,7 +11032,10 @@ function clientAuthConfig(settings) {
|
|
|
10850
11032
|
};
|
|
10851
11033
|
}
|
|
10852
11034
|
if (settings.authRequired) {
|
|
10853
|
-
return {
|
|
11035
|
+
return {
|
|
11036
|
+
mode: "deploymentKey",
|
|
11037
|
+
headerName: "x-opengeni-access-key"
|
|
11038
|
+
};
|
|
10854
11039
|
}
|
|
10855
11040
|
return { mode: "none" };
|
|
10856
11041
|
}
|
|
@@ -10892,7 +11077,10 @@ async function runReadinessChecks(checks, timeoutMs) {
|
|
|
10892
11077
|
} catch (error) {
|
|
10893
11078
|
return [
|
|
10894
11079
|
name,
|
|
10895
|
-
{
|
|
11080
|
+
{
|
|
11081
|
+
ok: false,
|
|
11082
|
+
error: error instanceof Error ? error.message : String(error)
|
|
11083
|
+
}
|
|
10896
11084
|
];
|
|
10897
11085
|
}
|
|
10898
11086
|
}
|
|
@@ -10941,15 +11129,24 @@ var routeLabelPatterns = [
|
|
|
10941
11129
|
pattern: /^\/v1\/workspaces\/[^/]+\/codex\/usage$/,
|
|
10942
11130
|
label: "/v1/workspaces/:workspaceId/codex/usage"
|
|
10943
11131
|
},
|
|
10944
|
-
{
|
|
11132
|
+
{
|
|
11133
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/codex$/,
|
|
11134
|
+
label: "/v1/workspaces/:workspaceId/codex"
|
|
11135
|
+
},
|
|
10945
11136
|
{ pattern: /^\/metrics$/, label: "/metrics" },
|
|
10946
11137
|
{ pattern: /^\/v1\/config\/client$/, label: "/v1/config/client" },
|
|
10947
11138
|
{ pattern: /^\/v1\/billing$/, label: "/v1/billing" },
|
|
10948
11139
|
{ pattern: /^\/v1\/billing\/checkout$/, label: "/v1/billing/checkout" },
|
|
10949
11140
|
{ pattern: /^\/v1\/billing\/usage$/, label: "/v1/billing/usage" },
|
|
10950
|
-
{
|
|
11141
|
+
{
|
|
11142
|
+
pattern: /^\/v1\/billing\/entitlements$/,
|
|
11143
|
+
label: "/v1/billing/entitlements"
|
|
11144
|
+
},
|
|
10951
11145
|
{ pattern: /^\/v1\/webhooks\/stripe$/, label: "/v1/webhooks/stripe" },
|
|
10952
|
-
{
|
|
11146
|
+
{
|
|
11147
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/mcp$/,
|
|
11148
|
+
label: "/v1/workspaces/:workspaceId/mcp"
|
|
11149
|
+
},
|
|
10953
11150
|
{
|
|
10954
11151
|
pattern: /^\/v1\/workspaces\/[^/]+\/mcp\/docs$/,
|
|
10955
11152
|
label: "/v1/workspaces/:workspaceId/mcp/docs"
|
|
@@ -10958,7 +11155,22 @@ var routeLabelPatterns = [
|
|
|
10958
11155
|
pattern: /^\/v1\/workspaces\/[^/]+\/default-rig$/,
|
|
10959
11156
|
label: "/v1/workspaces/:workspaceId/default-rig"
|
|
10960
11157
|
},
|
|
10961
|
-
{
|
|
11158
|
+
{
|
|
11159
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/sessions$/,
|
|
11160
|
+
label: "/v1/workspaces/:workspaceId/sessions"
|
|
11161
|
+
},
|
|
11162
|
+
{
|
|
11163
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/control-events\/stream$/,
|
|
11164
|
+
label: "/v1/workspaces/:workspaceId/control-events/stream"
|
|
11165
|
+
},
|
|
11166
|
+
{
|
|
11167
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/control-events$/,
|
|
11168
|
+
label: "/v1/workspaces/:workspaceId/control-events"
|
|
11169
|
+
},
|
|
11170
|
+
{
|
|
11171
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/inference-control$/,
|
|
11172
|
+
label: "/v1/workspaces/:workspaceId/inference-control"
|
|
11173
|
+
},
|
|
10962
11174
|
{
|
|
10963
11175
|
pattern: /^\/v1\/workspaces\/[^/]+\/sessions\/[^/]+\/events\/stream$/,
|
|
10964
11176
|
label: "/v1/workspaces/:workspaceId/sessions/:id/events/stream"
|
|
@@ -10972,16 +11184,20 @@ var routeLabelPatterns = [
|
|
|
10972
11184
|
label: "/v1/workspaces/:workspaceId/sessions/:id/events"
|
|
10973
11185
|
},
|
|
10974
11186
|
{
|
|
10975
|
-
pattern: /^\/v1\/workspaces\/[^/]+\/sessions\/[^/]+\/
|
|
10976
|
-
label: "/v1/workspaces/:workspaceId/sessions/:id/
|
|
11187
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/sessions\/[^/]+\/queue\/[^/]+\/(move|edit|steer|delete)$/,
|
|
11188
|
+
label: "/v1/workspaces/:workspaceId/sessions/:id/queue/:turnId/:action"
|
|
11189
|
+
},
|
|
11190
|
+
{
|
|
11191
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/sessions\/[^/]+\/queue$/,
|
|
11192
|
+
label: "/v1/workspaces/:workspaceId/sessions/:id/queue"
|
|
10977
11193
|
},
|
|
10978
11194
|
{
|
|
10979
|
-
pattern: /^\/v1\/workspaces\/[^/]+\/sessions\/[^/]+\/
|
|
10980
|
-
label: "/v1/workspaces/:workspaceId/sessions/:id/
|
|
11195
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/sessions\/[^/]+\/composer-draft$/,
|
|
11196
|
+
label: "/v1/workspaces/:workspaceId/sessions/:id/composer-draft"
|
|
10981
11197
|
},
|
|
10982
11198
|
{
|
|
10983
|
-
pattern: /^\/v1\/workspaces\/[^/]+\/sessions\/[^/]+\/
|
|
10984
|
-
label: "/v1/workspaces/:workspaceId/sessions/:id
|
|
11199
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/sessions\/[^/]+\/(control|steer)$/,
|
|
11200
|
+
label: "/v1/workspaces/:workspaceId/sessions/:id/:controlAction"
|
|
10985
11201
|
},
|
|
10986
11202
|
{
|
|
10987
11203
|
pattern: /^\/v1\/workspaces\/[^/]+\/sessions\/[^/]+\/stream-capabilities$/,
|
|
@@ -11023,7 +11239,10 @@ var routeLabelPatterns = [
|
|
|
11023
11239
|
pattern: /^\/v1\/workspaces\/[^/]+\/files\/[^/]+$/,
|
|
11024
11240
|
label: "/v1/workspaces/:workspaceId/files/:id"
|
|
11025
11241
|
},
|
|
11026
|
-
{
|
|
11242
|
+
{
|
|
11243
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/api-keys$/,
|
|
11244
|
+
label: "/v1/workspaces/:workspaceId/api-keys"
|
|
11245
|
+
},
|
|
11027
11246
|
{
|
|
11028
11247
|
pattern: /^\/v1\/workspaces\/[^/]+\/api-keys\/[^/]+$/,
|
|
11029
11248
|
label: "/v1/workspaces/:workspaceId/api-keys/:id"
|
|
@@ -11132,7 +11351,10 @@ var routeLabelPatterns = [
|
|
|
11132
11351
|
pattern: /^\/v1\/workspaces\/[^/]+\/environments\/[^/]+$/,
|
|
11133
11352
|
label: "/v1/workspaces/:workspaceId/environments/:id"
|
|
11134
11353
|
},
|
|
11135
|
-
{
|
|
11354
|
+
{
|
|
11355
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/packs$/,
|
|
11356
|
+
label: "/v1/workspaces/:workspaceId/packs"
|
|
11357
|
+
},
|
|
11136
11358
|
{
|
|
11137
11359
|
pattern: /^\/v1\/workspaces\/[^/]+\/packs\/installations$/,
|
|
11138
11360
|
label: "/v1/workspaces/:workspaceId/packs/installations"
|
|
@@ -11170,13 +11392,22 @@ var routeLabelPatterns = [
|
|
|
11170
11392
|
label: "/v1/workspaces/:workspaceId/connections/:connectionId"
|
|
11171
11393
|
},
|
|
11172
11394
|
{ pattern: /^\/v1\/catalog-assets\/.+$/, label: "/v1/catalog-assets/*" },
|
|
11173
|
-
{
|
|
11395
|
+
{
|
|
11396
|
+
pattern: /^\/v1\/integrations\/oauth\/callback$/,
|
|
11397
|
+
label: "/v1/integrations/oauth/callback"
|
|
11398
|
+
},
|
|
11174
11399
|
{
|
|
11175
11400
|
pattern: /^\/v1\/integrations\/oauth\/client-metadata\.json$/,
|
|
11176
11401
|
label: "/v1/integrations/oauth/client-metadata.json"
|
|
11177
11402
|
},
|
|
11178
|
-
{
|
|
11179
|
-
|
|
11403
|
+
{
|
|
11404
|
+
pattern: /^\/v1\/enrollments\/device\/start$/,
|
|
11405
|
+
label: "/v1/enrollments/device/start"
|
|
11406
|
+
},
|
|
11407
|
+
{
|
|
11408
|
+
pattern: /^\/v1\/enrollments\/device\/poll$/,
|
|
11409
|
+
label: "/v1/enrollments/device/poll"
|
|
11410
|
+
},
|
|
11180
11411
|
{
|
|
11181
11412
|
pattern: /^\/v1\/workspaces\/[^/]+\/enrollments\/device\/approve$/,
|
|
11182
11413
|
label: "/v1/workspaces/:workspaceId/enrollments/device/approve"
|
|
@@ -11193,11 +11424,23 @@ var routeLabelPatterns = [
|
|
|
11193
11424
|
pattern: /^\/v1\/workspaces\/[^/]+\/machines\/[^/]+\/metrics\/series$/,
|
|
11194
11425
|
label: "/v1/workspaces/:workspaceId/machines/:enrollmentId/metrics/series"
|
|
11195
11426
|
},
|
|
11196
|
-
{
|
|
11197
|
-
|
|
11427
|
+
{
|
|
11428
|
+
pattern: /^\/v1\/workspaces\/[^/]+\/machines$/,
|
|
11429
|
+
label: "/v1/workspaces/:workspaceId/machines"
|
|
11430
|
+
},
|
|
11431
|
+
{
|
|
11432
|
+
pattern: /^\/v1\/github\/app-manifest\/callback$/,
|
|
11433
|
+
label: "/v1/github/app-manifest/callback"
|
|
11434
|
+
},
|
|
11198
11435
|
{ pattern: /^\/v1\/github\/setup$/, label: "/v1/github/setup" },
|
|
11199
|
-
{
|
|
11200
|
-
|
|
11436
|
+
{
|
|
11437
|
+
pattern: /^\/v1\/github\/install\/callback$/,
|
|
11438
|
+
label: "/v1/github/install/callback"
|
|
11439
|
+
},
|
|
11440
|
+
{
|
|
11441
|
+
pattern: /^\/v1\/github\/oauth\/callback$/,
|
|
11442
|
+
label: "/v1/github/oauth/callback"
|
|
11443
|
+
}
|
|
11201
11444
|
];
|
|
11202
11445
|
function routeLabel(pathname) {
|
|
11203
11446
|
const match = routeLabelPatterns.find(({ pattern }) => pattern.test(pathname));
|
|
@@ -11206,14 +11449,29 @@ function routeLabel(pathname) {
|
|
|
11206
11449
|
}
|
|
11207
11450
|
return pathname.startsWith("/v1/") ? "/v1/unknown" : "/unknown";
|
|
11208
11451
|
}
|
|
11452
|
+
function isApiContractProtectedMutation(method, pathname) {
|
|
11453
|
+
if (!(/* @__PURE__ */ new Set(["POST", "PUT", "PATCH", "DELETE"])).has(method.toUpperCase())) {
|
|
11454
|
+
return false;
|
|
11455
|
+
}
|
|
11456
|
+
if (!pathname.startsWith("/v1/")) {
|
|
11457
|
+
return false;
|
|
11458
|
+
}
|
|
11459
|
+
if (pathname.startsWith("/v1/auth/") || pathname.startsWith("/v1/webhooks/") || pathname.startsWith("/v1/integrations/oauth/") || pathname.startsWith("/v1/github/") || pathname === "/v1/enrollments/device/start" || pathname === "/v1/enrollments/device/poll" || pathname === "/v1/enrollments/token/exchange") {
|
|
11460
|
+
return false;
|
|
11461
|
+
}
|
|
11462
|
+
return !pathname.split("/").includes("mcp");
|
|
11463
|
+
}
|
|
11209
11464
|
|
|
11210
11465
|
export {
|
|
11211
11466
|
sseSessionStream,
|
|
11212
11467
|
replaySessionEvents,
|
|
11468
|
+
sseWorkspaceControlStream,
|
|
11469
|
+
API_MAX_REQUEST_BODY_BYTES,
|
|
11213
11470
|
createApp,
|
|
11214
11471
|
allowedCorsOrigin,
|
|
11215
11472
|
httpStatusForError,
|
|
11216
11473
|
routeLabel,
|
|
11474
|
+
isApiContractProtectedMutation,
|
|
11217
11475
|
mergeResourceRefs,
|
|
11218
11476
|
mergeToolRefs,
|
|
11219
11477
|
normalizeResources,
|
|
@@ -11222,6 +11480,6 @@ export {
|
|
|
11222
11480
|
validateGitHubRepositorySelectionShape,
|
|
11223
11481
|
validateToolRefs,
|
|
11224
11482
|
withDefaultEnabledCapabilityMcpTools,
|
|
11225
|
-
|
|
11483
|
+
workflowIdForSession2 as workflowIdForSession
|
|
11226
11484
|
};
|
|
11227
|
-
//# sourceMappingURL=chunk-
|
|
11485
|
+
//# sourceMappingURL=chunk-HBEJMWD3.js.map
|