@opengeni/core 3.0.1 → 3.1.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 (257) hide show
  1. package/README.md +4 -4
  2. package/dist/access/index.d.ts +131 -7
  3. package/dist/access/service-initiator.d.ts +3 -0
  4. package/dist/application/archived-session-imports.d.ts +6 -0
  5. package/dist/application/composer-submit.d.ts +1 -1
  6. package/dist/application/connect-operation.d.ts +6 -0
  7. package/dist/application/external-workspace-members.d.ts +13 -1
  8. package/dist/application/modal-native-live-declaration-join.d.ts +37 -0
  9. package/dist/application/modal-native-original-configuration.d.ts +79 -0
  10. package/dist/application/modal-native-worker-host-transport.d.ts +297 -0
  11. package/dist/application/new-session-drafts.d.ts +29 -2
  12. package/dist/application/organization-privacy.d.ts +57 -0
  13. package/dist/application/prepared-mcp-connection.d.ts +31 -0
  14. package/dist/application/sandbox-recovery.d.ts +58 -0
  15. package/dist/application/session-commands.d.ts +3 -0
  16. package/dist/application/session-tenancy.d.ts +13 -4
  17. package/dist/billing/agent-run-admission.d.ts +21 -0
  18. package/dist/billing/limits.d.ts +27 -1
  19. package/dist/billing/model-call-admission.d.ts +34 -0
  20. package/dist/billing/model-usage-settlement.d.ts +112 -0
  21. package/dist/canonical-human-identities.js +1 -1
  22. package/dist/{chunk-VCZFFEPB.js → chunk-7T2SZ7BI.js} +16 -2
  23. package/dist/chunk-7T2SZ7BI.js.map +1 -0
  24. package/dist/{chunk-ZYCNLYGH.js → chunk-OMJFIIWK.js} +178 -12
  25. package/dist/chunk-OMJFIIWK.js.map +1 -0
  26. package/dist/{chunk-H7X52RI2.js → chunk-QI2M2B2K.js} +83 -8
  27. package/dist/chunk-QI2M2B2K.js.map +1 -0
  28. package/dist/{chunk-OF65T3PM.js → chunk-TTWTXQB2.js} +94 -6
  29. package/dist/chunk-TTWTXQB2.js.map +1 -0
  30. package/dist/codex-model-availability.d.ts +55 -0
  31. package/dist/default-session-model.d.ts +192 -0
  32. package/dist/dependencies.d.ts +41 -7
  33. package/dist/developer-setup-credential-ceiling.d.ts +10 -0
  34. package/dist/domain/agent-config-resolution.d.ts +49 -0
  35. package/dist/domain/automations.d.ts +8 -1
  36. package/dist/domain/capabilities.d.ts +112 -8
  37. package/dist/domain/connection-account-selection-error.d.ts +8 -0
  38. package/dist/domain/connector-tool-permissions.d.ts +62 -0
  39. package/dist/domain/direct-model-provider.d.ts +3 -0
  40. package/dist/domain/editable-artifacts/agent-application.d.ts +10 -1
  41. package/dist/domain/editable-artifacts/durable-export.d.ts +22 -1
  42. package/dist/domain/editable-artifacts/ports.d.ts +10 -0
  43. package/dist/domain/editable-artifacts/service.d.ts +3 -1
  44. package/dist/domain/editable-artifacts/types.d.ts +1 -1
  45. package/dist/domain/encryption-key.d.ts +12 -0
  46. package/dist/domain/insights-timing.d.ts +16 -0
  47. package/dist/domain/insights-usage.d.ts +27 -0
  48. package/dist/domain/insights.d.ts +21 -3
  49. package/dist/domain/knowledge-files.d.ts +1 -1
  50. package/dist/domain/knowledge-preparation.d.ts +10 -0
  51. package/dist/domain/knowledge-preparation.test.d.ts +1 -0
  52. package/dist/domain/knowledge-search.d.ts +15 -76
  53. package/dist/domain/mcp-account-bindings.d.ts +17 -0
  54. package/dist/domain/mcp-account-routes.d.ts +21 -0
  55. package/dist/domain/native-mcp-connection-admission.d.ts +3 -0
  56. package/dist/domain/organization-integration-catalog.d.ts +15 -0
  57. package/dist/domain/personal-connection-delegations.d.ts +73 -12
  58. package/dist/domain/pr-review.d.ts +121 -6
  59. package/dist/domain/realtime-voice-billing.d.ts +103 -0
  60. package/dist/domain/resources.d.ts +17 -1
  61. package/dist/domain/scheduled-task-access.d.ts +265 -0
  62. package/dist/domain/scheduled-task-account-audit.d.ts +27 -0
  63. package/dist/domain/scheduled-task-audience.d.ts +70 -0
  64. package/dist/domain/scheduled-tasks.d.ts +61 -18
  65. package/dist/domain/session-connection-accounts.d.ts +53 -0
  66. package/dist/domain/session-file-access.d.ts +4 -0
  67. package/dist/domain/session-native-connection-replacement.d.ts +14 -0
  68. package/dist/domain/session-start-timing.d.ts +7 -0
  69. package/dist/domain/session-tool-policy.d.ts +102 -4
  70. package/dist/domain/sessions.d.ts +179 -15
  71. package/dist/domain/site-audience.d.ts +52 -0
  72. package/dist/domain/skills.d.ts +29 -1
  73. package/dist/domain/slack-bot.d.ts +46 -1
  74. package/dist/domain/slack-publication-secret-safety.d.ts +1 -1
  75. package/dist/domain/vaults/index.d.ts +7 -0
  76. package/dist/domain/vaults/mapping.d.ts +25 -0
  77. package/dist/domain/vaults/provider-registry.d.ts +72 -0
  78. package/dist/domain/vaults/provider-sync.d.ts +176 -0
  79. package/dist/domain/vaults/provider-writes.d.ts +57 -0
  80. package/dist/domain/vaults/secret-resolver.d.ts +34 -0
  81. package/dist/domain/vaults/types.d.ts +24 -0
  82. package/dist/domain/vaults/vault-service.d.ts +35 -0
  83. package/dist/domain/voice-input-billing.d.ts +77 -0
  84. package/dist/domain/web-search-billing.d.ts +51 -0
  85. package/dist/domain/workspace-credits.d.ts +7 -0
  86. package/dist/editable-artifact-live/application.d.ts +2 -1
  87. package/dist/editable-artifact-live/server.d.ts +5 -1
  88. package/dist/editable-artifact-live/ticket.d.ts +2 -1
  89. package/dist/editable-artifact-live/types.d.ts +9 -0
  90. package/dist/editable-artifact-live.js +2 -2
  91. package/dist/editable-artifacts.js +10 -2
  92. package/dist/goal-admission.d.ts +627 -0
  93. package/dist/host-session-usage-limit.d.ts +15 -0
  94. package/dist/index.d.ts +43 -8
  95. package/dist/index.js +22682 -11743
  96. package/dist/index.js.map +1 -1
  97. package/dist/managed-session.d.ts +110 -7
  98. package/dist/model-call.d.ts +58 -0
  99. package/dist/model-catalog.d.ts +29 -3
  100. package/dist/model-provider-credentials.d.ts +43 -0
  101. package/dist/product-usage-metrics.d.ts +30 -0
  102. package/dist/rigs/index.d.ts +1 -13
  103. package/dist/sandbox/fleet.d.ts +58 -4
  104. package/dist/sandbox/routing.d.ts +42 -2
  105. package/dist/sandbox/runtime-settings.d.ts +27 -17
  106. package/dist/session-authorization.d.ts +10 -0
  107. package/dist/session-usage-limit-metrics.d.ts +60 -0
  108. package/dist/session-usage-limits.d.ts +89 -0
  109. package/dist/site-agent-clamp.d.ts +71 -0
  110. package/dist/site-session-origin.d.ts +39 -2
  111. package/dist/transcription.d.ts +120 -3
  112. package/dist/turn-surface.d.ts +20 -0
  113. package/dist/user-presence.d.ts +32 -0
  114. package/dist/workflow-wake-contract.d.ts +13 -1
  115. package/package.json +15 -22
  116. package/src/access/index.ts +961 -38
  117. package/src/access/service-initiator.ts +50 -0
  118. package/src/application/api-integration-servers.ts +9 -0
  119. package/src/application/archived-session-imports.ts +161 -0
  120. package/src/application/composer-submit.ts +3 -2
  121. package/src/application/connect-authority.ts +3 -3
  122. package/src/application/connect-operation.ts +37 -3
  123. package/src/application/external-continuation.ts +20 -3
  124. package/src/application/external-link-work-admission.ts +3 -0
  125. package/src/application/external-workspace-members.ts +51 -3
  126. package/src/application/modal-native-live-declaration-join.ts +196 -0
  127. package/src/application/modal-native-original-configuration.ts +261 -0
  128. package/src/application/modal-native-worker-host-transport.ts +263 -0
  129. package/src/application/new-session-drafts.ts +172 -55
  130. package/src/application/organization-privacy.ts +161 -0
  131. package/src/application/prepared-mcp-connection.ts +133 -0
  132. package/src/application/sandbox-recovery.ts +78 -0
  133. package/src/application/session-commands.ts +73 -1
  134. package/src/application/session-mcp-credential-rotation.ts +61 -18
  135. package/src/application/session-tenancy.ts +262 -44
  136. package/src/application/user-resource-grants.ts +1 -29
  137. package/src/billing/agent-run-admission.ts +117 -0
  138. package/src/billing/limits.ts +138 -14
  139. package/src/billing/model-call-admission.ts +118 -0
  140. package/src/billing/model-usage-settlement.ts +472 -0
  141. package/src/codex-model-availability.ts +264 -0
  142. package/src/default-session-model.ts +692 -0
  143. package/src/dependencies.ts +48 -6
  144. package/src/developer-setup-credential-ceiling.ts +60 -0
  145. package/src/domain/agent-config-resolution.ts +148 -0
  146. package/src/domain/automations.ts +76 -2
  147. package/src/domain/capabilities.ts +830 -181
  148. package/src/domain/connection-account-selection-error.ts +19 -0
  149. package/src/domain/connector-tool-permissions.ts +572 -0
  150. package/src/domain/direct-model-provider.ts +62 -0
  151. package/src/domain/editable-artifacts/agent-application.ts +44 -6
  152. package/src/domain/editable-artifacts/durable-export.ts +100 -5
  153. package/src/domain/editable-artifacts/in-memory.ts +6 -0
  154. package/src/domain/editable-artifacts/ports.ts +11 -0
  155. package/src/domain/editable-artifacts/service.ts +20 -0
  156. package/src/domain/editable-artifacts/types.ts +1 -1
  157. package/src/domain/encryption-key.ts +26 -0
  158. package/src/domain/file-owner.ts +16 -1
  159. package/src/domain/github-action-policies.ts +1 -1
  160. package/src/domain/github-skill-source.ts +3 -1
  161. package/src/domain/insights-timing.ts +95 -0
  162. package/src/domain/insights-usage.ts +67 -0
  163. package/src/domain/insights.ts +167 -43
  164. package/src/domain/knowledge-files.ts +10 -3
  165. package/src/domain/knowledge-messages.ts +1 -0
  166. package/src/domain/knowledge-preparation.test.ts +276 -0
  167. package/src/domain/knowledge-preparation.ts +147 -0
  168. package/src/domain/knowledge-search.test.ts +617 -5
  169. package/src/domain/knowledge-search.ts +240 -23
  170. package/src/domain/mcp-account-bindings.ts +169 -0
  171. package/src/domain/mcp-account-routes.ts +152 -0
  172. package/src/domain/native-mcp-connection-admission.ts +14 -0
  173. package/src/domain/organization-integration-catalog.ts +88 -0
  174. package/src/domain/personal-connection-delegations.ts +399 -257
  175. package/src/domain/pr-review.ts +24 -8
  176. package/src/domain/realtime-voice-billing.ts +425 -0
  177. package/src/domain/resources.ts +50 -4
  178. package/src/domain/scheduled-task-access.ts +1089 -0
  179. package/src/domain/scheduled-task-account-audit.ts +90 -0
  180. package/src/domain/scheduled-task-audience.ts +249 -0
  181. package/src/domain/scheduled-tasks.ts +1313 -374
  182. package/src/domain/session-connection-accounts.ts +239 -0
  183. package/src/domain/session-file-access.ts +47 -0
  184. package/src/domain/session-native-connection-replacement.ts +64 -0
  185. package/src/domain/session-start-timing.ts +60 -0
  186. package/src/domain/session-tool-policy.ts +489 -14
  187. package/src/domain/sessions.ts +2254 -717
  188. package/src/domain/site-audience.ts +130 -0
  189. package/src/domain/skills.ts +9 -0
  190. package/src/domain/slack-bot.ts +141 -4
  191. package/src/domain/slack-publication-secret-safety.ts +1 -1
  192. package/src/domain/vaults/index.ts +19 -0
  193. package/src/domain/vaults/mapping.ts +190 -0
  194. package/src/domain/vaults/provider-registry.ts +201 -0
  195. package/src/domain/vaults/provider-sync.ts +531 -0
  196. package/src/domain/vaults/provider-writes.ts +288 -0
  197. package/src/domain/vaults/secret-resolver.ts +464 -0
  198. package/src/domain/vaults/types.ts +26 -0
  199. package/src/domain/vaults/vault-service.ts +1316 -0
  200. package/src/domain/voice-input-billing.ts +330 -0
  201. package/src/domain/web-search-billing.ts +169 -0
  202. package/src/domain/workspace-credits.ts +13 -0
  203. package/src/editable-artifact-live/application.ts +8 -1
  204. package/src/editable-artifact-live/server.ts +154 -6
  205. package/src/editable-artifact-live/ticket.ts +86 -1
  206. package/src/editable-artifact-live/types.ts +10 -0
  207. package/src/goal-admission.ts +220 -0
  208. package/src/host-session-usage-limit.ts +25 -0
  209. package/src/index.ts +75 -11
  210. package/src/managed-session.ts +137 -6
  211. package/src/model-call.ts +79 -0
  212. package/src/model-catalog.ts +345 -91
  213. package/src/model-provider-credentials.ts +394 -0
  214. package/src/product-usage-metrics.ts +101 -0
  215. package/src/rigs/index.ts +23 -111
  216. package/src/sandbox/fleet.ts +253 -28
  217. package/src/sandbox/routing.ts +204 -43
  218. package/src/sandbox/runtime-settings.ts +159 -85
  219. package/src/session-authorization.ts +172 -23
  220. package/src/session-usage-limit-metrics.ts +95 -0
  221. package/src/session-usage-limits.ts +415 -0
  222. package/src/site-agent-clamp.ts +226 -0
  223. package/src/site-session-origin.ts +84 -5
  224. package/src/transcription.ts +123 -4
  225. package/src/turn-surface.ts +47 -0
  226. package/src/user-presence.ts +134 -0
  227. package/src/workflow-wake-contract.ts +14 -1
  228. package/dist/application/host-mcp-owner.d.ts +0 -6
  229. package/dist/application/host-mcp-resolvers.d.ts +0 -13
  230. package/dist/chunk-5WZYFL45.js +0 -266
  231. package/dist/chunk-5WZYFL45.js.map +0 -1
  232. package/dist/chunk-H7X52RI2.js.map +0 -1
  233. package/dist/chunk-OF65T3PM.js.map +0 -1
  234. package/dist/chunk-VCZFFEPB.js.map +0 -1
  235. package/dist/chunk-ZYCNLYGH.js.map +0 -1
  236. package/dist/domain/connection-authority.d.ts +0 -97
  237. package/dist/domain/connection-authority.js +0 -169
  238. package/dist/domain/connection-authority.js.map +0 -1
  239. package/dist/domain/environments.d.ts +0 -33
  240. package/dist/domain/host-mcp-authority-source-admission.d.ts +0 -10
  241. package/dist/domain/host-mcp-task-admission.d.ts +0 -18
  242. package/dist/domain/packs.d.ts +0 -59
  243. package/dist/domain/product-integration-pack.d.ts +0 -44
  244. package/dist/domain/product-integration-skill.gen.d.ts +0 -5
  245. package/dist/remote-mcp-credentials.d.ts +0 -23
  246. package/dist/remote-mcp-credentials.js +0 -11
  247. package/dist/remote-mcp-credentials.js.map +0 -1
  248. package/src/application/host-mcp-owner.ts +0 -41
  249. package/src/application/host-mcp-resolvers.ts +0 -84
  250. package/src/domain/connection-authority.ts +0 -329
  251. package/src/domain/environments.ts +0 -120
  252. package/src/domain/host-mcp-authority-source-admission.ts +0 -25
  253. package/src/domain/host-mcp-task-admission.ts +0 -121
  254. package/src/domain/packs.ts +0 -699
  255. package/src/domain/product-integration-pack.ts +0 -42
  256. package/src/domain/product-integration-skill.gen.ts +0 -52
  257. package/src/remote-mcp-credentials.ts +0 -361
