@opengeni/core 2.6.4 → 2.7.5-canary.0

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.
@@ -0,0 +1,25 @@
1
+ import type { Settings } from "@opengeni/config";
2
+ import type { McpServerConnectionRef } from "@opengeni/contracts";
3
+ import { HTTPException } from "hono/http-exception";
4
+
5
+ /**
6
+ * Explicit host-owned MCP refs change which credential authority executes an
7
+ * opaque connection id. Admit new external refs only after the operator has
8
+ * completed the two-phase fleet rollout. Readers and inheritance remain
9
+ * tolerant regardless of this switch, and markerless legacy refs retain their
10
+ * bounded non-UUID compatibility path.
11
+ */
12
+ export function assertHostMcpAuthoritySourceAdmissionEnabled(
13
+ settings: Pick<Settings, "hostMcpAuthoritySourceAdmissionEnabled">,
14
+ connectionRef: McpServerConnectionRef | null | undefined,
15
+ ): void {
16
+ if (
17
+ connectionRef?.authoritySource === "host" &&
18
+ !settings.hostMcpAuthoritySourceAdmissionEnabled
19
+ ) {
20
+ throw new HTTPException(422, {
21
+ message:
22
+ "new host-owned MCP connection refs are not admitted; upgrade the complete API/worker/web fleet, then set OPENGENI_HOST_MCP_AUTHORITY_SOURCE_ADMISSION_ENABLED=true",
23
+ });
24
+ }
25
+ }
@@ -305,6 +305,8 @@ export async function getWorkspaceInsights(
305
305
  creditUsd: microsToUsd(row.pricedCostMicros),
306
306
  estimatedProviderUsd: microsToUsd(row.estimatedProviderCostMicros),
307
307
  estimatedProviderCostKnownCalls: row.estimatedProviderCostKnownCalls,
308
+ equivalentCreditUsd: microsToUsd(row.equivalentCreditCostMicros),
309
+ equivalentCreditCostKnownCalls: row.equivalentCreditCostKnownCalls,
308
310
  }))
309
311
  .sort((a, b) => b.totalTokens - a.totalTokens);
310
312
 
@@ -326,6 +328,22 @@ export async function getWorkspaceInsights(
326
328
  (sum, row) => sum + row.estimatedProviderCostKnownCalls,
327
329
  0,
328
330
  );
331
+ const equivalentCreditCostMicros = modelRows.reduce(
332
+ (sum, row) => sum + row.equivalentCreditCostMicros,
333
+ 0,
334
+ );
335
+ const priorEquivalentCreditCostMicros = priorModelRows.reduce(
336
+ (sum, row) => sum + row.equivalentCreditCostMicros,
337
+ 0,
338
+ );
339
+ const equivalentCreditCostKnownCalls = modelRows.reduce(
340
+ (sum, row) => sum + row.equivalentCreditCostKnownCalls,
341
+ 0,
342
+ );
343
+ const priorEquivalentCreditCostKnownCalls = priorModelRows.reduce(
344
+ (sum, row) => sum + row.equivalentCreditCostKnownCalls,
345
+ 0,
346
+ );
329
347
  const modelCalls = modelRows.reduce((sum, row) => sum + row.calls, 0);
330
348
  const priorInputTokens = priorModelRows.reduce((sum, row) => sum + row.inputTokens, 0);
331
349
  const priorTotalTokens = priorModelRows.reduce((sum, row) => sum + row.totalTokens, 0);
