@opengeni/core 3.0.0-canary.0 → 3.0.1-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.
- package/dist/application/connect-operation.d.ts +3 -0
- package/dist/domain/connector-tool-permissions.d.ts +27 -0
- package/dist/domain/knowledge-files.d.ts +1 -1
- package/dist/domain/knowledge-messages.d.ts +2 -2
- package/dist/domain/knowledge-preparation.d.ts +9 -0
- package/dist/domain/knowledge-preparation.test.d.ts +1 -0
- package/dist/domain/organization-integration-catalog.d.ts +15 -0
- package/dist/domain/pr-review.d.ts +2 -2
- package/dist/index.d.ts +3 -0
- package/dist/index.js +666 -60
- package/dist/index.js.map +1 -1
- package/package.json +12 -12
- package/src/application/connect-operation.ts +32 -3
- package/src/domain/capabilities.ts +93 -1
- package/src/domain/connector-tool-permissions.ts +297 -0
- package/src/domain/knowledge-files.ts +10 -3
- package/src/domain/knowledge-messages.ts +1 -0
- package/src/domain/knowledge-preparation.test.ts +251 -0
- package/src/domain/knowledge-preparation.ts +126 -0
- package/src/domain/organization-integration-catalog.ts +83 -0
- package/src/domain/product-integration-pack.ts +1 -1
- package/src/domain/product-integration-skill.gen.ts +6 -2
- package/src/domain/resources.ts +8 -1
- package/src/domain/session-tool-policy.ts +12 -4
- package/src/domain/sessions.ts +165 -34
- package/src/index.ts +4 -0
package/src/domain/sessions.ts
CHANGED
|
@@ -209,6 +209,26 @@ const maxSessionMcpCredentialHeaderValueLength = 4096;
|
|
|
209
209
|
// the generic lossy projection cannot silently rewrite this audit fact.
|
|
210
210
|
const maxToolPolicyAuditRefs = 40;
|
|
211
211
|
|
|
212
|
+
function withoutExcludedMcpServers(
|
|
213
|
+
tools: ToolRef[],
|
|
214
|
+
excludedIds: readonly string[] = [],
|
|
215
|
+
): ToolRef[] {
|
|
216
|
+
const excluded = new Set(excludedIds);
|
|
217
|
+
return tools.filter((tool) => tool.id === "opengeni" || !excluded.has(tool.id));
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
function defaultPolicyExclusions(
|
|
221
|
+
ids: readonly string[] = [],
|
|
222
|
+
): Pick<SessionToolPolicy, "excludedMcpServerIds"> {
|
|
223
|
+
const sorted = [...new Set(ids)].filter((id) => id !== "opengeni").sort();
|
|
224
|
+
if (sorted.length > 64 || sorted.some((id) => id.length > 200 || !/^[A-Za-z0-9_-]+$/.test(id))) {
|
|
225
|
+
throw new HTTPException(422, {
|
|
226
|
+
message: "connector exclusions must contain at most 64 valid MCP server IDs",
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
return sorted.length ? { excludedMcpServerIds: sorted } : {};
|
|
230
|
+
}
|
|
231
|
+
|
|
212
232
|
function isCatalogOverlayModel(modelId: string | null | undefined): boolean {
|
|
213
233
|
return (
|
|
214
234
|
modelId?.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX) === true ||
|
|
@@ -2395,6 +2415,11 @@ async function createSessionForRequestInFileScope(
|
|
|
2395
2415
|
});
|
|
2396
2416
|
}
|
|
2397
2417
|
const toolsProvided = hasOwnProperty(rawPayload, "tools");
|
|
2418
|
+
if (toolsProvided && payload.excludedMcpServerIds !== undefined) {
|
|
2419
|
+
throw new HTTPException(422, {
|
|
2420
|
+
message: "connector exclusions require workspace-default tools",
|
|
2421
|
+
});
|
|
2422
|
+
}
|
|
2398
2423
|
// Visibility became durable draft state after older clients had already
|
|
2399
2424
|
// written rows without it. Compare it only when the create request supplied
|
|
2400
2425
|
// the field explicitly; the parsed schema default must not manufacture a
|
|
@@ -2417,6 +2442,9 @@ async function createSessionForRequestInFileScope(
|
|
|
2417
2442
|
)
|
|
2418
2443
|
: parentSession.tools,
|
|
2419
2444
|
runtimeSettings,
|
|
2445
|
+
).filter(
|
|
2446
|
+
(tool) =>
|
|
2447
|
+
tool.id === "opengeni" || !parentSession.toolPolicy.excludedMcpServerIds?.includes(tool.id),
|
|
2420
2448
|
);
|
|
2421
2449
|
if (toolsProvided) {
|
|
2422
2450
|
assertToolRefsSubset(
|
|
@@ -2434,6 +2462,7 @@ async function createSessionForRequestInFileScope(
|
|
|
2434
2462
|
toolPolicy = {
|
|
2435
2463
|
mode: parentTracksWorkspaceDefaults ? "workspace_default" : "inherited",
|
|
2436
2464
|
inheritedFromSessionId: parentSession.id,
|
|
2465
|
+
...defaultPolicyExclusions(parentSession.toolPolicy.excludedMcpServerIds),
|
|
2437
2466
|
};
|
|
2438
2467
|
}
|
|
2439
2468
|
} else if (toolsProvided) {
|
|
@@ -2448,6 +2477,21 @@ async function createSessionForRequestInFileScope(
|
|
|
2448
2477
|
);
|
|
2449
2478
|
toolPolicy = { mode: "workspace_default", inheritedFromSessionId: null };
|
|
2450
2479
|
}
|
|
2480
|
+
if (payload.excludedMcpServerIds !== undefined) {
|
|
2481
|
+
if (toolPolicy.mode !== "workspace_default") {
|
|
2482
|
+
throw new HTTPException(403, {
|
|
2483
|
+
message: "connector exclusions require workspace-default tools",
|
|
2484
|
+
});
|
|
2485
|
+
}
|
|
2486
|
+
toolPolicy = {
|
|
2487
|
+
...toolPolicy,
|
|
2488
|
+
...defaultPolicyExclusions([
|
|
2489
|
+
...(toolPolicy.excludedMcpServerIds ?? []),
|
|
2490
|
+
...payload.excludedMcpServerIds,
|
|
2491
|
+
]),
|
|
2492
|
+
};
|
|
2493
|
+
}
|
|
2494
|
+
selectedTools = withoutExcludedMcpServers(selectedTools, toolPolicy.excludedMcpServerIds);
|
|
2451
2495
|
// The first-party MCP server is attached to EVERY session. Registration is
|
|
2452
2496
|
// independently intersected with the exact model-visible selection and the
|
|
2453
2497
|
// tool's permission/target authorization predicate, so attachment alone
|
|
@@ -2584,6 +2628,9 @@ async function createSessionForRequestInFileScope(
|
|
|
2584
2628
|
reasoningEffort,
|
|
2585
2629
|
latencyMode,
|
|
2586
2630
|
options: {
|
|
2631
|
+
...(payload.excludedMcpServerIds !== undefined
|
|
2632
|
+
? { excludedMcpServerIds: payload.excludedMcpServerIds }
|
|
2633
|
+
: {}),
|
|
2587
2634
|
...(visibilityProvided ? { visibility: payload.visibility } : {}),
|
|
2588
2635
|
...(payload.sandboxBackend ? { sandboxBackend: payload.sandboxBackend } : {}),
|
|
2589
2636
|
...(payload.targetSandboxId ? { targetSandboxId: payload.targetSandboxId } : {}),
|
|
@@ -3976,6 +4023,12 @@ function toolPolicyAuditSnapshot(
|
|
|
3976
4023
|
return {
|
|
3977
4024
|
mode: policy.mode,
|
|
3978
4025
|
inheritedFromSessionId: policy.inheritedFromSessionId,
|
|
4026
|
+
...(policy.excludedMcpServerIds?.length
|
|
4027
|
+
? {
|
|
4028
|
+
excludedMcpServerIds: policy.excludedMcpServerIds.slice(0, maxToolPolicyAuditRefs),
|
|
4029
|
+
excludedMcpServerCount: policy.excludedMcpServerIds.length,
|
|
4030
|
+
}
|
|
4031
|
+
: {}),
|
|
3979
4032
|
// IDs only: no MCP URLs, names, headers, credentials, schemas, or args.
|
|
3980
4033
|
toolIds: [...toolRefs]
|
|
3981
4034
|
.sort((left, right) => `${left.kind}:${left.id}`.localeCompare(`${right.kind}:${right.id}`))
|
|
@@ -3984,7 +4037,9 @@ function toolPolicyAuditSnapshot(
|
|
|
3984
4037
|
toolCount: allToolRefs.length,
|
|
3985
4038
|
firstPartyMcpTools: [...firstPartyMcpTools].sort(),
|
|
3986
4039
|
firstPartyMcpToolCount: firstPartyMcpTools.length,
|
|
3987
|
-
truncated:
|
|
4040
|
+
truncated:
|
|
4041
|
+
allToolRefs.length > toolRefs.length ||
|
|
4042
|
+
(policy.excludedMcpServerIds?.length ?? 0) > maxToolPolicyAuditRefs,
|
|
3988
4043
|
};
|
|
3989
4044
|
}
|
|
3990
4045
|
|
|
@@ -4028,9 +4083,31 @@ export async function updateSessionToolPolicy(
|
|
|
4028
4083
|
);
|
|
4029
4084
|
const explicitRequest = request.mode === "workspace_default" ? null : request;
|
|
4030
4085
|
const requestedMode = explicitRequest ? "explicit" : "workspace_default";
|
|
4086
|
+
const connectorOnlyEdit =
|
|
4087
|
+
request.mode === "workspace_default" && request.excludedMcpServerIds !== undefined;
|
|
4088
|
+
const requestedExclusions =
|
|
4089
|
+
request.mode === "workspace_default" ? (request.excludedMcpServerIds ?? []) : [];
|
|
4031
4090
|
const explicitRequestedTools = explicitRequest
|
|
4032
4091
|
? (() => {
|
|
4033
|
-
|
|
4092
|
+
// A disconnected stored selection remains policy truth, not executable
|
|
4093
|
+
// authority. Preserve exact existing refs while validating every new or
|
|
4094
|
+
// changed ref against the current runtime registry.
|
|
4095
|
+
const availableIds = new Set(runtimeSettings.mcpServers.map((server) => server.id));
|
|
4096
|
+
const retainedUnavailableRefs = explicitRequest.tools.filter(
|
|
4097
|
+
(tool) =>
|
|
4098
|
+
!availableIds.has(tool.id) &&
|
|
4099
|
+
existingSession.tools.some((existing) => stableJson(existing) === stableJson(tool)),
|
|
4100
|
+
);
|
|
4101
|
+
const retainedIds = new Set(retainedUnavailableRefs.map((tool) => tool.id));
|
|
4102
|
+
const validatedCurrentRefs = validateToolRefs(
|
|
4103
|
+
explicitRequest.tools.filter((tool) => !retainedIds.has(tool.id)),
|
|
4104
|
+
runtimeSettings,
|
|
4105
|
+
);
|
|
4106
|
+
const validatedTools = explicitRequest.tools.filter(
|
|
4107
|
+
(tool) =>
|
|
4108
|
+
retainedUnavailableRefs.includes(tool) ||
|
|
4109
|
+
validatedCurrentRefs.some((validated) => validated.id === tool.id),
|
|
4110
|
+
);
|
|
4034
4111
|
const validatedIds = new Set(validatedTools.map((tool) => `${tool.kind}:${tool.id}`));
|
|
4035
4112
|
const unknown = explicitRequest.tools.find(
|
|
4036
4113
|
(tool) => !validatedIds.has(`${tool.kind}:${tool.id}`),
|
|
@@ -4100,6 +4177,9 @@ export async function updateSessionToolPolicy(
|
|
|
4100
4177
|
)
|
|
4101
4178
|
: parent.tools,
|
|
4102
4179
|
runtimeSettings,
|
|
4180
|
+
).filter(
|
|
4181
|
+
(tool) =>
|
|
4182
|
+
tool.id === "opengeni" || !parent.toolPolicy.excludedMcpServerIds?.includes(tool.id),
|
|
4103
4183
|
);
|
|
4104
4184
|
const deploymentAllowedFirstPartyMcpTools = new Set(
|
|
4105
4185
|
deploymentFirstPartyMcpToolPolicy.allowed,
|
|
@@ -4119,6 +4199,10 @@ export async function updateSessionToolPolicy(
|
|
|
4119
4199
|
nextPolicy = {
|
|
4120
4200
|
mode: "workspace_default",
|
|
4121
4201
|
inheritedFromSessionId: parent.id,
|
|
4202
|
+
...defaultPolicyExclusions([
|
|
4203
|
+
...(parent.toolPolicy.excludedMcpServerIds ?? []),
|
|
4204
|
+
...requestedExclusions,
|
|
4205
|
+
]),
|
|
4122
4206
|
};
|
|
4123
4207
|
} else {
|
|
4124
4208
|
nextTools = explicitRequestedTools!;
|
|
@@ -4149,41 +4233,88 @@ export async function updateSessionToolPolicy(
|
|
|
4149
4233
|
requestedMode === "workspace_default"
|
|
4150
4234
|
? workspaceDefaultFirstPartyTools
|
|
4151
4235
|
: explicitRequestedFirstPartyTools!;
|
|
4152
|
-
nextPolicy = {
|
|
4153
|
-
|
|
4154
|
-
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4236
|
+
nextPolicy = {
|
|
4237
|
+
mode: requestedMode,
|
|
4238
|
+
inheritedFromSessionId: null,
|
|
4239
|
+
...(requestedMode === "workspace_default"
|
|
4240
|
+
? defaultPolicyExclusions(requestedExclusions)
|
|
4241
|
+
: {}),
|
|
4242
|
+
};
|
|
4243
|
+
}
|
|
4244
|
+
if (connectorOnlyEdit) {
|
|
4245
|
+
if (session.toolPolicy.mode !== "workspace_default") {
|
|
4246
|
+
throw new HTTPException(409, {
|
|
4247
|
+
message: "adopt workspace defaults before editing connector exclusions",
|
|
4248
|
+
});
|
|
4249
|
+
}
|
|
4250
|
+
// A connector switch never rewrites built-in tool choices or selected refs.
|
|
4251
|
+
nextTools = session.tools;
|
|
4252
|
+
nextFirstPartyMcpTools = [
|
|
4253
|
+
...(session.firstPartyMcpTools ?? deploymentFirstPartyMcpToolPolicy.default),
|
|
4254
|
+
];
|
|
4255
|
+
}
|
|
4256
|
+
if (!connectorOnlyEdit) {
|
|
4257
|
+
nextTools = withoutExcludedMcpServers(nextTools, nextPolicy.excludedMcpServerIds);
|
|
4258
|
+
}
|
|
4259
|
+
if (agentAttemptCaller && !session.parentSessionId) {
|
|
4260
|
+
// A human or API key may widen a top-level session; a live agent
|
|
4261
|
+
// attempt may only narrow relative to the session's CURRENT
|
|
4262
|
+
// effective policy, in either mode. Adopting workspace defaults is a
|
|
4263
|
+
// widen whenever it adds a server or tool the session does not hold.
|
|
4264
|
+
const sessionTracksWorkspaceDefaults = session.toolPolicy?.mode === "workspace_default";
|
|
4265
|
+
const currentEffectiveTools = withFirstPartyTools(
|
|
4266
|
+
sessionTracksWorkspaceDefaults
|
|
4267
|
+
? withWorkspaceDefaultMcpTools(
|
|
4268
|
+
availableToolRefs(session.tools, runtimeSettings),
|
|
4269
|
+
deps.settings,
|
|
4270
|
+
runtimeSettings,
|
|
4271
|
+
workspaceSessionToolDefaults,
|
|
4272
|
+
)
|
|
4273
|
+
: session.tools,
|
|
4274
|
+
runtimeSettings,
|
|
4275
|
+
);
|
|
4276
|
+
const currentAllowedTools = withoutExcludedMcpServers(
|
|
4277
|
+
currentEffectiveTools,
|
|
4278
|
+
session.toolPolicy.excludedMcpServerIds,
|
|
4279
|
+
);
|
|
4280
|
+
const nextEffectiveTools =
|
|
4281
|
+
nextPolicy.mode === "workspace_default"
|
|
4282
|
+
? withFirstPartyTools(
|
|
4283
|
+
withWorkspaceDefaultMcpTools(
|
|
4284
|
+
availableToolRefs(nextTools, runtimeSettings),
|
|
4163
4285
|
deps.settings,
|
|
4164
4286
|
runtimeSettings,
|
|
4165
4287
|
workspaceSessionToolDefaults,
|
|
4166
|
-
)
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4174
|
-
)
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
);
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
)
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4288
|
+
),
|
|
4289
|
+
runtimeSettings,
|
|
4290
|
+
)
|
|
4291
|
+
: nextTools;
|
|
4292
|
+
if (
|
|
4293
|
+
nextPolicy.mode === "workspace_default" &&
|
|
4294
|
+
(session.toolPolicy.excludedMcpServerIds ?? []).some(
|
|
4295
|
+
(id) => !nextPolicy.excludedMcpServerIds?.includes(id),
|
|
4296
|
+
)
|
|
4297
|
+
) {
|
|
4298
|
+
throw new HTTPException(403, {
|
|
4299
|
+
message: "an agent may not remove session connector exclusions",
|
|
4300
|
+
});
|
|
4301
|
+
}
|
|
4302
|
+
assertToolRefsSubset(
|
|
4303
|
+
withoutExcludedMcpServers(nextEffectiveTools, nextPolicy.excludedMcpServerIds),
|
|
4304
|
+
currentAllowedTools,
|
|
4305
|
+
"an agent may only narrow its session tool policy",
|
|
4306
|
+
);
|
|
4307
|
+
const currentFirstPartyCeiling = effectiveFirstPartyMcpToolCeiling(
|
|
4308
|
+
session.firstPartyMcpTools,
|
|
4309
|
+
deploymentFirstPartyMcpToolPolicy,
|
|
4310
|
+
);
|
|
4311
|
+
const widenedFirstPartyTool = nextFirstPartyMcpTools.find(
|
|
4312
|
+
(tool) => !currentFirstPartyCeiling.has(tool),
|
|
4313
|
+
);
|
|
4314
|
+
if (widenedFirstPartyTool) {
|
|
4315
|
+
throw new HTTPException(403, {
|
|
4316
|
+
message: `an agent may only narrow its session OpenGeni tools: ${widenedFirstPartyTool}`,
|
|
4317
|
+
});
|
|
4187
4318
|
}
|
|
4188
4319
|
}
|
|
4189
4320
|
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./domain/skills";
|
|
2
|
+
export * from "./domain/organization-integration-catalog";
|
|
2
3
|
export * from "./domain/knowledge";
|
|
3
4
|
export * from "./domain/knowledge-search";
|
|
4
5
|
// @opengeni/core — the framework-agnostic OpenGeni core.
|
|
@@ -129,5 +130,8 @@ export { withSiteSessionOrigin } from "./site-session-origin";
|
|
|
129
130
|
export { fileOwnerContextForAccess, fileOwnerContextForAgent } from "./domain/file-owner";
|
|
130
131
|
|
|
131
132
|
export { prepareKnowledgeFile } from "./domain/knowledge-files";
|
|
133
|
+
export { prepareKnowledgeSave } from "./domain/knowledge-preparation";
|
|
132
134
|
|
|
133
135
|
export { retainKnowledgeMessage } from "./domain/knowledge-messages";
|
|
136
|
+
|
|
137
|
+
export * from "./domain/connector-tool-permissions";
|