@@ -1,15 +1,46 @@
1
- import type { Settings } from "@opengeni/config";
2
1
  import {
2
+ resolveSessionFirstPartyMcpTools,
3
+ codeSearchDeploymentPolicy,
4
+ resolveModelProviderForTurn,
5
+ resolveFirstPartyDelegationSecret,
6
+ webSearchToolPlan,
7
+ type Settings,
8
+ } from "@opengeni/config";
9
+ import {
10
+ AGENT_SKILL_MANAGE_TOOL_NAMES,
11
+ AUTOMATIC_SESSION_TITLE_FALLBACK,
12
+ bundledSkillSelectionForAgentConfig,
13
+ CUA_DESKTOP_TOOLS,
14
+ DEFAULT_FIRST_PARTY_MCP_PERMISSIONS,
15
+ FIRST_PARTY_IN_PROCESS_TOOL_NAMES,
16
+ FirstPartyMcpToolName,
3
17
  SESSION_EFFECTIVE_TOOL_POLICY_ID_LIMIT,
4
18
  SESSION_EFFECTIVE_TOOL_POLICY_ID_MAX_LENGTH,
5
19
  mergeToolRefs,
20
+ projectAgentEffectiveTools,
21
+ resolveAgentToolFamilies,
22
+ resolveAgentMediaToolSurface,
23
+ resolveWorkspaceAgentHumanInputEnabled,
6
24
  resolveWorkspaceSessionToolDefaults,
25
+ workspaceSettingsAllowCreditModels,
26
+ type AgentFunctionToolName,
27
+ type AgentToolEnvironment,
28
+ type AgentMediaAttachment,
7
29
  type Session,
30
+ type SessionTurn,
8
31
  type SessionEffectiveToolPolicy,
9
32
  type SessionToolPolicy,
10
33
  type ToolRef,
11
34
  } from "@opengeni/contracts";