@@ -342,6 +360,8 @@ export async function getWorkspaceInsights(
342
360
  costMicros: 0,
343
361
  estimatedProviderCostMicros: 0,
344
362
  estimatedProviderCostKnownCalls: 0,
363
+ equivalentCreditCostMicros: 0,
364
+ equivalentCreditCostKnownCalls: 0,
345
365
  inputTokens: 0,
346
366
  outputTokens: 0,
347
367
  cachedTokens: 0,
@@ -361,6 +381,8 @@ export async function getWorkspaceInsights(
361
381
  modelCostUsd: microsToUsd(modelCostMicros),
362
382
  estimatedProviderUsd: microsToUsd(facts.estimatedProviderCostMicros),
363
383
  estimatedProviderCostKnownCalls: facts.estimatedProviderCostKnownCalls,
384
+ equivalentCreditUsd: microsToUsd(facts.equivalentCreditCostMicros),
385
+ equivalentCreditCostKnownCalls: facts.equivalentCreditCostKnownCalls,
364
386
  warmSeconds: usageBuckets.get(bucket)?.warmSeconds ?? 0,
365
387
  inputTokens: facts.inputTokens,
366
388
  outputTokens: facts.outputTokens,
@@ -393,6 +415,8 @@ export async function getWorkspaceInsights(
393
415
  creditUsd,
394
416
  estimatedProviderUsd: microsToUsd(row.estimatedProviderCostMicros),
395
417
  estimatedProviderCostKnownCalls: row.estimatedProviderCostKnownCalls,
418
+ equivalentCreditUsd: microsToUsd(row.equivalentCreditCostMicros),
419
+ equivalentCreditCostKnownCalls: row.equivalentCreditCostKnownCalls,
396
420
  tokens: row.totalTokens,
397
421
  cacheHitPct: cacheHitPct(row.cachedTokens, row.cacheInputTokens),
398
422
  pctOfCreditUsd:
@@ -414,6 +438,8 @@ export async function getWorkspaceInsights(
414
438
  creditUsd: fact ? microsToUsd(fact.pricedCostMicros) : null,
415
439
  estimatedProviderUsd: fact ? microsToUsd(fact.estimatedProviderCostMicros) : null,
416
440
  estimatedProviderCostKnownCalls: fact ? fact.estimatedProviderCostKnownCalls : null,
441
+ equivalentCreditUsd: fact ? microsToUsd(fact.equivalentCreditCostMicros) : null,
442
+ equivalentCreditCostKnownCalls: fact ? fact.equivalentCreditCostKnownCalls : null,
417
443
  tokens: fact ? fact.totalTokens : null,
418
444
  cacheHitPct: fact ? cacheHitPct(fact.cachedTokens, fact.cacheInputTokens) : null,
419
445
  billing: fact ? billingPathOf(fact.billingPath) : null,
@@ -489,6 +515,8 @@ export async function getWorkspaceInsights(
489
515
  row.estimatedProviderCostMicros == null
490
516
  ? null
491
517
  : microsToUsd(row.estimatedProviderCostMicros),
518
+ equivalentCreditUsd:
519
+ row.equivalentCreditCostMicros == null ? null : microsToUsd(row.equivalentCreditCostMicros),
492
520
  pricingSource: pricingSourceOf(row.pricingSource),
493
521
  })),
494
522
  promptContributions,
@@ -522,6 +550,10 @@ export async function getWorkspaceInsights(
522
550
  priorEstimatedProviderUsd: microsToUsd(priorEstimatedProviderCostMicros),
523
551
  estimatedProviderCostKnownCalls,
524
552
  priorEstimatedProviderCostKnownCalls,
553
+ equivalentCreditUsd: microsToUsd(equivalentCreditCostMicros),
554
+ priorEquivalentCreditUsd: microsToUsd(priorEquivalentCreditCostMicros),
555
+ equivalentCreditCostKnownCalls,
556
+ priorEquivalentCreditCostKnownCalls,
525
557
  modelCalls,
526
558
  priorInputTokens,
527
559
  priorTotalTokens,
@@ -31,6 +31,7 @@ import {
31
31
  PR_REVIEW_AUTOMATION_ADAPTER_ID,
32
32
  PR_REVIEW_AUTOMATION_TEMPLATE_ID,
33
33
  } from "./pr-review";
34
+ import { OPENGENI_PRODUCT_INTEGRATION_PACK } from "./product-integration-pack";
34
35
 
35
36
  export const MARKETING_SOCIAL_PACK_ID = "marketing-social-daily-analysis";
36
37
 
@@ -277,7 +278,11 @@ const openGeniPrReviewPack: CapabilityPack = {
277
278
  },
278
279
  };
279
280
 
280
- const packs = [marketingSocialPack, openGeniPrReviewPack] satisfies CapabilityPack[];
281
+ const packs = [
282
+ marketingSocialPack,
283
+ openGeniPrReviewPack,
284
+ OPENGENI_PRODUCT_INTEGRATION_PACK,
285
+ ] satisfies CapabilityPack[];
281
286
 
282
287
  export function listCapabilityPacks(): CapabilityPack[] {
283
288
  return packs;
@@ -355,6 +360,7 @@ export type InlinePackSkillInstall = {
355
360
  sourcePath: string;
356
361
  name: string;
357
362
  description: string;
363
+ activationMode: "workspace_managed" | "session_selected";
358
364
  contentSha256: string;
359
365
  totalBytes: number;
360
366
  files: Array<{ path: string; content: string; byteSize: number; contentSha256: string }>;
@@ -372,19 +378,22 @@ export function inlinePackSkillInstall(
372
378
  });
373
379
  }
374
380
  const normalizedName = skill.name.toLowerCase();
381
+ const activationMode = skill.activationMode ?? "workspace_managed";
382
+ const activationIdentity = activationMode === "session_selected" ? "session-selected/" : "";
375
383
  const encodedSkill = encodeURIComponent(normalizedName);
376
- const sourceUrl = `https://opengeni.invalid/pack-inline-skills/${encodedSkill}/${artifact.contentSha256}`;
377
- const capabilityId = `skill:pack-inline/${normalizedName}@${artifact.contentSha256}`;
384
+ const sourceUrl = `https://opengeni.invalid/pack-inline-skills/${activationIdentity}${encodedSkill}/${artifact.contentSha256}`;
385
+ const capabilityId = `skill:pack-inline/${activationIdentity}${normalizedName}@${artifact.contentSha256}`;
378
386
  return {
379
387
  componentKey: `inline-skill/${normalizedName}`,
380
388
  capabilityId,
381
- pluginKey: `pack-skill/${normalizedName}/${artifact.contentSha256}`,
389
+ pluginKey: `pack-skill/${activationIdentity}${normalizedName}/${artifact.contentSha256}`,
382
390
  sourceUrl,
383
391
  repositoryUrl: "https://opengeni.invalid/pack-inline-skills",
384
392
  sourceCommit: artifact.contentSha256,
385
393
  sourcePath: normalizedName,
386
394
  name: artifact.name,
387
395
  description: artifact.description,
396
+ activationMode,
388
397
  contentSha256: artifact.contentSha256,
389
398
  totalBytes: artifact.totalBytes,
390
399
  files: artifact.files.map((file) => ({
@@ -405,21 +414,42 @@ export async function previewCapabilityPackInstallation(
405
414
  const { workspaceId } = access;
406
415
  const installation = await getPackInstallation(db, workspaceId, pack.id);
407
416
  const inlineInstalls = pack.skills.map((skill) => inlinePackSkillInstall(pack, skill));
408
- const [referencedComponents, inlineComponents] = await Promise.all([
409
- resolvePackComponentReferences(db, workspaceId, pack.components),
410
- resolvePackInlineSkillReferences(
411
- db,
412
- workspaceId,
413
- inlineInstalls.map((inline) => ({
414
- key: inline.componentKey,
415
- capabilityId: inline.capabilityId,
416
- name: inline.name,
417
- contentSha256: inline.contentSha256,
418
- })),
419
- installation?.id,
420
- ),
421
- ]);
422
417
  const manifestDigest = capabilityPackManifestDigest(pack);
418
+ const inlineRequirements = inlineInstalls.map((inline) => ({
419
+ key: inline.componentKey,
420
+ capabilityId: inline.capabilityId,
421
+ name: inline.name,
422
+ activationMode: inline.activationMode,
423
+ contentSha256: inline.contentSha256,
424
+ }));
425
+ const [referencedComponents, plannedInlineComponents, installedSessionSelectedComponents] =
426
+ await Promise.all([
427
+ resolvePackComponentReferences(db, workspaceId, pack.components),
428
+ resolvePackInlineSkillReferences(db, workspaceId, inlineRequirements, installation?.id),
429
+ installation?.status === "active" && installation.manifestDigest === manifestDigest
430
+ ? resolvePackInlineSkillReferences(
431
+ db,
432
+ workspaceId,
433
+ inlineRequirements.filter(
434
+ (requirement) => requirement.activationMode === "session_selected",
435
+ ),
436
+ )
437
+ : Promise.resolve([]),
438
+ ]);
439
+ const installedSessionSelectedByKey = new Map(
440
+ installedSessionSelectedComponents.map((component) => [component.key, component]),
441
+ );
442
+ // Installation planning excludes the Pack's own current ownership so an
443
+ // update can replace old inline content. For launch affordances, preserve an
444
+ // independently resolved active facet-installation id on an exact installed
445
+ // manifest. A missing facet retains the future capability id and therefore
446
+ // cannot be mistaken for something a new session can select right now.
447
+ const inlineComponents = plannedInlineComponents.map((component) => {
448
+ const installed = installedSessionSelectedByKey.get(component.key);
449
+ return installed?.status === "ready" && installed.resolvedId
450
+ ? { ...component, resolvedId: installed.resolvedId }
451
+ : component;
452
+ });
423
453
  const components: PackComponentResolution[] = [...referencedComponents, ...inlineComponents];
424
454
  const blockers = components
425
455
  .filter((component) => component.required && component.status !== "ready")
@@ -4,6 +4,7 @@ import type {
4
4
  ConnectionMetadata,
5
5
  McpConnectionAuthoritySelection,
6
6
  McpPersonalConnectionDelegation,
7
+ McpServerConnectionRef,
7
8
  ResourceRef,
8
9
  SessionTurn,
9
10
  SocialConnection,
@@ -290,10 +291,16 @@ export function selectedPersonalConnectionServers(
290
291
  ): McpServerConfig[] {
291
292
  const selected = new Set(tools.map((tool) => tool.id));
292
293
  return settings.mcpServers.filter(
293
- (server) => selected.has(server.id) && server.connectionRef?.subjectScope === "subject",
294
+ (server) => selected.has(server.id) && isNativeSubjectConnectionRef(server.connectionRef),
294
295
  );
295
296
  }
296
297
 
298
+ function isNativeSubjectConnectionRef(
299
+ ref: McpServerConnectionRef | null | undefined,
300
+ ): ref is McpServerConnectionRef & { subjectScope: "subject" } {
301
+ return ref?.subjectScope === "subject" && ref.authoritySource !== "host";
302
+ }
303
+
297
304
  function canonicalPersonalConnections(connections: ConnectionMetadata[]): ConnectionMetadata[] {
298
305
  return [...connections].sort((left, right) => {
299
306
  const active = Number(right.status === "active") - Number(left.status === "active");
@@ -324,7 +331,7 @@ export function personalConnectionDelegationsFromVisibleConnections(input: {
324
331
  );
325
332
  for (const server of input.servers) {
326
333
  const ref = server.connectionRef;
327
- if (!ref || ref.subjectScope !== "subject") continue;
334
+ if (!isNativeSubjectConnectionRef(ref)) continue;
328
335
  const selection = selections.get(server.id);
329
336
  const eligible = connections.filter(
330
337
  (candidate) =>
@@ -400,7 +407,7 @@ export function personalConnectionDelegationsFromParent(input: {
400
407
  };
401
408
  const mcp = input.servers.flatMap((server) => {
402
409
  const ref = server.connectionRef;
403
- if (!ref || ref.subjectScope !== "subject") return [];
410
+ if (!isNativeSubjectConnectionRef(ref)) return [];
404
411
  const delegation = input.parentDelegations.find(
405
412
  (candidate) =>
406
413
  candidate.serverId === server.id &&
@@ -700,7 +707,7 @@ export function personalConnectionDelegationForServer(
700
707
  server: Pick<McpServerConfig, "id" | "connectionRef">,
701
708
  ): McpPersonalConnectionDelegation | null {
702
709
  const ref = server.connectionRef;
703
- if (!ref || ref.subjectScope !== "subject") return null;
710
+ if (!isNativeSubjectConnectionRef(ref)) return null;
704
711
  return (
705
712
  delegations.find(
706
713
  (delegation) =>
@@ -750,7 +757,8 @@ export function withFrozenPersonalConnectionDelegations(input: {
750
757
  }): ConnectionCredentialResolver {
751
758
  return async (request) => {
752
759
  let effectiveRequest = request;
753
- if (request.connectionRef.subjectScope === "subject") {
760
+ const nativeSubjectAuthority = isNativeSubjectConnectionRef(request.connectionRef);
761
+ if (nativeSubjectAuthority) {
754
762
  const config = input.settings.mcpServers.find((server) => server.id === request.serverId);
755
763
  const publicationDelegations =
756
764
  request.serverId === GOOGLE_DRIVE_PUBLICATION_SERVER_ID &&
@@ -787,7 +795,7 @@ export function withFrozenPersonalConnectionDelegations(input: {
787
795
  };
788
796
  }
789
797
  const result = await input.resolveCredential(effectiveRequest);
790
- if (result.status === "ok" || request.connectionRef.subjectScope !== "subject") {
798
+ if (result.status === "ok" || !nativeSubjectAuthority) {
791
799
  return result;
792
800
  }
793
801
  return personalAuthorityUnavailable(request);