@opengeni/core 0.16.2 → 0.17.1
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/domain/personal-connection-delegations.d.ts +48 -0
- package/dist/domain/scheduled-tasks.d.ts +8 -3
- package/dist/domain/sessions.d.ts +11 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +241 -1
- package/dist/index.js.map +1 -1
- package/dist/sandbox/routing.d.ts +2 -1
- package/package.json +9 -9
- package/src/domain/personal-connection-delegations.ts +247 -0
- package/src/domain/scheduled-tasks.ts +79 -3
- package/src/domain/sessions.ts +29 -2
- package/src/index.ts +1 -0
- package/src/sandbox/routing.ts +4 -1
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import type { McpServerConfig, Settings } from "@opengeni/config";
|
|
2
|
+
import type { AccessGrant, ConnectionMetadata, McpPersonalConnectionDelegation, SessionTurn, ToolRef } from "@opengeni/contracts";
|
|
3
|
+
import { type Database, type ResolveConnectionCredentialInput, type ResolveConnectionCredentialResult } from "@opengeni/db";
|
|
4
|
+
export type PersonalConnectionDelegationSource = {
|
|
5
|
+
kind: "subject";
|
|
6
|
+
subjectId: string;
|
|
7
|
+
} | {
|
|
8
|
+
kind: "turn";
|
|
9
|
+
sessionId: string;
|
|
10
|
+
turnId: string;
|
|
11
|
+
} | {
|
|
12
|
+
kind: "none";
|
|
13
|
+
};
|
|
14
|
+
export declare function directPersonalConnectionSubjectId(turn: Pick<SessionTurn, "source" | "initiator" | "initiatorContext">): string | undefined;
|
|
15
|
+
export declare function personalConnectionDelegationSourceForGrant(grant: AccessGrant): PersonalConnectionDelegationSource;
|
|
16
|
+
export declare function selectedPersonalConnectionServers(settings: Pick<Settings, "mcpServers">, tools: ToolRef[]): McpServerConfig[];
|
|
17
|
+
export declare function personalConnectionDelegationsFromVisibleConnections(input: {
|
|
18
|
+
servers: McpServerConfig[];
|
|
19
|
+
subjectId: string;
|
|
20
|
+
connections: ConnectionMetadata[];
|
|
21
|
+
}): McpPersonalConnectionDelegation[];
|
|
22
|
+
export declare function personalConnectionDelegationsFromParent(input: {
|
|
23
|
+
servers: McpServerConfig[];
|
|
24
|
+
parentDelegations: McpPersonalConnectionDelegation[];
|
|
25
|
+
}): McpPersonalConnectionDelegation[];
|
|
26
|
+
export declare function personalConnectionDelegationsEqual(left: McpPersonalConnectionDelegation[], right: McpPersonalConnectionDelegation[]): boolean;
|
|
27
|
+
export declare function personalConnectionDelegationForServer(delegations: McpPersonalConnectionDelegation[], server: Pick<McpServerConfig, "id" | "connectionRef">): McpPersonalConnectionDelegation | null;
|
|
28
|
+
type ConnectionCredentialResolver = (request: ResolveConnectionCredentialInput) => Promise<ResolveConnectionCredentialResult>;
|
|
29
|
+
/**
|
|
30
|
+
* Resolves subject-owned MCP credentials only through the exact authority
|
|
31
|
+
* frozen on the causal turn. A direct human subject, worker Toolspace caller,
|
|
32
|
+
* retry, or recovery can identify the caller, but none may widen or replace
|
|
33
|
+
* the persisted connection UUID.
|
|
34
|
+
*/
|
|
35
|
+
export declare function withFrozenPersonalConnectionDelegations(input: {
|
|
36
|
+
resolveCredential: ConnectionCredentialResolver;
|
|
37
|
+
settings: Pick<Settings, "mcpServers">;
|
|
38
|
+
personalConnectionDelegations: McpPersonalConnectionDelegation[];
|
|
39
|
+
ownerHasWorkspaceMembership: (subjectId: string) => Promise<boolean>;
|
|
40
|
+
}): ConnectionCredentialResolver;
|
|
41
|
+
export declare function freezePersonalConnectionDelegations(input: {
|
|
42
|
+
db: Database;
|
|
43
|
+
workspaceId: string;
|
|
44
|
+
settings: Pick<Settings, "mcpServers">;
|
|
45
|
+
tools: ToolRef[];
|
|
46
|
+
source: PersonalConnectionDelegationSource;
|
|
47
|
+
}): Promise<McpPersonalConnectionDelegation[]>;
|
|
48
|
+
export {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Settings } from "@opengeni/config";
|
|
2
|
-
import type { AccessGrant, ScheduledTask, CreateScheduledTaskRequest as CreateScheduledTaskPayload, UpdateScheduledTaskRequest as UpdateScheduledTaskPayload } from "@opengeni/contracts";
|
|
2
|
+
import type { AccessGrant, McpPersonalConnectionDelegation, ScheduledTask, CreateScheduledTaskRequest as CreateScheduledTaskPayload, UpdateScheduledTaskRequest as UpdateScheduledTaskPayload } from "@opengeni/contracts";
|
|
3
3
|
import { type Database, type UpdateScheduledTaskInput } from "@opengeni/db";
|
|
4
4
|
import type { SessionWorkflowClient } from "../dependencies";
|
|
5
5
|
import type { ObjectStorageDependency } from "../dependencies";
|
|
@@ -32,7 +32,12 @@ export declare function validatedScheduledTaskUpdate(input: {
|
|
|
32
32
|
toolsProvided?: boolean;
|
|
33
33
|
}): Promise<UpdateScheduledTaskInput>;
|
|
34
34
|
export declare function requireScheduledTaskForApi(db: Database, workspaceId: string, taskId: string): Promise<ScheduledTask>;
|
|
35
|
-
export
|
|
35
|
+
export type ScheduledTaskRestoreState = {
|
|
36
|
+
task: ScheduledTask;
|
|
37
|
+
personalConnectionDelegations: McpPersonalConnectionDelegation[];
|
|
38
|
+
};
|
|
39
|
+
export declare function captureScheduledTaskRestoreState(db: Database, task: ScheduledTask): Promise<ScheduledTaskRestoreState>;
|
|
40
|
+
export declare function restoreScheduledTask(db: Database, previous: ScheduledTaskRestoreState): Promise<ScheduledTask>;
|
|
36
41
|
export declare function syncCreatedScheduledTask(input: {
|
|
37
42
|
db: Database;
|
|
38
43
|
workflowClient: SessionWorkflowClient;
|
|
@@ -41,7 +46,7 @@ export declare function syncCreatedScheduledTask(input: {
|
|
|
41
46
|
export declare function syncUpdatedScheduledTask(input: {
|
|
42
47
|
db: Database;
|
|
43
48
|
workflowClient: SessionWorkflowClient;
|
|
44
|
-
previous:
|
|
49
|
+
previous: ScheduledTaskRestoreState;
|
|
45
50
|
task: ScheduledTask;
|
|
46
51
|
}): Promise<void>;
|
|
47
52
|
export declare function scheduledTaskTemporalScheduleId(taskId: string): string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Settings } from "@opengeni/config";
|
|
2
|
-
import { SessionSpawnDenial, type AccessGrant, type CreateSessionResponse, type GoalSpec, type FirstPartyMcpToolName, type Permission, type ReasoningEffort, type ResourceRef, type Session, type SessionSkill, type SessionEvent, SessionMcpApprovalPolicy, type SessionMcpCredentialUpdateInput, type SessionMcpServerMetadata, type UpdateSessionMcpApprovalPolicyResponse, type UpdateSessionToolPolicyRequest, type SessionAuthorizationPort, type SessionToolPolicy, type SessionTurn, type ToolRef, type TurnInitiator, type TurnInitiatorContext, type TurnExecutionPolicyV1 } from "@opengeni/contracts";
|
|
2
|
+
import { SessionSpawnDenial, type AccessGrant, type CreateSessionResponse, type GoalSpec, type FirstPartyMcpToolName, type McpPersonalConnectionDelegation, type Permission, type ReasoningEffort, type ResourceRef, type Session, type SessionSkill, type SessionEvent, SessionMcpApprovalPolicy, type SessionMcpCredentialUpdateInput, type SessionMcpServerMetadata, type UpdateSessionMcpApprovalPolicyResponse, type UpdateSessionToolPolicyRequest, type SessionAuthorizationPort, type SessionToolPolicy, type SessionTurn, type ToolRef, type TurnInitiator, type TurnInitiatorContext, type TurnExecutionPolicyV1 } from "@opengeni/contracts";
|
|
3
3
|
import { type CreateSessionMcpServerInput, type Database, type UpdateSessionMcpServerCredentialsInput, type SessionCommandActor } from "@opengeni/db";
|
|
4
4
|
import { type EventBus } from "@opengeni/events";
|
|
5
5
|
import type { AcceptSessionUserMessageDependencies, ApiRouteDeps, SessionWorkflowClient } from "../dependencies";
|
|
@@ -40,6 +40,14 @@ export declare function sessionSpawnDenialEnvelope(error: SessionSpawnDeniedErro
|
|
|
40
40
|
};
|
|
41
41
|
};
|
|
42
42
|
};
|
|
43
|
+
export type FrozenCreationInitiator = {
|
|
44
|
+
initiator?: TurnInitiator;
|
|
45
|
+
context?: TurnInitiatorContext;
|
|
46
|
+
actor?: Extract<SessionCommandActor, {
|
|
47
|
+
type: "agent_attempt";
|
|
48
|
+
}>;
|
|
49
|
+
};
|
|
50
|
+
export declare function creationInitiatorForGrant(grant: AccessGrant): FrozenCreationInitiator;
|
|
43
51
|
export declare function settingsWithSessionMcpServerMetadata(settings: Settings, servers: SessionMcpServerMetadata[]): Settings;
|
|
44
52
|
export declare function createAndStartSession(input: {
|
|
45
53
|
requestedSessionId?: string;
|
|
@@ -79,6 +87,7 @@ export declare function createAndStartSession(input: {
|
|
|
79
87
|
firstPartyMcpTools: FirstPartyMcpToolName[];
|
|
80
88
|
mcpServers?: CreateSessionMcpServerInput[];
|
|
81
89
|
sessionMcpServers?: SessionMcpServerMetadata[];
|
|
90
|
+
personalConnectionDelegations?: McpPersonalConnectionDelegation[];
|
|
82
91
|
parentSessionId?: string | null;
|
|
83
92
|
createIdempotencyKey?: string | null;
|
|
84
93
|
sandboxGroupId?: string | null;
|
|
@@ -165,6 +174,7 @@ export declare function postUserMessageTurn(input: {
|
|
|
165
174
|
latencyMode?: "standard" | "priority" | "fast" | null;
|
|
166
175
|
clientEventId?: string;
|
|
167
176
|
mcpCredentialUpdates?: UpdateSessionMcpServerCredentialsInput[];
|
|
177
|
+
personalConnectionDelegations?: McpPersonalConnectionDelegation[];
|
|
168
178
|
delivery?: "send" | "steer";
|
|
169
179
|
origin?: "human" | "operator";
|
|
170
180
|
actor?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export * from "./domain/capabilities";
|
|
|
12
12
|
export * from "./domain/environments";
|
|
13
13
|
export * from "./rigs";
|
|
14
14
|
export * from "./domain/packs";
|
|
15
|
+
export * from "./domain/personal-connection-delegations";
|
|
15
16
|
export * from "./domain/resources";
|
|
16
17
|
export * from "./domain/session-tool-policy";
|
|
17
18
|
export * from "./domain/scheduled-tasks";
|
package/dist/index.js
CHANGED
|
@@ -354,6 +354,7 @@ function wrapChannelABoxWithRouting(services, ids, established) {
|
|
|
354
354
|
return pointer ?? { activeSandboxId: null, activeEpoch: 0 };
|
|
355
355
|
},
|
|
356
356
|
resolveActiveBackend: resolver,
|
|
357
|
+
...services.onSandboxOperation ? { onOperation: services.onSandboxOperation } : {},
|
|
357
358
|
...beforeMutation ? { beforeMutation } : {},
|
|
358
359
|
...afterMutation ? { afterMutation } : {},
|
|
359
360
|
...beforeProcessMutation ? { beforeProcessMutation } : {},
|
|
@@ -3150,6 +3151,158 @@ async function listRigChangesForApi(deps, workspaceId, rigId, limit) {
|
|
|
3150
3151
|
return await listRigChanges(deps.db, workspaceId, rigId, limit);
|
|
3151
3152
|
}
|
|
3152
3153
|
|
|
3154
|
+
// src/domain/personal-connection-delegations.ts
|
|
3155
|
+
import {
|
|
3156
|
+
getSessionTurnPersonalConnectionDelegations,
|
|
3157
|
+
getWorkspaceGrant as getWorkspaceGrant2,
|
|
3158
|
+
listConnectionsMetadata as listConnectionsMetadata2
|
|
3159
|
+
} from "@opengeni/db";
|
|
3160
|
+
function directPersonalConnectionSubjectId(turn) {
|
|
3161
|
+
if (turn.source !== "user" && turn.source !== "api" || turn.initiator.kind !== "subject") {
|
|
3162
|
+
return void 0;
|
|
3163
|
+
}
|
|
3164
|
+
return ["via", "viaTruncated", "provenanceError", "backfill"].some(
|
|
3165
|
+
(key) => Object.prototype.hasOwnProperty.call(turn.initiatorContext, key)
|
|
3166
|
+
) ? void 0 : turn.initiator.subjectId;
|
|
3167
|
+
}
|
|
3168
|
+
function personalConnectionDelegationSourceForGrant(grant) {
|
|
3169
|
+
const callerSessionId = grant.metadata?.["sessionId"];
|
|
3170
|
+
const callerTurnId = grant.metadata?.["turnId"];
|
|
3171
|
+
if (typeof callerSessionId === "string" && typeof callerTurnId === "string") {
|
|
3172
|
+
return { kind: "turn", sessionId: callerSessionId, turnId: callerTurnId };
|
|
3173
|
+
}
|
|
3174
|
+
if (grant.principalKind === "agent_attempt" || grant.principalKind === "service" || grant.serviceInitiator) {
|
|
3175
|
+
return { kind: "none" };
|
|
3176
|
+
}
|
|
3177
|
+
return { kind: "subject", subjectId: grant.subjectId };
|
|
3178
|
+
}
|
|
3179
|
+
function selectedPersonalConnectionServers(settings, tools) {
|
|
3180
|
+
const selected = new Set(tools.map((tool) => tool.id));
|
|
3181
|
+
return settings.mcpServers.filter(
|
|
3182
|
+
(server) => selected.has(server.id) && server.connectionRef?.subjectScope === "subject"
|
|
3183
|
+
);
|
|
3184
|
+
}
|
|
3185
|
+
function canonicalPersonalConnections(connections) {
|
|
3186
|
+
return [...connections].sort((left, right) => {
|
|
3187
|
+
const active = Number(right.status === "active") - Number(left.status === "active");
|
|
3188
|
+
if (active !== 0) return active;
|
|
3189
|
+
const updated = Date.parse(right.updatedAt) - Date.parse(left.updatedAt);
|
|
3190
|
+
if (updated !== 0) return updated;
|
|
3191
|
+
const created = Date.parse(right.createdAt) - Date.parse(left.createdAt);
|
|
3192
|
+
if (created !== 0) return created;
|
|
3193
|
+
return right.id.localeCompare(left.id);
|
|
3194
|
+
});
|
|
3195
|
+
}
|
|
3196
|
+
function sameProviderDomain(left, right) {
|
|
3197
|
+
return left.toLowerCase() === right.toLowerCase();
|
|
3198
|
+
}
|
|
3199
|
+
function personalConnectionDelegationsFromVisibleConnections(input) {
|
|
3200
|
+
const delegations = [];
|
|
3201
|
+
const connections = canonicalPersonalConnections(input.connections);
|
|
3202
|
+
for (const server of input.servers) {
|
|
3203
|
+
const ref = server.connectionRef;
|
|
3204
|
+
if (!ref || ref.subjectScope !== "subject") continue;
|
|
3205
|
+
const connection = connections.find(
|
|
3206
|
+
(candidate) => candidate.subjectId === input.subjectId && candidate.status === "active" && sameProviderDomain(candidate.providerDomain, ref.providerDomain) && (!ref.kind || candidate.kind === ref.kind) && (!ref.connectionId || candidate.id === ref.connectionId)
|
|
3207
|
+
);
|
|
3208
|
+
if (!connection) continue;
|
|
3209
|
+
delegations.push({
|
|
3210
|
+
serverId: server.id,
|
|
3211
|
+
connectionId: connection.id,
|
|
3212
|
+
ownerSubjectId: input.subjectId,
|
|
3213
|
+
providerDomain: connection.providerDomain,
|
|
3214
|
+
kind: connection.kind
|
|
3215
|
+
});
|
|
3216
|
+
}
|
|
3217
|
+
return delegations;
|
|
3218
|
+
}
|
|
3219
|
+
function personalConnectionDelegationsFromParent(input) {
|
|
3220
|
+
return input.servers.flatMap((server) => {
|
|
3221
|
+
const ref = server.connectionRef;
|
|
3222
|
+
if (!ref || ref.subjectScope !== "subject") return [];
|
|
3223
|
+
const delegation = input.parentDelegations.find(
|
|
3224
|
+
(candidate) => candidate.serverId === server.id && sameProviderDomain(candidate.providerDomain, ref.providerDomain) && (!ref.kind || !candidate.kind || candidate.kind === ref.kind)
|
|
3225
|
+
);
|
|
3226
|
+
return delegation ? [{ ...delegation }] : [];
|
|
3227
|
+
});
|
|
3228
|
+
}
|
|
3229
|
+
function personalConnectionDelegationsEqual(left, right) {
|
|
3230
|
+
if (left.length !== right.length) return false;
|
|
3231
|
+
const byServer = new Map(right.map((delegation) => [delegation.serverId, delegation]));
|
|
3232
|
+
return left.every((delegation) => {
|
|
3233
|
+
const other = byServer.get(delegation.serverId);
|
|
3234
|
+
return other?.connectionId === delegation.connectionId && other.ownerSubjectId === delegation.ownerSubjectId && sameProviderDomain(other.providerDomain, delegation.providerDomain) && other.kind === delegation.kind;
|
|
3235
|
+
});
|
|
3236
|
+
}
|
|
3237
|
+
function personalConnectionDelegationForServer(delegations, server) {
|
|
3238
|
+
const ref = server.connectionRef;
|
|
3239
|
+
if (!ref || ref.subjectScope !== "subject") return null;
|
|
3240
|
+
return delegations.find(
|
|
3241
|
+
(delegation) => delegation.serverId === server.id && sameProviderDomain(delegation.providerDomain, ref.providerDomain) && (!ref.kind || !delegation.kind || delegation.kind === ref.kind)
|
|
3242
|
+
) ?? null;
|
|
3243
|
+
}
|
|
3244
|
+
function personalAuthorityUnavailable(request) {
|
|
3245
|
+
const ref = request.connectionRef;
|
|
3246
|
+
return {
|
|
3247
|
+
status: "auth_needed",
|
|
3248
|
+
reason: "personal_authority_unavailable",
|
|
3249
|
+
providerDomain: ref.providerDomain,
|
|
3250
|
+
...ref.provider ? { provider: ref.provider } : {},
|
|
3251
|
+
...ref.scopes ? { scopes: ref.scopes } : {},
|
|
3252
|
+
...ref.resource ? { resource: ref.resource } : {},
|
|
3253
|
+
...ref.selectedResources ? { selectedResources: ref.selectedResources } : {}
|
|
3254
|
+
};
|
|
3255
|
+
}
|
|
3256
|
+
function withFrozenPersonalConnectionDelegations(input) {
|
|
3257
|
+
return async (request) => {
|
|
3258
|
+
let effectiveRequest = request;
|
|
3259
|
+
if (request.connectionRef.subjectScope === "subject") {
|
|
3260
|
+
const config = input.settings.mcpServers.find((server) => server.id === request.serverId);
|
|
3261
|
+
const delegation = config ? personalConnectionDelegationForServer(input.personalConnectionDelegations, config) : null;
|
|
3262
|
+
if (!delegation || !await input.ownerHasWorkspaceMembership(delegation.ownerSubjectId)) {
|
|
3263
|
+
return personalAuthorityUnavailable(request);
|
|
3264
|
+
}
|
|
3265
|
+
effectiveRequest = {
|
|
3266
|
+
...request,
|
|
3267
|
+
subjectId: delegation.ownerSubjectId,
|
|
3268
|
+
connectionRef: {
|
|
3269
|
+
...request.connectionRef,
|
|
3270
|
+
providerDomain: delegation.providerDomain,
|
|
3271
|
+
connectionId: delegation.connectionId,
|
|
3272
|
+
...delegation.kind ? { kind: delegation.kind } : {}
|
|
3273
|
+
}
|
|
3274
|
+
};
|
|
3275
|
+
}
|
|
3276
|
+
const result = await input.resolveCredential(effectiveRequest);
|
|
3277
|
+
if (result.status === "ok" || request.connectionRef.subjectScope !== "subject") {
|
|
3278
|
+
return result;
|
|
3279
|
+
}
|
|
3280
|
+
return personalAuthorityUnavailable(request);
|
|
3281
|
+
};
|
|
3282
|
+
}
|
|
3283
|
+
async function freezePersonalConnectionDelegations(input) {
|
|
3284
|
+
const servers = selectedPersonalConnectionServers(input.settings, input.tools);
|
|
3285
|
+
if (servers.length === 0 || input.source.kind === "none") return [];
|
|
3286
|
+
if (input.source.kind === "turn") {
|
|
3287
|
+
return personalConnectionDelegationsFromParent({
|
|
3288
|
+
servers,
|
|
3289
|
+
parentDelegations: await getSessionTurnPersonalConnectionDelegations(
|
|
3290
|
+
input.db,
|
|
3291
|
+
input.workspaceId,
|
|
3292
|
+
input.source.sessionId,
|
|
3293
|
+
input.source.turnId
|
|
3294
|
+
)
|
|
3295
|
+
});
|
|
3296
|
+
}
|
|
3297
|
+
const membership = await getWorkspaceGrant2(input.db, input.source.subjectId, input.workspaceId);
|
|
3298
|
+
if (!membership) return [];
|
|
3299
|
+
return personalConnectionDelegationsFromVisibleConnections({
|
|
3300
|
+
servers,
|
|
3301
|
+
subjectId: input.source.subjectId,
|
|
3302
|
+
connections: await listConnectionsMetadata2(input.db, input.workspaceId, input.source.subjectId)
|
|
3303
|
+
});
|
|
3304
|
+
}
|
|
3305
|
+
|
|
3153
3306
|
// src/domain/resources.ts
|
|
3154
3307
|
import {
|
|
3155
3308
|
gitCredentialBindingIdForRepository,
|
|
@@ -3551,6 +3704,7 @@ import {
|
|
|
3551
3704
|
getNestedAgentDepthDeploymentPolicy,
|
|
3552
3705
|
getRig as getRig3,
|
|
3553
3706
|
getScheduledTask,
|
|
3707
|
+
getScheduledTaskPersonalConnectionDelegations,
|
|
3554
3708
|
requireWorkspace as requireWorkspace2,
|
|
3555
3709
|
updateScheduledTask
|
|
3556
3710
|
} from "@opengeni/db";
|
|
@@ -4008,6 +4162,7 @@ async function createAndStartSession(input) {
|
|
|
4008
4162
|
sandboxGroupId: input.sandboxGroupId ?? null,
|
|
4009
4163
|
...input.sandboxOs ? { sandboxOs: input.sandboxOs } : {},
|
|
4010
4164
|
mcpServers: input.mcpServers ?? [],
|
|
4165
|
+
personalConnectionDelegations: input.personalConnectionDelegations ?? [],
|
|
4011
4166
|
maxNestedAgentDepthOverride: input.maxNestedAgentDepthOverride ?? null,
|
|
4012
4167
|
allowNestedAgentDepthIncrease: input.allowNestedAgentDepthIncrease ?? false,
|
|
4013
4168
|
subjectId: input.subjectId ?? null
|
|
@@ -4052,6 +4207,7 @@ async function createAndStartSession(input) {
|
|
|
4052
4207
|
sandboxGroupId: input.sandboxGroupId ?? null,
|
|
4053
4208
|
...input.sandboxOs ? { sandboxOs: input.sandboxOs } : {},
|
|
4054
4209
|
mcpServers: input.mcpServers ?? [],
|
|
4210
|
+
personalConnectionDelegations: input.personalConnectionDelegations ?? [],
|
|
4055
4211
|
maxNestedAgentDepthOverride: input.maxNestedAgentDepthOverride ?? null,
|
|
4056
4212
|
allowNestedAgentDepthIncrease: input.allowNestedAgentDepthIncrease ?? false,
|
|
4057
4213
|
subjectId: input.subjectId ?? null
|
|
@@ -4250,6 +4406,7 @@ async function postUserMessageTurn(input) {
|
|
|
4250
4406
|
reasoningEffortFallback: input.reasoningEffortFallback ?? settings.openaiReasoningEffort,
|
|
4251
4407
|
turnExecutionPolicy: input.turnExecutionPolicy,
|
|
4252
4408
|
source: input.origin === "operator" ? "api" : "user",
|
|
4409
|
+
personalConnectionDelegations: input.personalConnectionDelegations ?? [],
|
|
4253
4410
|
mcpCredentialUpdates: input.mcpCredentialUpdates ?? []
|
|
4254
4411
|
})
|
|
4255
4412
|
)
|
|
@@ -4404,6 +4561,13 @@ async function createSessionForRequest(deps, grant, workspaceId, rawPayload) {
|
|
|
4404
4561
|
toolPolicy = { mode: "workspace_default", inheritedFromSessionId: null };
|
|
4405
4562
|
}
|
|
4406
4563
|
const tools = withFirstPartyTools(selectedTools, runtimeSettings);
|
|
4564
|
+
const personalConnectionDelegations = await freezePersonalConnectionDelegations({
|
|
4565
|
+
db,
|
|
4566
|
+
workspaceId,
|
|
4567
|
+
settings: runtimeSettings,
|
|
4568
|
+
tools,
|
|
4569
|
+
source: personalConnectionDelegationSourceForGrant(grant)
|
|
4570
|
+
});
|
|
4407
4571
|
await validateGitHubRepositorySelection(db, workspaceId, resources);
|
|
4408
4572
|
if (resources.some((resource) => resource.kind === "file") && !objectStorage) {
|
|
4409
4573
|
throw new HTTPException10(503, { message: "object storage is not configured" });
|
|
@@ -4639,6 +4803,7 @@ async function createSessionForRequest(deps, grant, workspaceId, rawPayload) {
|
|
|
4639
4803
|
firstPartyMcpTools,
|
|
4640
4804
|
mcpServers: sessionMcpServers.dbServers,
|
|
4641
4805
|
sessionMcpServers: sessionMcpServers.metadata,
|
|
4806
|
+
personalConnectionDelegations,
|
|
4642
4807
|
parentSessionId,
|
|
4643
4808
|
createIdempotencyKey: payload.idempotencyKey ?? null,
|
|
4644
4809
|
maxNestedAgentDepthOverride: payload.maxNestedAgentDepth ?? null,
|
|
@@ -4741,6 +4906,14 @@ async function acceptSessionUserMessage(deps, grant, workspaceId, sessionId, inp
|
|
|
4741
4906
|
session: existingSession,
|
|
4742
4907
|
updates: input.mcpCredentialUpdates ?? []
|
|
4743
4908
|
});
|
|
4909
|
+
const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(db, workspaceId, settings);
|
|
4910
|
+
const personalConnectionDelegations = await freezePersonalConnectionDelegations({
|
|
4911
|
+
db,
|
|
4912
|
+
workspaceId,
|
|
4913
|
+
settings: runtimeSettings,
|
|
4914
|
+
tools: existingSession.tools,
|
|
4915
|
+
source: personalConnectionDelegationSourceForGrant(grant)
|
|
4916
|
+
});
|
|
4744
4917
|
const delegatedServiceInitiator = serviceInitiatorForGrant(grant);
|
|
4745
4918
|
const { accepted, turn } = await postUserMessageTurn({
|
|
4746
4919
|
db,
|
|
@@ -4759,6 +4932,7 @@ async function acceptSessionUserMessage(deps, grant, workspaceId, sessionId, inp
|
|
|
4759
4932
|
reasoningEffortFallback: sessionReasoningEffort,
|
|
4760
4933
|
turnExecutionPolicy,
|
|
4761
4934
|
mcpCredentialUpdates,
|
|
4935
|
+
personalConnectionDelegations,
|
|
4762
4936
|
delivery: input.delivery ?? "send",
|
|
4763
4937
|
origin: delegatedServiceInitiator ? "operator" : input.origin ?? "human",
|
|
4764
4938
|
actor: grant.subjectId,
|
|
@@ -5100,6 +5274,19 @@ async function createValidatedScheduledTask(input) {
|
|
|
5100
5274
|
if (input.payload.rigId) {
|
|
5101
5275
|
await requireScheduledTaskRig(input.db, input.grant.workspaceId, input.payload.rigId);
|
|
5102
5276
|
}
|
|
5277
|
+
const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(
|
|
5278
|
+
input.db,
|
|
5279
|
+
input.grant.workspaceId,
|
|
5280
|
+
input.settings
|
|
5281
|
+
);
|
|
5282
|
+
const personalConnectionDelegations = await freezePersonalConnectionDelegations({
|
|
5283
|
+
db: input.db,
|
|
5284
|
+
workspaceId: input.grant.workspaceId,
|
|
5285
|
+
settings: runtimeSettings,
|
|
5286
|
+
tools: agentConfig.tools,
|
|
5287
|
+
source: personalConnectionDelegationSourceForGrant(input.grant)
|
|
5288
|
+
});
|
|
5289
|
+
const creationInitiator = creationInitiatorForGrant(input.grant);
|
|
5103
5290
|
return await createScheduledTask(input.db, {
|
|
5104
5291
|
id,
|
|
5105
5292
|
accountId: input.grant.accountId,
|
|
@@ -5111,6 +5298,10 @@ async function createValidatedScheduledTask(input) {
|
|
|
5111
5298
|
runMode: input.payload.runMode,
|
|
5112
5299
|
overlapPolicy: input.payload.overlapPolicy,
|
|
5113
5300
|
agentConfig,
|
|
5301
|
+
...creationInitiator.initiator ? { createdBy: creationInitiator.initiator } : {},
|
|
5302
|
+
...creationInitiator.context ? { createdByContext: creationInitiator.context } : {},
|
|
5303
|
+
createdByActor: creationInitiator.actor ?? null,
|
|
5304
|
+
personalConnectionDelegations,
|
|
5114
5305
|
variableSetId: input.payload.variableSetId ?? null,
|
|
5115
5306
|
rigId: input.payload.rigId ?? null,
|
|
5116
5307
|
metadata: input.payload.metadata
|
|
@@ -5191,6 +5382,31 @@ async function validatedScheduledTaskUpdate(input) {
|
|
|
5191
5382
|
});
|
|
5192
5383
|
}
|
|
5193
5384
|
update.agentConfig = nextAgentConfig;
|
|
5385
|
+
const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(
|
|
5386
|
+
input.db,
|
|
5387
|
+
input.existing.workspaceId,
|
|
5388
|
+
input.settings
|
|
5389
|
+
);
|
|
5390
|
+
const personalConnectionDelegations = await freezePersonalConnectionDelegations({
|
|
5391
|
+
db: input.db,
|
|
5392
|
+
workspaceId: input.existing.workspaceId,
|
|
5393
|
+
settings: runtimeSettings,
|
|
5394
|
+
tools: nextAgentConfig.tools,
|
|
5395
|
+
source: personalConnectionDelegationSourceForGrant(input.grant)
|
|
5396
|
+
});
|
|
5397
|
+
if (input.existing.reusableSessionId && input.existing.runMode === "reusable_session") {
|
|
5398
|
+
const existingDelegations = await getScheduledTaskPersonalConnectionDelegations(
|
|
5399
|
+
input.db,
|
|
5400
|
+
input.existing.workspaceId,
|
|
5401
|
+
input.existing.id
|
|
5402
|
+
);
|
|
5403
|
+
if (!personalConnectionDelegationsEqual(existingDelegations, personalConnectionDelegations)) {
|
|
5404
|
+
throw new HTTPException11(409, {
|
|
5405
|
+
message: "cannot change personal MCP connections of a task with a live reusable session; recreate the task"
|
|
5406
|
+
});
|
|
5407
|
+
}
|
|
5408
|
+
}
|
|
5409
|
+
update.personalConnectionDelegations = personalConnectionDelegations;
|
|
5194
5410
|
}
|
|
5195
5411
|
return update;
|
|
5196
5412
|
}
|
|
@@ -5201,7 +5417,18 @@ async function requireScheduledTaskForApi(db, workspaceId, taskId) {
|
|
|
5201
5417
|
}
|
|
5202
5418
|
return task;
|
|
5203
5419
|
}
|
|
5204
|
-
async function
|
|
5420
|
+
async function captureScheduledTaskRestoreState(db, task) {
|
|
5421
|
+
return {
|
|
5422
|
+
task,
|
|
5423
|
+
personalConnectionDelegations: await getScheduledTaskPersonalConnectionDelegations(
|
|
5424
|
+
db,
|
|
5425
|
+
task.workspaceId,
|
|
5426
|
+
task.id
|
|
5427
|
+
)
|
|
5428
|
+
};
|
|
5429
|
+
}
|
|
5430
|
+
async function restoreScheduledTask(db, previous) {
|
|
5431
|
+
const { task } = previous;
|
|
5205
5432
|
return await updateScheduledTask(db, task.workspaceId, task.id, {
|
|
5206
5433
|
name: task.name,
|
|
5207
5434
|
status: task.status,
|
|
@@ -5209,8 +5436,10 @@ async function restoreScheduledTask(db, task) {
|
|
|
5209
5436
|
runMode: task.runMode,
|
|
5210
5437
|
overlapPolicy: task.overlapPolicy,
|
|
5211
5438
|
agentConfig: task.agentConfig,
|
|
5439
|
+
personalConnectionDelegations: previous.personalConnectionDelegations,
|
|
5212
5440
|
reusableSessionId: task.reusableSessionId,
|
|
5213
5441
|
variableSetId: task.variableSetId,
|
|
5442
|
+
rigId: task.rigId,
|
|
5214
5443
|
metadata: task.metadata
|
|
5215
5444
|
});
|
|
5216
5445
|
}
|
|
@@ -6483,6 +6712,7 @@ export {
|
|
|
6483
6712
|
buildFleetContextForSession,
|
|
6484
6713
|
buildMarketingDailyAnalysisAgentConfig,
|
|
6485
6714
|
canonicalConfiguredModel,
|
|
6715
|
+
captureScheduledTaskRestoreState,
|
|
6486
6716
|
checkLimit,
|
|
6487
6717
|
classifyRigVerificationOutcome,
|
|
6488
6718
|
controlAgentSessionWorkstream,
|
|
@@ -6494,9 +6724,11 @@ export {
|
|
|
6494
6724
|
createRigVersionForApi,
|
|
6495
6725
|
createSessionForRequest,
|
|
6496
6726
|
createValidatedScheduledTask,
|
|
6727
|
+
creationInitiatorForGrant,
|
|
6497
6728
|
defaultSessionMcpServerIds,
|
|
6498
6729
|
deleteHumanQueuePrompt,
|
|
6499
6730
|
deleteRigForApi,
|
|
6731
|
+
directPersonalConnectionSubjectId,
|
|
6500
6732
|
disableCapability,
|
|
6501
6733
|
discoverMcpRegistryCapabilities,
|
|
6502
6734
|
editHumanQueuePrompt,
|
|
@@ -6504,6 +6736,7 @@ export {
|
|
|
6504
6736
|
enabledCapabilityMcpToolRefs,
|
|
6505
6737
|
executeRunOnSelfhostedMachine,
|
|
6506
6738
|
filenameForMimeType,
|
|
6739
|
+
freezePersonalConnectionDelegations,
|
|
6507
6740
|
getActorNewSessionDraft,
|
|
6508
6741
|
getCapabilityPack,
|
|
6509
6742
|
getHumanComposerDraft,
|
|
@@ -6533,6 +6766,11 @@ export {
|
|
|
6533
6766
|
normalizeResources,
|
|
6534
6767
|
officialMcpRegistryUrl,
|
|
6535
6768
|
openGeniSlackBotMetadata,
|
|
6769
|
+
personalConnectionDelegationForServer,
|
|
6770
|
+
personalConnectionDelegationSourceForGrant,
|
|
6771
|
+
personalConnectionDelegationsEqual,
|
|
6772
|
+
personalConnectionDelegationsFromParent,
|
|
6773
|
+
personalConnectionDelegationsFromVisibleConnections,
|
|
6536
6774
|
postUserMessageTurn,
|
|
6537
6775
|
promoteSetupAppendChange,
|
|
6538
6776
|
promoteVerifiedDefinitionEditChangeForApi,
|
|
@@ -6574,6 +6812,7 @@ export {
|
|
|
6574
6812
|
scheduledTaskTemporalScheduleId,
|
|
6575
6813
|
scheduledTaskToolsProvided,
|
|
6576
6814
|
scheduledTaskTriggerToken,
|
|
6815
|
+
selectedPersonalConnectionServers,
|
|
6577
6816
|
sendAgentSessionMessage,
|
|
6578
6817
|
sessionSpawnDenialEnvelope,
|
|
6579
6818
|
sessionWithEffectiveToolPolicy,
|
|
@@ -6603,6 +6842,7 @@ export {
|
|
|
6603
6842
|
validateVariableSetAttachment,
|
|
6604
6843
|
validatedScheduledTaskUpdate,
|
|
6605
6844
|
withDefaultEnabledCapabilityMcpTools,
|
|
6845
|
+
withFrozenPersonalConnectionDelegations,
|
|
6606
6846
|
workflowIdForSession,
|
|
6607
6847
|
workspaceSessionToolPolicyDefaultServerIds,
|
|
6608
6848
|
workspaceSessionToolPolicyServerIds,
|