@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/core",
3
- "version": "0.12.1",
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.8",
39
- "@opengeni/contracts": "^0.20.1",
40
- "@opengeni/db": "^0.13.1",
41
- "@opengeni/documents": "^0.2.38",
42
- "@opengeni/events": "^0.3.29",
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.13.12",
45
- "@opengeni/storage": "^0.2.32",
44
+ "@opengeni/runtime": "^0.14.0",
45
+ "@opengeni/storage": "^0.2.34",
46
46
  "hono": "^4.12.18"
47
47
  },
48
48
  "engines": {
@@ -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
- if (ref.subjectScope === "subject") {
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: "workspace",
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
- if (!normalized.connectionId) {
454
- return normalized;
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.connectionId does not reference a visible connection",
476
+ message: "connectionRef does not reference a visible active connection",
465
477
  });
466
478
  }
467
- if (connection.subjectId !== null) {
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: "agent runtime connection refs must reference workspace-shared connections in I1",
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
- typeof connectionId !== "string" ||
1163
- typeof providerDomain !== "string" ||
1164
- typeof kind !== "string"
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 };
@@ -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 } : {}),