@opengeni/core 2.10.0-canary.0 → 2.10.0-canary.2

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.
Files changed (50) hide show
  1. package/dist/application/external-workspace-members.d.ts +16 -0
  2. package/dist/application/host-mcp-resolvers.d.ts +13 -0
  3. package/dist/application/new-session-drafts.d.ts +4 -2
  4. package/dist/chunk-5WZYFL45.js +266 -0
  5. package/dist/chunk-5WZYFL45.js.map +1 -0
  6. package/dist/domain/file-owner.d.ts +8 -0
  7. package/dist/domain/knowledge-files.d.ts +20 -0
  8. package/dist/domain/knowledge-messages.d.ts +39 -0
  9. package/dist/domain/knowledge-messages.test.d.ts +1 -0
  10. package/dist/domain/knowledge-search.d.ts +80 -0
  11. package/dist/domain/knowledge-search.test.d.ts +1 -0
  12. package/dist/domain/knowledge.d.ts +9 -0
  13. package/dist/domain/pr-review.d.ts +2 -2
  14. package/dist/domain/resources.d.ts +2 -2
  15. package/dist/domain/scheduled-tasks.d.ts +12 -2
  16. package/dist/domain/sessions.d.ts +6 -2
  17. package/dist/domain/skills.d.ts +16 -0
  18. package/dist/index.d.ts +6 -4
  19. package/dist/index.js +3948 -3939
  20. package/dist/index.js.map +1 -1
  21. package/dist/remote-mcp-credentials.d.ts +16 -1
  22. package/dist/remote-mcp-credentials.js +7 -215
  23. package/dist/remote-mcp-credentials.js.map +1 -1
  24. package/package.json +12 -12
  25. package/src/application/external-workspace-members.ts +89 -0
  26. package/src/application/host-mcp-resolvers.ts +85 -0
  27. package/src/application/new-session-drafts.ts +37 -3
  28. package/src/domain/file-owner.ts +52 -0
  29. package/src/domain/host-mcp-task-admission.ts +27 -17
  30. package/src/domain/knowledge-files.ts +39 -0
  31. package/src/domain/knowledge-messages.test.ts +91 -0
  32. package/src/domain/knowledge-messages.ts +105 -0
  33. package/src/domain/knowledge-search.test.ts +45 -0
  34. package/src/domain/knowledge-search.ts +55 -0
  35. package/src/domain/knowledge.ts +133 -0
  36. package/src/domain/product-integration-skill.gen.ts +7 -7
  37. package/src/domain/resources.ts +36 -25
  38. package/src/domain/scheduled-tasks.ts +362 -139
  39. package/src/domain/sessions.ts +117 -20
  40. package/src/domain/skills.ts +8 -0
  41. package/src/index.ts +9 -4
  42. package/src/remote-mcp-credentials.ts +76 -8
  43. package/dist/domain/company-brain-governed-writes.d.ts +0 -79
  44. package/dist/domain/governed-learning-activation.d.ts +0 -16
  45. package/dist/domain/governed-learning-evaluator.d.ts +0 -6
  46. package/dist/domain/remember.d.ts +0 -72
  47. package/src/domain/company-brain-governed-writes.ts +0 -346
  48. package/src/domain/governed-learning-activation.ts +0 -44
  49. package/src/domain/governed-learning-evaluator.ts +0 -49
  50. package/src/domain/remember.ts +0 -577
@@ -1,7 +1,11 @@
1
+ import { knowledgeContextForAccess } from "./knowledge";
2
+ import { saveAgentLearningSettings } from "@opengeni/db";
3
+ import { withSessionRlsActorContext } from "@opengeni/db";
4
+ import { fileOwnerContextForAccess, fileOwnerContextForAgent } from "./file-owner";
1
5
  import { CODEX_MODEL_ID_PREFIX, isCodexBilledModel } from "@opengeni/codex";
2
6
  import { sessionCreationMetadata } from "../site-session-origin";
3
7
  import {
4
- HostMcpBindingDefinition,
8
+ hostMcpBindingMatchesSelection,
5
9
  HostMcpCreateSelections,
6
10
  type HostMcpCreateSelection,
7
11
  } from "@opengeni/contracts/host-mcp-bindings";
@@ -30,6 +34,7 @@ import {
30
34
  CreateSessionRequest,
31
35
  DEFAULT_FIRST_PARTY_MCP_PERMISSIONS,
32
36
  DEFAULT_FIRST_PARTY_MCP_TOOLS,
37
+ currentAgentLearningToolSelection,
33
38
  DraftTimelineAnnotations,
34
39
  FIRST_PARTY_MCP_TOOL_NAMES,
35
40
  OPENGENI_SLACK_BOT_SESSION_METADATA_KEY,
@@ -272,8 +277,10 @@ export function effectiveFirstPartyMcpToolCeiling(
272
277
  allowed: readonly FirstPartyMcpToolName[];
273
278
  },
274
279
  ): Set<FirstPartyMcpToolName> {
275
- const allowed = new Set(policy.allowed);
276
- const ceiling = new Set([...(stored ?? policy.default)].filter((tool) => allowed.has(tool)));
280
+ const allowed = new Set(currentAgentLearningToolSelection(policy.allowed));
281
+ const ceiling = new Set(
282
+ currentAgentLearningToolSelection(stored ?? policy.default).filter((tool) => allowed.has(tool)),
283
+ );
277
284
  if (ceiling.has("goal_pause") && allowed.has("goal_resume")) ceiling.add("goal_resume");
278
285
  return ceiling;
279
286
  }