12
- import { requireWorkspace, type Database } from "@opengeni/db";
35
+ import { codeSearchEnabledForTurn } from "@opengeni/contracts/code-search";
36
+ import {
37
+ getSandbox,
38
+ listSkillDescriptors,
39
+ requireWorkspace,
40
+ sessionHasToolRouterHistory,
41
+ type Database,
42
+ } from "@opengeni/db";
43
+ import { resolveWorkspaceCatalogSettings } from "../model-catalog";
13
44
  import { settingsWithEnabledCapabilityMcpServers } from "./capabilities";
14
45
 
15
46
  const MANDATORY_SESSION_MCP_SERVER_IDS = ["opengeni"] as const;
@@ -65,8 +96,11 @@ export function resolveSessionToolPolicy(input: SessionToolPolicyInput): Resolve
65
96
  availableIds.has(id),
66
97
  );
67
98
  const mandatoryIdSet = new Set<string>(mandatoryIds);
68
- const selectedRefs = mergeToolRefs([], input.sessionTools);
69
99
  const tracksWorkspaceDefaults = policy.mode === "workspace_default";
100
+ const excludedIds = new Set(tracksWorkspaceDefaults ? policy.excludedMcpServerIds : []);
101
+ const selectedRefs = mergeToolRefs([], input.sessionTools).filter(
102
+ (tool) => !excludedIds.has(tool.id) || mandatoryIdSet.has(tool.id),
103
+ );
70
104
 
