@opengeni/core 0.12.1 → 0.12.5
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/index.d.ts +2 -1
- package/dist/index.js +39 -16
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/src/access/index.ts +5 -1
- package/src/domain/capabilities.ts +47 -23
- package/src/domain/sessions.ts +8 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/core",
|
|
3
|
-
"version": "0.12.
|
|
3
|
+
"version": "0.12.5",
|
|
4
4
|
"description": "OpenGeni framework-agnostic core: the domain, access, and billing layers (neutral access, off-HTTP V2 surface). Behavior-preserving extraction from apps/api — keeps Hono's HTTPException for error throwing (typed-errors cleanup deferred).",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -35,14 +35,14 @@
|
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@modelcontextprotocol/sdk": "^1.29.0",
|
|
37
37
|
"@opengeni/codex": "^0.2.7",
|
|
38
|
-
"@opengeni/config": "^0.7.
|
|
39
|
-
"@opengeni/contracts": "^0.
|
|
40
|
-
"@opengeni/db": "^0.13.
|
|
41
|
-
"@opengeni/documents": "^0.2.
|
|
42
|
-
"@opengeni/events": "^0.3.
|
|
38
|
+
"@opengeni/config": "^0.7.10",
|
|
39
|
+
"@opengeni/contracts": "^0.21.0",
|
|
40
|
+
"@opengeni/db": "^0.13.4",
|
|
41
|
+
"@opengeni/documents": "^0.2.41",
|
|
42
|
+
"@opengeni/events": "^0.3.32",
|
|
43
43
|
"@opengeni/observability": "^0.3.0",
|
|
44
|
-
"@opengeni/runtime": "^0.
|
|
45
|
-
"@opengeni/storage": "^0.2.
|
|
44
|
+
"@opengeni/runtime": "^0.14.0",
|
|
45
|
+
"@opengeni/storage": "^0.2.34",
|
|
46
46
|
"hono": "^4.12.18"
|
|
47
47
|
},
|
|
48
48
|
"engines": {
|
package/src/access/index.ts
CHANGED
|
@@ -86,6 +86,10 @@ export function hasPermission(permissions: Permission[], permission: Permission)
|
|
|
86
86
|
|
|
87
87
|
async function resolveAccessContext(c: Context, deps: AccessDeps): Promise<AccessContext | null> {
|
|
88
88
|
if (deps.settings.productAccessMode === "local") {
|
|
89
|
+
const delegated = await delegatedAccessContext(c, deps, "local");
|
|
90
|
+
if (delegated) {
|
|
91
|
+
return delegated;
|
|
92
|
+
}
|
|
89
93
|
return await bootstrapWorkspace(deps.db, {
|
|
90
94
|
accountExternalSource: "opengeni:local",
|
|
91
95
|
accountExternalId: "default",
|
|
@@ -198,7 +202,7 @@ async function apiKeyAccessContext(
|
|
|
198
202
|
async function delegatedAccessContext(
|
|
199
203
|
c: Context,
|
|
200
204
|
deps: AccessDeps,
|
|
201
|
-
mode: "configured" | "managed",
|
|
205
|
+
mode: "local" | "configured" | "managed",
|
|
202
206
|
token = bearerToken(c),
|
|
203
207
|
): Promise<AccessContext | null> {
|
|
204
208
|
if (!token || !deps.settings.delegationSecret) {
|
|
@@ -27,6 +27,7 @@ import {
|
|
|
27
27
|
getVariableSet,
|
|
28
28
|
listCapabilityCatalogItems,
|
|
29
29
|
listCapabilityInstallations,
|
|
30
|
+
listConnectionsMetadata,
|
|
30
31
|
listEnabledMcpCapabilityServers,
|
|
31
32
|
listPackInstallations,
|
|
32
33
|
mcpServerIdForCapability,
|
|
@@ -424,14 +425,10 @@ async function validateMcpCapabilityConnectionRef(
|
|
|
424
425
|
item: CapabilityCatalogItem,
|
|
425
426
|
ref: McpServerConnectionRef,
|
|
426
427
|
): Promise<McpServerConnectionRef> {
|
|
427
|
-
|
|
428
|
-
throw new HTTPException(422, {
|
|
429
|
-
message: "subject-owned connection refs are not supported for agent runtime use yet",
|
|
430
|
-
});
|
|
431
|
-
}
|
|
428
|
+
const subjectScope = ref.subjectScope ?? "workspace";
|
|
432
429
|
const normalized: McpServerConnectionRef = {
|
|
433
430
|
providerDomain: ref.providerDomain.trim(),
|
|
434
|
-
subjectScope
|
|
431
|
+
subjectScope,
|
|
435
432
|
...(ref.connectionId ? { connectionId: ref.connectionId } : {}),
|
|
436
433
|
...(ref.provider ? { provider: ref.provider.trim() } : {}),
|
|
437
434
|
...(ref.kind ? { kind: ref.kind } : {}),
|
|
@@ -450,23 +447,41 @@ async function validateMcpCapabilityConnectionRef(
|
|
|
450
447
|
"MCP capabilities need a remote streamable HTTP endpoint before they can use a connectionRef",
|
|
451
448
|
});
|
|
452
449
|
}
|
|
453
|
-
|
|
454
|
-
|
|
450
|
+
|
|
451
|
+
let connection = normalized.connectionId
|
|
452
|
+
? await getConnectionMetadata(
|
|
453
|
+
input.db,
|
|
454
|
+
input.workspaceId,
|
|
455
|
+
normalized.connectionId,
|
|
456
|
+
input.grant.subjectId,
|
|
457
|
+
)
|
|
458
|
+
: null;
|
|
459
|
+
if (!connection && subjectScope === "subject" && !normalized.connectionId) {
|
|
460
|
+
const visible = await listConnectionsMetadata(
|
|
461
|
+
input.db,
|
|
462
|
+
input.workspaceId,
|
|
463
|
+
input.grant.subjectId,
|
|
464
|
+
);
|
|
465
|
+
connection =
|
|
466
|
+
visible.find(
|
|
467
|
+
(candidate) =>
|
|
468
|
+
candidate.subjectId === input.grant.subjectId &&
|
|
469
|
+
candidate.providerDomain === normalized.providerDomain &&
|
|
470
|
+
(!normalized.kind || candidate.kind === normalized.kind) &&
|
|
471
|
+
candidate.status === "active",
|
|
472
|
+
) ?? null;
|
|
455
473
|
}
|
|
456
|
-
const connection = await getConnectionMetadata(
|
|
457
|
-
input.db,
|
|
458
|
-
input.workspaceId,
|
|
459
|
-
normalized.connectionId,
|
|
460
|
-
input.grant.subjectId,
|
|
461
|
-
);
|
|
462
474
|
if (!connection) {
|
|
463
475
|
throw new HTTPException(422, {
|
|
464
|
-
message: "connectionRef
|
|
476
|
+
message: "connectionRef does not reference a visible active connection",
|
|
465
477
|
});
|
|
466
478
|
}
|
|
467
|
-
if (
|
|
479
|
+
if (
|
|
480
|
+
(subjectScope === "subject" && connection.subjectId !== input.grant.subjectId) ||
|
|
481
|
+
(subjectScope === "workspace" && connection.subjectId !== null)
|
|
482
|
+
) {
|
|
468
483
|
throw new HTTPException(422, {
|
|
469
|
-
message:
|
|
484
|
+
message: `connectionRef does not reference a ${subjectScope}-owned connection`,
|
|
470
485
|
});
|
|
471
486
|
}
|
|
472
487
|
if (connection.status !== "active") {
|
|
@@ -484,6 +499,11 @@ async function validateMcpCapabilityConnectionRef(
|
|
|
484
499
|
message: "connectionRef.kind does not match the referenced connection",
|
|
485
500
|
});
|
|
486
501
|
}
|
|
502
|
+
if (subjectScope === "subject") {
|
|
503
|
+
const genericSubjectRef = { ...normalized, kind: connection.kind };
|
|
504
|
+
delete genericSubjectRef.connectionId;
|
|
505
|
+
return genericSubjectRef;
|
|
506
|
+
}
|
|
487
507
|
return normalized;
|
|
488
508
|
}
|
|
489
509
|
|
|
@@ -1157,12 +1177,16 @@ function installationConnectionRef(
|
|
|
1157
1177
|
if (!ref || typeof ref !== "object") {
|
|
1158
1178
|
return null;
|
|
1159
1179
|
}
|
|
1160
|
-
const { connectionId, providerDomain, kind } = ref as Record<string, unknown>;
|
|
1161
|
-
if (
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1180
|
+
const { connectionId, providerDomain, kind, subjectScope } = ref as Record<string, unknown>;
|
|
1181
|
+
if (typeof providerDomain !== "string" || typeof kind !== "string") {
|
|
1182
|
+
return null;
|
|
1183
|
+
}
|
|
1184
|
+
if (subjectScope === "subject") {
|
|
1185
|
+
// Never project a personal connection UUID through workspace-visible
|
|
1186
|
+
// capability configuration, including legacy rows that still contain one.
|
|
1187
|
+
return { providerDomain, kind, subjectScope: "subject" };
|
|
1188
|
+
}
|
|
1189
|
+
if (typeof connectionId !== "string") {
|
|
1166
1190
|
return null;
|
|
1167
1191
|
}
|
|
1168
1192
|
return { connectionId, providerDomain, kind };
|
package/src/domain/sessions.ts
CHANGED
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
type ReasoningEffort,
|
|
24
24
|
type ResourceRef,
|
|
25
25
|
type Session,
|
|
26
|
+
type SessionSkill,
|
|
26
27
|
type SessionEvent,
|
|
27
28
|
SessionMcpApprovalPolicy,
|
|
28
29
|
type SessionMcpCredentialUpdateInput,
|
|
@@ -491,6 +492,7 @@ export async function createAndStartSession(input: {
|
|
|
491
492
|
initialMessage: string;
|
|
492
493
|
turnInstructions?: string | null;
|
|
493
494
|
resources: ResourceRef[];
|
|
495
|
+
skills?: SessionSkill[];
|
|
494
496
|
tools: ToolRef[];
|
|
495
497
|
// Public admission always supplies provenance; optional keeps internal
|
|
496
498
|
// callers that predate durable tool-policy provenance source-compatible
|
|
@@ -578,6 +580,7 @@ export async function createAndStartSession(input: {
|
|
|
578
580
|
initialMessage: input.initialMessage,
|
|
579
581
|
initialTurnInstructions: input.turnInstructions ?? null,
|
|
580
582
|
resources: input.resources,
|
|
583
|
+
skills: input.skills ?? [],
|
|
581
584
|
tools: input.tools,
|
|
582
585
|
...(input.toolPolicy ? { toolPolicy: input.toolPolicy } : {}),
|
|
583
586
|
metadata: sessionMetadata,
|
|
@@ -621,6 +624,7 @@ export async function createAndStartSession(input: {
|
|
|
621
624
|
initialMessage: input.initialMessage,
|
|
622
625
|
initialTurnInstructions: input.turnInstructions ?? null,
|
|
623
626
|
resources: input.resources,
|
|
627
|
+
skills: input.skills ?? [],
|
|
624
628
|
tools: input.tools,
|
|
625
629
|
...(input.toolPolicy ? { toolPolicy: input.toolPolicy } : {}),
|
|
626
630
|
metadata: sessionMetadata,
|
|
@@ -1090,6 +1094,9 @@ export async function createSessionForRequest(
|
|
|
1090
1094
|
? payload.resources
|
|
1091
1095
|
: (parentSession?.resources ?? payload.resources),
|
|
1092
1096
|
);
|
|
1097
|
+
const skills = hasOwnProperty(rawPayload, "skills")
|
|
1098
|
+
? payload.skills
|
|
1099
|
+
: (parentSession?.skills ?? payload.skills);
|
|
1093
1100
|
const toolsProvided = hasOwnProperty(rawPayload, "tools");
|
|
1094
1101
|
const requestedTools = validateToolRefs(
|
|
1095
1102
|
toolsProvided ? payload.tools : (parentSession?.tools ?? payload.tools),
|
|
@@ -1501,6 +1508,7 @@ export async function createSessionForRequest(
|
|
|
1501
1508
|
initialMessage: payload.initialMessage,
|
|
1502
1509
|
turnInstructions: payload.turnInstructions ?? null,
|
|
1503
1510
|
resources,
|
|
1511
|
+
skills,
|
|
1504
1512
|
tools,
|
|
1505
1513
|
toolPolicy,
|
|
1506
1514
|
...(payload.clientEventId ? { clientEventId: payload.clientEventId } : {}),
|