@@ -300,6 +307,7 @@ export function resolveFirstPartyMcpToolsForCreate(
300
307
  },
301
308
  ): FirstPartyMcpToolName[] {
302
309
  if (requested !== undefined) {
310
+ requested = currentAgentLearningToolSelection(requested);
303
311
  if (parentStored !== undefined) {
304
312
  const parentCeiling = effectiveFirstPartyMcpToolCeiling(parentStored, policy);
305
313
  const widened = requested.find((tool) => !parentCeiling.has(tool));
@@ -311,9 +319,9 @@ export function resolveFirstPartyMcpToolsForCreate(
311
319
  }
312
320
  return [...requested];
313
321
  }
314
- const allowed = new Set(policy.allowed);
322
+ const allowed = new Set(currentAgentLearningToolSelection(policy.allowed));
315
323
  const inherited = parentStored === undefined ? policy.default : (parentStored ?? policy.default);
316
- return [...inherited].filter((tool) => allowed.has(tool));
324
+ return currentAgentLearningToolSelection(inherited).filter((tool) => allowed.has(tool));
317
325
  }
318
326
 
319
327
  function sessionSpawnDeniedMessage(denial: SessionSpawnDenial): string {
@@ -738,6 +746,7 @@ function automaticTitleForAgentChildCreate(
738
746
  }
739
747
 
740
748
  export async function createAndStartSessionWithOutcome(input: {
749
+ initialAgentLearning?: import("@opengeni/contracts").AgentLearningOverrides | undefined;
741
750
  requestedSessionId?: string;
742
751
  db: Database;
743
752
  bus: EventBus;
@@ -1024,6 +1033,7 @@ export async function createAndStartSessionWithOutcome(input: {
1024
1033
  tools: input.tools,
1025
1034
  toolPolicy: input.toolPolicy,
1026
1035
  metadata: sessionMetadata,
1036
+ initialAgentLearning: input.initialAgentLearning,
1027
1037
  selectedHostMcpDelegations: input.selectedHostMcpDelegations ?? [],
1028
1038
  ...(input.createdBy ? { createdBy: input.createdBy } : {}),
1029
1039
  ...(frozenCreatedByContext ? { createdByContext: frozenCreatedByContext } : {}),
@@ -1119,6 +1129,7 @@ export async function createAndStartSessionWithOutcome(input: {
1119
1129
  tools: input.tools,
1120
1130
  toolPolicy: input.toolPolicy,
1121
1131
  metadata: sessionMetadata,
1132
+ initialAgentLearning: input.initialAgentLearning,
1122
1133
  ...(input.createdBy ? { createdBy: input.createdBy } : {}),
1123
1134
  selectedHostMcpDelegations: input.selectedHostMcpDelegations ?? [],
1124
1135
  ...(frozenCreatedByContext ? { createdByContext: frozenCreatedByContext } : {}),
@@ -2004,7 +2015,7 @@ async function withSessionCreateUsageRecording(input: {
2004
2015
  return { ...input.createOutcome, usageRecording };
2005
2016
  }
2006
2017
 
2007
- export async function createSessionForRequestWithOutcome(
2018
+ async function createSessionForRequestInFileScope(
2008
2019
  unresolvedDeps: ApiRouteDeps,
2009
2020
  grant: AccessGrant,
2010
2021
  workspaceId: string,
@@ -2180,6 +2191,8 @@ export async function createSessionForRequestWithOutcome(
2180
2191
  : {}),
2181
2192
  createIdempotencyKey: payload.idempotencyKey,
2182
2193
  selectedInstalledSkillIds: payload.installedSkillIds ?? [],
2194
+ initialAgentLearning: payload.agentLearning,
2195
+ ...sessionScope,
2183
2196
  selectedHostMcpDelegations: hostSelections,
2184
2197
  ...(payload.requestedSessionId ? { requestedSessionId: payload.requestedSessionId } : {}),
2185
2198
  visibility: effectiveVisibility,
@@ -2455,7 +2468,21 @@ export async function createSessionForRequestWithOutcome(
2455
2468
  message: "object storage is not configured",
2456
2469
  });
2457
2470
  }
2458
- await validateFileResources(db, grant.accountId, workspaceId, grant.subjectId, resources);
2471
+ await validateFileResources(
2472
+ db,
2473
+ grant.accountId,
2474
+ workspaceId,
2475
+ personalResourceSubjectId ?? grant.subjectId,
2476
+ resources,
2477
+ (authorization || grant.principalKind === "agent_attempt") &&
2478
+ (effectiveVisibility === "user_private" ||
2479
+ sessionScope.memoryScope === "user" ||
2480
+ workspace.kind === "personal")
2481
+ ? authorization
2482
+ ? await fileOwnerContextForAccess({ db }, authorization, "sessions:create")
2483
+ : await fileOwnerContextForAgent({ db }, grant, "sessions:create")
2484
+ : undefined,
2485
+ );
2459
2486
  // Every selected Variable Set is independently authorized. Scope does not
2460
2487
  // affect precedence: explicit order is low-to-high and later sets win name
2461
2488
  // collisions.
@@ -3016,6 +3043,46 @@ export async function createSessionForRequestWithOutcome(
3016
3043
  model,
3017
3044
  });
3018
3045
  }
3046
+ const initialLearning =
3047
+ payload.agentLearning && Object.keys(payload.agentLearning).length
3048
+ ? payload.agentLearning
3049
+ : null;
3050
+ const initialLearningContext =
3051
+ initialLearning && authorization
3052
+ ? await knowledgeContextForAccess(deps, authorization, "sessions:control")
3053
+ : null;
3054
+ if (initialLearning && initialLearningContext?.actor.kind !== "human") {
3055
+ throw new HTTPException(403, {
3056
+ message: "Chat learning settings require authenticated human session control",
3057
+ });
3058
+ }
3059
+ const initialLearningScope =
3060
+ effectiveVisibility === "user_private" ||
3061
+ sessionScope.memoryScope === "user" ||
3062
+ workspace.kind === "personal"
3063
+ ? ("personal" as const)
3064
+ : ("workspace" as const);
3065
+ const initialLearningActor = initialLearningContext?.actor;
3066
+ const beforeCreateCommit =
3067
+ initialLearning && initialLearningContext && initialLearningActor?.kind === "human"
3068
+ ? async (tx: Database, sessionId: string) => {
3069
+ await externalBeforeCreateCommit?.(tx);
3070
+ await saveAgentLearningSettings(
3071
+ tx,
3072
+ {
3073
+ ...initialLearningContext,
3074
+ actor: { ...initialLearningActor, settingsScopes: [initialLearningScope] },
3075
+ },
3076
+ {
3077
+ scope: initialLearningScope,
3078
+ source: { kind: "chat", id: sessionId },
3079
+ operationId: sessionId,
3080
+ expectedVersion: 0,
3081
+ settings: initialLearning,
3082
+ },
3083
+ );
3084
+ }
3085
+ : externalBeforeCreateCommit;
3019
3086
  let createOutcome: CreateSessionOutcome;
3020
3087
  try {
3021
3088
  createOutcome = await createAndStartSessionWithOutcome({
@@ -3050,7 +3117,7 @@ export async function createSessionForRequestWithOutcome(
3050
3117
  ...(effectiveSandboxOs ? { sandboxOs: effectiveSandboxOs } : {}),
3051
3118
  sandboxGroupId,
3052
3119
  metadata: creationMetadata ?? {},
3053
- ...(externalBeforeCreateCommit ? { beforeCreateCommit: externalBeforeCreateCommit } : {}),
3120
+ ...(beforeCreateCommit ? { beforeCreateCommit } : {}),
3054
3121
  selectedHostMcpDelegations: hostSelections,
3055
3122
  ...(captureSelectedHostAuthority || captureLinkedAuthority
3056
3123
  ? {
@@ -3098,6 +3165,7 @@ export async function createSessionForRequestWithOutcome(
3098
3165
  parentSessionId,
3099
3166
  createIdempotencyKey: payload.idempotencyKey ?? null,
3100
3167
  selectedInstalledSkillIds,
3168
+ initialAgentLearning: payload.agentLearning,
3101
3169
  maxNestedAgentDepthOverride: payload.maxNestedAgentDepth ?? null,
3102
3170
  allowNestedAgentDepthIncrease: hasPermission(grant.permissions, "workspace:admin"),
3103
3171
  subjectId: grant.subjectId,
@@ -3263,22 +3331,17 @@ function prepareSelectedHostTurnAuthority(
3263
3331
  const delegation = await getHostMcpDelegation(tx, owner, selection.delegationId);
3264
3332
  const binding = delegation ? await getHostMcpBinding(tx, owner, delegation.bindingId) : null;
3265
3333
  const configured = configs.get(selection.serverId)!;
3266
- const { hostBinding, ...connectionRef } = configured.connectionRef!;
3267
- const definition = HostMcpBindingDefinition.safeParse({
3268
- serverId: selection.serverId,
3269
- destinationUrl: configured.url,
3270
- connectionRef,
3271
- });
3272
3334
  if (
3273
3335
  !delegation ||
3274
3336
  !binding ||
3275
3337
  delegation.status !== "active" ||
3276
3338
  binding.status !== "active" ||
3277
- !definition.success ||
3278
3339
  delegation.generation !== selection.generation ||
3279
- binding.id !== hostBinding!.bindingId ||
3280
- binding.generation !== hostBinding!.generation ||
3281
- stableJson(definition.data) !== stableJson(binding.definition)
3340
+ !hostMcpBindingMatchesSelection(binding, {
3341
+ serverId: selection.serverId,
3342
+ destinationUrl: configured.url!,
3343
+ connectionRef: configured.connectionRef!,
3344
+ })
3282
3345
  )
3283
3346
  throw new HTTPException(403, { message: "Host delegation selection changed" });
3284
3347
  try {
@@ -3357,7 +3420,7 @@ function sessionPromptBoundaryRequestHash(input: {
3357
3420
  * enqueue, and usage recording. `toolsProvided: false` durably preserves an
3358
3421
  * Tool selection is durable session state and never rides a follow-up prompt.
3359
3422
  */
3360
- export async function acceptSessionUserMessageWithOutcome(
3423
+ async function acceptSessionUserMessageInFileScope(
3361
3424
  deps: AcceptSessionUserMessageDependencies,
3362
3425
  grant: AccessGrant,
3363
3426
  workspaceId: string,
@@ -3582,6 +3645,15 @@ export async function acceptSessionUserMessageWithOutcome(
3582
3645
  workspaceId,
3583
3646
  grant.subjectId,
3584
3647
  requestedResources,
3648
+ (input.authorization || grant.principalKind === "agent_attempt") &&
3649
+ ((await getSessionAuthorityProjection(db, workspaceId, sessionId))?.visibility ===
3650
+ "user_private" ||
3651
+ existingSession.memoryScope === "user" ||
3652
+ (await requireWorkspace(db, workspaceId)).kind === "personal")
3653
+ ? input.authorization
3654
+ ? await fileOwnerContextForAccess({ db }, input.authorization, "sessions:control")
3655
+ : await fileOwnerContextForAgent({ db }, grant, "sessions:control")
3656
+ : undefined,
3585
3657
  );
3586
3658
  await validateGitHubRepositorySelection(db, workspaceId, [
3587
3659
  ...existingSession.resources,
@@ -3634,7 +3706,7 @@ export async function acceptSessionUserMessageWithOutcome(
3634
3706
  ...(input.connectionAuthorities ? { authoritySelections: input.connectionAuthorities } : {}),
3635
3707
  });
3636
3708
  const captureSelectedHostAuthority = prepareSelectedHostTurnAuthority(
3637
- runtimeSettings,
3709
+ settingsWithSessionMcpServerMetadata(runtimeSettings, existingSession.mcpServers),
3638
3710
  existingSession.tools,
3639
3711
  grant,
3640
3712
  workspaceId,
@@ -4215,3 +4287,28 @@ function hasOwnProperty(value: unknown, key: string): boolean {
4215
4287
  value && typeof value === "object" && Object.prototype.hasOwnProperty.call(value, key),
4216
4288
  );
4217
4289
  }
4290
+
4291
+ /** Keep original-file ownership scoped across admission, history hydration and setup. */
4292
+ export async function createSessionForRequestWithOutcome(
4293
+ ...args: Parameters<typeof createSessionForRequestInFileScope>
4294
+ ): Promise<CreateSessionRequestOutcome> {
4295
+ const [deps, grant, , , authorization] = args;
4296
+ const actor = authorization
4297
+ ? await fileOwnerContextForAccess(deps, authorization, "sessions:create")
4298
+ : grant.principalKind === "agent_attempt"
4299
+ ? await fileOwnerContextForAgent(deps, grant, "sessions:create")
4300
+ : { subjectId: grant.subjectId, privateFileOwnerSubjectId: null };
4301
+ return withSessionRlsActorContext(actor, () => createSessionForRequestInFileScope(...args));
4302
+ }
4303
+
4304
+ export async function acceptSessionUserMessageWithOutcome(
4305
+ ...args: Parameters<typeof acceptSessionUserMessageInFileScope>
4306
+ ): ReturnType<typeof acceptSessionUserMessageInFileScope> {
4307
+ const [deps, grant, , , input] = args;
4308
+ const actor = input.authorization
4309
+ ? await fileOwnerContextForAccess(deps, input.authorization, "sessions:control")
4310
+ : grant.principalKind === "agent_attempt"
4311
+ ? await fileOwnerContextForAgent(deps, grant, "sessions:control")
4312
+ : { subjectId: grant.subjectId, privateFileOwnerSubjectId: null };
4313
+ return withSessionRlsActorContext(actor, () => acceptSessionUserMessageInFileScope(...args));
4314
+ }
@@ -77,6 +77,14 @@ export async function approveSkill(db: Database, input: SkillRevisionInput) {
77
77
  { ...request, operation: "approve" },
78
78
  );
79
79
  }
80
+ export async function rejectSkill(db: Database, input: SkillRevisionInput) {
81
+ const { accountId, workspaceId, actor, ...request } = input;
82
+ return applySkillLifecycle(
83
+ db,
84
+ { accountId, workspaceId, actor },
85
+ { ...request, operation: "reject" },
86
+ );
87
+ }
80
88
  export async function restoreSkill(db: Database, input: SkillRevisionInput) {
81
89
  const { accountId, workspaceId, actor, ...request } = input;
82
90
  return applySkillLifecycle(
package/src/index.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  export * from "./domain/skills";
2
+ export * from "./domain/knowledge";
3
+ export * from "./domain/knowledge-search";
2
4
  // @opengeni/core — the framework-agnostic OpenGeni core.
3
5
  //
4
6
  // WHAT THIS PACKAGE IS: the OpenGeni domain, access, and billing layers carved
@@ -63,6 +65,7 @@ export * from "./sandbox/runtime-settings";
63
65
  export * from "./access";
64
66
  export * from "./application/external-workspace-members";
65
67
  export * from "./application/external-identity-lifecycle";
68
+ export * from "./application/host-mcp-resolvers";
66
69
  export * from "./application/external-continuation";
67
70
  export * from "./application/session-mcp-credential-rotation";
68
71
  export * from "./application/external-link-work-admission";
@@ -102,10 +105,6 @@ export * from "./domain/governed-learning-slack-publication";
102
105
  export * from "./domain/slack-publication-secret-safety";
103
106
  export * from "./domain/company-profile-durable-learning-adapter";
104
107
  export * from "./domain/company-profile-agent-admin";
105
- export * from "./domain/company-brain-governed-writes";
106
- export * from "./domain/governed-learning-evaluator";
107
- export * from "./domain/governed-learning-activation";
108
- export * from "./domain/remember";
109
108
  export * from "./domain/slack-bot";
110
109
  export * from "./domain/conversation-integrations";
111
110
  export * from "./domain/fiken";
@@ -126,3 +125,9 @@ export * from "./editable-artifact-live";
126
125
  // Transport-neutral editable-artifact domain service, ports, and contracts.
127
126
  export * from "./editable-artifacts";
128
127
  export { withSiteSessionOrigin } from "./site-session-origin";
128
+
129
+ export { fileOwnerContextForAccess, fileOwnerContextForAgent } from "./domain/file-owner";
130
+
131
+ export { prepareKnowledgeFile } from "./domain/knowledge-files";
132
+
133
+ export { retainKnowledgeMessage } from "./domain/knowledge-messages";
@@ -1,6 +1,14 @@
1
1
  import type { Settings } from "@opengeni/config";
2
+ import { environmentsEncryptionKeyBytes } from "@opengeni/config";
3
+ import {
4
+ resolveHostMcpResolverRoute,
5
+ hostMcpResolverRouteIsCurrent,
6
+ type Database,
7
+ type HostMcpResolverRoute,
8
+ } from "@opengeni/db";
2
9
  import {
3
10
  McpConnectionResourceScope,
11
+ hostMcpCredentialUseGuard,
4
12
  type ConnectionCredentialsPort,
5
13
  type McpCredentialsRequest,
6
14
  type McpCredentialResolution,
@@ -144,11 +152,18 @@ export function createRemoteMcpCredentialsPort(
144
152
  "hostMcpCredentialResolversJson" | "environment" | "integrationsAllowPrivateNetworkTargets"
145
153
  >,
146
154
  transport: typeof pinnedFetch = pinnedFetch,
155
+ routes?: {
156
+ resolve: (input: { accountId: string; workspaceId: string }) => Promise<HostMcpResolverRoute>;
157
+ isCurrent: (
158
+ input: { accountId: string; workspaceId: string },
159
+ route: HostMcpResolverRoute,
160
+ ) => Promise<boolean>;
161
+ },
147
162
  ): ConnectionCredentialsPort {
148
- if (!settings.hostMcpCredentialResolversJson) return {};
163
+ if (!settings.hostMcpCredentialResolversJson && !routes) return {};
149
164
  let entries: z.infer<typeof configuration>;
150
165
  try {
151
- entries = configuration.parse(JSON.parse(settings.hostMcpCredentialResolversJson));
166
+ entries = configuration.parse(JSON.parse(settings.hostMcpCredentialResolversJson || "[]"));
152
167
  for (const entry of entries) validateHttpUrl(entry.url);
153
168
  if (new Set(entries.map((entry) => entry.accountId)).size !== entries.length) throw new Error();
154
169
  } catch {
@@ -188,15 +203,39 @@ export function createRemoteMcpCredentialsPort(
188
203
  : {}),
189
204
  reason,
190
205
  });
191
- const config = byAccount.get(request.accountId);
206
+ let route: HostMcpResolverRoute = { mode: "legacy" };
207
+ try {
208
+ if (routes) route = await routes.resolve(request);
209
+ } catch {
210
+ return unavailable("refresh_failed");
211
+ }
212
+ if (route.mode === "denied") return unavailable("unsupported_auth");
213
+ const config = route.mode === "namespace" ? route : byAccount.get(request.accountId);
192
214
  if (!config || request.connectionRef.authoritySource !== "host")
193
215
  return unavailable("unsupported_auth");
216
+ const current = async () => {
217
+ try {
218
+ return routes ? await routes.isCurrent(request, route) : true;
219
+ } catch {
220
+ return false;
221
+ }
222
+ };
223
+ const finish = async (value: RemoteResolution): Promise<RemoteResolution> => {
224
+ if (!(await current())) return unavailable("refresh_failed");
225
+ const result = structuredClone(value);
226
+ if (result.status === "ok" && routes) result[hostMcpCredentialUseGuard] = current;
227
+ return result;
228
+ };
194
229
  // Snapshot before any asynchronous operation; never retain mutable caller
195
230
  // objects as the authority for a delayed response.
196
231
  if (new TextEncoder().encode(serialized).byteLength > 65_536)
197
232
  return unavailable("refresh_failed");
198
- const pending = active.get(serialized);
199
- if (pending) return structuredClone(await pending);
233
+ const activeKey = JSON.stringify([
234
+ route.mode === "namespace" ? [route.id, route.generation] : "legacy",
235
+ serialized,
236
+ ]);
237
+ const pending = active.get(activeKey);
238
+ if (pending) return finish(await pending);
200
239
  if (physicalRequests >= 128) return unavailable("refresh_failed");
201
240
  const run = async (): Promise<RemoteResolution> => {
202
241
  const requestId = crypto.randomUUID();
@@ -213,6 +252,7 @@ export function createRemoteMcpCredentialsPort(
213
252
  return await Promise.race([
214
253
  deadline,
215
254
  (async () => {
255
+ if (!(await current())) return unavailable("refresh_failed");
216
256
  const response = await transport(
217
257
  config.url,
218
258
  {
@@ -270,11 +310,11 @@ export function createRemoteMcpCredentialsPort(
270
310
  }
271
311
  };
272
312
  const task = run();
273
- active.set(serialized, task);
313
+ active.set(activeKey, task);
274
314
  try {
275
- return structuredClone(await task);
315
+ return finish(await task);
276
316
  } finally {
277
- if (active.get(serialized) === task) active.delete(serialized);
317
+ if (active.get(activeKey) === task) active.delete(activeKey);
278
318
  }
279
319
  };
280
320
  return {
@@ -291,3 +331,31 @@ export function createRemoteMcpCredentialsPort(
291
331
  },
292
332
  };
293
333
  }
334
+
335
+ /** Native standalone transport; the database remains authoritative on every
336
+ * resolution/use. Embedded in-process ports retain their existing precedence. */
337
+ export function createNativeRemoteMcpCredentialsPort(
338
+ settings: Settings,
339
+ db: Database,
340
+ transport: typeof pinnedFetch = pinnedFetch,
341
+ ): ConnectionCredentialsPort {
342
+ return createRemoteMcpCredentialsPort(settings, transport, {
343
+ resolve: (request) =>
344
+ resolveHostMcpResolverRoute(db, request, environmentsEncryptionKeyBytes(settings)),
345
+ isCurrent: (request, route) => hostMcpResolverRouteIsCurrent(db, request, route),
346
+ });
347
+ }
348
+
349
+ /** Parses only server configuration; never return parser errors containing secrets. */
350
+ export function hasLegacyHostMcpResolver(
351
+ settings: Pick<Settings, "hostMcpCredentialResolversJson">,
352
+ accountId: string,
353
+ ): boolean {
354
+ try {
355
+ return configuration
356
+ .parse(JSON.parse(settings.hostMcpCredentialResolversJson || "[]"))
357
+ .some((entry) => entry.accountId === accountId);
358
+ } catch {
359
+ throw new Error("Invalid host MCP credential resolver configuration");
360
+ }
361
+ }
@@ -1,79 +0,0 @@
1
- import { type CompanyBrainGovernedWriteReceipt as CompanyBrainGovernedWriteReceiptType, type CompanyBrainLearningPolicyRouteReceipt as CompanyBrainLearningPolicyRouteReceiptType, type GovernedLearningActivationDestination, type GovernedLearningActivationReceipt } from "@opengeni/contracts";
2
- import { type Database, activateGovernedLearningDecision, evaluateGovernedLearningProposal, getOrCreateWorkspaceLearningPolicySnapshot, writeCompanyBrainGovernedProposal } from "@opengeni/db";
3
- import { type GovernedLearningSlackPublicationResult } from "./governed-learning-slack-publication.js";
4
- export type CompanyBrainGovernedWriteInput = {
5
- attempt: unknown;
6
- request: unknown;
7
- };
8
- export type CompanyBrainGovernedWriteRouterOptions = {
9
- db: Database;
10
- authority?: typeof writeCompanyBrainGovernedProposal;
11
- learningPolicySnapshot?: typeof getOrCreateWorkspaceLearningPolicySnapshot;
12
- /** Governed-learning evaluator (migration 0268). Defaults to the DB capability. */
13
- evaluate?: typeof evaluateGovernedLearningProposal;
14
- /** Governed-learning activation controller (migration 0269). Defaults to the DB capability. */
15
- activate?: typeof activateGovernedLearningDecision;
16
- /**
17
- * Destinations the router may activate automatically from a final eligible
18
- * decision. Defaults to Skills and instruction policy. Both still pass
19
- * through the evaluator and destination-owned activation lifecycle.
20
- */
21
- automaticDestinations?: ReadonlyArray<GovernedLearningActivationDestination>;
22
- /**
23
- * Optional post-activation notification sink (Slack publication outbox).
24
- * Notification is never authority: failures are swallowed after the
25
- * activation receipt is durable and never change the route receipt.
26
- */
27
- notifyActivation?: (input: {
28
- db: Database;
29
- receipt: GovernedLearningActivationReceipt;
30
- sessionId: string;
31
- attemptId: string;
32
- }) => Promise<GovernedLearningSlackPublicationResult>;
33
- };
34
- export declare const DEFAULT_AUTOMATIC_LEARNING_DESTINATIONS: ReadonlyArray<GovernedLearningActivationDestination>;
35
- /**
36
- * Start a non-authoritative post-activation notification without making the
37
- * durable activation receipt wait for its settlement. The callback is invoked
38
- * synchronously so immediate enqueue work begins before the router returns;
39
- * both synchronous throws and later promise rejections are contained.
40
- *
41
- * Exact retries intentionally dispatch again: the publication sink owns an
42
- * activation-receipt idempotency key, while the activation receipt remains the
43
- * caller-facing source of truth even if notification delivery stalls forever.
44
- */
45
- export declare function dispatchBestEffortGovernedLearningNotification(notify: () => Promise<unknown>): void;
46
- /**
47
- * Transport-neutral facade for explicit governed Company Brain proposals.
48
- * It intentionally exposes no generic remember call, selector, activation,
49
- * rollback token, or personal/organization destination.
50
- */
51
- export declare function createCompanyBrainGovernedWriteRouter(options: CompanyBrainGovernedWriteRouterOptions): {
52
- write: (input: CompanyBrainGovernedWriteInput) => Promise<CompanyBrainGovernedWriteReceiptType>;
53
- };
54
- /**
55
- * Deterministic UUIDv5-shaped operation id derived from the caller's proposal
56
- * operation id, so an exact retry of the same write converges on the same
57
- * evaluator/activation receipts instead of conflicting.
58
- */
59
- export declare function derivedGovernedLearningOperationId(operationId: string, stage: "evaluation" | "activation"): string;
60
- /**
61
- * Resolve one derived Company Brain write from the immutable policy snapshot
62
- * frozen for the exact accepted attempt. The evidence identity is the policy
63
- * source identity; callers cannot select another override key to widen the
64
- * decision.
65
- *
66
- * After the proposal commits, a Ways-of-working proposal (instruction policy or
67
- * preference, i.e. one that materialized a `knowledge_change_proposals` row) is
68
- * evaluated by the governed-learning evaluator against the same accepted
69
- * snapshot. `suggest` records the content-free decision receipt only. Under
70
- * `automatic`, a final `automaticEligible` receipt is handed to the activation
71
- * controller, which revalidates current authority and applies the change only
72
- * through the destination-owned lifecycle. Eligible Skills and instruction
73
- * policies may activate automatically. Evaluation or activation failure
74
- * never rolls back the durable proposal; it is reported as a bounded
75
- * `learningFailure` and the proposal remains for human review.
76
- */
77
- export declare function createCompanyBrainLearningPolicyRouter(options: CompanyBrainGovernedWriteRouterOptions): {
78
- write: (input: CompanyBrainGovernedWriteInput) => Promise<CompanyBrainLearningPolicyRouteReceiptType>;
79
- };
@@ -1,16 +0,0 @@
1
- import { type GovernedLearningActivationReceipt, type GovernedLearningActivationUndoReceipt } from "@opengeni/contracts";
2
- import { activateGovernedLearningDecision, undoGovernedLearningActivation, type Database } from "@opengeni/db";
3
- export declare function createGovernedLearningActivationController(options: {
4
- db: Database;
5
- activate?: typeof activateGovernedLearningDecision;
6
- undo?: typeof undoGovernedLearningActivation;
7
- }): {
8
- activate(input: {
9
- caller: unknown;
10
- request: unknown;
11
- }): Promise<GovernedLearningActivationReceipt>;
12
- undo(input: {
13
- caller: unknown;
14
- request: unknown;
15
- }): Promise<GovernedLearningActivationUndoReceipt>;
16
- };
@@ -1,6 +0,0 @@
1
- import { type GovernedLearningDecision as GovernedLearningDecisionType, type GovernedLearningDecisionFacts as GovernedLearningDecisionFactsType } from "@opengeni/contracts";
2
- /**
3
- * Pure, closed evaluator mirrored by the 0268 database authority. It never
4
- * receives source content and cannot activate a destination authority.
5
- */
6
- export declare function deriveGovernedLearningDecision(input: GovernedLearningDecisionFactsType): GovernedLearningDecisionType;
@@ -1,72 +0,0 @@
1
- import { type RememberLane, type GovernedLearningActivationReceipt, type RememberConfirmReceipt as RememberConfirmReceiptType, type RememberReceipt as RememberReceiptType } from "@opengeni/contracts";
2
- import { type Database, activateHumanConfirmedLearningDecision, archiveTaskNote, confirmRememberKnowledgeClaim, createTaskNote, getWorkspaceInstructionPolicyBaseline, getWorkspaceKnowledgeChangeProposalSummary, getWorkspaceKnowledgeClaimInitiatingHuman, materializeConfirmedRememberKnowledgeMemory, rebaselineWorkspaceInstructionPolicyKnowledgeProposal } from "@opengeni/db";
3
- import { createCompanyBrainLearningPolicyRouter } from "./company-brain-governed-writes.js";
4
- export declare class RememberError extends Error {
5
- readonly code: "proposal_unavailable" | "proposal_not_confirmable" | "human_confirmation_unavailable" | "preference_retired" | "baseline_stale";
6
- readonly name = "RememberError";
7
- constructor(code: "proposal_unavailable" | "proposal_not_confirmable" | "human_confirmation_unavailable" | "preference_retired" | "baseline_stale", message: string);
8
- }
9
- export type RememberRouterOptions = {
10
- db: Database;
11
- learningRouter?: Pick<ReturnType<typeof createCompanyBrainLearningPolicyRouter>, "write">;
12
- createNote?: typeof createTaskNote;
13
- archiveNote?: typeof archiveTaskNote;
14
- rebaselineProposal?: typeof rebaselineWorkspaceInstructionPolicyKnowledgeProposal;
15
- activateHumanConfirmed?: typeof activateHumanConfirmedLearningDecision;
16
- confirmKnowledgeClaim?: typeof confirmRememberKnowledgeClaim;
17
- materializeKnowledgeMemory?: typeof materializeConfirmedRememberKnowledgeMemory;
18
- proposalSummary?: typeof getWorkspaceKnowledgeChangeProposalSummary;
19
- claimInitiatingHuman?: typeof getWorkspaceKnowledgeClaimInitiatingHuman;
20
- instructionPolicyBaseline?: typeof getWorkspaceInstructionPolicyBaseline;
21
- notifyActivation?: (input: {
22
- db: Database;
23
- receipt: GovernedLearningActivationReceipt;
24
- sessionId: string;
25
- attemptId: string;
26
- }) => Promise<unknown>;
27
- };
28
- /** Deterministic UUID-shaped id derived from the caller's remember operation id. */
29
- export declare function derivedRememberOperationId(operationId: string, stage: "note" | "note-archive" | "promotion" | "evaluation" | "activation" | "rebaseline"): string;
30
- /**
31
- * What saving this costs, shown on the confirmation card so a human can judge
32
- * the length before agreeing. A mandatory rule is composed into the prompt of
33
- * every session it applies to; a preference contributes only its short
34
- * descriptor to that prompt and keeps its content behind on-demand retrieval;
35
- * knowledge is retrieval evidence and never joins the always-composed prefix.
36
- *
37
- * `HumanInputForm` renders a single question's `label` as the card heading and
38
- * its `prompt` as the sub-text, so this stays a title with a parenthetical
39
- * rather than a sentence: the question the human answers has to keep reading as
40
- * the heading of the card.
41
- *
42
- * This deliberately lives on `label` rather than `helpText`: migrations 0272 /
43
- * 0274 / 0284 / 0293 / 0316 byte-verify the reconstructed `prompt`, `helpText`,
44
- * and `options` against the exact Task-note text before authorizing an
45
- * activation, and `label` is the one field of the canonical question those
46
- * capabilities do not constrain.
47
- */
48
- export declare function rememberConfirmationLabel(input: {
49
- lane: RememberLane;
50
- contentChars: number;
51
- /** Role-scoped rules compose only for sessions bound to that role. */
52
- policyScope?: "global" | "role" | undefined;
53
- }): string;
54
- /**
55
- * Explicit user-directed remember. Content becomes an exact task note (the
56
- * evidence), the note is promoted through the frozen learning policy router,
57
- * and the result is either an immediate activation (automatic policy), a
58
- * proposal for the human Knowledge review lifecycle, or a durable proposal that
59
- * still needs one bound human confirmation through `request_human_input`.
60
- * A confirmed Knowledge claim is then materialized as a keyword-searchable
61
- * Memory record from its exact approved Task-note text.
62
- */
63
- export declare function createRememberRouter(options: RememberRouterOptions): {
64
- remember: (input: {
65
- attempt: unknown;
66
- request: unknown;
67
- }) => Promise<RememberReceiptType>;
68
- confirm: (input: {
69
- attempt: unknown;
70
- request: unknown;
71
- }) => Promise<RememberConfirmReceiptType>;
72
- };