71
105
  // Persisted refs may outlive a capability installation, deployment config,
72
106
  // or its credentials. Admission remains strict for newly requested refs, but
@@ -80,7 +114,7 @@ export function resolveSessionToolPolicy(input: SessionToolPolicyInput): Resolve
80
114
  toolRefs = mergeToolRefs(
81
115
  toolRefs,
82
116
  sortedIds(defaultIds)
83
- .filter((id) => availableIds.has(id))
117
+ .filter((id) => availableIds.has(id) && !excludedIds.has(id))
84
118
  .map((id) => ({ kind: "mcp" as const, id, optional: true as const })),
85
119
  );
86
120
  }
@@ -97,7 +131,7 @@ export function resolveSessionToolPolicy(input: SessionToolPolicyInput): Resolve
97
131
  selectedRefs,
98
132
  tracksWorkspaceDefaults
99
133
  ? sortedIds(defaultIds)
100
- .filter((id) => availableIds.has(id))
134
+ .filter((id) => availableIds.has(id) && !excludedIds.has(id))
101
135
  .map((id) => ({ kind: "mcp" as const, id, optional: true as const }))
102
136
  : [],
103
137
  );
@@ -162,6 +196,74 @@ export function resolveSessionToolPolicy(input: SessionToolPolicyInput): Resolve
162
196
  };
163
197
  }
164
198
 
