@opengeni/core 0.4.10 → 0.10.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/index.d.ts +165 -141
- package/dist/index.js +1132 -186
- package/dist/index.js.map +1 -1
- package/package.json +9 -9
- package/src/access/index.ts +4 -0
- package/src/application/session-commands.ts +192 -38
- package/src/billing/limits.ts +20 -1
- package/src/dependencies.ts +28 -2
- package/src/domain/capabilities.ts +171 -3
- package/src/domain/resources.ts +121 -31
- package/src/domain/scheduled-tasks.ts +4 -8
- package/src/domain/session-tool-policy.ts +211 -0
- package/src/domain/sessions.ts +658 -122
- package/src/index.ts +2 -0
- package/src/sandbox/fleet.ts +2 -2
- package/src/sandbox/routing.ts +1 -1
- package/src/session-authorization.ts +208 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import type { Settings } from "@opengeni/config";
|
|
2
|
+
import {
|
|
3
|
+
SESSION_EFFECTIVE_TOOL_POLICY_ID_LIMIT,
|
|
4
|
+
SESSION_EFFECTIVE_TOOL_POLICY_ID_MAX_LENGTH,
|
|
5
|
+
mergeToolRefs,
|
|
6
|
+
type Session,
|
|
7
|
+
type SessionEffectiveToolPolicy,
|
|
8
|
+
type SessionToolPolicy,
|
|
9
|
+
type ToolRef,
|
|
10
|
+
} from "@opengeni/contracts";
|
|
11
|
+
import type { Database } from "@opengeni/db";
|
|
12
|
+
import { settingsWithEnabledCapabilityMcpServers } from "./capabilities";
|
|
13
|
+
import { enabledCapabilityMcpToolRefs } from "./resources";
|
|
14
|
+
|
|
15
|
+
const MANDATORY_SESSION_MCP_SERVER_IDS = ["opengeni"] as const;
|
|
16
|
+
const PROJECTABLE_REGISTRY_ID = /^[A-Za-z0-9_-]+$/;
|
|
17
|
+
|
|
18
|
+
export type ResolvedSessionToolPolicy = {
|
|
19
|
+
toolRefs: ToolRef[];
|
|
20
|
+
effectivePolicy: SessionEffectiveToolPolicy;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export type SessionToolPolicyInput = {
|
|
24
|
+
toolPolicy?: SessionToolPolicy | null;
|
|
25
|
+
sessionTools: ToolRef[];
|
|
26
|
+
turnTools?: ToolRef[];
|
|
27
|
+
/** Undefined preserves the legacy merge path for pre-provenance callers. */
|
|
28
|
+
turnToolsProvided?: boolean;
|
|
29
|
+
availableMcpServerIds: Iterable<string>;
|
|
30
|
+
/** Current omitted-tools defaults, intentionally narrower than all servers. */
|
|
31
|
+
defaultMcpServerIds?: Iterable<string>;
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
function sortedIds(ids: Iterable<string>): string[] {
|
|
35
|
+
return [...new Set(ids)].sort();
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function projectIds(ids: readonly string[]): { ids: string[]; truncated: boolean } {
|
|
39
|
+
const projectable = ids.filter(
|
|
40
|
+
(id) =>
|
|
41
|
+
id.length <= SESSION_EFFECTIVE_TOOL_POLICY_ID_MAX_LENGTH && PROJECTABLE_REGISTRY_ID.test(id),
|
|
42
|
+
);
|
|
43
|
+
return {
|
|
44
|
+
ids: projectable.slice(0, SESSION_EFFECTIVE_TOOL_POLICY_ID_LIMIT),
|
|
45
|
+
truncated:
|
|
46
|
+
projectable.length !== ids.length ||
|
|
47
|
+
projectable.length > SESSION_EFFECTIVE_TOOL_POLICY_ID_LIMIT,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Resolve the same ID-only policy used by API projections and worker turns.
|
|
53
|
+
* This function never receives endpoint URLs, credentials, schemas, or live
|
|
54
|
+
* probe results. `availableMcpServerIds` is the resolved runtime registry;
|
|
55
|
+
* `defaultMcpServerIds` is the capability-only omitted-tools set.
|
|
56
|
+
*/
|
|
57
|
+
export function resolveSessionToolPolicy(input: SessionToolPolicyInput): ResolvedSessionToolPolicy {
|
|
58
|
+
const policy = input.toolPolicy ?? { mode: "legacy" as const, inheritedFromSessionId: null };
|
|
59
|
+
const availableIds = new Set(input.availableMcpServerIds);
|
|
60
|
+
// Never infer omitted-tools defaults from the full runtime registry: static
|
|
61
|
+
// MCPs are explicit-only unless they are capability-derived defaults.
|
|
62
|
+
const defaultIds = new Set(input.defaultMcpServerIds ?? []);
|
|
63
|
+
const mandatoryIds: string[] = MANDATORY_SESSION_MCP_SERVER_IDS.filter((id) =>
|
|
64
|
+
availableIds.has(id),
|
|
65
|
+
);
|
|
66
|
+
const mandatoryIdSet = new Set<string>(mandatoryIds);
|
|
67
|
+
const selectedRefs =
|
|
68
|
+
input.turnToolsProvided === true
|
|
69
|
+
? mergeToolRefs([], input.turnTools ?? [])
|
|
70
|
+
: input.turnToolsProvided === false
|
|
71
|
+
? mergeToolRefs([], input.sessionTools)
|
|
72
|
+
: mergeToolRefs(input.sessionTools, input.turnTools ?? []);
|
|
73
|
+
const tracksWorkspaceDefaults =
|
|
74
|
+
policy.mode === "workspace_default" && input.turnToolsProvided !== true;
|
|
75
|
+
|
|
76
|
+
// Optional capability refs are a historical materialization of a
|
|
77
|
+
// workspace-default selection. They may outlive an installation or its
|
|
78
|
+
// credentials; do not hand an unavailable optional ref to runtime, where it
|
|
79
|
+
// would otherwise be an unknown MCP id. Strict historical refs intentionally
|
|
80
|
+
// remain so their fail-loud compatibility contract is preserved.
|
|
81
|
+
let toolRefs = selectedRefs.filter((tool) => tool.optional !== true || availableIds.has(tool.id));
|
|
82
|
+
if (tracksWorkspaceDefaults) {
|
|
83
|
+
toolRefs = mergeToolRefs(
|
|
84
|
+
toolRefs,
|
|
85
|
+
sortedIds(defaultIds)
|
|
86
|
+
.filter((id) => availableIds.has(id))
|
|
87
|
+
.map((id) => ({ kind: "mcp" as const, id, optional: true as const })),
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
toolRefs = mergeToolRefs(
|
|
91
|
+
toolRefs,
|
|
92
|
+
mandatoryIds.map((id) => ({ kind: "mcp" as const, id })),
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// `effectiveIds` is the requested policy truth, including unavailable
|
|
96
|
+
// optional refs retained in the persisted selection. `toolRefs` above is
|
|
97
|
+
// the runtime-safe materialization, so projections can distinguish dropped
|
|
98
|
+
// history from what is actually handed to the MCP router.
|
|
99
|
+
const requestedEffectiveRefs = mergeToolRefs(
|
|
100
|
+
selectedRefs,
|
|
101
|
+
tracksWorkspaceDefaults
|
|
102
|
+
? sortedIds(defaultIds)
|
|
103
|
+
.filter((id) => availableIds.has(id))
|
|
104
|
+
.map((id) => ({ kind: "mcp" as const, id, optional: true as const }))
|
|
105
|
+
: [],
|
|
106
|
+
);
|
|
107
|
+
const effectiveIds = sortedIds(
|
|
108
|
+
mergeToolRefs(
|
|
109
|
+
requestedEffectiveRefs,
|
|
110
|
+
mandatoryIds.map((id) => ({ kind: "mcp" as const, id })),
|
|
111
|
+
).map((tool) => tool.id),
|
|
112
|
+
);
|
|
113
|
+
const configuredIds = effectiveIds.filter((id) => availableIds.has(id));
|
|
114
|
+
const configuredIdSet = new Set(configuredIds);
|
|
115
|
+
const droppedIds = effectiveIds.filter((id) => !configuredIdSet.has(id));
|
|
116
|
+
const deferredIds = tracksWorkspaceDefaults
|
|
117
|
+
? sortedIds(
|
|
118
|
+
toolRefs
|
|
119
|
+
.filter(
|
|
120
|
+
(tool) =>
|
|
121
|
+
tool.optional === true &&
|
|
122
|
+
configuredIdSet.has(tool.id) &&
|
|
123
|
+
!mandatoryIdSet.has(tool.id),
|
|
124
|
+
)
|
|
125
|
+
.map((tool) => tool.id),
|
|
126
|
+
)
|
|
127
|
+
: [];
|
|
128
|
+
const selectedIds = sortedIds(
|
|
129
|
+
selectedRefs
|
|
130
|
+
.filter(
|
|
131
|
+
(tool) =>
|
|
132
|
+
!mandatoryIdSet.has(tool.id) && !(tracksWorkspaceDefaults && tool.optional === true),
|
|
133
|
+
)
|
|
134
|
+
.map((tool) => tool.id),
|
|
135
|
+
);
|
|
136
|
+
const projections = {
|
|
137
|
+
selected: projectIds(selectedIds),
|
|
138
|
+
effective: projectIds(effectiveIds),
|
|
139
|
+
mandatory: projectIds(sortedIds(mandatoryIds)),
|
|
140
|
+
deferred: projectIds(deferredIds),
|
|
141
|
+
configured: projectIds(configuredIds),
|
|
142
|
+
dropped: projectIds(droppedIds),
|
|
143
|
+
};
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
toolRefs,
|
|
147
|
+
effectivePolicy: {
|
|
148
|
+
mode: policy.mode,
|
|
149
|
+
inheritedFromSessionId: policy.inheritedFromSessionId,
|
|
150
|
+
selectedIds: projections.selected.ids,
|
|
151
|
+
effectiveIds: projections.effective.ids,
|
|
152
|
+
mandatoryIds: projections.mandatory.ids,
|
|
153
|
+
lazyRouter: {
|
|
154
|
+
state: tracksWorkspaceDefaults ? "required" : "disabled",
|
|
155
|
+
deferredIds: projections.deferred.ids,
|
|
156
|
+
},
|
|
157
|
+
configuredIds: projections.configured.ids,
|
|
158
|
+
droppedIds: projections.dropped.ids,
|
|
159
|
+
counts: {
|
|
160
|
+
selected: selectedIds.length,
|
|
161
|
+
effective: effectiveIds.length,
|
|
162
|
+
mandatory: mandatoryIds.length,
|
|
163
|
+
deferred: deferredIds.length,
|
|
164
|
+
configured: configuredIds.length,
|
|
165
|
+
dropped: droppedIds.length,
|
|
166
|
+
},
|
|
167
|
+
idsTruncated: Object.values(projections).some((projection) => projection.truncated),
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/** Current full runtime registry IDs, including configured static servers. */
|
|
173
|
+
export async function workspaceSessionToolPolicyServerIds(
|
|
174
|
+
db: Database,
|
|
175
|
+
workspaceId: string,
|
|
176
|
+
settings: Settings,
|
|
177
|
+
): Promise<string[]> {
|
|
178
|
+
const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings);
|
|
179
|
+
return sortedIds(runtimeSettings.mcpServers.map((server) => server.id));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Current omitted-tools defaults; this preserves capability-first behavior. */
|
|
183
|
+
export async function workspaceSessionToolPolicyDefaultServerIds(
|
|
184
|
+
db: Database,
|
|
185
|
+
workspaceId: string,
|
|
186
|
+
settings: Settings,
|
|
187
|
+
): Promise<string[]> {
|
|
188
|
+
const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings);
|
|
189
|
+
return sortedIds(enabledCapabilityMcpToolRefs(settings, runtimeSettings).map((tool) => tool.id));
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Add a bounded, secret-safe effective projection to a session response. */
|
|
193
|
+
export function sessionWithEffectiveToolPolicy(
|
|
194
|
+
session: Session,
|
|
195
|
+
workspaceServerIds: Iterable<string>,
|
|
196
|
+
workspaceDefaultServerIds: Iterable<string> = [],
|
|
197
|
+
): Session {
|
|
198
|
+
const availableIds = new Set(workspaceServerIds);
|
|
199
|
+
for (const server of session.mcpServers) {
|
|
200
|
+
availableIds.add(server.id);
|
|
201
|
+
}
|
|
202
|
+
return {
|
|
203
|
+
...session,
|
|
204
|
+
effectiveToolPolicy: resolveSessionToolPolicy({
|
|
205
|
+
...(session.toolPolicy ? { toolPolicy: session.toolPolicy } : {}),
|
|
206
|
+
sessionTools: session.tools,
|
|
207
|
+
availableMcpServerIds: availableIds,
|
|
208
|
+
defaultMcpServerIds: workspaceDefaultServerIds,
|
|
209
|
+
}).effectivePolicy,
|
|
210
|
+
};
|
|
211
|
+
}
|