@opengeni/core 0.12.7 → 0.12.10
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 +25 -15
- package/dist/index.js +65 -62
- package/dist/index.js.map +1 -1
- package/package.json +8 -8
- package/src/application/session-commands.ts +19 -8
- package/src/domain/session-tool-policy.ts +5 -14
- package/src/domain/sessions.ts +65 -68
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Settings } from '@opengeni/config';
|
|
|
2
2
|
import { ScheduledTask, TurnInitiator, Document, GitHubAppApiPort, ConnectionCredentialsPort, SessionAuthorizationPort, Permission, AccessContext, AccessGrant, SessionAuthorizationActor, SessionAuthorizationTarget, SessionAuthorizationOperation, SessionAuthorizationSurface, SessionAuthorizationListScope, LimitAction, LimitDecision, TurnInitiatorContext, SessionTurnSource, CapabilityCatalogItem, CapabilityInstallation, CapabilityCatalogResponse, CreateCapabilityCatalogItemRequest, EnableCapabilityRequest, VariableSet, Rig, RigVersion, CreateRigRequest, RigDefinitionEditPayload, RigChange, ProposeRigChangeRequest, UpdateRigRequest, CapabilityPack, SocialConnection, ScheduledTaskAgentConfig, ToolRef, ResourceRef, SessionEffectiveToolPolicy, SessionToolPolicy, Session, CreateScheduledTaskRequest, UpdateScheduledTaskRequest, SessionSpawnDenial, ReasoningEffort, SessionMcpCredentialUpdateInput, SessionEvent, SessionTurn, SessionSkill, TurnExecutionPolicyV1, GoalSpec, FirstPartyMcpToolName, SessionMcpServerMetadata, CreateSessionResponse, SessionMcpApprovalPolicy, UpdateSessionMcpApprovalPolicyResponse, UpdateSessionToolPolicyRequest, ConnectionMetadata, OpenGeniSlackBotConnectionMetadata, WorkspaceMember, NewSessionDraft, SessionControlRequest, SessionControlResponse, WorkspaceInferenceControlRequest, WorkspaceInferenceControlResponse, DeleteSessionQueueItemRequest, SessionQueueMutationResponse, EditSessionQueueItemRequest, ComposerDraft, MoveSessionQueueItemRequest, SaveComposerDraftRequest, SteerSessionQueueItemRequest } from '@opengeni/contracts';
|
|
3
3
|
export { mergeToolRefs, stableJson } from '@opengeni/contracts';
|
|
4
4
|
import * as _opengeni_db from '@opengeni/db';
|
|
5
|
-
import { Database, SandboxRecord, EnabledMcpCapabilityServer, UpdateScheduledTaskInput, SessionCommandActor, CreateSessionMcpServerInput, UpdateSessionMcpServerCredentialsInput, ConnectionMetadataWithVerification } from '@opengeni/db';
|
|
5
|
+
import { Database, SandboxRecord, EnabledMcpCapabilityServer, UpdateScheduledTaskInput, SessionCommandActor, CreateSessionMcpServerInput, UpdateSessionMcpServerCredentialsInput, ConnectionMetadataWithVerification, SessionCommandReceiptRow } from '@opengeni/db';
|
|
6
6
|
import { DocumentServices } from '@opengeni/documents';
|
|
7
7
|
import { EventBus } from '@opengeni/events';
|
|
8
8
|
import { Observability } from '@opengeni/observability';
|
|
@@ -699,11 +699,8 @@ type ResolvedSessionToolPolicy = {
|
|
|
699
699
|
effectivePolicy: SessionEffectiveToolPolicy;
|
|
700
700
|
};
|
|
701
701
|
type SessionToolPolicyInput = {
|
|
702
|
-
toolPolicy
|
|
702
|
+
toolPolicy: SessionToolPolicy;
|
|
703
703
|
sessionTools: ToolRef[];
|
|
704
|
-
turnTools?: ToolRef[];
|
|
705
|
-
/** Undefined preserves the legacy merge path for pre-provenance callers. */
|
|
706
|
-
turnToolsProvided?: boolean;
|
|
707
704
|
availableMcpServerIds: Iterable<string>;
|
|
708
705
|
/** Current omitted-tools defaults, intentionally narrower than all servers. */
|
|
709
706
|
defaultMcpServerIds?: Iterable<string>;
|
|
@@ -809,7 +806,7 @@ declare class SessionSpawnDeniedError extends Error {
|
|
|
809
806
|
* as null); child omission snapshots the parent's exact effective selection.
|
|
810
807
|
* Explicit [] is authoritative and must never widen.
|
|
811
808
|
*/
|
|
812
|
-
declare function resolveFirstPartyMcpToolsForCreate(requested: FirstPartyMcpToolName[] | undefined, parentStored: FirstPartyMcpToolName[] | null | undefined): FirstPartyMcpToolName[]
|
|
809
|
+
declare function resolveFirstPartyMcpToolsForCreate(requested: FirstPartyMcpToolName[] | undefined, parentStored: FirstPartyMcpToolName[] | null | undefined): FirstPartyMcpToolName[];
|
|
813
810
|
declare function sessionSpawnDenialEnvelope(error: SessionSpawnDeniedError): {
|
|
814
811
|
readonly error: {
|
|
815
812
|
readonly code: "nested_agent_depth_exceeded" | "nested_agent_depth_override_forbidden";
|
|
@@ -848,7 +845,7 @@ declare function createAndStartSession(input: {
|
|
|
848
845
|
resources: ResourceRef[];
|
|
849
846
|
skills?: SessionSkill[];
|
|
850
847
|
tools: ToolRef[];
|
|
851
|
-
toolPolicy
|
|
848
|
+
toolPolicy: SessionToolPolicy;
|
|
852
849
|
clientEventId?: string;
|
|
853
850
|
model: string;
|
|
854
851
|
reasoningEffort: Settings["openaiReasoningEffort"];
|
|
@@ -869,7 +866,7 @@ declare function createAndStartSession(input: {
|
|
|
869
866
|
goal?: GoalSpec | null;
|
|
870
867
|
instructions?: string | null;
|
|
871
868
|
firstPartyMcpPermissions?: Permission[] | null;
|
|
872
|
-
firstPartyMcpTools
|
|
869
|
+
firstPartyMcpTools: FirstPartyMcpToolName[];
|
|
873
870
|
mcpServers?: CreateSessionMcpServerInput[];
|
|
874
871
|
sessionMcpServers?: SessionMcpServerMetadata[];
|
|
875
872
|
parentSessionId?: string | null;
|
|
@@ -940,8 +937,6 @@ declare function postUserMessageTurn(input: {
|
|
|
940
937
|
text: string;
|
|
941
938
|
turnInstructions?: string | null;
|
|
942
939
|
resources: ResourceRef[];
|
|
943
|
-
tools: ToolRef[];
|
|
944
|
-
toolsProvided: boolean;
|
|
945
940
|
model?: string | null;
|
|
946
941
|
reasoningEffort?: Settings["openaiReasoningEffort"] | null;
|
|
947
942
|
clientEventId?: string;
|
|
@@ -974,15 +969,12 @@ declare function createSessionForRequest(deps: ApiRouteDeps, grant: AccessGrant,
|
|
|
974
969
|
* `POST /sessions/:id/events` and the first-party MCP `session_send_message`
|
|
975
970
|
* tool: resource/tool validation, usage limits, the locked append + turn
|
|
976
971
|
* enqueue, and usage recording. `toolsProvided: false` durably preserves an
|
|
977
|
-
*
|
|
978
|
-
* empty array is a deliberate per-turn narrowing.
|
|
972
|
+
* Tool selection is durable session state and never rides a follow-up prompt.
|
|
979
973
|
*/
|
|
980
974
|
declare function acceptSessionUserMessage(deps: AcceptSessionUserMessageDependencies, grant: AccessGrant, workspaceId: string, sessionId: string, input: {
|
|
981
975
|
text: string;
|
|
982
976
|
turnInstructions?: string | null;
|
|
983
977
|
resources?: ResourceRef[];
|
|
984
|
-
tools?: ToolRef[];
|
|
985
|
-
toolsProvided: boolean;
|
|
986
978
|
model?: string | null;
|
|
987
979
|
reasoningEffort?: ReasoningEffort | null;
|
|
988
980
|
clientEventId?: string;
|
|
@@ -1107,6 +1099,8 @@ type HumanSessionCommandContext = {
|
|
|
1107
1099
|
workspaceId: string;
|
|
1108
1100
|
sessionId: string;
|
|
1109
1101
|
subjectId: string;
|
|
1102
|
+
/** See AgentSessionCommandContext.authorizationSurface. */
|
|
1103
|
+
authorizationSurface?: SessionAuthorizationSurface;
|
|
1110
1104
|
};
|
|
1111
1105
|
type AgentSessionCommandContext = {
|
|
1112
1106
|
accountId: string;
|
|
@@ -1116,6 +1110,13 @@ type AgentSessionCommandContext = {
|
|
|
1116
1110
|
callerTurnId: string;
|
|
1117
1111
|
callerAttemptId: string;
|
|
1118
1112
|
callerExecutionGeneration: number;
|
|
1113
|
+
/**
|
|
1114
|
+
* The trusted adapter surface that owns this command's one authorization
|
|
1115
|
+
* decision. Direct core callers omit it and retain the canonical `core`
|
|
1116
|
+
* surface; adapters that delegate the complete command set it explicitly so
|
|
1117
|
+
* they do not authorize once at the edge and then repeat the host call here.
|
|
1118
|
+
*/
|
|
1119
|
+
authorizationSurface?: SessionAuthorizationSurface;
|
|
1119
1120
|
};
|
|
1120
1121
|
type SessionAuthorizationCommandDeps = {
|
|
1121
1122
|
db: Database;
|
|
@@ -1151,7 +1152,16 @@ declare function controlAgentSessionWorkstream(deps: {
|
|
|
1151
1152
|
action: "pause" | "resume";
|
|
1152
1153
|
idempotencyKey: string;
|
|
1153
1154
|
reason?: string | null;
|
|
1154
|
-
}): Promise<
|
|
1155
|
+
}): Promise<{
|
|
1156
|
+
authorization: ResolvedSessionAuthorization | null;
|
|
1157
|
+
receipt: SessionCommandReceiptRow;
|
|
1158
|
+
control: _opengeni_db.EffectiveSessionControl;
|
|
1159
|
+
sessionControlEventId: string;
|
|
1160
|
+
workspaceControlEventId: string;
|
|
1161
|
+
interruptionCount: number;
|
|
1162
|
+
wakeCount: number;
|
|
1163
|
+
replay: boolean;
|
|
1164
|
+
}>;
|
|
1155
1165
|
declare function moveHumanQueuePrompt(deps: {
|
|
1156
1166
|
db: Database;
|
|
1157
1167
|
bus: EventBus;
|
package/dist/index.js
CHANGED
|
@@ -3251,15 +3251,15 @@ function projectIds(ids) {
|
|
|
3251
3251
|
};
|
|
3252
3252
|
}
|
|
3253
3253
|
function resolveSessionToolPolicy(input) {
|
|
3254
|
-
const policy = input.toolPolicy
|
|
3254
|
+
const policy = input.toolPolicy;
|
|
3255
3255
|
const availableIds = new Set(input.availableMcpServerIds);
|
|
3256
3256
|
const defaultIds = new Set(input.defaultMcpServerIds ?? []);
|
|
3257
3257
|
const mandatoryIds = MANDATORY_SESSION_MCP_SERVER_IDS.filter(
|
|
3258
3258
|
(id) => availableIds.has(id)
|
|
3259
3259
|
);
|
|
3260
3260
|
const mandatoryIdSet = new Set(mandatoryIds);
|
|
3261
|
-
const selectedRefs =
|
|
3262
|
-
const tracksWorkspaceDefaults = policy.mode === "workspace_default"
|
|
3261
|
+
const selectedRefs = mergeToolRefs2([], input.sessionTools);
|
|
3262
|
+
const tracksWorkspaceDefaults = policy.mode === "workspace_default";
|
|
3263
3263
|
let toolRefs = selectedRefs.filter((tool) => tool.optional !== true || availableIds.has(tool.id));
|
|
3264
3264
|
if (tracksWorkspaceDefaults) {
|
|
3265
3265
|
toolRefs = mergeToolRefs2(
|
|
@@ -3345,7 +3345,7 @@ function sessionWithEffectiveToolPolicy(session, workspaceServerIds, workspaceDe
|
|
|
3345
3345
|
return {
|
|
3346
3346
|
...session,
|
|
3347
3347
|
effectiveToolPolicy: resolveSessionToolPolicy({
|
|
3348
|
-
|
|
3348
|
+
toolPolicy: session.toolPolicy,
|
|
3349
3349
|
sessionTools: session.tools,
|
|
3350
3350
|
availableMcpServerIds: availableIds,
|
|
3351
3351
|
defaultMcpServerIds: workspaceDefaultServerIds
|
|
@@ -3378,6 +3378,7 @@ import {
|
|
|
3378
3378
|
CreateSessionRequest,
|
|
3379
3379
|
DEFAULT_FIRST_PARTY_MCP_PERMISSIONS,
|
|
3380
3380
|
DEFAULT_FIRST_PARTY_MCP_TOOLS,
|
|
3381
|
+
FIRST_PARTY_MCP_TOOL_NAMES,
|
|
3381
3382
|
OPENGENI_SLACK_BOT_SESSION_METADATA_KEY as OPENGENI_SLACK_BOT_SESSION_METADATA_KEY2,
|
|
3382
3383
|
SessionSpawnDenial,
|
|
3383
3384
|
ServiceTurnInitiator,
|
|
@@ -3502,7 +3503,7 @@ var SessionSpawnDeniedError = class extends Error {
|
|
|
3502
3503
|
};
|
|
3503
3504
|
function resolveFirstPartyMcpToolsForCreate(requested, parentStored) {
|
|
3504
3505
|
if (requested !== void 0) return [...requested];
|
|
3505
|
-
if (parentStored === void 0) return
|
|
3506
|
+
if (parentStored === void 0) return [...DEFAULT_FIRST_PARTY_MCP_TOOLS];
|
|
3506
3507
|
return [...parentStored ?? DEFAULT_FIRST_PARTY_MCP_TOOLS];
|
|
3507
3508
|
}
|
|
3508
3509
|
function sessionSpawnDeniedMessage(denial) {
|
|
@@ -3798,7 +3799,7 @@ async function createAndStartSession(input) {
|
|
|
3798
3799
|
resources: input.resources,
|
|
3799
3800
|
skills: input.skills ?? [],
|
|
3800
3801
|
tools: input.tools,
|
|
3801
|
-
|
|
3802
|
+
toolPolicy: input.toolPolicy,
|
|
3802
3803
|
metadata: sessionMetadata,
|
|
3803
3804
|
...input.createdBy ? { createdBy: input.createdBy } : {},
|
|
3804
3805
|
...input.createdByContext ? { createdByContext: input.createdByContext } : {},
|
|
@@ -3809,7 +3810,7 @@ async function createAndStartSession(input) {
|
|
|
3809
3810
|
rigId: input.rigId ?? null,
|
|
3810
3811
|
rigVersionId: input.rigVersionId ?? null,
|
|
3811
3812
|
firstPartyMcpPermissions: input.firstPartyMcpPermissions ?? null,
|
|
3812
|
-
firstPartyMcpTools: input.firstPartyMcpTools
|
|
3813
|
+
firstPartyMcpTools: input.firstPartyMcpTools,
|
|
3813
3814
|
instructions: input.instructions ?? null,
|
|
3814
3815
|
parentSessionId: input.parentSessionId ?? null,
|
|
3815
3816
|
createIdempotencyKey: input.createIdempotencyKey,
|
|
@@ -3843,7 +3844,7 @@ async function createAndStartSession(input) {
|
|
|
3843
3844
|
resources: input.resources,
|
|
3844
3845
|
skills: input.skills ?? [],
|
|
3845
3846
|
tools: input.tools,
|
|
3846
|
-
|
|
3847
|
+
toolPolicy: input.toolPolicy,
|
|
3847
3848
|
metadata: sessionMetadata,
|
|
3848
3849
|
...input.createdBy ? { createdBy: input.createdBy } : {},
|
|
3849
3850
|
...input.createdByContext ? { createdByContext: input.createdByContext } : {},
|
|
@@ -3854,7 +3855,7 @@ async function createAndStartSession(input) {
|
|
|
3854
3855
|
rigId: input.rigId ?? null,
|
|
3855
3856
|
rigVersionId: input.rigVersionId ?? null,
|
|
3856
3857
|
firstPartyMcpPermissions: input.firstPartyMcpPermissions ?? null,
|
|
3857
|
-
firstPartyMcpTools: input.firstPartyMcpTools
|
|
3858
|
+
firstPartyMcpTools: input.firstPartyMcpTools,
|
|
3858
3859
|
instructions: input.instructions ?? null,
|
|
3859
3860
|
parentSessionId: input.parentSessionId ?? null,
|
|
3860
3861
|
sandboxGroupId: input.sandboxGroupId ?? null,
|
|
@@ -3908,7 +3909,7 @@ async function finishStartSession(input, session) {
|
|
|
3908
3909
|
reasoningEffortFallback: input.reasoningEffort,
|
|
3909
3910
|
turnExecutionPolicy: input.turnExecutionPolicy,
|
|
3910
3911
|
createdEventPayload: {
|
|
3911
|
-
|
|
3912
|
+
toolPolicy: input.toolPolicy,
|
|
3912
3913
|
...input.variableSet ? { variableSetId: input.variableSet.id, variableSetName: input.variableSet.name } : {},
|
|
3913
3914
|
...input.sessionMcpServers?.length ? { mcpServers: input.sessionMcpServers } : {}
|
|
3914
3915
|
},
|
|
@@ -4021,8 +4022,6 @@ async function postUserMessageTurn(input) {
|
|
|
4021
4022
|
text: input.text,
|
|
4022
4023
|
turnInstructions: input.turnInstructions ?? null,
|
|
4023
4024
|
resources: input.resources,
|
|
4024
|
-
tools: input.tools,
|
|
4025
|
-
toolsProvided: input.toolsProvided,
|
|
4026
4025
|
model: requestedModel,
|
|
4027
4026
|
reasoningEffort: requestedReasoningEffort,
|
|
4028
4027
|
reasoningEffortFallback: input.reasoningEffortFallback ?? settings.openaiReasoningEffort,
|
|
@@ -4255,9 +4254,8 @@ async function createSessionForRequest(deps, grant, workspaceId, rawPayload) {
|
|
|
4255
4254
|
parentSession ? parentSession.firstPartyMcpTools : void 0
|
|
4256
4255
|
);
|
|
4257
4256
|
if (payload.goal) {
|
|
4258
|
-
const effectiveTools = firstPartyMcpTools ?? [...DEFAULT_FIRST_PARTY_MCP_TOOLS];
|
|
4259
4257
|
const missingGoalTools = ["goal_update", "goal_complete", "goal_pause"].filter(
|
|
4260
|
-
(name) => !
|
|
4258
|
+
(name) => !firstPartyMcpTools.includes(name)
|
|
4261
4259
|
);
|
|
4262
4260
|
if (missingGoalTools.length > 0) {
|
|
4263
4261
|
throw new HTTPException10(422, {
|
|
@@ -4458,22 +4456,12 @@ async function createSessionForRequest(deps, grant, workspaceId, rawPayload) {
|
|
|
4458
4456
|
return session;
|
|
4459
4457
|
}
|
|
4460
4458
|
async function acceptSessionUserMessage(deps, grant, workspaceId, sessionId, input) {
|
|
4461
|
-
if (input.toolsProvided && !deps.settings.sessionTurnToolReplacementEnabled) {
|
|
4462
|
-
throw new HTTPException10(503, {
|
|
4463
|
-
message: "explicit follow-up tool replacement is temporarily unavailable until provenance-aware turn workers finish rolling out; omit tools to inherit the session policy and retry"
|
|
4464
|
-
});
|
|
4465
|
-
}
|
|
4466
4459
|
const { settings, db, bus, workflowClient, objectStorage } = deps;
|
|
4467
4460
|
await requireSessionAuthorization(deps, grant, {
|
|
4468
4461
|
sessionId,
|
|
4469
4462
|
operation: input.delivery === "steer" ? "session.steer" : "session.append",
|
|
4470
4463
|
surface: "core"
|
|
4471
4464
|
});
|
|
4472
|
-
const capabilityRuntimeSettings = await settingsWithEnabledCapabilityMcpServers(
|
|
4473
|
-
db,
|
|
4474
|
-
workspaceId,
|
|
4475
|
-
settings
|
|
4476
|
-
);
|
|
4477
4465
|
const existingSession = await requireSession2(db, workspaceId, sessionId);
|
|
4478
4466
|
const requestedModel = canonicalConfiguredModel(settings, input.model ?? null) ?? null;
|
|
4479
4467
|
const effectiveModel = canonicalConfiguredModel(settings, requestedModel ?? existingSession.model) ?? null;
|
|
@@ -4492,27 +4480,7 @@ async function acceptSessionUserMessage(deps, grant, workspaceId, sessionId, inp
|
|
|
4492
4480
|
reasoningEffort: effectiveReasoningEffort,
|
|
4493
4481
|
reasoningSource: input.reasoningEffort == null ? "session" : "explicit"
|
|
4494
4482
|
});
|
|
4495
|
-
const runtimeSettings = settingsWithSessionMcpServerMetadata(
|
|
4496
|
-
capabilityRuntimeSettings,
|
|
4497
|
-
existingSession.mcpServers
|
|
4498
|
-
);
|
|
4499
4483
|
const requestedResources = normalizeResources(input.resources ?? []);
|
|
4500
|
-
const tracksWorkspaceDefaults = existingSession.toolPolicy?.mode === "workspace_default";
|
|
4501
|
-
const sessionPolicyTools = withFirstPartyTools(
|
|
4502
|
-
tracksWorkspaceDefaults ? withDefaultEnabledCapabilityMcpTools(
|
|
4503
|
-
availableToolRefs(existingSession.tools, runtimeSettings),
|
|
4504
|
-
settings,
|
|
4505
|
-
capabilityRuntimeSettings
|
|
4506
|
-
) : existingSession.tools,
|
|
4507
|
-
runtimeSettings
|
|
4508
|
-
);
|
|
4509
|
-
const validatedTools = input.toolsProvided ? validateToolRefsForSessionPolicy({
|
|
4510
|
-
requested: input.tools ?? [],
|
|
4511
|
-
settings: runtimeSettings,
|
|
4512
|
-
allowedTools: sessionPolicyTools,
|
|
4513
|
-
message: "message tools may only narrow the session tool policy"
|
|
4514
|
-
}) : [];
|
|
4515
|
-
const requestedTools = input.toolsProvided ? validatedTools : [];
|
|
4516
4484
|
await requireLimit(deps, {
|
|
4517
4485
|
accountId: grant.accountId,
|
|
4518
4486
|
workspaceId,
|
|
@@ -4546,8 +4514,6 @@ async function acceptSessionUserMessage(deps, grant, workspaceId, sessionId, inp
|
|
|
4546
4514
|
text: input.text,
|
|
4547
4515
|
turnInstructions: input.turnInstructions ?? null,
|
|
4548
4516
|
resources: requestedResources,
|
|
4549
|
-
tools: requestedTools,
|
|
4550
|
-
toolsProvided: input.toolsProvided,
|
|
4551
4517
|
model: input.model ?? null,
|
|
4552
4518
|
reasoningEffort: input.reasoningEffort ?? null,
|
|
4553
4519
|
reasoningEffortFallback: sessionReasoningEffort,
|
|
@@ -4654,7 +4620,7 @@ async function updateSessionMcpApprovalPolicy(deps, grant, sessionId, serverId,
|
|
|
4654
4620
|
effectiveFrom: "next_attempt"
|
|
4655
4621
|
};
|
|
4656
4622
|
}
|
|
4657
|
-
function toolPolicyAuditSnapshot(session, tools, policy = session.toolPolicy
|
|
4623
|
+
function toolPolicyAuditSnapshot(session, tools, firstPartyMcpTools, policy = session.toolPolicy) {
|
|
4658
4624
|
const allToolRefs = mergeToolRefs([], tools).sort((left, right) => {
|
|
4659
4625
|
const leftMandatory = left.kind === "mcp" && left.id === "opengeni";
|
|
4660
4626
|
const rightMandatory = right.kind === "mcp" && right.id === "opengeni";
|
|
@@ -4673,6 +4639,8 @@ function toolPolicyAuditSnapshot(session, tools, policy = session.toolPolicy ??
|
|
|
4673
4639
|
toolIds: [...toolRefs].sort((left, right) => `${left.kind}:${left.id}`.localeCompare(`${right.kind}:${right.id}`)).map((tool) => tool.id),
|
|
4674
4640
|
toolRefs,
|
|
4675
4641
|
toolCount: allToolRefs.length,
|
|
4642
|
+
firstPartyMcpTools: [...firstPartyMcpTools].sort(),
|
|
4643
|
+
firstPartyMcpToolCount: firstPartyMcpTools.length,
|
|
4676
4644
|
truncated: allToolRefs.length > toolRefs.length
|
|
4677
4645
|
};
|
|
4678
4646
|
}
|
|
@@ -4706,10 +4674,12 @@ async function updateSessionToolPolicy(deps, grant, sessionId, request) {
|
|
|
4706
4674
|
}
|
|
4707
4675
|
return withFirstPartyTools(validatedTools, runtimeSettings);
|
|
4708
4676
|
})() : null;
|
|
4677
|
+
const explicitRequestedFirstPartyTools = explicitRequest ? [...explicitRequest.firstPartyMcpTools] : null;
|
|
4709
4678
|
const workspaceDefaultTools = withFirstPartyTools(
|
|
4710
4679
|
withDefaultEnabledCapabilityMcpTools([], deps.settings, capabilityRuntimeSettings),
|
|
4711
4680
|
runtimeSettings
|
|
4712
4681
|
);
|
|
4682
|
+
const workspaceDefaultFirstPartyTools = [...FIRST_PARTY_MCP_TOOL_NAMES];
|
|
4713
4683
|
const events = await appendSessionEventsWithLockedSessionUpdate(
|
|
4714
4684
|
deps.db,
|
|
4715
4685
|
grant.workspaceId,
|
|
@@ -4720,6 +4690,7 @@ async function updateSessionToolPolicy(deps, grant, sessionId, request) {
|
|
|
4720
4690
|
throw new SessionToolPolicyVersionConflictError(currentVersion);
|
|
4721
4691
|
}
|
|
4722
4692
|
let nextTools;
|
|
4693
|
+
let nextFirstPartyMcpTools;
|
|
4723
4694
|
let nextPolicy;
|
|
4724
4695
|
if (session.parentSessionId) {
|
|
4725
4696
|
const parent = await context.getLockedSession(session.parentSessionId);
|
|
@@ -4735,6 +4706,9 @@ async function updateSessionToolPolicy(deps, grant, sessionId, request) {
|
|
|
4735
4706
|
) : parent.tools,
|
|
4736
4707
|
runtimeSettings
|
|
4737
4708
|
);
|
|
4709
|
+
const parentFirstPartyMcpTools = [
|
|
4710
|
+
...parent.firstPartyMcpTools ?? DEFAULT_FIRST_PARTY_MCP_TOOLS
|
|
4711
|
+
];
|
|
4738
4712
|
if (requestedMode === "workspace_default") {
|
|
4739
4713
|
if (!parentTracksWorkspaceDefaults) {
|
|
4740
4714
|
throw new HTTPException10(403, {
|
|
@@ -4742,6 +4716,7 @@ async function updateSessionToolPolicy(deps, grant, sessionId, request) {
|
|
|
4742
4716
|
});
|
|
4743
4717
|
}
|
|
4744
4718
|
nextTools = parentEffective;
|
|
4719
|
+
nextFirstPartyMcpTools = parentFirstPartyMcpTools;
|
|
4745
4720
|
nextPolicy = {
|
|
4746
4721
|
mode: "workspace_default",
|
|
4747
4722
|
inheritedFromSessionId: parent.id
|
|
@@ -4753,6 +4728,16 @@ async function updateSessionToolPolicy(deps, grant, sessionId, request) {
|
|
|
4753
4728
|
parentEffective,
|
|
4754
4729
|
"session tools may only narrow the parent session tool policy"
|
|
4755
4730
|
);
|
|
4731
|
+
const parentFirstPartySet = new Set(parentFirstPartyMcpTools);
|
|
4732
|
+
const widenedFirstPartyTool = explicitRequestedFirstPartyTools.find(
|
|
4733
|
+
(tool) => !parentFirstPartySet.has(tool)
|
|
4734
|
+
);
|
|
4735
|
+
if (widenedFirstPartyTool) {
|
|
4736
|
+
throw new HTTPException10(403, {
|
|
4737
|
+
message: `session OpenGeni tools may only narrow the parent policy: ${widenedFirstPartyTool}`
|
|
4738
|
+
});
|
|
4739
|
+
}
|
|
4740
|
+
nextFirstPartyMcpTools = explicitRequestedFirstPartyTools;
|
|
4756
4741
|
nextPolicy = {
|
|
4757
4742
|
mode: "explicit",
|
|
4758
4743
|
inheritedFromSessionId: parent.id
|
|
@@ -4760,13 +4745,19 @@ async function updateSessionToolPolicy(deps, grant, sessionId, request) {
|
|
|
4760
4745
|
}
|
|
4761
4746
|
} else {
|
|
4762
4747
|
nextTools = requestedMode === "workspace_default" ? workspaceDefaultTools : explicitRequestedTools;
|
|
4748
|
+
nextFirstPartyMcpTools = requestedMode === "workspace_default" ? workspaceDefaultFirstPartyTools : explicitRequestedFirstPartyTools;
|
|
4763
4749
|
nextPolicy = { mode: requestedMode, inheritedFromSessionId: null };
|
|
4764
4750
|
}
|
|
4765
|
-
const currentPolicy = session.toolPolicy
|
|
4766
|
-
|
|
4767
|
-
|
|
4768
|
-
|
|
4769
|
-
|
|
4751
|
+
const currentPolicy = session.toolPolicy;
|
|
4752
|
+
const unchanged = stableJson2({
|
|
4753
|
+
tools: session.tools,
|
|
4754
|
+
firstPartyMcpTools: session.firstPartyMcpTools ?? DEFAULT_FIRST_PARTY_MCP_TOOLS,
|
|
4755
|
+
policy: currentPolicy
|
|
4756
|
+
}) === stableJson2({
|
|
4757
|
+
tools: nextTools,
|
|
4758
|
+
firstPartyMcpTools: nextFirstPartyMcpTools,
|
|
4759
|
+
policy: nextPolicy
|
|
4760
|
+
});
|
|
4770
4761
|
if (unchanged) {
|
|
4771
4762
|
return { events: [] };
|
|
4772
4763
|
}
|
|
@@ -4776,8 +4767,18 @@ async function updateSessionToolPolicy(deps, grant, sessionId, request) {
|
|
|
4776
4767
|
{
|
|
4777
4768
|
type: "session.tool_policy.updated",
|
|
4778
4769
|
payload: {
|
|
4779
|
-
before: toolPolicyAuditSnapshot(
|
|
4780
|
-
|
|
4770
|
+
before: toolPolicyAuditSnapshot(
|
|
4771
|
+
session,
|
|
4772
|
+
session.tools,
|
|
4773
|
+
[...session.firstPartyMcpTools ?? DEFAULT_FIRST_PARTY_MCP_TOOLS],
|
|
4774
|
+
currentPolicy
|
|
4775
|
+
),
|
|
4776
|
+
after: toolPolicyAuditSnapshot(
|
|
4777
|
+
session,
|
|
4778
|
+
nextTools,
|
|
4779
|
+
nextFirstPartyMcpTools,
|
|
4780
|
+
nextPolicy
|
|
4781
|
+
),
|
|
4781
4782
|
version: nextVersion,
|
|
4782
4783
|
effectiveFrom: "next_attempt"
|
|
4783
4784
|
}
|
|
@@ -4785,6 +4786,7 @@ async function updateSessionToolPolicy(deps, grant, sessionId, request) {
|
|
|
4785
4786
|
],
|
|
4786
4787
|
update: {
|
|
4787
4788
|
tools: nextTools,
|
|
4789
|
+
firstPartyMcpTools: nextFirstPartyMcpTools,
|
|
4788
4790
|
toolPolicy: nextPolicy,
|
|
4789
4791
|
toolPolicyVersion: nextVersion,
|
|
4790
4792
|
expectedToolPolicyVersion: request.expectedVersion
|
|
@@ -5355,14 +5357,14 @@ async function authorizeHumanSessionCommand(deps, context, operation) {
|
|
|
5355
5357
|
return await requireSessionAuthorization(deps, humanAccessGrant(context), {
|
|
5356
5358
|
sessionId: context.sessionId,
|
|
5357
5359
|
operation,
|
|
5358
|
-
surface: "core"
|
|
5360
|
+
surface: context.authorizationSurface ?? "core"
|
|
5359
5361
|
});
|
|
5360
5362
|
}
|
|
5361
5363
|
async function authorizeAgentSessionCommand(deps, context, targetSessionId, operation) {
|
|
5362
5364
|
return await requireSessionAuthorization(deps, agentAccessGrant(context), {
|
|
5363
5365
|
sessionId: targetSessionId,
|
|
5364
5366
|
operation,
|
|
5365
|
-
surface: "core"
|
|
5367
|
+
surface: context.authorizationSurface ?? "core"
|
|
5366
5368
|
});
|
|
5367
5369
|
}
|
|
5368
5370
|
function agentActor(context) {
|
|
@@ -5493,7 +5495,12 @@ async function steerAgentSession(deps, context, input) {
|
|
|
5493
5495
|
return result;
|
|
5494
5496
|
}
|
|
5495
5497
|
async function controlAgentSessionWorkstream(deps, context, input) {
|
|
5496
|
-
await authorizeAgentSessionCommand(
|
|
5498
|
+
const authorization = await authorizeAgentSessionCommand(
|
|
5499
|
+
deps,
|
|
5500
|
+
context,
|
|
5501
|
+
input.targetSessionId,
|
|
5502
|
+
"session.control"
|
|
5503
|
+
);
|
|
5497
5504
|
const result = await withWorkspaceRls(
|
|
5498
5505
|
deps.db,
|
|
5499
5506
|
context.workspaceId,
|
|
@@ -5514,7 +5521,7 @@ async function controlAgentSessionWorkstream(deps, context, input) {
|
|
|
5514
5521
|
]);
|
|
5515
5522
|
await publishWorkspaceControlEvent(deps, context.workspaceId, result.workspaceControlEventId);
|
|
5516
5523
|
await requestControlWakeDispatch(deps, result.wakeCount);
|
|
5517
|
-
return result;
|
|
5524
|
+
return { ...result, authorization };
|
|
5518
5525
|
}
|
|
5519
5526
|
function receipt(row) {
|
|
5520
5527
|
return {
|
|
@@ -5536,8 +5543,6 @@ function composerDraft(row) {
|
|
|
5536
5543
|
revision: row.revision,
|
|
5537
5544
|
text: row.text,
|
|
5538
5545
|
resources: row.resources,
|
|
5539
|
-
tools: row.tools,
|
|
5540
|
-
toolsProvided: row.toolsProvided,
|
|
5541
5546
|
model: row.model,
|
|
5542
5547
|
reasoningEffort: row.reasoningEffort,
|
|
5543
5548
|
sourceTurnId: row.sourceTurnId,
|
|
@@ -5755,8 +5760,6 @@ async function getHumanComposerDraft(deps, context) {
|
|
|
5755
5760
|
revision: 0,
|
|
5756
5761
|
text: "",
|
|
5757
5762
|
resources: [],
|
|
5758
|
-
tools: [],
|
|
5759
|
-
toolsProvided: false,
|
|
5760
5763
|
model: session.model,
|
|
5761
5764
|
reasoningEffort: reasoningEffortForMetadata2(session.metadata, "medium"),
|
|
5762
5765
|
sourceTurnId: null,
|