199
+ /** Null is ordinary work; an empty list is a frozen scheduled selection. */
200
+ export function scheduledTurnMcpServerIds(turn: Pick<SessionTurn, "metadata">): string[] | null {
201
+ const metadata = turn.metadata;
202
+ const value =
203
+ metadata && typeof metadata === "object" && !Array.isArray(metadata)
204
+ ? metadata.scheduledEffectiveMcpServerIds
205
+ : null;
206
+ return Array.isArray(value) && value.every((id) => typeof id === "string")
207
+ ? sortedIds(value)
208
+ : null;
209
+ }
210
+
211
+ /** The accepted scheduled built-in selection, including an explicit empty list. */
212
+ export function scheduledTurnFirstPartyMcpTools(
213
+ turn: Pick<SessionTurn, "metadata">,
214
+ ): FirstPartyMcpToolName[] | null {
215
+ const value = turn.metadata?.scheduledFirstPartyMcpTools;
216
+ if (value === undefined) return null; // Older accepted snapshots use the stored list.
217
+ return FirstPartyMcpToolName.array().parse(value);
218
+ }
219
+
220
+ /**
221
+ * Execution's canonical turn selection. Ordinary turns use the durable session
222
+ * policy, not the queue's omitted-tools `[]`. Scheduled turns instead retain
223
+ * their frozen registry and refs, including an explicitly empty selection.
224
+ */
225
+ export function resolveTurnToolPolicy(
226
+ input: Omit<SessionToolPolicyInput, "sessionTools"> & {
227
+ session: Pick<Session, "tools">;
228
+ turn: Pick<SessionTurn, "tools" | "metadata">;
229
+ },
230
+ ): ResolvedSessionToolPolicy {
231
+ const scheduledIds = scheduledTurnMcpServerIds(input.turn);
232
+ const availableIds = new Set(input.availableMcpServerIds);
233
+ return resolveSessionToolPolicy({
234
+ toolPolicy: input.toolPolicy,
235
+ sessionTools: scheduledIds ? input.turn.tools : input.session.tools,
236
+ availableMcpServerIds: scheduledIds
237
+ ? scheduledIds.filter((id) => availableIds.has(id))
238
+ : availableIds,
239
+ defaultMcpServerIds: scheduledIds ?? input.defaultMcpServerIds ?? [],
240
+ });
241
+ }
242
+
243
+ /** Resolve availability and defaults from the same subject-scoped registry read. */
244
+ export async function workspaceSessionToolPolicyContext(
245
+ db: Database,
246
+ workspaceId: string,
247
+ settings: Settings,
248
+ subjectId?: string,
249
+ /** An in-flight read of this exact workspace a caller already started. */
250
+ workspaceRead?: ReturnType<typeof requireWorkspace>,
251
+ ): Promise<{ workspaceServerIds: string[]; workspaceDefaultServerIds: string[] }> {
252
+ const [runtimeSettings, workspace] = await Promise.all([
253
+ settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings, {
254
+ ...(subjectId ? { subjectId } : {}),
255
+ }),
256
+ workspaceRead ?? requireWorkspace(db, workspaceId),
257
+ ]);
258
+ return {
259
+ workspaceServerIds: sortedIds(runtimeSettings.mcpServers.map((server) => server.id)),
260
+ workspaceDefaultServerIds: workspaceSessionToolPolicyDefaultServerIdsFor(
261
+ runtimeSettings.mcpServers,
262
+ workspace.settings,
263
+ ),
264
+ };
265
+ }
266
+
165
267
  /** Current full runtime registry IDs, including configured static servers. */
166
268
  export async function workspaceSessionToolPolicyServerIds(
167
269
  db: Database,
@@ -185,12 +287,371 @@ export async function workspaceSessionToolPolicyDefaultServerIds(
185
287
  const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings, {
186
288
  ...(subjectId ? { subjectId } : {}),
187
289
  });
188
- const availableDefaults = defaultSessionMcpServerIds(runtimeSettings.mcpServers);
189
290
  const workspace = await requireWorkspace(db, workspaceId);
190
- const configured = resolveWorkspaceSessionToolDefaults(workspace.settings);
291
+ return workspaceSessionToolPolicyDefaultServerIdsFor(
292
+ runtimeSettings.mcpServers,
293
+ workspace.settings,
294
+ );
295
+ }
296
+
297
+ /**
298
+ * The omitted-tools default for one resolved runtime registry and one
299
+ * workspace settings bag. Pure so a caller that already holds both never has
300
+ * to re-query the capability registry to agree with the worker and the
301
+ * composer on which connectors a `workspace_default` session executes with.
302
+ */
303
+ export function workspaceSessionToolPolicyDefaultServerIdsFor(
304
+ runtimeMcpServers: Iterable<{ id: string }>,
305
+ workspaceSettings: unknown,
306
+ ): string[] {
307
+ const availableDefaults = defaultSessionMcpServerIds(runtimeMcpServers);
308
+ const configured = resolveWorkspaceSessionToolDefaults(workspaceSettings);
191
309
  if (!configured?.mcpServerIds) return availableDefaults;
192
310
  const available = new Set(availableDefaults);
193
- return sortedIds(configured.mcpServerIds.filter((id) => available.has(id)));
311
+ return sortedIds([
312
+ ...configured.mcpServerIds.filter((id) => available.has(id)),
313
+ ...(configured.inheritConnectedMcpServers
314
+ ? availableDefaults.filter((id) => !["opengeni", "files", "docs"].includes(id))
315
+ : []),
316
+ ]);
317
+ }
318
+
319
+ /** Metadata only: no MCP listing, provider probes, account selection or credentials. */
320
+ export type SessionEffectiveToolsContext = {
321
+ settings: Settings;
322
+ humanInputEnabled: boolean;
323
+ hasWorkspaceSkills: boolean;
324
+ workspaceSettings?: unknown;
325
+ objectStorageAvailable: boolean;
326
+ activeSandboxBackends?: ReadonlyMap<string, Settings["sandboxBackend"]>;
327
+ /** Exact build options after adapter/credential resolution, keyed by session. No pool-readiness inference. */
328
+ mediaAttachments?: ReadonlyMap<string, AgentMediaAttachment>;
329
+ routerInHistory?: boolean;
330
+ routerHistorySessionIds?: ReadonlySet<string>;
331
+ };
332
+
333
+ /**
334
+ * Resolve one context for a response page, not one catalog per session. Legacy
335
+ * rows require no additional reads and never acquire an effectiveTools field.
336
+ */
337
+ export async function workspaceSessionEffectiveToolsContext(
338
+ deps: { db: Database; settings: Settings; objectStorage?: unknown },
339
+ workspaceId: string,
340
+ subjectId: string,
341
+ sessions: readonly Session[],
342
+ /** An in-flight read of this exact workspace a caller already started. */
343
+ workspaceRead?: ReturnType<typeof requireWorkspace>,
344
+ ): Promise<SessionEffectiveToolsContext> {
345
+ const configured = sessions.filter((session) => session.agent != null);
346
+ const baseline: SessionEffectiveToolsContext = {
347
+ settings: deps.settings,
348
+ humanInputEnabled: false,
349
+ hasWorkspaceSkills: false,
350
+ objectStorageAvailable: Boolean(deps.objectStorage),
351
+ };
352
+ if (configured.length === 0) return baseline;
353
+ const [workspace, catalog, descriptors, sandboxes, routerHistory] = await Promise.all([
354
+ workspaceRead ?? requireWorkspace(deps.db, workspaceId),
355
+ resolveWorkspaceCatalogSettings(deps.db, deps.settings, {
356
+ accountId: configured[0]!.accountId,
357
+ workspaceId,
358
+ retainedProductModelIds: configured.map((session) => session.model),
359
+ }),
360
+ configured.some((session) => session.agent?.capabilities.skills === "read")
361
+ ? listSkillDescriptors(deps.db, {
362
+ accountId: configured[0]!.accountId,
363
+ workspaceId,
364
+ subjectId,
365
+ })
366
+ : Promise.resolve([]),
367
+ deps.settings.sandboxSelfhostedEnabled
368
+ ? Promise.all(
369
+ sortedIds(configured.flatMap((session) => session.activeSandboxId ?? [])).map(
370
+ async (id) =>
371
+ [
372
+ id,
373
+ await getSandbox(
374
+ deps.db,
375
+ { accountId: configured[0]!.accountId, workspaceId, subjectId },
376
+ id,
377
+ ),
378
+ ] as const,
379
+ ),
380
+ )
381
+ : Promise.resolve([]),
382
+ Promise.all(
383
+ [...new Map(configured.map((session) => [session.id, session])).values()].map(
384
+ async (session) =>
385
+ [
386
+ session.id,
387
+ await sessionHasToolRouterHistory(deps.db, {
388
+ accountId: session.accountId,
389
+ workspaceId,
390
+ sessionId: session.id,
391
+ }),
392
+ ] as const,
393
+ ),
394
+ ),
395
+ ]);
396
+ return {
397
+ ...baseline,
398
+ settings: catalog.settings,
399
+ workspaceSettings: workspace.settings,
400
+ humanInputEnabled: resolveWorkspaceAgentHumanInputEnabled(workspace.settings),
401
+ hasWorkspaceSkills: descriptors.some((entry) => entry.activationMode === "workspace_managed"),
402
+ activeSandboxBackends: new Map(
403
+ sandboxes.flatMap(([id, sandbox]) =>
404
+ sandbox?.kind === "selfhosted" ? [[id, "selfhosted" as const]] : [],
405
+ ),
406
+ ),
407
+ routerHistorySessionIds: new Set(
408
+ routerHistory.filter(([, present]) => present).map(([id]) => id),
409
+ ),
410
+ };
411
+ }
412
+
413
+ function sessionHasSkills(session: Session, context: SessionEffectiveToolsContext): boolean {
414
+ if (context.hasWorkspaceSkills || session.skills.length > 0) return true;
415
+ // Undefined is the worker's bundled default. Explicit [] means no bundles,
416
+ // and a "none" agent without an explicit list has none (as in the worker).
417
+ const bundledSkillIds = bundledSkillSelectionForAgentConfig(
418
+ session.bundledSkillIds,
419
+ session.agent,
420
+ );
421
+ if (bundledSkillIds === undefined) return true;
422
+ const tools = new Set(
423
+ resolveAgentToolFamilies(session.agent).firstPartyTools(
424
+ resolveSessionFirstPartyMcpTools(context.settings, session, context.workspaceSettings),
425
+ ),
426
+ );
427
+ return bundledSkillIds.some((id) => {
428
+ if (
429
+ [
430
+ "builtin:opengeni-documents",
431
+ "builtin:opengeni-spreadsheets",
432
+ "builtin:opengeni-presentations",
433
+ ].includes(id)
434
+ ) {
435
+ return tools.has("editable_artifact_list") && tools.has("editable_artifact_get");
436
+ }
437
+ if (id === "builtin:opengeni-sites") {
438
+ return tools.has("artifacts_create") && tools.has("artifacts_publish");
439
+ }
440
+ if (id === "builtin:opengeni-video-generation") {
441
+ return context.mediaAttachments?.get(session.id)?.video === true;
442
+ }
443
+ if (id === "builtin:opengeni-secrets") return tools.has("secret_search");
444
+ return true;
445
+ });
446
+ }
447
+
448
+ /** The server can prove attachment policy, not successful future provider calls. */
449
+ export function sessionEffectiveToolProjectionInput(
450
+ session: Session & { agent: NonNullable<Session["agent"]> },
451
+ toolRefs: readonly ToolRef[],
452
+ context?: SessionEffectiveToolsContext,
453
+ ) {
454
+ const model = context ? resolveModelProviderForTurn(context.settings, session.model) : undefined;
455
+ const sandboxBackend =
456
+ (session.activeSandboxId
457
+ ? context?.activeSandboxBackends?.get(session.activeSandboxId)
458
+ : undefined) ?? session.sandboxBackend;
459
+ const sandboxAvailable = context !== undefined && sandboxBackend !== "none";
460
+ const supportsImages =
461
+ model?.model.api === "responses" && model.model.capabilities.inputModalities.includes("image");
462
+ const hostedToolNames: AgentFunctionToolName[] = [];
463
+ // Same plan the worker applies: provider web_search/web_fetch where the
464
+ // model has no hosted search (or the operator chose `replace`).
465
+ const webSearchPlan = context
466
+ ? webSearchToolPlan(context.settings, {
467
+ hostedWebSearch: model?.model.hostedWebSearch ?? context.settings.webSearchEnabled,
468
+ transportHostedSearch: model?.provider.kind === "xai-subscription",
469
+ creditsDisabled: !workspaceSettingsAllowCreditModels(context.workspaceSettings),
470
+ })
471
+ : { hostedWebSearch: false, providerTools: [] };
472
+ if (model?.provider.kind === "xai-subscription") {
473
+ if (context?.settings.webSearchEnabled) hostedToolNames.push("web_search", "x_search");
474
+ } else if (model?.model.hostedWebSearch && webSearchPlan.hostedWebSearch)
475
+ hostedToolNames.push("web_search");
476
+ const mediaAttachment =
477
+ context?.mediaAttachments?.get(session.id) ??
478
+ (context?.objectStorageAvailable === false
479
+ ? ({ image: null, video: false } as const)
480
+ : undefined);
481
+ const media = resolveAgentMediaToolSurface(session.agent, mediaAttachment);
482
+ hostedToolNames.push(...media.hosted);
483
+ const runtimeToolNames: AgentFunctionToolName[] = context
484
+ ? [
485
+ "request_human_input",
486
+ "list_models",
487
+ "skill_read",
488
+ ...AGENT_SKILL_MANAGE_TOOL_NAMES,
489
+ ...media.runtime,
490
+ ...webSearchPlan.providerTools,
491
+ ]
492
+ : [];
493
+ const sandboxToolNames: AgentFunctionToolName[] = sandboxAvailable
494
+ ? [
495
+ "exec_command",
496
+ "write_stdin",
497
+ "apply_patch",
498
+ ...(supportsImages ? ["view_image" as const] : []),
499
+ ...(session.resources.some((resource) => resource.kind === "repository")
500
+ ? ["repository_skill_read" as const]
501
+ : []),
502
+ ...(codeSearchEnabledForTurn(
503
+ session.codeSearchEnabled,
504
+ context?.workspaceSettings,
505
+ codeSearchDeploymentPolicy(context!.settings),
506
+ ) && session.sandboxOs !== "windows"
507
+ ? ["code_search" as const]
508
+ : []),
509
+ ]
510
+ : [];
511
+ const needsTitle =
512
+ session.titleSource !== "user" &&
513
+ (!session.title?.trim() || session.title.trim() === AUTOMATIC_SESSION_TITLE_FALLBACK);
514
+ const selectedFirstPartyMcpTools = context
515
+ ? resolveSessionFirstPartyMcpTools(context.settings, session, context.workspaceSettings)
516
+ : [];
517
+ const firstPartyMcpTools =
518
+ context && toolRefs.some((ref) => ref.id === "opengeni")
519
+ ? resolveAgentToolFamilies(session.agent, { sandboxAttached: sandboxAvailable })
520
+ .firstPartyTools(selectedFirstPartyMcpTools)
521
+ .filter((name) => name !== "set_session_title" || !needsTitle)
522
+ : [];
523
+ const interactionNames = new Set<string>(FIRST_PARTY_IN_PROCESS_TOOL_NAMES);
524
+ const firstPartyModelNames = new Map<FirstPartyMcpToolName, string>();
525
+ const permissions: readonly string[] =
526
+ session.firstPartyMcpPermissions ?? DEFAULT_FIRST_PARTY_MCP_PERMISSIONS;
527
+ const permissionAllowed = (permission: string) =>
528
+ permissions.includes(permission as never) || permissions.includes("workspace:admin");
529
+ if (context && resolveFirstPartyDelegationSecret(context.settings)) {
530
+ for (const name of FIRST_PARTY_IN_PROCESS_TOOL_NAMES) {
531
+ const readOnly = [
532
+ "interaction_discover",
533
+ "browser_observe",
534
+ "browser_read",
535
+ "browser_screenshot",
536
+ "browser_clipboard",
537
+ "browser_debug",
538
+ "browser_downloads",
539
+ "computer_targets",
540
+ "computer_observe",
541
+ "computer_clipboard",
542
+ ].includes(name);
543
+ if (
544
+ permissionAllowed(readOnly ? "sessions:read" : "sessions:control") &&
545
+ (name !== "browser_download_save" || permissionAllowed("files:upload"))
546
+ ) {
547
+ firstPartyModelNames.set(name, `interaction__${name}`);
548
+ if (
549
+ !firstPartyMcpTools.includes(name) &&
550
+ resolveAgentToolFamilies(session.agent, {
551
+ sandboxAttached: sandboxAvailable,
552
+ }).allowsFirstPartyTool(name) &&
553
+ selectedFirstPartyMcpTools.includes(name)
554
+ )
555
+ firstPartyMcpTools.push(name);
556
+ }
557
+ }
558
+ }
559
+ // Interaction names are never registered by the remote first-party server.
560
+ for (let index = firstPartyMcpTools.length - 1; index >= 0; index--) {
561
+ const name = firstPartyMcpTools[index]!;
562
+ if (interactionNames.has(name) && !firstPartyModelNames.has(name))
563
+ firstPartyMcpTools.splice(index, 1);
564
+ }
565
+ const codex = model?.provider.kind === "codex-subscription";
566
+ const nativeComputerTools = Boolean(
567
+ context &&
568
+ resolveFirstPartyDelegationSecret(context.settings) &&
569
+ permissionAllowed("sessions:control") &&
570
+ ["computer_open", "computer_act"].every((name) =>
571
+ resolveAgentToolFamilies(session.agent, { sandboxAttached: sandboxAvailable })
572
+ .firstPartyTools(selectedFirstPartyMcpTools)
573
+ .includes(name as FirstPartyMcpToolName),
574
+ ),
575
+ );
576
+ const retainedRouter =
577
+ context?.routerInHistory === true || context?.routerHistorySessionIds?.has(session.id) === true;
578
+ const progressiveDisclosure =
579
+ retainedRouter ||
580
+ (context
581
+ ? codex
582
+ ? context.settings.codexToolSearchEnabled
583
+ : context.settings.lazyToolSearchEnabled
584
+ : false);
585
+ const upfrontToolNames = new Set<string>([
586
+ ...hostedToolNames,
587
+ ...sandboxToolNames,
588
+ "skill_read",
589
+ "request_human_input",
590
+ "list_models",
591
+ ...webSearchPlan.providerTools,
592
+ ...(toolRefs.some((ref) => ref.id === "opengeni" && ref.eager === true) ||
593
+ !progressiveDisclosure
594
+ ? firstPartyMcpTools.filter((name) => !interactionNames.has(name) || !progressiveDisclosure)
595
+ : []),
596
+ ...(!progressiveDisclosure ? runtimeToolNames : []),
597
+ ...(nativeComputerTools && !progressiveDisclosure
598
+ ? CUA_DESKTOP_TOOLS.map((tool) => `interaction__cua_${tool.name}`)
599
+ : []),
600
+ ]);
601
+ const environment: AgentToolEnvironment = {
602
+ productServerIds: new Set([
603
+ ...session.mcpServers.map((server) => server.id),
604
+ ...(session.toolPolicy.mode !== "workspace_default"
605
+ ? session.tools.map((tool) => tool.id)
606
+ : []),
607
+ ]),
608
+ hasSkills: context ? sessionHasSkills(session, context) : false,
609
+ webSearch: hostedToolNames.includes("web_search") || webSearchPlan.providerTools.length > 0,
610
+ humanInput: context?.humanInputEnabled ?? false,
611
+ media: media.toolsKnown ? media.hosted.length + media.runtime.length > 0 : undefined,
612
+ routerInHistory:
613
+ context?.routerInHistory === true ||
614
+ context?.routerHistorySessionIds?.has(session.id) === true,
615
+ ...(context ? { sandboxAttached: sandboxAvailable } : {}),
616
+ };
617
+ const families = resolveAgentToolFamilies(session.agent, environment);
618
+ environment.hasDeferredTools =
619
+ (nativeComputerTools && progressiveDisclosure) ||
620
+ toolRefs.some(
621
+ (ref) => ref.id !== "opengeni" && ref.eager !== true && families.allowsMcpServer(ref.id),
622
+ ) ||
623
+ firstPartyMcpTools.some(
624
+ (name) => families.allowsFirstPartyTool(name) && !upfrontToolNames.has(name),
625
+ ) ||
626
+ runtimeToolNames.some(
627
+ (name) => families.allowsFunctionTool(name) && !upfrontToolNames.has(name),
628
+ );
629
+ const provider = model?.provider;
630
+ const native =
631
+ codex ||
632
+ (provider?.api === "responses" &&
633
+ (provider.wireProfile === "azure-openai" ||
634
+ (provider.builtin && provider.id === "openai" && provider.baseUrl === undefined)));
635
+ const routerToolNames: AgentFunctionToolName[] =
636
+ progressiveDisclosure && resolveAgentToolFamilies(session.agent, environment).router
637
+ ? ["tool_search", "tool_list", ...(native ? [] : ["tool_invoke" as const])]
638
+ : [];
639
+ for (const name of routerToolNames) upfrontToolNames.add(name);
640
+ return {
641
+ config: session.agent,
642
+ firstPartyMcpTools,
643
+ firstPartyModelNames,
644
+ nativeComputerTools,
645
+ mcpServerIds: toolRefs.map((ref) => ref.id),
646
+ productServerIds: environment.productServerIds ?? new Set<string>(),
647
+ environment,
648
+ runtimeToolNames,
649
+ hostedToolNames,
650
+ sandboxToolNames,
651
+ routerToolNames,
652
+ upfrontToolNames,
653
+ mediaAttachment,
654
+ };
194
655
  }
195
656
 
196
657
  /** Add a bounded, secret-safe effective projection to a session response. */
@@ -198,18 +659,32 @@ export function sessionWithEffectiveToolPolicy(
198
659
  session: Session,
199
660
  workspaceServerIds: Iterable<string>,
200
661
  workspaceDefaultServerIds: Iterable<string> = [],
662
+ effectiveToolsContext?: SessionEffectiveToolsContext,
201
663
  ): Session {
202
664
  const availableIds = new Set(workspaceServerIds);
203
665
  for (const server of session.mcpServers) {
204
666
  availableIds.add(server.id);
205
667
  }
668
+ const { effectivePolicy: effectiveToolPolicy, toolRefs } = resolveSessionToolPolicy({
669
+ toolPolicy: session.toolPolicy,
670
+ sessionTools: session.tools,
671
+ availableMcpServerIds: availableIds,
672
+ defaultMcpServerIds: workspaceDefaultServerIds,
673
+ });
206
674
  return {
207
675
  ...session,
208
- effectiveToolPolicy: resolveSessionToolPolicy({
209
- toolPolicy: session.toolPolicy,
210
- sessionTools: session.tools,
211
- availableMcpServerIds: availableIds,
212
- defaultMcpServerIds: workspaceDefaultServerIds,
213
- }).effectivePolicy,
676
+ effectiveToolPolicy,
677
+ // Configured sessions also report what they can use at capability level.
678
+ ...(session.agent
679
+ ? {
680
+ effectiveTools: projectAgentEffectiveTools(
681
+ sessionEffectiveToolProjectionInput(
682
+ { ...session, agent: session.agent },
683
+ toolRefs,
684
+ effectiveToolsContext,
685
+ ),
686
+ ),
687
+ }
688
+ : {}),
214
689
  };
215
690
  }