@opengeni/core 2.5.3 → 2.6.4-canary.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access/index.d.ts +24 -0
- package/dist/billing/limits.d.ts +5 -0
- package/dist/canonical-human-identities.js +2 -2
- package/dist/{chunk-ZVZJTMSV.js → chunk-OF65T3PM.js} +2 -2
- package/dist/{chunk-YGOMUGYS.js → chunk-QO5GVFFO.js} +17 -8
- package/dist/{chunk-YGOMUGYS.js.map → chunk-QO5GVFFO.js.map} +1 -1
- package/dist/dependencies.d.ts +10 -1
- package/dist/domain/company-brain-governed-writes.d.ts +15 -6
- package/dist/domain/company-profile-agent-admin.d.ts +3 -2
- package/dist/domain/environments.d.ts +1 -1
- package/dist/domain/memory-slack-delivery.d.ts +4 -1
- package/dist/domain/personal-connection-delegations.d.ts +1 -0
- package/dist/domain/pr-review.d.ts +1 -1
- package/dist/domain/scheduled-tasks.d.ts +12 -0
- package/dist/domain/sessions.d.ts +37 -11
- package/dist/domain/workspace-members.d.ts +8 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1706 -667
- package/dist/index.js.map +1 -1
- package/dist/managed-auth-session-sets.d.ts +18 -0
- package/dist/managed-auth-session-sets.js +3 -1
- package/dist/model-catalog.d.ts +89 -0
- package/dist/sandbox/fleet.d.ts +6 -4
- package/dist/sandbox/routing.d.ts +7 -2
- package/dist/sandbox/runtime-settings.d.ts +17 -1
- package/package.json +10 -10
- package/src/access/index.ts +140 -5
- package/src/application/user-resource-grants.ts +31 -2
- package/src/billing/limits.ts +57 -24
- package/src/dependencies.ts +15 -1
- package/src/domain/company-brain-governed-writes.ts +29 -13
- package/src/domain/company-profile-agent-admin.ts +3 -2
- package/src/domain/environments.ts +6 -34
- package/src/domain/memory-slack-delivery.ts +30 -0
- package/src/domain/personal-connection-delegations.ts +40 -7
- package/src/domain/remember.ts +5 -6
- package/src/domain/scheduled-tasks.ts +146 -1
- package/src/domain/sessions.ts +912 -358
- package/src/domain/workspace-members.ts +34 -2
- package/src/index.ts +1 -0
- package/src/managed-auth-session-sets.ts +38 -11
- package/src/model-catalog.ts +565 -0
- package/src/sandbox/fleet.ts +20 -17
- package/src/sandbox/routing.ts +18 -4
- package/src/sandbox/runtime-settings.ts +32 -0
- /package/dist/{chunk-ZVZJTMSV.js.map → chunk-OF65T3PM.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -125,8 +125,8 @@ import {
|
|
|
125
125
|
markManagedAuthRequestActorTransitionApplied,
|
|
126
126
|
releaseManagedAuthRequestActorLease,
|
|
127
127
|
validateManagedAuthRequestActorLease
|
|
128
|
-
} from "./chunk-
|
|
129
|
-
import "./chunk-
|
|
128
|
+
} from "./chunk-OF65T3PM.js";
|
|
129
|
+
import "./chunk-QO5GVFFO.js";
|
|
130
130
|
|
|
131
131
|
// src/workflow-wake-contract.ts
|
|
132
132
|
var SESSION_WORKFLOW_WAKE_DISPATCHER_SCHEDULE_ID = "opengeni-session-workflow-wake-dispatcher";
|
|
@@ -208,6 +208,367 @@ function filenameForMimeType(mimeType) {
|
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
|
|
211
|
+
// src/model-catalog.ts
|
|
212
|
+
import {
|
|
213
|
+
applyModelCatalogDocument,
|
|
214
|
+
configuredGatewayWorkspaceProductModelIds,
|
|
215
|
+
configuredModels,
|
|
216
|
+
configuredModelNotes,
|
|
217
|
+
configuredOpenRouterWorkspaceProductModelIds,
|
|
218
|
+
configuredProviders,
|
|
219
|
+
validateModelCatalogSettings,
|
|
220
|
+
withCodexCatalogProvider,
|
|
221
|
+
withWorkspaceGatewayCatalogProvider,
|
|
222
|
+
withWorkspaceOpenRouterCatalogProvider,
|
|
223
|
+
withXaiSubscriptionCatalogProvider,
|
|
224
|
+
WORKSPACE_GATEWAY_MODEL_ID_PREFIX,
|
|
225
|
+
WORKSPACE_OPENROUTER_MODEL_ID_PREFIX,
|
|
226
|
+
WORKSPACE_OPENROUTER_PROVIDER_ID
|
|
227
|
+
} from "@opengeni/config";
|
|
228
|
+
import {
|
|
229
|
+
evaluateWorkspaceModelPolicy
|
|
230
|
+
} from "@opengeni/contracts";
|
|
231
|
+
import {
|
|
232
|
+
getDeploymentModelCatalog,
|
|
233
|
+
getWorkspaceGatewayCustomModelForExecution,
|
|
234
|
+
getWorkspaceOpenRouterCustomModelForExecution,
|
|
235
|
+
listWorkspaceGatewayCustomModels,
|
|
236
|
+
listWorkspaceOpenRouterCustomModels
|
|
237
|
+
} from "@opengeni/db";
|
|
238
|
+
function isWorkspaceGatewayCustomModelId(settings, modelId) {
|
|
239
|
+
return modelId.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX) && !configuredGatewayWorkspaceProductModelIds(settings).includes(modelId);
|
|
240
|
+
}
|
|
241
|
+
function isWorkspaceOpenRouterCustomModelId(settings, modelId) {
|
|
242
|
+
return modelId.startsWith(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX) && !configuredOpenRouterWorkspaceProductModelIds(settings).includes(modelId);
|
|
243
|
+
}
|
|
244
|
+
function workspaceCustomModelReference(settings, modelId) {
|
|
245
|
+
if (isWorkspaceGatewayCustomModelId(settings, modelId)) {
|
|
246
|
+
return {
|
|
247
|
+
providerKind: "vercel_gateway",
|
|
248
|
+
upstreamModelId: modelId.slice(WORKSPACE_GATEWAY_MODEL_ID_PREFIX.length)
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
if (isWorkspaceOpenRouterCustomModelId(settings, modelId)) {
|
|
252
|
+
return {
|
|
253
|
+
providerKind: "openrouter",
|
|
254
|
+
upstreamModelId: modelId.slice(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX.length)
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
return null;
|
|
258
|
+
}
|
|
259
|
+
function isWorkspaceCustomModelId(settings, modelId) {
|
|
260
|
+
return workspaceCustomModelReference(settings, modelId) !== null;
|
|
261
|
+
}
|
|
262
|
+
async function resolveCatalogSettings(db, envSettings) {
|
|
263
|
+
if (envSettings.modelCatalogSource === "code") {
|
|
264
|
+
validateModelCatalogSettings(envSettings);
|
|
265
|
+
return {
|
|
266
|
+
settings: envSettings,
|
|
267
|
+
source: "code",
|
|
268
|
+
version: null,
|
|
269
|
+
modelNotes: configuredModelNotes(envSettings)
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
const row = await getDeploymentModelCatalog(db);
|
|
273
|
+
if (!row) {
|
|
274
|
+
throw new Error("database model catalog source is configured but the singleton row is missing");
|
|
275
|
+
}
|
|
276
|
+
const settings = applyModelCatalogDocument(envSettings, row.document);
|
|
277
|
+
validateModelCatalogSettings(settings);
|
|
278
|
+
return {
|
|
279
|
+
settings,
|
|
280
|
+
source: "database",
|
|
281
|
+
version: row.version,
|
|
282
|
+
modelNotes: configuredModelNotes(settings)
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
async function resolveWorkspaceCatalogSettings(db, envSettings, input) {
|
|
286
|
+
const retainedProductModelIds = [
|
|
287
|
+
...input.retainedProductModelIds ?? [],
|
|
288
|
+
input.retainedProductModelId
|
|
289
|
+
];
|
|
290
|
+
const retainedGatewayUpstreamModelIds = retainedProductModelIds.flatMap(
|
|
291
|
+
(productModelId) => productModelId?.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX) ? [productModelId.slice(WORKSPACE_GATEWAY_MODEL_ID_PREFIX.length)] : []
|
|
292
|
+
);
|
|
293
|
+
const retainedOpenRouterUpstreamModelIds = retainedProductModelIds.flatMap(
|
|
294
|
+
(productModelId) => productModelId?.startsWith(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX) ? [productModelId.slice(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX.length)] : []
|
|
295
|
+
);
|
|
296
|
+
const [
|
|
297
|
+
resolved,
|
|
298
|
+
activeGatewayCustomModels,
|
|
299
|
+
activeOpenRouterCustomModels,
|
|
300
|
+
retainedGatewayCustomModels,
|
|
301
|
+
retainedOpenRouterCustomModels
|
|
302
|
+
] = await Promise.all([
|
|
303
|
+
resolveCatalogSettings(db, envSettings),
|
|
304
|
+
listWorkspaceGatewayCustomModels(db, {
|
|
305
|
+
accountId: input.accountId,
|
|
306
|
+
workspaceId: input.workspaceId
|
|
307
|
+
}),
|
|
308
|
+
listWorkspaceOpenRouterCustomModels(db, {
|
|
309
|
+
accountId: input.accountId,
|
|
310
|
+
workspaceId: input.workspaceId
|
|
311
|
+
}),
|
|
312
|
+
Promise.all(
|
|
313
|
+
[...new Set(retainedGatewayUpstreamModelIds)].map(
|
|
314
|
+
async (upstreamModelId) => await getWorkspaceGatewayCustomModelForExecution(db, {
|
|
315
|
+
accountId: input.accountId,
|
|
316
|
+
workspaceId: input.workspaceId,
|
|
317
|
+
upstreamModelId
|
|
318
|
+
})
|
|
319
|
+
)
|
|
320
|
+
),
|
|
321
|
+
Promise.all(
|
|
322
|
+
[...new Set(retainedOpenRouterUpstreamModelIds)].map(
|
|
323
|
+
async (upstreamModelId) => await getWorkspaceOpenRouterCustomModelForExecution(db, {
|
|
324
|
+
accountId: input.accountId,
|
|
325
|
+
workspaceId: input.workspaceId,
|
|
326
|
+
upstreamModelId
|
|
327
|
+
})
|
|
328
|
+
)
|
|
329
|
+
)
|
|
330
|
+
]);
|
|
331
|
+
const includeRetainedModels = (activeModels, retainedModels) => {
|
|
332
|
+
const customModels = [...activeModels];
|
|
333
|
+
const includedUpstreamModelIds = new Set(activeModels.map((model) => model.upstreamModelId));
|
|
334
|
+
for (const retainedCustomModel of retainedModels) {
|
|
335
|
+
if (retainedCustomModel && !includedUpstreamModelIds.has(retainedCustomModel.upstreamModelId)) {
|
|
336
|
+
customModels.push(retainedCustomModel);
|
|
337
|
+
includedUpstreamModelIds.add(retainedCustomModel.upstreamModelId);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return customModels;
|
|
341
|
+
};
|
|
342
|
+
const gatewayCustomModels = includeRetainedModels(
|
|
343
|
+
activeGatewayCustomModels,
|
|
344
|
+
retainedGatewayCustomModels
|
|
345
|
+
);
|
|
346
|
+
const openRouterCustomModels = includeRetainedModels(
|
|
347
|
+
activeOpenRouterCustomModels,
|
|
348
|
+
retainedOpenRouterCustomModels
|
|
349
|
+
);
|
|
350
|
+
return {
|
|
351
|
+
...resolved,
|
|
352
|
+
settings: withWorkspaceOpenRouterCatalogProvider(
|
|
353
|
+
withWorkspaceGatewayCatalogProvider(resolved.settings, gatewayCustomModels),
|
|
354
|
+
openRouterCustomModels
|
|
355
|
+
)
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
var MODEL_CREDENTIAL_READINESS_OBSERVATION_MAX_AGE_MS = 5 * 6e4;
|
|
359
|
+
function modelDefinitionRunnable(model) {
|
|
360
|
+
return model.capabilities.inputModalities.includes("text") && model.capabilities.outputModalities.includes("text") && model.capabilities.transports.sse.runnable;
|
|
361
|
+
}
|
|
362
|
+
function observedCredentialReadiness(input) {
|
|
363
|
+
if (!input.observation) {
|
|
364
|
+
return {
|
|
365
|
+
status: "not_ready",
|
|
366
|
+
reason: "prerequisites_missing",
|
|
367
|
+
basis: input.basis,
|
|
368
|
+
checkedAt: null
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
const checkedAtMs = Date.parse(input.observation.checkedAt);
|
|
372
|
+
if (!Number.isFinite(checkedAtMs)) {
|
|
373
|
+
return {
|
|
374
|
+
status: "error",
|
|
375
|
+
reason: "resolver_error",
|
|
376
|
+
basis: input.basis,
|
|
377
|
+
checkedAt: null
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
const checkedAt = new Date(checkedAtMs).toISOString();
|
|
381
|
+
if (Math.abs(input.nowMs - checkedAtMs) > input.maxAgeMs) {
|
|
382
|
+
return {
|
|
383
|
+
status: "not_ready",
|
|
384
|
+
reason: "observation_stale",
|
|
385
|
+
basis: input.basis,
|
|
386
|
+
checkedAt
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
if (input.observation.status === "ready") {
|
|
390
|
+
return { status: "ready", reason: null, basis: input.basis, checkedAt };
|
|
391
|
+
}
|
|
392
|
+
if (input.observation.status === "not_ready") {
|
|
393
|
+
return {
|
|
394
|
+
status: "not_ready",
|
|
395
|
+
reason: input.observation.reason === "needs_reauth" ? "needs_reauth" : "prerequisites_missing",
|
|
396
|
+
basis: input.basis,
|
|
397
|
+
checkedAt
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
return {
|
|
401
|
+
status: "error",
|
|
402
|
+
reason: "resolver_error",
|
|
403
|
+
basis: input.basis,
|
|
404
|
+
checkedAt
|
|
405
|
+
};
|
|
406
|
+
}
|
|
407
|
+
function credentialReadinessFor(input) {
|
|
408
|
+
const source = input.model.credentialSource;
|
|
409
|
+
if (source.kind === "connected_subscription") {
|
|
410
|
+
const active = source.provider === "xai" ? input.xaiSubscriptionActive : input.codexSubscriptionActive;
|
|
411
|
+
return active ? { status: "ready", reason: null, basis: "connection", checkedAt: null } : {
|
|
412
|
+
status: "not_ready",
|
|
413
|
+
reason: "needs_reauth",
|
|
414
|
+
basis: "connection",
|
|
415
|
+
checkedAt: null
|
|
416
|
+
};
|
|
417
|
+
}
|
|
418
|
+
if (source.kind === "workspace_connection") {
|
|
419
|
+
const connectionActive = input.model.providerId === WORKSPACE_OPENROUTER_PROVIDER_ID ? input.workspaceOpenRouterConnectionActive : input.workspaceGatewayConnectionActive;
|
|
420
|
+
return connectionActive ? { status: "ready", reason: null, basis: "connection", checkedAt: null } : {
|
|
421
|
+
status: "not_ready",
|
|
422
|
+
reason: "needs_reauth",
|
|
423
|
+
basis: "connection",
|
|
424
|
+
checkedAt: null
|
|
425
|
+
};
|
|
426
|
+
}
|
|
427
|
+
if (source.kind === "deployment" && source.mechanism === "none") {
|
|
428
|
+
return { status: "ready", reason: null, basis: "configuration", checkedAt: null };
|
|
429
|
+
}
|
|
430
|
+
if (source.kind === "deployment" && source.mechanism === "api_key") {
|
|
431
|
+
return input.provider?.apiKey ? { status: "ready", reason: null, basis: "configuration", checkedAt: null } : {
|
|
432
|
+
status: "not_ready",
|
|
433
|
+
reason: "missing_credential",
|
|
434
|
+
basis: "configuration",
|
|
435
|
+
checkedAt: null
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
return observedCredentialReadiness({
|
|
439
|
+
observation: input.observation,
|
|
440
|
+
basis: "resolver",
|
|
441
|
+
nowMs: input.nowMs,
|
|
442
|
+
maxAgeMs: input.maxAgeMs
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
function isXaiGrokModel(model) {
|
|
446
|
+
return model.providerId === "xai" && model.id.startsWith("xai/grok-");
|
|
447
|
+
}
|
|
448
|
+
function observationTimestamp(observation) {
|
|
449
|
+
if (!observation || typeof observation.checkedAt !== "string") {
|
|
450
|
+
return { checkedAt: null, checkedAtMs: null };
|
|
451
|
+
}
|
|
452
|
+
const checkedAtMs = Date.parse(observation.checkedAt);
|
|
453
|
+
if (!Number.isFinite(checkedAtMs)) {
|
|
454
|
+
return { checkedAt: null, checkedAtMs: null };
|
|
455
|
+
}
|
|
456
|
+
return { checkedAt: new Date(checkedAtMs).toISOString(), checkedAtMs };
|
|
457
|
+
}
|
|
458
|
+
function xaiGrokAvailabilityFor(input) {
|
|
459
|
+
const { checkedAt, checkedAtMs } = observationTimestamp(input.observation);
|
|
460
|
+
const freshSuccessfulObservation = input.observation?.status === "available" && input.observation.reason === null && checkedAtMs !== null && checkedAtMs <= input.nowMs && input.nowMs - checkedAtMs <= input.maxAgeMs;
|
|
461
|
+
if (freshSuccessfulObservation) {
|
|
462
|
+
return {
|
|
463
|
+
status: "available",
|
|
464
|
+
selectable: true,
|
|
465
|
+
reason: null,
|
|
466
|
+
checkedAt
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
return {
|
|
470
|
+
status: "unavailable",
|
|
471
|
+
selectable: false,
|
|
472
|
+
reason: input.observation?.status === "unavailable" ? input.observation.reason ?? "provider_unhealthy" : "provider_unhealthy",
|
|
473
|
+
checkedAt
|
|
474
|
+
};
|
|
475
|
+
}
|
|
476
|
+
function availabilityFor(input) {
|
|
477
|
+
if (!modelDefinitionRunnable(input.model)) {
|
|
478
|
+
return {
|
|
479
|
+
status: "unavailable",
|
|
480
|
+
selectable: false,
|
|
481
|
+
reason: "unsupported",
|
|
482
|
+
checkedAt: null
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
if (input.credentialReadiness.status !== "ready") {
|
|
486
|
+
return {
|
|
487
|
+
status: "unavailable",
|
|
488
|
+
selectable: false,
|
|
489
|
+
reason: input.credentialReadiness.reason === "missing_credential" ? "missing_credential" : input.credentialReadiness.reason === "needs_reauth" ? "needs_reauth" : "credential_not_ready",
|
|
490
|
+
checkedAt: input.credentialReadiness.checkedAt
|
|
491
|
+
};
|
|
492
|
+
}
|
|
493
|
+
if (!input.policyAllowed) {
|
|
494
|
+
return {
|
|
495
|
+
status: "unavailable",
|
|
496
|
+
selectable: false,
|
|
497
|
+
reason: "policy_blocked",
|
|
498
|
+
checkedAt: null
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
if (isXaiGrokModel(input.model)) {
|
|
502
|
+
return xaiGrokAvailabilityFor({
|
|
503
|
+
observation: input.observation,
|
|
504
|
+
nowMs: input.nowMs,
|
|
505
|
+
maxAgeMs: input.maxAgeMs
|
|
506
|
+
});
|
|
507
|
+
}
|
|
508
|
+
if (!input.observation) {
|
|
509
|
+
return { status: "unknown", selectable: true, reason: null, checkedAt: null };
|
|
510
|
+
}
|
|
511
|
+
if (input.observation.status === "unavailable") {
|
|
512
|
+
return {
|
|
513
|
+
status: "unavailable",
|
|
514
|
+
selectable: false,
|
|
515
|
+
reason: input.observation.reason ?? "provider_unhealthy",
|
|
516
|
+
checkedAt: input.observation.checkedAt
|
|
517
|
+
};
|
|
518
|
+
}
|
|
519
|
+
return {
|
|
520
|
+
status: input.observation.status,
|
|
521
|
+
selectable: true,
|
|
522
|
+
reason: null,
|
|
523
|
+
checkedAt: input.observation.checkedAt
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
function resolveWorkspaceModelSelection(input) {
|
|
527
|
+
const codexSettings = input.settings.codexSubscriptionEnabled ? withCodexCatalogProvider(input.settings) : input.settings;
|
|
528
|
+
const xaiSettings = input.settings.supergrokSubscriptionEnabled ? withXaiSubscriptionCatalogProvider(codexSettings) : codexSettings;
|
|
529
|
+
const catalogSettings = withWorkspaceOpenRouterCatalogProvider(
|
|
530
|
+
withWorkspaceGatewayCatalogProvider(xaiSettings, input.workspaceGatewayCustomModels ?? []),
|
|
531
|
+
input.workspaceOpenRouterCustomModels ?? []
|
|
532
|
+
);
|
|
533
|
+
const providers = new Map(
|
|
534
|
+
configuredProviders(catalogSettings).map((provider) => [provider.id, provider])
|
|
535
|
+
);
|
|
536
|
+
const requestedNowMs = input.now?.getTime();
|
|
537
|
+
const nowMs = typeof requestedNowMs === "number" && Number.isFinite(requestedNowMs) ? requestedNowMs : Date.now();
|
|
538
|
+
const maxAgeMs = typeof input.credentialReadinessMaxAgeMs === "number" && Number.isFinite(input.credentialReadinessMaxAgeMs) && input.credentialReadinessMaxAgeMs >= 0 ? input.credentialReadinessMaxAgeMs : MODEL_CREDENTIAL_READINESS_OBSERVATION_MAX_AGE_MS;
|
|
539
|
+
return configuredModels(catalogSettings).map((model) => {
|
|
540
|
+
const provider = providers.get(model.providerId);
|
|
541
|
+
const policyAllowed = evaluateWorkspaceModelPolicy(input.policy, {
|
|
542
|
+
providerId: model.providerId,
|
|
543
|
+
modelId: model.id
|
|
544
|
+
}).allowed;
|
|
545
|
+
const credentialReadiness = credentialReadinessFor({
|
|
546
|
+
model,
|
|
547
|
+
provider,
|
|
548
|
+
codexSubscriptionActive: input.codexSubscriptionActive,
|
|
549
|
+
xaiSubscriptionActive: input.xaiSubscriptionActive === true,
|
|
550
|
+
workspaceGatewayConnectionActive: input.workspaceGatewayConnectionActive === true,
|
|
551
|
+
workspaceOpenRouterConnectionActive: input.workspaceOpenRouterConnectionActive === true,
|
|
552
|
+
observation: input.credentialReadinessObservations?.[model.definitionVersion],
|
|
553
|
+
nowMs,
|
|
554
|
+
maxAgeMs
|
|
555
|
+
});
|
|
556
|
+
return {
|
|
557
|
+
model,
|
|
558
|
+
credentialReadiness,
|
|
559
|
+
policyAllowed,
|
|
560
|
+
availability: availabilityFor({
|
|
561
|
+
model,
|
|
562
|
+
credentialReadiness,
|
|
563
|
+
policyAllowed,
|
|
564
|
+
observation: input.observations?.[model.definitionVersion],
|
|
565
|
+
nowMs,
|
|
566
|
+
maxAgeMs
|
|
567
|
+
})
|
|
568
|
+
};
|
|
569
|
+
});
|
|
570
|
+
}
|
|
571
|
+
|
|
211
572
|
// src/sandbox/fleet.ts
|
|
212
573
|
import {
|
|
213
574
|
authorizePersonalMachineForAttempt,
|
|
@@ -260,6 +621,16 @@ import {
|
|
|
260
621
|
function directRetainedProcessMatchesBackend(durable, process, backend) {
|
|
261
622
|
return durable.providerSessionId === process.providerSessionId && durable.providerBackend === backend.kind && durable.providerInstanceId === backend.providerInstanceId && durable.leaseEpoch === backend.leaseEpoch && durable.routeKind === "active" && durable.routeTargetId === backend.sandboxId && durable.routeEpoch === backend.activeEpoch;
|
|
262
623
|
}
|
|
624
|
+
function retainedProcessBackgroundSettlement(process, fallback) {
|
|
625
|
+
if (process.state === "active") {
|
|
626
|
+
throw new Error("Retained-process settlement returned an active durable process");
|
|
627
|
+
}
|
|
628
|
+
return {
|
|
629
|
+
outcome: process.state,
|
|
630
|
+
exitCode: process.exitCode,
|
|
631
|
+
reason: process.settlementReason ?? fallback.reason
|
|
632
|
+
};
|
|
633
|
+
}
|
|
263
634
|
function relayConfigFromSettings(settings) {
|
|
264
635
|
const raw = settings.selfhostedRelayUrl?.trim();
|
|
265
636
|
if (!raw) {
|
|
@@ -460,7 +831,7 @@ function wrapChannelABoxWithRouting(services, ids, established) {
|
|
|
460
831
|
"API retained-process settlement lost its exact durable backend identity"
|
|
461
832
|
);
|
|
462
833
|
}
|
|
463
|
-
await settleRetainedProcess(db, {
|
|
834
|
+
const settlement = await settleRetainedProcess(db, {
|
|
464
835
|
accountId: ids.accountId,
|
|
465
836
|
workspaceId: ids.workspaceId,
|
|
466
837
|
sessionId: ids.sessionId,
|
|
@@ -471,14 +842,13 @@ function wrapChannelABoxWithRouting(services, ids, established) {
|
|
|
471
842
|
reason: proof.reason,
|
|
472
843
|
idleGraceMs: settings.sandboxIdleGraceMs
|
|
473
844
|
});
|
|
845
|
+
const backgroundSettlement = retainedProcessBackgroundSettlement(settlement.process, proof);
|
|
474
846
|
await settleSessionBackgroundCommandForRetainedProcess(db, {
|
|
475
847
|
accountId: ids.accountId,
|
|
476
848
|
workspaceId: ids.workspaceId,
|
|
477
849
|
sessionId: ids.sessionId,
|
|
478
850
|
retainedProcessId: process.id,
|
|
479
|
-
|
|
480
|
-
exitCode: proof.exitCode,
|
|
481
|
-
reason: proof.reason
|
|
851
|
+
...backgroundSettlement
|
|
482
852
|
});
|
|
483
853
|
} : void 0;
|
|
484
854
|
const resolver = makeActiveBackendResolver({
|
|
@@ -588,6 +958,235 @@ function wrapChannelABoxWithRouting(services, ids, established) {
|
|
|
588
958
|
return { ...established, session: proxy };
|
|
589
959
|
}
|
|
590
960
|
|
|
961
|
+
// src/sandbox/runtime-settings.ts
|
|
962
|
+
import {
|
|
963
|
+
CapabilityPack
|
|
964
|
+
} from "@opengeni/contracts";
|
|
965
|
+
import {
|
|
966
|
+
getRigVersion,
|
|
967
|
+
getWorkspacePack,
|
|
968
|
+
listPackInstallations
|
|
969
|
+
} from "@opengeni/db";
|
|
970
|
+
import { resolveModalCheckpointProviderBinding } from "@opengeni/runtime/sandbox";
|
|
971
|
+
|
|
972
|
+
// src/rigs/provider-images.ts
|
|
973
|
+
import { createHash } from "crypto";
|
|
974
|
+
import {
|
|
975
|
+
RigProviderImage as RigProviderImageContract,
|
|
976
|
+
stableJson
|
|
977
|
+
} from "@opengeni/contracts";
|
|
978
|
+
function sha256(value) {
|
|
979
|
+
return `sha256:${createHash("sha256").update(value, "utf8").digest("hex")}`;
|
|
980
|
+
}
|
|
981
|
+
function rigProviderImageProviderBindingKeyHash(bindingKey) {
|
|
982
|
+
return sha256(bindingKey);
|
|
983
|
+
}
|
|
984
|
+
function rigProviderImageSetupHash(definition) {
|
|
985
|
+
return sha256(definition.setupScript ?? "");
|
|
986
|
+
}
|
|
987
|
+
function rigProviderImageContentHash(input) {
|
|
988
|
+
return sha256(
|
|
989
|
+
stableJson({
|
|
990
|
+
version: 2,
|
|
991
|
+
backend: input.backend,
|
|
992
|
+
sourceImage: input.sourceImage,
|
|
993
|
+
setupScript: input.definition.setupScript,
|
|
994
|
+
checks: input.definition.checks,
|
|
995
|
+
credentialHooks: input.definition.credentialHooks,
|
|
996
|
+
defaultVariableSetIds: input.definition.defaultVariableSetIds
|
|
997
|
+
})
|
|
998
|
+
);
|
|
999
|
+
}
|
|
1000
|
+
function rigProviderImageBuildRequestId(input) {
|
|
1001
|
+
const bytes = createHash("sha256").update("opengeni-rig-provider-image-build-v2\0", "utf8").update(input.targetId, "utf8").update("\0", "utf8").update(input.backend, "utf8").update("\0", "utf8").update(input.contentHash, "utf8").digest().subarray(0, 16);
|
|
1002
|
+
bytes[6] = bytes[6] & 15 | 80;
|
|
1003
|
+
bytes[8] = bytes[8] & 63 | 128;
|
|
1004
|
+
const hex = bytes.toString("hex");
|
|
1005
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
1006
|
+
}
|
|
1007
|
+
function rigProviderImageMatchesDefinition(image, definition) {
|
|
1008
|
+
return image.setupHash === rigProviderImageSetupHash(definition) && image.contentHash === rigProviderImageContentHash({
|
|
1009
|
+
backend: image.backend,
|
|
1010
|
+
sourceImage: image.sourceImage,
|
|
1011
|
+
definition
|
|
1012
|
+
});
|
|
1013
|
+
}
|
|
1014
|
+
function rigProviderImagesFromVerification(verification, definition) {
|
|
1015
|
+
const parsed = RigProviderImageContract.safeParse(verification?.providerImage);
|
|
1016
|
+
if (!parsed.success || parsed.data.status === "building") return {};
|
|
1017
|
+
if (!rigProviderImageMatchesDefinition(parsed.data, definition)) return {};
|
|
1018
|
+
return { [parsed.data.backend]: parsed.data };
|
|
1019
|
+
}
|
|
1020
|
+
|
|
1021
|
+
// src/sandbox/runtime-settings.ts
|
|
1022
|
+
function managedSessionGroupBackend(deploymentBackend, sessionBackend) {
|
|
1023
|
+
if (sessionBackend === "none") return null;
|
|
1024
|
+
const backend = sessionBackend === "selfhosted" ? deploymentBackend : sessionBackend;
|
|
1025
|
+
return backend === "none" || backend === "selfhosted" ? null : backend;
|
|
1026
|
+
}
|
|
1027
|
+
function managedSessionGroupOs(sessionBackend, sessionOs) {
|
|
1028
|
+
return sessionBackend === "selfhosted" ? "linux" : sessionOs;
|
|
1029
|
+
}
|
|
1030
|
+
function packInstallationUsesLegacyRuntime(input) {
|
|
1031
|
+
return input.manifestSnapshot === null && input.manifestDigest === null;
|
|
1032
|
+
}
|
|
1033
|
+
async function resolveWorkspaceLegacyRuntimePacks(db, workspaceId) {
|
|
1034
|
+
const installations = await listPackInstallations(db, workspaceId);
|
|
1035
|
+
const packs2 = [];
|
|
1036
|
+
for (const installation of installations) {
|
|
1037
|
+
if (installation.status !== "active" || !packInstallationUsesLegacyRuntime(installation)) {
|
|
1038
|
+
continue;
|
|
1039
|
+
}
|
|
1040
|
+
const registration = await getWorkspacePack(db, workspaceId, installation.packId);
|
|
1041
|
+
const parsed = CapabilityPack.safeParse(registration?.pack);
|
|
1042
|
+
if (parsed.success) packs2.push(parsed.data);
|
|
1043
|
+
}
|
|
1044
|
+
return packs2;
|
|
1045
|
+
}
|
|
1046
|
+
function legacySandboxRuntimeFromPacks(packs2) {
|
|
1047
|
+
const imagePacks = packs2.filter(
|
|
1048
|
+
(pack) => typeof pack.sandboxImage === "string" && pack.sandboxImage.trim().length > 0
|
|
1049
|
+
);
|
|
1050
|
+
if (imagePacks.length > 1) {
|
|
1051
|
+
const ids = imagePacks.map((pack) => pack.id).sort().join(", ");
|
|
1052
|
+
throw new Error(
|
|
1053
|
+
`Multiple enabled packs declare a sandbox image (${ids}). Only one enabled pack per workspace may declare sandboxImage; disable the others and retry.`
|
|
1054
|
+
);
|
|
1055
|
+
}
|
|
1056
|
+
return {
|
|
1057
|
+
sandboxImage: imagePacks[0]?.sandboxImage?.trim() ?? null,
|
|
1058
|
+
sandboxProviderImages: imagePacks[0]?.sandboxProviderImages ?? null
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
1061
|
+
function settingsWithPackSandboxImage(settings, sandboxImage, sandboxProviderImages = null) {
|
|
1062
|
+
if (!sandboxImage) return settings;
|
|
1063
|
+
return {
|
|
1064
|
+
...settings,
|
|
1065
|
+
dockerImage: sandboxImage,
|
|
1066
|
+
modalImageRef: sandboxImage,
|
|
1067
|
+
modalImageId: sandboxProviderImages?.modal?.imageId
|
|
1068
|
+
};
|
|
1069
|
+
}
|
|
1070
|
+
function settingsWithRigImage(settings, rigImage) {
|
|
1071
|
+
void rigImage;
|
|
1072
|
+
return settings;
|
|
1073
|
+
}
|
|
1074
|
+
function rigProviderImageSourceImage(settings, backend) {
|
|
1075
|
+
if (backend === "modal") return settings.modalImageId ?? settings.modalImageRef ?? null;
|
|
1076
|
+
if (backend === "docker") return settings.dockerImage ?? null;
|
|
1077
|
+
return null;
|
|
1078
|
+
}
|
|
1079
|
+
function resolveRigProviderImageSelection(settings, version, backend, currentProviderBindingKeyHash) {
|
|
1080
|
+
if (!version) return { settings, reason: "missing", contentHash: null, imageId: null };
|
|
1081
|
+
if (backend !== "modal") {
|
|
1082
|
+
return { settings, reason: "provider_unsupported", contentHash: null, imageId: null };
|
|
1083
|
+
}
|
|
1084
|
+
const image = version.providerImages[backend];
|
|
1085
|
+
if (!image) return { settings, reason: "missing", contentHash: null, imageId: null };
|
|
1086
|
+
if (image.status !== "ready" || !image.imageId) {
|
|
1087
|
+
return {
|
|
1088
|
+
settings,
|
|
1089
|
+
reason: "not_ready",
|
|
1090
|
+
contentHash: image.contentHash,
|
|
1091
|
+
imageId: image.imageId
|
|
1092
|
+
};
|
|
1093
|
+
}
|
|
1094
|
+
if (image.coldBootValidation?.version !== 1) {
|
|
1095
|
+
return {
|
|
1096
|
+
settings,
|
|
1097
|
+
reason: "not_cold_boot_validated",
|
|
1098
|
+
contentHash: image.contentHash,
|
|
1099
|
+
imageId: null
|
|
1100
|
+
};
|
|
1101
|
+
}
|
|
1102
|
+
const sourceImage = rigProviderImageSourceImage(settings, backend);
|
|
1103
|
+
const expectedContentHash = rigProviderImageContentHash({
|
|
1104
|
+
backend,
|
|
1105
|
+
sourceImage,
|
|
1106
|
+
definition: version
|
|
1107
|
+
});
|
|
1108
|
+
if (image.sourceImage !== sourceImage || image.contentHash !== expectedContentHash || !rigProviderImageMatchesDefinition(image, version)) {
|
|
1109
|
+
return {
|
|
1110
|
+
settings,
|
|
1111
|
+
reason: "content_mismatch",
|
|
1112
|
+
contentHash: expectedContentHash,
|
|
1113
|
+
imageId: null
|
|
1114
|
+
};
|
|
1115
|
+
}
|
|
1116
|
+
if (!image.providerBindingKeyHash || !currentProviderBindingKeyHash) {
|
|
1117
|
+
return {
|
|
1118
|
+
settings,
|
|
1119
|
+
reason: "provider_binding_unavailable",
|
|
1120
|
+
contentHash: expectedContentHash,
|
|
1121
|
+
imageId: null
|
|
1122
|
+
};
|
|
1123
|
+
}
|
|
1124
|
+
if (image.providerBindingKeyHash !== currentProviderBindingKeyHash) {
|
|
1125
|
+
return {
|
|
1126
|
+
settings,
|
|
1127
|
+
reason: "provider_binding_mismatch",
|
|
1128
|
+
contentHash: expectedContentHash,
|
|
1129
|
+
imageId: null
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
return {
|
|
1133
|
+
settings: { ...settings, modalImageId: image.imageId },
|
|
1134
|
+
reason: "selected",
|
|
1135
|
+
contentHash: expectedContentHash,
|
|
1136
|
+
imageId: image.imageId
|
|
1137
|
+
};
|
|
1138
|
+
}
|
|
1139
|
+
async function resolveRigProviderImageForRun(settings, version, backend, resolveBinding = resolveModalCheckpointProviderBinding) {
|
|
1140
|
+
const image = backend === "modal" ? version?.providerImages.modal : null;
|
|
1141
|
+
if (image?.status !== "ready" || !image.providerBindingKeyHash) {
|
|
1142
|
+
return resolveRigProviderImageSelection(settings, version, backend, null);
|
|
1143
|
+
}
|
|
1144
|
+
const structural = resolveRigProviderImageSelection(
|
|
1145
|
+
settings,
|
|
1146
|
+
version,
|
|
1147
|
+
backend,
|
|
1148
|
+
image.providerBindingKeyHash
|
|
1149
|
+
);
|
|
1150
|
+
if (structural.reason !== "selected") return structural;
|
|
1151
|
+
let currentProviderBindingKeyHash = null;
|
|
1152
|
+
try {
|
|
1153
|
+
const binding = await resolveBinding(settings);
|
|
1154
|
+
currentProviderBindingKeyHash = rigProviderImageProviderBindingKeyHash(binding.key);
|
|
1155
|
+
} catch {
|
|
1156
|
+
}
|
|
1157
|
+
return resolveRigProviderImageSelection(
|
|
1158
|
+
settings,
|
|
1159
|
+
version,
|
|
1160
|
+
backend,
|
|
1161
|
+
currentProviderBindingKeyHash
|
|
1162
|
+
);
|
|
1163
|
+
}
|
|
1164
|
+
async function settingsWithRigProviderImage(settings, version, backend, resolveBinding = resolveModalCheckpointProviderBinding) {
|
|
1165
|
+
return (await resolveRigProviderImageForRun(settings, version, backend, resolveBinding)).settings;
|
|
1166
|
+
}
|
|
1167
|
+
async function resolveSessionSandboxRuntime(db, settings, session) {
|
|
1168
|
+
const [packs2, rigVersion] = await Promise.all([
|
|
1169
|
+
resolveWorkspaceLegacyRuntimePacks(db, session.workspaceId),
|
|
1170
|
+
session.rigId && session.rigVersionId ? getRigVersion(db, session.workspaceId, session.rigId, session.rigVersionId) : Promise.resolve(null)
|
|
1171
|
+
]);
|
|
1172
|
+
if (session.rigVersionId && !rigVersion) {
|
|
1173
|
+
throw new Error(`Frozen rig version ${session.rigVersionId} is unavailable`);
|
|
1174
|
+
}
|
|
1175
|
+
const legacy = legacySandboxRuntimeFromPacks(packs2);
|
|
1176
|
+
const logicalSettings = rigVersion ? settings : settingsWithPackSandboxImage(settings, legacy.sandboxImage, legacy.sandboxProviderImages);
|
|
1177
|
+
return {
|
|
1178
|
+
settings: {
|
|
1179
|
+
...logicalSettings,
|
|
1180
|
+
sandboxBackend: session.sandboxBackend
|
|
1181
|
+
},
|
|
1182
|
+
image: rigProviderImageSourceImage(logicalSettings, session.sandboxBackend),
|
|
1183
|
+
rigVersion
|
|
1184
|
+
};
|
|
1185
|
+
}
|
|
1186
|
+
async function providerSettingsForSessionSandboxRuntime(runtime, backend) {
|
|
1187
|
+
return await settingsWithRigProviderImage(runtime.settings, runtime.rigVersion, backend);
|
|
1188
|
+
}
|
|
1189
|
+
|
|
591
1190
|
// src/sandbox/fleet.ts
|
|
592
1191
|
async function buildFleetContextForSession(deps, ctx) {
|
|
593
1192
|
const session = await requireSession(deps.db, ctx.workspaceId, ctx.sessionId);
|
|
@@ -661,7 +1260,11 @@ async function listFleet(services, ctx) {
|
|
|
661
1260
|
activeEpoch: 0
|
|
662
1261
|
};
|
|
663
1262
|
const entries = [];
|
|
664
|
-
|
|
1263
|
+
const groupBackend = managedSessionGroupBackend(
|
|
1264
|
+
services.settings.sandboxBackend,
|
|
1265
|
+
ctx.sessionBackend
|
|
1266
|
+
);
|
|
1267
|
+
if (groupBackend) {
|
|
665
1268
|
const groupActive = pointer.activeSandboxId === null;
|
|
666
1269
|
const groupLease = await readLease(db, ctx.workspaceId, ctx.sessionGroupId);
|
|
667
1270
|
const groupOnline = Boolean(
|
|
@@ -673,10 +1276,10 @@ async function listFleet(services, ctx) {
|
|
|
673
1276
|
const groupRecoveryUnavailable = Boolean(
|
|
674
1277
|
groupLease && (groupLease.recovery.restore.status === "degraded" || groupLease.recovery.restore.status === "unrecoverable" || groupLease.recovery.workspace.status === "degraded" || groupLease.recovery.workspace.status === "unrecoverable")
|
|
675
1278
|
);
|
|
676
|
-
const groupOperationAvailability = groupOnline ? "ready" : groupRecoveryUnavailable ? "unavailable" : groupRecovering ? "recovering" :
|
|
1279
|
+
const groupOperationAvailability = groupOnline ? "ready" : groupRecoveryUnavailable ? "unavailable" : groupRecovering ? "recovering" : "wakeable";
|
|
677
1280
|
entries.push({
|
|
678
1281
|
id: ctx.sessionGroupId,
|
|
679
|
-
kind:
|
|
1282
|
+
kind: groupBackend === "opensandbox" ? "opensandbox" : "modal",
|
|
680
1283
|
name: "session sandbox",
|
|
681
1284
|
liveness: groupOnline ? "online" : groupRecovering ? "reconnecting" : "offline",
|
|
682
1285
|
active: groupActive,
|
|
@@ -780,10 +1383,10 @@ async function listFleet(services, ctx) {
|
|
|
780
1383
|
}
|
|
781
1384
|
async function resolveTarget(services, ctx, target) {
|
|
782
1385
|
if (target === ctx.sessionGroupId || target === "session" || target === "default") {
|
|
783
|
-
if (ctx.sessionBackend
|
|
1386
|
+
if (!managedSessionGroupBackend(services.settings.sandboxBackend, ctx.sessionBackend)) {
|
|
784
1387
|
return {
|
|
785
1388
|
ok: false,
|
|
786
|
-
reason: "this session has no home sandbox; attach a Connected Machine",
|
|
1389
|
+
reason: ctx.sessionBackend === "none" ? "this session has no home sandbox; attach a Connected Machine" : "this deployment has no managed session sandbox; select an enrolled machine",
|
|
787
1390
|
code: "unsupported_backend_context"
|
|
788
1391
|
};
|
|
789
1392
|
}
|
|
@@ -1227,228 +1830,7 @@ async function provisionSandbox(services, ctx, input) {
|
|
|
1227
1830
|
kind: "modal",
|
|
1228
1831
|
sandbox,
|
|
1229
1832
|
note: "A named Modal sandbox record was created, but it is NOT yet attachable as a swap target: routing a session onto a second Modal box is not supported yet, so a sandbox_swap to this id is rejected. Use the session's own box (the default) or attach a Connected Machine instead."
|
|
1230
|
-
};
|
|
1231
|
-
}
|
|
1232
|
-
|
|
1233
|
-
// src/sandbox/runtime-settings.ts
|
|
1234
|
-
import {
|
|
1235
|
-
CapabilityPack
|
|
1236
|
-
} from "@opengeni/contracts";
|
|
1237
|
-
import {
|
|
1238
|
-
getRigVersion,
|
|
1239
|
-
getWorkspacePack,
|
|
1240
|
-
listPackInstallations
|
|
1241
|
-
} from "@opengeni/db";
|
|
1242
|
-
import { resolveModalCheckpointProviderBinding } from "@opengeni/runtime/sandbox";
|
|
1243
|
-
|
|
1244
|
-
// src/rigs/provider-images.ts
|
|
1245
|
-
import { createHash } from "crypto";
|
|
1246
|
-
import {
|
|
1247
|
-
RigProviderImage as RigProviderImageContract,
|
|
1248
|
-
stableJson
|
|
1249
|
-
} from "@opengeni/contracts";
|
|
1250
|
-
function sha256(value) {
|
|
1251
|
-
return `sha256:${createHash("sha256").update(value, "utf8").digest("hex")}`;
|
|
1252
|
-
}
|
|
1253
|
-
function rigProviderImageProviderBindingKeyHash(bindingKey) {
|
|
1254
|
-
return sha256(bindingKey);
|
|
1255
|
-
}
|
|
1256
|
-
function rigProviderImageSetupHash(definition) {
|
|
1257
|
-
return sha256(definition.setupScript ?? "");
|
|
1258
|
-
}
|
|
1259
|
-
function rigProviderImageContentHash(input) {
|
|
1260
|
-
return sha256(
|
|
1261
|
-
stableJson({
|
|
1262
|
-
version: 2,
|
|
1263
|
-
backend: input.backend,
|
|
1264
|
-
sourceImage: input.sourceImage,
|
|
1265
|
-
setupScript: input.definition.setupScript,
|
|
1266
|
-
checks: input.definition.checks,
|
|
1267
|
-
credentialHooks: input.definition.credentialHooks,
|
|
1268
|
-
defaultVariableSetIds: input.definition.defaultVariableSetIds
|
|
1269
|
-
})
|
|
1270
|
-
);
|
|
1271
|
-
}
|
|
1272
|
-
function rigProviderImageBuildRequestId(input) {
|
|
1273
|
-
const bytes = createHash("sha256").update("opengeni-rig-provider-image-build-v2\0", "utf8").update(input.targetId, "utf8").update("\0", "utf8").update(input.backend, "utf8").update("\0", "utf8").update(input.contentHash, "utf8").digest().subarray(0, 16);
|
|
1274
|
-
bytes[6] = bytes[6] & 15 | 80;
|
|
1275
|
-
bytes[8] = bytes[8] & 63 | 128;
|
|
1276
|
-
const hex = bytes.toString("hex");
|
|
1277
|
-
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
1278
|
-
}
|
|
1279
|
-
function rigProviderImageMatchesDefinition(image, definition) {
|
|
1280
|
-
return image.setupHash === rigProviderImageSetupHash(definition) && image.contentHash === rigProviderImageContentHash({
|
|
1281
|
-
backend: image.backend,
|
|
1282
|
-
sourceImage: image.sourceImage,
|
|
1283
|
-
definition
|
|
1284
|
-
});
|
|
1285
|
-
}
|
|
1286
|
-
function rigProviderImagesFromVerification(verification, definition) {
|
|
1287
|
-
const parsed = RigProviderImageContract.safeParse(verification?.providerImage);
|
|
1288
|
-
if (!parsed.success || parsed.data.status === "building") return {};
|
|
1289
|
-
if (!rigProviderImageMatchesDefinition(parsed.data, definition)) return {};
|
|
1290
|
-
return { [parsed.data.backend]: parsed.data };
|
|
1291
|
-
}
|
|
1292
|
-
|
|
1293
|
-
// src/sandbox/runtime-settings.ts
|
|
1294
|
-
function packInstallationUsesLegacyRuntime(input) {
|
|
1295
|
-
return input.manifestSnapshot === null && input.manifestDigest === null;
|
|
1296
|
-
}
|
|
1297
|
-
async function resolveWorkspaceLegacyRuntimePacks(db, workspaceId) {
|
|
1298
|
-
const installations = await listPackInstallations(db, workspaceId);
|
|
1299
|
-
const packs2 = [];
|
|
1300
|
-
for (const installation of installations) {
|
|
1301
|
-
if (installation.status !== "active" || !packInstallationUsesLegacyRuntime(installation)) {
|
|
1302
|
-
continue;
|
|
1303
|
-
}
|
|
1304
|
-
const registration = await getWorkspacePack(db, workspaceId, installation.packId);
|
|
1305
|
-
const parsed = CapabilityPack.safeParse(registration?.pack);
|
|
1306
|
-
if (parsed.success) packs2.push(parsed.data);
|
|
1307
|
-
}
|
|
1308
|
-
return packs2;
|
|
1309
|
-
}
|
|
1310
|
-
function legacySandboxRuntimeFromPacks(packs2) {
|
|
1311
|
-
const imagePacks = packs2.filter(
|
|
1312
|
-
(pack) => typeof pack.sandboxImage === "string" && pack.sandboxImage.trim().length > 0
|
|
1313
|
-
);
|
|
1314
|
-
if (imagePacks.length > 1) {
|
|
1315
|
-
const ids = imagePacks.map((pack) => pack.id).sort().join(", ");
|
|
1316
|
-
throw new Error(
|
|
1317
|
-
`Multiple enabled packs declare a sandbox image (${ids}). Only one enabled pack per workspace may declare sandboxImage; disable the others and retry.`
|
|
1318
|
-
);
|
|
1319
|
-
}
|
|
1320
|
-
return {
|
|
1321
|
-
sandboxImage: imagePacks[0]?.sandboxImage?.trim() ?? null,
|
|
1322
|
-
sandboxProviderImages: imagePacks[0]?.sandboxProviderImages ?? null
|
|
1323
|
-
};
|
|
1324
|
-
}
|
|
1325
|
-
function settingsWithPackSandboxImage(settings, sandboxImage, sandboxProviderImages = null) {
|
|
1326
|
-
if (!sandboxImage) return settings;
|
|
1327
|
-
return {
|
|
1328
|
-
...settings,
|
|
1329
|
-
dockerImage: sandboxImage,
|
|
1330
|
-
modalImageRef: sandboxImage,
|
|
1331
|
-
modalImageId: sandboxProviderImages?.modal?.imageId
|
|
1332
|
-
};
|
|
1333
|
-
}
|
|
1334
|
-
function settingsWithRigImage(settings, rigImage) {
|
|
1335
|
-
void rigImage;
|
|
1336
|
-
return settings;
|
|
1337
|
-
}
|
|
1338
|
-
function rigProviderImageSourceImage(settings, backend) {
|
|
1339
|
-
if (backend === "modal") return settings.modalImageId ?? settings.modalImageRef ?? null;
|
|
1340
|
-
if (backend === "docker") return settings.dockerImage ?? null;
|
|
1341
|
-
return null;
|
|
1342
|
-
}
|
|
1343
|
-
function resolveRigProviderImageSelection(settings, version, backend, currentProviderBindingKeyHash) {
|
|
1344
|
-
if (!version) return { settings, reason: "missing", contentHash: null, imageId: null };
|
|
1345
|
-
if (backend !== "modal") {
|
|
1346
|
-
return { settings, reason: "provider_unsupported", contentHash: null, imageId: null };
|
|
1347
|
-
}
|
|
1348
|
-
const image = version.providerImages[backend];
|
|
1349
|
-
if (!image) return { settings, reason: "missing", contentHash: null, imageId: null };
|
|
1350
|
-
if (image.status !== "ready" || !image.imageId) {
|
|
1351
|
-
return {
|
|
1352
|
-
settings,
|
|
1353
|
-
reason: "not_ready",
|
|
1354
|
-
contentHash: image.contentHash,
|
|
1355
|
-
imageId: image.imageId
|
|
1356
|
-
};
|
|
1357
|
-
}
|
|
1358
|
-
if (image.coldBootValidation?.version !== 1) {
|
|
1359
|
-
return {
|
|
1360
|
-
settings,
|
|
1361
|
-
reason: "not_cold_boot_validated",
|
|
1362
|
-
contentHash: image.contentHash,
|
|
1363
|
-
imageId: null
|
|
1364
|
-
};
|
|
1365
|
-
}
|
|
1366
|
-
const sourceImage = rigProviderImageSourceImage(settings, backend);
|
|
1367
|
-
const expectedContentHash = rigProviderImageContentHash({
|
|
1368
|
-
backend,
|
|
1369
|
-
sourceImage,
|
|
1370
|
-
definition: version
|
|
1371
|
-
});
|
|
1372
|
-
if (image.sourceImage !== sourceImage || image.contentHash !== expectedContentHash || !rigProviderImageMatchesDefinition(image, version)) {
|
|
1373
|
-
return {
|
|
1374
|
-
settings,
|
|
1375
|
-
reason: "content_mismatch",
|
|
1376
|
-
contentHash: expectedContentHash,
|
|
1377
|
-
imageId: null
|
|
1378
|
-
};
|
|
1379
|
-
}
|
|
1380
|
-
if (!image.providerBindingKeyHash || !currentProviderBindingKeyHash) {
|
|
1381
|
-
return {
|
|
1382
|
-
settings,
|
|
1383
|
-
reason: "provider_binding_unavailable",
|
|
1384
|
-
contentHash: expectedContentHash,
|
|
1385
|
-
imageId: null
|
|
1386
|
-
};
|
|
1387
|
-
}
|
|
1388
|
-
if (image.providerBindingKeyHash !== currentProviderBindingKeyHash) {
|
|
1389
|
-
return {
|
|
1390
|
-
settings,
|
|
1391
|
-
reason: "provider_binding_mismatch",
|
|
1392
|
-
contentHash: expectedContentHash,
|
|
1393
|
-
imageId: null
|
|
1394
|
-
};
|
|
1395
|
-
}
|
|
1396
|
-
return {
|
|
1397
|
-
settings: { ...settings, modalImageId: image.imageId },
|
|
1398
|
-
reason: "selected",
|
|
1399
|
-
contentHash: expectedContentHash,
|
|
1400
|
-
imageId: image.imageId
|
|
1401
|
-
};
|
|
1402
|
-
}
|
|
1403
|
-
async function resolveRigProviderImageForRun(settings, version, backend, resolveBinding = resolveModalCheckpointProviderBinding) {
|
|
1404
|
-
const image = backend === "modal" ? version?.providerImages.modal : null;
|
|
1405
|
-
if (image?.status !== "ready" || !image.providerBindingKeyHash) {
|
|
1406
|
-
return resolveRigProviderImageSelection(settings, version, backend, null);
|
|
1407
|
-
}
|
|
1408
|
-
const structural = resolveRigProviderImageSelection(
|
|
1409
|
-
settings,
|
|
1410
|
-
version,
|
|
1411
|
-
backend,
|
|
1412
|
-
image.providerBindingKeyHash
|
|
1413
|
-
);
|
|
1414
|
-
if (structural.reason !== "selected") return structural;
|
|
1415
|
-
let currentProviderBindingKeyHash = null;
|
|
1416
|
-
try {
|
|
1417
|
-
const binding = await resolveBinding(settings);
|
|
1418
|
-
currentProviderBindingKeyHash = rigProviderImageProviderBindingKeyHash(binding.key);
|
|
1419
|
-
} catch {
|
|
1420
|
-
}
|
|
1421
|
-
return resolveRigProviderImageSelection(
|
|
1422
|
-
settings,
|
|
1423
|
-
version,
|
|
1424
|
-
backend,
|
|
1425
|
-
currentProviderBindingKeyHash
|
|
1426
|
-
);
|
|
1427
|
-
}
|
|
1428
|
-
async function settingsWithRigProviderImage(settings, version, backend, resolveBinding = resolveModalCheckpointProviderBinding) {
|
|
1429
|
-
return (await resolveRigProviderImageForRun(settings, version, backend, resolveBinding)).settings;
|
|
1430
|
-
}
|
|
1431
|
-
async function resolveSessionSandboxRuntime(db, settings, session) {
|
|
1432
|
-
const [packs2, rigVersion] = await Promise.all([
|
|
1433
|
-
resolveWorkspaceLegacyRuntimePacks(db, session.workspaceId),
|
|
1434
|
-
session.rigId && session.rigVersionId ? getRigVersion(db, session.workspaceId, session.rigId, session.rigVersionId) : Promise.resolve(null)
|
|
1435
|
-
]);
|
|
1436
|
-
if (session.rigVersionId && !rigVersion) {
|
|
1437
|
-
throw new Error(`Frozen rig version ${session.rigVersionId} is unavailable`);
|
|
1438
|
-
}
|
|
1439
|
-
const legacy = legacySandboxRuntimeFromPacks(packs2);
|
|
1440
|
-
const logicalSettings = rigVersion ? settings : settingsWithPackSandboxImage(settings, legacy.sandboxImage, legacy.sandboxProviderImages);
|
|
1441
|
-
return {
|
|
1442
|
-
settings: {
|
|
1443
|
-
...logicalSettings,
|
|
1444
|
-
sandboxBackend: session.sandboxBackend
|
|
1445
|
-
},
|
|
1446
|
-
image: rigProviderImageSourceImage(logicalSettings, session.sandboxBackend),
|
|
1447
|
-
rigVersion
|
|
1448
|
-
};
|
|
1449
|
-
}
|
|
1450
|
-
async function providerSettingsForSessionSandboxRuntime(runtime, backend) {
|
|
1451
|
-
return await settingsWithRigProviderImage(runtime.settings, runtime.rigVersion, backend);
|
|
1833
|
+
};
|
|
1452
1834
|
}
|
|
1453
1835
|
|
|
1454
1836
|
// src/access/index.ts
|
|
@@ -1467,7 +1849,38 @@ import { HTTPException } from "hono/http-exception";
|
|
|
1467
1849
|
var bearerPrefix = "Bearer ";
|
|
1468
1850
|
var accessContextByRequest = /* @__PURE__ */ new WeakMap();
|
|
1469
1851
|
var canonicalManagedCookieContexts = /* @__PURE__ */ new WeakSet();
|
|
1852
|
+
var canonicalLocalHumanContexts = /* @__PURE__ */ new WeakSet();
|
|
1470
1853
|
var resolvedAccessGrantAuthorizations = /* @__PURE__ */ new WeakSet();
|
|
1854
|
+
var accountScopedApiKeyContexts = /* @__PURE__ */ new WeakMap();
|
|
1855
|
+
var accountScopedApiKeyAccountPermissions = /* @__PURE__ */ new Set([
|
|
1856
|
+
"account:read",
|
|
1857
|
+
"account:admin",
|
|
1858
|
+
"workspace:create",
|
|
1859
|
+
"billing:read",
|
|
1860
|
+
"billing:manage",
|
|
1861
|
+
"api_keys:manage"
|
|
1862
|
+
]);
|
|
1863
|
+
var accountScopedApiKeyWorkspaceExcludedPermissions = /* @__PURE__ */ new Set([
|
|
1864
|
+
"account:read",
|
|
1865
|
+
"account:admin",
|
|
1866
|
+
"workspace:create",
|
|
1867
|
+
"billing:read",
|
|
1868
|
+
"billing:manage"
|
|
1869
|
+
]);
|
|
1870
|
+
function accountScopedApiKeyWorkspaceAuthority(context) {
|
|
1871
|
+
const authority = accountScopedApiKeyContexts.get(context);
|
|
1872
|
+
if (!authority) return null;
|
|
1873
|
+
const matchingAccountGrants = context.accountGrants.filter(
|
|
1874
|
+
(grant) => grant.accountId === authority.accountId && grant.subjectId === context.subjectId
|
|
1875
|
+
);
|
|
1876
|
+
if (!context.subjectId.startsWith("api_key:") || matchingAccountGrants.length !== 1 || context.defaultAccountId !== authority.accountId || context.defaultWorkspaceId !== null) {
|
|
1877
|
+
return null;
|
|
1878
|
+
}
|
|
1879
|
+
return {
|
|
1880
|
+
accountId: authority.accountId,
|
|
1881
|
+
permissions: [...authority.permissions]
|
|
1882
|
+
};
|
|
1883
|
+
}
|
|
1471
1884
|
async function requireAccessContext(c, deps) {
|
|
1472
1885
|
let pending = accessContextByRequest.get(c.req.raw);
|
|
1473
1886
|
if (!pending) {
|
|
@@ -1505,7 +1918,8 @@ function accessGrantAuthorizationFromContext(context, grant) {
|
|
|
1505
1918
|
accountGrant: contextIntegrity ? matchingAccountGrants[0] : null,
|
|
1506
1919
|
authenticatedSubjectId: context.subjectId,
|
|
1507
1920
|
contextIntegrity,
|
|
1508
|
-
canonicalManagedHumanSession: isCanonicalManagedHumanSession(context, grant)
|
|
1921
|
+
canonicalManagedHumanSession: isCanonicalManagedHumanSession(context, grant),
|
|
1922
|
+
canonicalLocalHumanSession: isCanonicalLocalHumanSession(context, grant)
|
|
1509
1923
|
};
|
|
1510
1924
|
resolvedAccessGrantAuthorizations.add(authorization);
|
|
1511
1925
|
return authorization;
|
|
@@ -1522,13 +1936,31 @@ function requireAccountAdminAuthorizationStamp(authorization) {
|
|
|
1522
1936
|
permission: "account:admin"
|
|
1523
1937
|
});
|
|
1524
1938
|
}
|
|
1939
|
+
async function requireCanonicalLocalAccountAdministrator(c, deps, accountId) {
|
|
1940
|
+
if (c.req.header("authorization")) {
|
|
1941
|
+
throw new HTTPException(401, { message: "organization administrator session required" });
|
|
1942
|
+
}
|
|
1943
|
+
const context = await requireAccessContext(c, deps);
|
|
1944
|
+
const grant = context.workspaceGrants.find((candidate) => candidate.accountId === accountId);
|
|
1945
|
+
if (!grant) {
|
|
1946
|
+
throw new HTTPException(403, {
|
|
1947
|
+
message: "local organization administration is not authorized"
|
|
1948
|
+
});
|
|
1949
|
+
}
|
|
1950
|
+
const authorization = accessGrantAuthorizationFromContext(context, grant);
|
|
1951
|
+
if (!authorization.canonicalLocalHumanSession) {
|
|
1952
|
+
throw new HTTPException(401, { message: "organization administrator session required" });
|
|
1953
|
+
}
|
|
1954
|
+
requireAccountAdminAuthorizationStamp(authorization);
|
|
1955
|
+
return { subjectId: context.subjectId, authorization };
|
|
1956
|
+
}
|
|
1525
1957
|
async function requireAccessGrantAuthorization(c, deps, workspaceId, permission) {
|
|
1526
1958
|
const context = await requireAccessContext(c, deps);
|
|
1527
1959
|
return await accessGrantAuthorization(context, deps, workspaceId, permission);
|
|
1528
1960
|
}
|
|
1529
1961
|
async function accessGrantAuthorization(context, deps, workspaceId, permission) {
|
|
1530
1962
|
const principalKind = hostedHumanSessionPrincipalKind(context);
|
|
1531
|
-
|
|
1963
|
+
let grant = context.workspaceGrants.find((candidate) => candidate.workspaceId === workspaceId) ?? await getWorkspaceGrant(
|
|
1532
1964
|
deps.db,
|
|
1533
1965
|
context.subjectId,
|
|
1534
1966
|
workspaceId,
|
|
@@ -1539,7 +1971,20 @@ async function accessGrantAuthorization(context, deps, workspaceId, permission)
|
|
|
1539
1971
|
if (!workspace) {
|
|
1540
1972
|
throw new HTTPException(404, { message: "workspace not found" });
|
|
1541
1973
|
}
|
|
1542
|
-
|
|
1974
|
+
const authority = accountScopedApiKeyWorkspaceAuthority(context);
|
|
1975
|
+
const requiredWorkspacePermission = permission ?? "workspace:read";
|
|
1976
|
+
if (authority && workspace.accountId === authority.accountId && workspace.kind === "shared" && hasPermission(authority.permissions, requiredWorkspacePermission)) {
|
|
1977
|
+
grant = {
|
|
1978
|
+
workspaceId: workspace.id,
|
|
1979
|
+
accountId: workspace.accountId,
|
|
1980
|
+
subjectId: context.subjectId,
|
|
1981
|
+
...context.subjectLabel ? { subjectLabel: context.subjectLabel } : {},
|
|
1982
|
+
permissions: authority.permissions,
|
|
1983
|
+
principalKind: "api_key"
|
|
1984
|
+
};
|
|
1985
|
+
} else {
|
|
1986
|
+
throw new HTTPException(403, { message: "workspace access denied" });
|
|
1987
|
+
}
|
|
1543
1988
|
}
|
|
1544
1989
|
if (permission) {
|
|
1545
1990
|
requirePermission(grant, permission);
|
|
@@ -1549,6 +1994,9 @@ async function accessGrantAuthorization(context, deps, workspaceId, permission)
|
|
|
1549
1994
|
function isCanonicalManagedHumanSession(context, grant) {
|
|
1550
1995
|
return canonicalManagedCookieContexts.has(context) && grant.subjectId === context.subjectId && grant.subjectId.startsWith("user:");
|
|
1551
1996
|
}
|
|
1997
|
+
function isCanonicalLocalHumanSession(context, grant) {
|
|
1998
|
+
return canonicalLocalHumanContexts.has(context) && context.mode === "local" && context.subjectId === "dev" && grant.subjectId === context.subjectId && grant.principalKind === "human_session" && grant.metadata?.delegated !== true && !grant.serviceInitiator;
|
|
1999
|
+
}
|
|
1552
2000
|
function hostedHumanSessionPrincipalKind(context) {
|
|
1553
2001
|
if (context.mode !== "managed" || context.workspaceGrants.length === 0) {
|
|
1554
2002
|
return void 0;
|
|
@@ -1598,7 +2046,7 @@ async function resolveAccessContext(c, deps) {
|
|
|
1598
2046
|
if (delegated) {
|
|
1599
2047
|
return delegated;
|
|
1600
2048
|
}
|
|
1601
|
-
|
|
2049
|
+
const context = await bootstrapWorkspace(deps.db, {
|
|
1602
2050
|
accountExternalSource: "opengeni:local",
|
|
1603
2051
|
accountExternalId: "default",
|
|
1604
2052
|
accountName: "Local",
|
|
@@ -1608,6 +2056,8 @@ async function resolveAccessContext(c, deps) {
|
|
|
1608
2056
|
subjectId: "dev",
|
|
1609
2057
|
subjectLabel: "Local dev"
|
|
1610
2058
|
});
|
|
2059
|
+
canonicalLocalHumanContexts.add(context);
|
|
2060
|
+
return context;
|
|
1611
2061
|
}
|
|
1612
2062
|
if (deps.settings.productAccessMode === "configured") {
|
|
1613
2063
|
const delegated = await delegatedAccessContext(c, deps, "configured");
|
|
@@ -1676,8 +2126,10 @@ async function apiKeyAccessContext(c, deps, mode) {
|
|
|
1676
2126
|
const subjectId = `api_key:${apiKey.id}`;
|
|
1677
2127
|
const accountPermissions = apiKey.workspaceId ? apiKey.permissions.filter(
|
|
1678
2128
|
(permission) => permission === "billing:read" || permission === "billing:manage"
|
|
1679
|
-
) : apiKey.permissions
|
|
1680
|
-
|
|
2129
|
+
) : apiKey.permissions.filter(
|
|
2130
|
+
(permission) => accountScopedApiKeyAccountPermissions.has(permission)
|
|
2131
|
+
);
|
|
2132
|
+
const context = {
|
|
1681
2133
|
mode,
|
|
1682
2134
|
subjectId,
|
|
1683
2135
|
subjectLabel: apiKey.name,
|
|
@@ -1702,6 +2154,20 @@ async function apiKeyAccessContext(c, deps, mode) {
|
|
|
1702
2154
|
defaultAccountId: apiKey.accountId,
|
|
1703
2155
|
defaultWorkspaceId: apiKey.workspaceId
|
|
1704
2156
|
};
|
|
2157
|
+
if (apiKey.workspaceId === null && apiKey.credentialKind === "organization") {
|
|
2158
|
+
accountScopedApiKeyContexts.set(
|
|
2159
|
+
context,
|
|
2160
|
+
Object.freeze({
|
|
2161
|
+
accountId: apiKey.accountId,
|
|
2162
|
+
permissions: Object.freeze(
|
|
2163
|
+
apiKey.permissions.filter(
|
|
2164
|
+
(permission) => !accountScopedApiKeyWorkspaceExcludedPermissions.has(permission)
|
|
2165
|
+
)
|
|
2166
|
+
)
|
|
2167
|
+
})
|
|
2168
|
+
);
|
|
2169
|
+
}
|
|
2170
|
+
return context;
|
|
1705
2171
|
}
|
|
1706
2172
|
async function delegatedAccessContext(c, deps, mode, token = bearerToken(c)) {
|
|
1707
2173
|
const delegationSecret = resolveFirstPartyDelegationSecret(deps.settings);
|
|
@@ -1969,9 +2435,13 @@ async function resolveSessionAuthorizationActor(db, grant) {
|
|
|
1969
2435
|
}
|
|
1970
2436
|
|
|
1971
2437
|
// src/billing/limits.ts
|
|
1972
|
-
import {
|
|
2438
|
+
import {
|
|
2439
|
+
configuredStaticUsageLimits,
|
|
2440
|
+
resolveModelProviderForTurn
|
|
2441
|
+
} from "@opengeni/config";
|
|
1973
2442
|
import {
|
|
1974
2443
|
countActiveApiKeysForWorkspace,
|
|
2444
|
+
countActiveOrganizationApiKeysForAccount,
|
|
1975
2445
|
countScheduledTasksForWorkspace,
|
|
1976
2446
|
countWorkspacesForAccount,
|
|
1977
2447
|
getBillingBalance,
|
|
@@ -1980,6 +2450,18 @@ import {
|
|
|
1980
2450
|
sumUsageQuantity
|
|
1981
2451
|
} from "@opengeni/db";
|
|
1982
2452
|
import { HTTPException as HTTPException2 } from "hono/http-exception";
|
|
2453
|
+
function modelFundingForAdmission(settings, model, codexBilled) {
|
|
2454
|
+
const resolvedModel = model ? resolveModelProviderForTurn(settings, model)?.model : null;
|
|
2455
|
+
const codexSubscriptionModel = resolvedModel?.credentialSource.kind === "connected_subscription" && resolvedModel.credentialSource.provider === "codex";
|
|
2456
|
+
return {
|
|
2457
|
+
// A Codex namespace/definition never bypasses credits by itself: the live
|
|
2458
|
+
// workspace credential predicate above remains authoritative. SuperGrok's
|
|
2459
|
+
// static overlay is likewise secret-free; its worker/provider admission
|
|
2460
|
+
// owns live account selection before any upstream request can occur.
|
|
2461
|
+
fundedWithoutCredits: codexBilled || resolvedModel != null && !codexSubscriptionModel && resolvedModel.cost !== "credits",
|
|
2462
|
+
countsTowardTokenCap: !codexBilled && resolvedModel != null && resolvedModel.billing.upstreamPayer === "deployment"
|
|
2463
|
+
};
|
|
2464
|
+
}
|
|
1983
2465
|
async function requireLimit(deps, input) {
|
|
1984
2466
|
const decision = await checkLimit(deps, input);
|
|
1985
2467
|
if (decision.allowed) {
|
|
@@ -1996,19 +2478,22 @@ async function checkLimit(deps, input) {
|
|
|
1996
2478
|
workspaceId: input.workspaceId,
|
|
1997
2479
|
model: input.model
|
|
1998
2480
|
}) : false;
|
|
1999
|
-
const
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2004
|
-
const creditDecision = await checkCreditBalance(deps, input,
|
|
2481
|
+
const { fundedWithoutCredits, countsTowardTokenCap } = modelFundingForAdmission(
|
|
2482
|
+
deps.settings,
|
|
2483
|
+
input.model,
|
|
2484
|
+
codexBilled
|
|
2485
|
+
);
|
|
2486
|
+
const creditDecision = await checkCreditBalance(deps, input, fundedWithoutCredits);
|
|
2005
2487
|
if (!creditDecision.allowed) {
|
|
2006
2488
|
return creditDecision;
|
|
2007
2489
|
}
|
|
2008
2490
|
if (deps.settings.usageLimitsMode !== "static" && deps.settings.usageLimitsMode !== "managed") {
|
|
2009
2491
|
return { allowed: true };
|
|
2010
2492
|
}
|
|
2011
|
-
return await checkStaticCaps(deps, input,
|
|
2493
|
+
return await checkStaticCaps(deps, input, {
|
|
2494
|
+
fundedWithoutCredits,
|
|
2495
|
+
countsTowardTokenCap
|
|
2496
|
+
});
|
|
2012
2497
|
}
|
|
2013
2498
|
async function checkCreditBalance(deps, input, externallyBilled) {
|
|
2014
2499
|
if (externallyBilled) {
|
|
@@ -2023,9 +2508,9 @@ async function checkCreditBalance(deps, input, externallyBilled) {
|
|
|
2023
2508
|
}
|
|
2024
2509
|
return { allowed: false, code: "insufficient_credits", message: "insufficient OpenGeni credits" };
|
|
2025
2510
|
}
|
|
2026
|
-
async function checkStaticCaps(deps, input,
|
|
2511
|
+
async function checkStaticCaps(deps, input, funding) {
|
|
2027
2512
|
const limits = configuredStaticUsageLimits(deps.settings);
|
|
2028
|
-
if (limits.maxMonthlyCostMicrosPerAccount && isCostlyAction(input.action) && !
|
|
2513
|
+
if (limits.maxMonthlyCostMicrosPerAccount && isCostlyAction(input.action) && !funding.fundedWithoutCredits) {
|
|
2029
2514
|
const used = await sumUsageQuantity(deps.db, {
|
|
2030
2515
|
accountId: input.accountId,
|
|
2031
2516
|
eventType: "model.cost",
|
|
@@ -2050,10 +2535,10 @@ async function checkStaticCaps(deps, input, externallyBilled) {
|
|
|
2050
2535
|
);
|
|
2051
2536
|
}
|
|
2052
2537
|
case "api_key:create": {
|
|
2053
|
-
if (!limits.maxApiKeysPerWorkspace
|
|
2538
|
+
if (!limits.maxApiKeysPerWorkspace) {
|
|
2054
2539
|
return { allowed: true };
|
|
2055
2540
|
}
|
|
2056
|
-
const count = await countActiveApiKeysForWorkspace(deps.db, input.workspaceId);
|
|
2541
|
+
const count = input.workspaceId ? await countActiveApiKeysForWorkspace(deps.db, input.workspaceId) : await countActiveOrganizationApiKeysForAccount(deps.db, input.accountId);
|
|
2057
2542
|
return count < limits.maxApiKeysPerWorkspace ? { allowed: true } : blocked(
|
|
2058
2543
|
"max_api_keys_per_workspace",
|
|
2059
2544
|
`API key limit reached (${limits.maxApiKeysPerWorkspace})`
|
|
@@ -2094,7 +2579,7 @@ async function checkStaticCaps(deps, input, externallyBilled) {
|
|
|
2094
2579
|
);
|
|
2095
2580
|
}
|
|
2096
2581
|
case "tokens:consume": {
|
|
2097
|
-
if (
|
|
2582
|
+
if (!funding.countsTowardTokenCap || !limits.maxMonthlyTokensPerWorkspace || !input.workspaceId) {
|
|
2098
2583
|
return { allowed: true };
|
|
2099
2584
|
}
|
|
2100
2585
|
const used = await sumUsageQuantity(deps.db, {
|
|
@@ -4965,42 +5450,15 @@ function sha256Hex2(bytes) {
|
|
|
4965
5450
|
|
|
4966
5451
|
// src/domain/environments.ts
|
|
4967
5452
|
import { environmentsEncryptionKeyBytes as environmentsEncryptionKeyBytes2 } from "@opengeni/config";
|
|
5453
|
+
import {
|
|
5454
|
+
variableSetVariableNameReservation
|
|
5455
|
+
} from "@opengeni/contracts";
|
|
4968
5456
|
import { getVariableSet as getVariableSet2, recordAuditEvent } from "@opengeni/db";
|
|
4969
5457
|
import { HTTPException as HTTPException6 } from "hono/http-exception";
|
|
4970
5458
|
var MAX_ENVIRONMENTS_PER_WORKSPACE = 25;
|
|
4971
5459
|
var MAX_VARIABLES_PER_ENVIRONMENT = 100;
|
|
4972
|
-
var reservedExactNames = /* @__PURE__ */ new Set([
|
|
4973
|
-
"HOME",
|
|
4974
|
-
"PATH",
|
|
4975
|
-
"SHELL",
|
|
4976
|
-
"USER",
|
|
4977
|
-
"LOGNAME",
|
|
4978
|
-
"TMPDIR",
|
|
4979
|
-
"IFS",
|
|
4980
|
-
"ENV",
|
|
4981
|
-
"BASH_ENV",
|
|
4982
|
-
"NODE_OPTIONS",
|
|
4983
|
-
"PYTHONPATH",
|
|
4984
|
-
"PYTHONSTARTUP",
|
|
4985
|
-
"PERL5OPT",
|
|
4986
|
-
"PERL5LIB",
|
|
4987
|
-
"GH_TOKEN",
|
|
4988
|
-
"GITHUB_TOKEN",
|
|
4989
|
-
"GITLAB_TOKEN",
|
|
4990
|
-
"AZURE_DEVOPS_EXT_PAT",
|
|
4991
|
-
"GIT_ASKPASS",
|
|
4992
|
-
"GIT_TERMINAL_PROMPT"
|
|
4993
|
-
]);
|
|
4994
|
-
var reservedPrefixes = [
|
|
4995
|
-
"OPENGENI_",
|
|
4996
|
-
"GIT_CONFIG_",
|
|
4997
|
-
"GIT_AUTHOR_",
|
|
4998
|
-
"GIT_COMMITTER_",
|
|
4999
|
-
"LD_",
|
|
5000
|
-
"DYLD_"
|
|
5001
|
-
];
|
|
5002
5460
|
function assertAllowedVariableSetVariableName(name) {
|
|
5003
|
-
if (
|
|
5461
|
+
if (variableSetVariableNameReservation(name)) {
|
|
5004
5462
|
throw new HTTPException6(422, {
|
|
5005
5463
|
message: `reserved variable set variable name / reserved environment variable name: ${name}`
|
|
5006
5464
|
});
|
|
@@ -6250,15 +6708,40 @@ function personalConnectionDelegationsFromParent(input) {
|
|
|
6250
6708
|
const projected = [
|
|
6251
6709
|
...mcp,
|
|
6252
6710
|
...input.parentDelegations.filter(
|
|
6253
|
-
(item) => childEligible(item) && (item.connectionType === "social" || item.connectionType === "atlassian" || item.serverId === GOOGLE_DRIVE_PUBLICATION_SERVER_ID)
|
|
6711
|
+
(item) => childEligible(item) && (item.connectionType === "social" || item.connectionType === "atlassian" || item.connectionType === "github_personal" || item.serverId === GOOGLE_DRIVE_PUBLICATION_SERVER_ID)
|
|
6254
6712
|
).map((item) => ({ ...item }))
|
|
6255
6713
|
];
|
|
6256
|
-
|
|
6714
|
+
const requestedGitHub = personalGitHubRepositoryResources(input.personalGitHubResources ?? []);
|
|
6715
|
+
const inherited = projected.flatMap((delegation) => {
|
|
6716
|
+
if (delegation.connectionType !== "github_personal") return [delegation];
|
|
6717
|
+
if (requestedGitHub.length === 0) return [];
|
|
6718
|
+
const snapshot = delegation.personalGitHubRepositorySelection;
|
|
6719
|
+
if (!snapshot) return [];
|
|
6720
|
+
const repositories = requestedGitHub.map((resource) => {
|
|
6721
|
+
const parent = snapshot.repositories.find(
|
|
6722
|
+
(candidate) => candidate.repositoryId === resource.repositoryId && candidate.canonicalUrl === resource.uri && candidate.ref === resource.ref
|
|
6723
|
+
);
|
|
6724
|
+
if (!parent || resource.credentialBindingId !== snapshot.credentialBindingId || resource.access === "write" && parent.access !== "write") {
|
|
6725
|
+
throw new Error("agent-created personal GitHub repository exceeds parent authority");
|
|
6726
|
+
}
|
|
6727
|
+
return { ...parent, access: resource.access };
|
|
6728
|
+
});
|
|
6729
|
+
return [
|
|
6730
|
+
{
|
|
6731
|
+
...delegation,
|
|
6732
|
+
personalGitHubRepositorySelection: { ...snapshot, repositories }
|
|
6733
|
+
}
|
|
6734
|
+
];
|
|
6735
|
+
});
|
|
6736
|
+
if (requestedGitHub.length > 0 && !inherited.some((delegation) => delegation.connectionType === "github_personal")) {
|
|
6737
|
+
throw new Error("agent-created personal GitHub repository authority is unavailable");
|
|
6738
|
+
}
|
|
6739
|
+
if (input.rejectActivatedConnections && inherited.some((delegation) => delegation.userDelegation)) {
|
|
6257
6740
|
throw new Error(
|
|
6258
6741
|
"scheduled connection authority is not available until task occurrence authority is activated"
|
|
6259
6742
|
);
|
|
6260
6743
|
}
|
|
6261
|
-
return
|
|
6744
|
+
return inherited;
|
|
6262
6745
|
}
|
|
6263
6746
|
function googleDrivePublicationDelegationFromVisibleConnections(input) {
|
|
6264
6747
|
const selection = input.authoritySelection;
|
|
@@ -6471,11 +6954,6 @@ async function freezePersonalConnectionDelegations(input) {
|
|
|
6471
6954
|
"agent-created work inherits connection authority from its exact parent turn"
|
|
6472
6955
|
);
|
|
6473
6956
|
}
|
|
6474
|
-
if (personalGitHubResources.length > 0) {
|
|
6475
|
-
throw new Error(
|
|
6476
|
-
"agent-created personal GitHub repository authority is not activated in this delivery phase"
|
|
6477
|
-
);
|
|
6478
|
-
}
|
|
6479
6957
|
const inherited = personalConnectionDelegationsFromParent({
|
|
6480
6958
|
servers,
|
|
6481
6959
|
parentDelegations: await getSessionTurnPersonalConnectionDelegations(
|
|
@@ -6484,6 +6962,7 @@ async function freezePersonalConnectionDelegations(input) {
|
|
|
6484
6962
|
input.source.sessionId,
|
|
6485
6963
|
input.source.turnId
|
|
6486
6964
|
),
|
|
6965
|
+
personalGitHubResources,
|
|
6487
6966
|
...input.targetSessionId ? { targetSessionId: input.targetSessionId } : {},
|
|
6488
6967
|
...input.rejectUnselectedActivatedConnections !== void 0 ? { rejectActivatedConnections: input.rejectUnselectedActivatedConnections } : {}
|
|
6489
6968
|
});
|
|
@@ -6935,6 +7414,8 @@ import {
|
|
|
6935
7414
|
createScheduledTask,
|
|
6936
7415
|
deleteScheduledTask,
|
|
6937
7416
|
getConnectionMetadata as getConnectionMetadata4,
|
|
7417
|
+
getEnrollment as getEnrollment3,
|
|
7418
|
+
getLiveEnrollmentConnection as getLiveEnrollmentConnection3,
|
|
6938
7419
|
getKnowledgeSourceForSyncAuthority,
|
|
6939
7420
|
getNestedAgentDepthDeploymentPolicy,
|
|
6940
7421
|
getRig as getRig5,
|
|
@@ -6942,8 +7423,11 @@ import {
|
|
|
6942
7423
|
getScheduledTaskIncludingDeletedForUpdate,
|
|
6943
7424
|
getScheduledTaskPersonalConnectionDelegations,
|
|
6944
7425
|
getScheduledTaskXaiProviderAccountAuthoritySnapshot,
|
|
7426
|
+
getSandbox as getSandbox4,
|
|
6945
7427
|
getSessionTurnXaiProviderAccountAuthoritySnapshot as getSessionTurnXaiProviderAccountAuthoritySnapshot2,
|
|
6946
7428
|
getSession as getSession3,
|
|
7429
|
+
lockActiveWorkspaceGatewayCustomModelForAdmission as lockActiveWorkspaceGatewayCustomModelForAdmission2,
|
|
7430
|
+
lockActiveWorkspaceOpenRouterCustomModelForAdmission as lockActiveWorkspaceOpenRouterCustomModelForAdmission2,
|
|
6947
7431
|
nestedPostgresSqlState as nestedPostgresSqlState2,
|
|
6948
7432
|
requireWorkspace as requireWorkspace4,
|
|
6949
7433
|
scopedKnowledgeScopeKey,
|
|
@@ -6959,13 +7443,15 @@ import { CODEX_MODEL_ID_PREFIX, isCodexBilledModel } from "@opengeni/codex";
|
|
|
6959
7443
|
import {
|
|
6960
7444
|
canonicalizeConfiguredModelId,
|
|
6961
7445
|
configuredAllowedModels,
|
|
7446
|
+
WORKSPACE_GATEWAY_MODEL_ID_PREFIX as WORKSPACE_GATEWAY_MODEL_ID_PREFIX2,
|
|
7447
|
+
WORKSPACE_OPENROUTER_MODEL_ID_PREFIX as WORKSPACE_OPENROUTER_MODEL_ID_PREFIX2,
|
|
6962
7448
|
resolveFirstPartyMcpToolPolicy,
|
|
6963
7449
|
policyProviderIdForModel,
|
|
6964
7450
|
resolveTurnExecutionPolicyV1,
|
|
6965
|
-
WORKSPACE_GATEWAY_MODEL_ID_PREFIX,
|
|
6966
7451
|
XAI_SUBSCRIPTION_MODEL_ID_PREFIX
|
|
6967
7452
|
} from "@opengeni/config";
|
|
6968
7453
|
import {
|
|
7454
|
+
AUTOMATIC_SESSION_TITLE_FALLBACK,
|
|
6969
7455
|
CreateSessionRequest,
|
|
6970
7456
|
DEFAULT_FIRST_PARTY_MCP_PERMISSIONS,
|
|
6971
7457
|
DEFAULT_FIRST_PARTY_MCP_TOOLS,
|
|
@@ -6975,14 +7461,18 @@ import {
|
|
|
6975
7461
|
SessionSpawnDenial,
|
|
6976
7462
|
ServiceTurnInitiator,
|
|
6977
7463
|
ServiceTurnInitiatorContext,
|
|
6978
|
-
evaluateWorkspaceModelPolicy,
|
|
7464
|
+
evaluateWorkspaceModelPolicy as evaluateWorkspaceModelPolicy2,
|
|
7465
|
+
normalizeAutomaticSessionTitle,
|
|
6979
7466
|
resolveWorkspaceSessionToolDefaults as resolveWorkspaceSessionToolDefaults2,
|
|
7467
|
+
metadataWithTurnExecutionPolicyV1,
|
|
7468
|
+
readTurnExecutionPolicyV1,
|
|
6980
7469
|
stableJson as stableJson4,
|
|
6981
7470
|
SessionMcpApprovalPolicy
|
|
6982
7471
|
} from "@opengeni/contracts";
|
|
6983
7472
|
import {
|
|
6984
7473
|
createSession,
|
|
6985
7474
|
createSessionWithIdempotencyKeyResult,
|
|
7475
|
+
canonicalSessionCommandHash,
|
|
6986
7476
|
encryptVariableSetValue as encryptVariableSetValue2,
|
|
6987
7477
|
getAnySessionInGroup,
|
|
6988
7478
|
getEnrollment as getEnrollment2,
|
|
@@ -6993,10 +7483,10 @@ import {
|
|
|
6993
7483
|
listDistinctRigVersionIdsInGroup,
|
|
6994
7484
|
getSandbox as getSandbox3,
|
|
6995
7485
|
getSession as getSession2,
|
|
7486
|
+
getInitializedSessionCreateReplay,
|
|
6996
7487
|
getSessionAuthorityProjection as getSessionAuthorityProjection2,
|
|
6997
7488
|
SessionIdConflictError,
|
|
6998
7489
|
NewSessionDraftConflictError,
|
|
6999
|
-
getSessionSpawnDenialByIdempotencyKey,
|
|
7000
7490
|
getWorkspaceControlEvent,
|
|
7001
7491
|
getSessionLineage,
|
|
7002
7492
|
getSessionTurn,
|
|
@@ -7008,7 +7498,10 @@ import {
|
|
|
7008
7498
|
initializeSessionStartAtomically,
|
|
7009
7499
|
listSessionTurns,
|
|
7010
7500
|
listSessionMcpServersForChildInheritance,
|
|
7501
|
+
lockActiveWorkspaceGatewayCustomModelForAdmission,
|
|
7502
|
+
lockActiveWorkspaceOpenRouterCustomModelForAdmission,
|
|
7011
7503
|
requireSession as requireSession2,
|
|
7504
|
+
replaySubmittedHumanPromptFromBoundaryReceipt,
|
|
7012
7505
|
submitHumanPromptInTransaction,
|
|
7013
7506
|
appendSessionEventsWithLockedSessionUpdate,
|
|
7014
7507
|
updateSessionTitleWithEvent,
|
|
@@ -7876,13 +8369,60 @@ function validateSessionMcpCredentialUpdates(input) {
|
|
|
7876
8369
|
});
|
|
7877
8370
|
return encryptedUpdates;
|
|
7878
8371
|
}
|
|
8372
|
+
var AGENT_CHILD_AUTOMATIC_TITLE_CONTEXT_KEY = "agentChildAutomaticTitle";
|
|
8373
|
+
function freezeAgentChildAutomaticTitleInCreatorContext(context, title) {
|
|
8374
|
+
return title ? { ...context ?? {}, [AGENT_CHILD_AUTOMATIC_TITLE_CONTEXT_KEY]: title } : context;
|
|
8375
|
+
}
|
|
8376
|
+
function initialAutomaticTitleForSessionStart(session, requestedTitle) {
|
|
8377
|
+
const frozenTitle = session.createdByContext[AGENT_CHILD_AUTOMATIC_TITLE_CONTEXT_KEY];
|
|
8378
|
+
return typeof frozenTitle === "string" ? frozenTitle : requestedTitle ?? null;
|
|
8379
|
+
}
|
|
8380
|
+
function automaticTitleForAgentChildCreate(presentation, goal, initialMessage) {
|
|
8381
|
+
for (const candidate of [presentation.automaticTitleCandidate, goal?.text, initialMessage]) {
|
|
8382
|
+
if (typeof candidate !== "string") continue;
|
|
8383
|
+
const normalized = normalizeAutomaticSessionTitle(candidate);
|
|
8384
|
+
if (normalized && normalized !== AUTOMATIC_SESSION_TITLE_FALLBACK) return normalized;
|
|
8385
|
+
}
|
|
8386
|
+
return null;
|
|
8387
|
+
}
|
|
7879
8388
|
async function createAndStartSessionWithOutcome(input) {
|
|
7880
|
-
const sessionMetadata =
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
8389
|
+
const sessionMetadata = metadataWithTurnExecutionPolicyV1(
|
|
8390
|
+
{
|
|
8391
|
+
...input.metadata,
|
|
8392
|
+
model: input.model,
|
|
8393
|
+
reasoningEffort: input.reasoningEffort,
|
|
8394
|
+
...input.latencyMode !== void 0 ? { latencyMode: input.latencyMode } : {}
|
|
8395
|
+
},
|
|
8396
|
+
input.turnExecutionPolicy
|
|
8397
|
+
);
|
|
8398
|
+
const frozenCreatedByContext = freezeAgentChildAutomaticTitleInCreatorContext(
|
|
8399
|
+
input.createdByContext,
|
|
8400
|
+
input.initialAutomaticTitle
|
|
8401
|
+
);
|
|
8402
|
+
const requiresActiveWorkspaceCustomModel = (input.workspaceCustomModel === true || input.workspaceGatewayCustomModel === true) && input.retainWorkspaceCustomModel !== true && input.retainWorkspaceGatewayModel !== true;
|
|
8403
|
+
const beforeCreateCommit = requiresActiveWorkspaceCustomModel || input.beforeCreateCommit ? async (tx, sessionId, context) => {
|
|
8404
|
+
if (requiresActiveWorkspaceCustomModel && context?.created !== false) {
|
|
8405
|
+
const openRouter = input.model.startsWith(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX2);
|
|
8406
|
+
const upstreamModelId = input.model.slice(
|
|
8407
|
+
openRouter ? WORKSPACE_OPENROUTER_MODEL_ID_PREFIX2.length : WORKSPACE_GATEWAY_MODEL_ID_PREFIX2.length
|
|
8408
|
+
);
|
|
8409
|
+
const active = openRouter ? await lockActiveWorkspaceOpenRouterCustomModelForAdmission(tx, {
|
|
8410
|
+
accountId: input.accountId,
|
|
8411
|
+
workspaceId: input.workspaceId,
|
|
8412
|
+
upstreamModelId
|
|
8413
|
+
}) : await lockActiveWorkspaceGatewayCustomModelForAdmission(tx, {
|
|
8414
|
+
accountId: input.accountId,
|
|
8415
|
+
workspaceId: input.workspaceId,
|
|
8416
|
+
upstreamModelId
|
|
8417
|
+
});
|
|
8418
|
+
if (!active) {
|
|
8419
|
+
throw new HTTPException11(422, {
|
|
8420
|
+
message: `model is not available: ${input.model}`
|
|
8421
|
+
});
|
|
8422
|
+
}
|
|
8423
|
+
}
|
|
8424
|
+
await input.beforeCreateCommit?.(tx, sessionId);
|
|
8425
|
+
} : void 0;
|
|
7886
8426
|
if (input.createIdempotencyKey) {
|
|
7887
8427
|
const keyedResult = await createSessionWithIdempotencyKeyResult(input.db, {
|
|
7888
8428
|
...input.requestedSessionId ? { requestedSessionId: input.requestedSessionId } : {},
|
|
@@ -7897,7 +8437,7 @@ async function createAndStartSessionWithOutcome(input) {
|
|
|
7897
8437
|
toolPolicy: input.toolPolicy,
|
|
7898
8438
|
metadata: sessionMetadata,
|
|
7899
8439
|
...input.createdBy ? { createdBy: input.createdBy } : {},
|
|
7900
|
-
...
|
|
8440
|
+
...frozenCreatedByContext ? { createdByContext: frozenCreatedByContext } : {},
|
|
7901
8441
|
createdByActor: input.createdByActor ?? null,
|
|
7902
8442
|
model: input.model,
|
|
7903
8443
|
reasoningEffort: input.reasoningEffort,
|
|
@@ -7925,15 +8465,23 @@ async function createAndStartSessionWithOutcome(input) {
|
|
|
7925
8465
|
maxNestedAgentDepthOverride: input.maxNestedAgentDepthOverride ?? null,
|
|
7926
8466
|
allowNestedAgentDepthIncrease: input.allowNestedAgentDepthIncrease ?? false,
|
|
7927
8467
|
subjectId: input.subjectId ?? null,
|
|
7928
|
-
...
|
|
8468
|
+
...beforeCreateCommit ? { beforeCreateCommit } : {}
|
|
7929
8469
|
});
|
|
7930
8470
|
if (keyedResult.denied) {
|
|
7931
8471
|
throw new SessionSpawnDeniedError(SessionSpawnDenial.parse(keyedResult.denial));
|
|
7932
8472
|
}
|
|
7933
8473
|
const { session: keyed, created } = keyedResult;
|
|
7934
8474
|
if (!created) {
|
|
8475
|
+
const persistedPolicy = readTurnExecutionPolicyV1(keyed.metadata);
|
|
7935
8476
|
const finished3 = await finishStartSession(
|
|
7936
|
-
keyed.temporalWorkflowId ? {
|
|
8477
|
+
keyed.temporalWorkflowId ? {
|
|
8478
|
+
...input,
|
|
8479
|
+
seedTargetSandbox: null,
|
|
8480
|
+
...persistedPolicy.kind === "valid" ? { turnExecutionPolicy: persistedPolicy.policy } : {}
|
|
8481
|
+
} : {
|
|
8482
|
+
...input,
|
|
8483
|
+
...persistedPolicy.kind === "valid" ? { turnExecutionPolicy: persistedPolicy.policy } : {}
|
|
8484
|
+
},
|
|
7937
8485
|
keyed
|
|
7938
8486
|
);
|
|
7939
8487
|
return {
|
|
@@ -7966,7 +8514,7 @@ async function createAndStartSessionWithOutcome(input) {
|
|
|
7966
8514
|
toolPolicy: input.toolPolicy,
|
|
7967
8515
|
metadata: sessionMetadata,
|
|
7968
8516
|
...input.createdBy ? { createdBy: input.createdBy } : {},
|
|
7969
|
-
...
|
|
8517
|
+
...frozenCreatedByContext ? { createdByContext: frozenCreatedByContext } : {},
|
|
7970
8518
|
createdByActor: input.createdByActor ?? null,
|
|
7971
8519
|
model: input.model,
|
|
7972
8520
|
reasoningEffort: input.reasoningEffort,
|
|
@@ -7993,7 +8541,7 @@ async function createAndStartSessionWithOutcome(input) {
|
|
|
7993
8541
|
maxNestedAgentDepthOverride: input.maxNestedAgentDepthOverride ?? null,
|
|
7994
8542
|
allowNestedAgentDepthIncrease: input.allowNestedAgentDepthIncrease ?? false,
|
|
7995
8543
|
subjectId: input.subjectId ?? null,
|
|
7996
|
-
...
|
|
8544
|
+
...beforeCreateCommit ? { beforeCreateCommit } : {}
|
|
7997
8545
|
});
|
|
7998
8546
|
} catch (error) {
|
|
7999
8547
|
if (error instanceof SessionSpawnDeniedDbError) {
|
|
@@ -8070,6 +8618,10 @@ async function finishStartSession(input, session) {
|
|
|
8070
8618
|
...input.goal.maxAutoContinuations !== void 0 ? { maxAutoContinuations: input.goal.maxAutoContinuations } : {},
|
|
8071
8619
|
...input.goal.mutationPolicy !== void 0 ? { mutationPolicy: input.goal.mutationPolicy } : {}
|
|
8072
8620
|
} : null,
|
|
8621
|
+
initialAutomaticTitle: initialAutomaticTitleForSessionStart(
|
|
8622
|
+
session,
|
|
8623
|
+
input.initialAutomaticTitle
|
|
8624
|
+
),
|
|
8073
8625
|
consumeNewSessionDraft: input.consumeNewSessionDraft ?? null,
|
|
8074
8626
|
rememberNewSessionSelection: input.rememberNewSessionSelection ?? null,
|
|
8075
8627
|
deferInitialTurn: input.deferInitialTurn === true
|
|
@@ -8108,9 +8660,6 @@ function canonicalConfiguredModel(settings, model) {
|
|
|
8108
8660
|
if (settings.supergrokSubscriptionEnabled && canonicalModel.startsWith(XAI_SUBSCRIPTION_MODEL_ID_PREFIX)) {
|
|
8109
8661
|
return canonicalModel;
|
|
8110
8662
|
}
|
|
8111
|
-
if (canonicalModel.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX)) {
|
|
8112
|
-
return canonicalModel;
|
|
8113
|
-
}
|
|
8114
8663
|
throw new HTTPException11(422, { message: `model is not available: ${model}` });
|
|
8115
8664
|
}
|
|
8116
8665
|
function assertConfiguredModel(settings, model) {
|
|
@@ -8147,7 +8696,7 @@ async function assertWorkspaceModelPolicyAllows(db, settings, workspaceId, model
|
|
|
8147
8696
|
return;
|
|
8148
8697
|
}
|
|
8149
8698
|
const providerId = policyProviderIdForModel(settings, canonicalModel);
|
|
8150
|
-
const verdict =
|
|
8699
|
+
const verdict = evaluateWorkspaceModelPolicy2(policy, {
|
|
8151
8700
|
providerId,
|
|
8152
8701
|
modelId: canonicalModel
|
|
8153
8702
|
});
|
|
@@ -8169,91 +8718,8 @@ async function requireQueuedTurnForApi(db, workspaceId, sessionId, turnId) {
|
|
|
8169
8718
|
}
|
|
8170
8719
|
return turn;
|
|
8171
8720
|
}
|
|
8172
|
-
|
|
8173
|
-
const { db, bus, workflowClient,
|
|
8174
|
-
const requestedModel = canonicalConfiguredModel(settings, input.model ?? null) ?? null;
|
|
8175
|
-
const requestedReasoningEffort = input.reasoningEffort ?? null;
|
|
8176
|
-
assertConfiguredModel(settings, requestedModel);
|
|
8177
|
-
await assertWorkspaceModelPolicyAllows(db, settings, workspaceId, requestedModel);
|
|
8178
|
-
const sessionForModelGate = await requireSession2(db, workspaceId, sessionId);
|
|
8179
|
-
const effectiveModelForGate = requestedModel ?? sessionForModelGate.model;
|
|
8180
|
-
try {
|
|
8181
|
-
assertSessionAllowsProductModel(sessionForModelGate, effectiveModelForGate);
|
|
8182
|
-
} catch (error) {
|
|
8183
|
-
if (error instanceof CodexCompactionV2ProviderLockedError) {
|
|
8184
|
-
throw new HTTPException11(422, { message: error.message, cause: error });
|
|
8185
|
-
}
|
|
8186
|
-
throw error;
|
|
8187
|
-
}
|
|
8188
|
-
const operationKey = input.clientEventId ?? crypto.randomUUID();
|
|
8189
|
-
let result;
|
|
8190
|
-
try {
|
|
8191
|
-
result = await runIdempotentPersistenceTransaction(
|
|
8192
|
-
{
|
|
8193
|
-
stage: "session.prompt.submit",
|
|
8194
|
-
eventTypes: ["user.message", "turn.queued", "session.status.changed"],
|
|
8195
|
-
maxAttempts: 3
|
|
8196
|
-
},
|
|
8197
|
-
async () => await withWorkspaceSubjectSessionActivityRls(
|
|
8198
|
-
db,
|
|
8199
|
-
workspaceId,
|
|
8200
|
-
input.actor ?? accountId,
|
|
8201
|
-
(scoped) => submitHumanPromptInTransaction(scoped, {
|
|
8202
|
-
accountId,
|
|
8203
|
-
workspaceId,
|
|
8204
|
-
sessionId,
|
|
8205
|
-
subjectId: input.actor ?? accountId,
|
|
8206
|
-
...input.actorLabel ? { subjectLabel: input.actorLabel } : {},
|
|
8207
|
-
actor: input.commandActor ?? {
|
|
8208
|
-
type: "human",
|
|
8209
|
-
subjectId: input.actor ?? accountId
|
|
8210
|
-
},
|
|
8211
|
-
operationKey,
|
|
8212
|
-
delivery: input.delivery ?? "send",
|
|
8213
|
-
controlEtag: input.controlEtag ?? null,
|
|
8214
|
-
expectedDraftRevision: input.expectedDraftRevision ?? null,
|
|
8215
|
-
text: input.text,
|
|
8216
|
-
annotations: input.annotations ?? [],
|
|
8217
|
-
modelContext: input.modelContext ?? null,
|
|
8218
|
-
resources: input.resources,
|
|
8219
|
-
...input.composerDraftResources ? { composerDraftResources: input.composerDraftResources } : {},
|
|
8220
|
-
model: requestedModel,
|
|
8221
|
-
reasoningEffort: requestedReasoningEffort,
|
|
8222
|
-
latencyMode: input.latencyMode ?? null,
|
|
8223
|
-
reasoningEffortFallback: input.reasoningEffortFallback ?? settings.openaiReasoningEffort,
|
|
8224
|
-
turnExecutionPolicy: input.turnExecutionPolicy,
|
|
8225
|
-
source: input.origin === "operator" ? "api" : "user",
|
|
8226
|
-
...input.recordAgentRunUsage !== void 0 ? { recordAgentRunUsage: input.recordAgentRunUsage } : {},
|
|
8227
|
-
personalConnectionDelegations: input.personalConnectionDelegations ?? [],
|
|
8228
|
-
...input.personalResourceAttachment ? {
|
|
8229
|
-
personalResourceAttachment: input.personalResourceAttachment
|
|
8230
|
-
} : {},
|
|
8231
|
-
mcpCredentialUpdates: input.mcpCredentialUpdates ?? [],
|
|
8232
|
-
controlLockTimeoutMs: workspaceControlRequestLockTimeoutMs()
|
|
8233
|
-
})
|
|
8234
|
-
)
|
|
8235
|
-
);
|
|
8236
|
-
} catch (error) {
|
|
8237
|
-
if (error instanceof WorkspaceControlBusyError) {
|
|
8238
|
-
throw error;
|
|
8239
|
-
}
|
|
8240
|
-
if (error instanceof PersonalResourceAttachmentAcceptanceError) {
|
|
8241
|
-
throw new HTTPException11(
|
|
8242
|
-
error.kind === "invalid" ? 422 : error.kind === "forbidden" ? 403 : 409,
|
|
8243
|
-
{ message: error.message, cause: error }
|
|
8244
|
-
);
|
|
8245
|
-
}
|
|
8246
|
-
if (error instanceof QueueCommandConflictError || error instanceof SessionControlConflictError) {
|
|
8247
|
-
throw new HTTPException11(409, { message: error.message });
|
|
8248
|
-
}
|
|
8249
|
-
if (error instanceof Error && error.message.includes("cancelled")) {
|
|
8250
|
-
throw new HTTPException11(409, { message: error.message });
|
|
8251
|
-
}
|
|
8252
|
-
if (error instanceof Error && error.message.startsWith("Unknown session MCP server")) {
|
|
8253
|
-
throw new HTTPException11(422, { message: error.message });
|
|
8254
|
-
}
|
|
8255
|
-
throw error;
|
|
8256
|
-
}
|
|
8721
|
+
function finalizePostUserMessageTurn(input, result) {
|
|
8722
|
+
const { db, bus, workflowClient, accountId, workspaceId, sessionId } = input;
|
|
8257
8723
|
const postCommitTask = async () => {
|
|
8258
8724
|
await Promise.all([
|
|
8259
8725
|
(async () => {
|
|
@@ -8312,37 +8778,151 @@ async function postUserMessageTurn(input) {
|
|
|
8312
8778
|
origin: "core"
|
|
8313
8779
|
});
|
|
8314
8780
|
}
|
|
8315
|
-
return {
|
|
8316
|
-
accepted: result.accepted,
|
|
8317
|
-
turn: result.turn,
|
|
8318
|
-
receipt: {
|
|
8319
|
-
id: result.receipt.id,
|
|
8320
|
-
action: result.receipt.action,
|
|
8321
|
-
operationKey: result.receipt.operationKey,
|
|
8322
|
-
targetSessionId: result.receipt.targetSessionId,
|
|
8323
|
-
targetTurnId: result.receipt.targetTurnId,
|
|
8324
|
-
appliedControlRevision: result.receipt.appliedControlRevision,
|
|
8325
|
-
appliedQueueVersion: result.receipt.appliedQueueVersion,
|
|
8326
|
-
appliedTurnVersion: result.receipt.appliedTurnVersion,
|
|
8327
|
-
appliedDraftRevision: result.receipt.appliedDraftRevision,
|
|
8328
|
-
createdAt: result.receipt.createdAt.toISOString()
|
|
8329
|
-
},
|
|
8330
|
-
routing: result.routing,
|
|
8331
|
-
draft: result.draft ? {
|
|
8332
|
-
revision: result.draft.revision,
|
|
8333
|
-
text: result.draft.text,
|
|
8334
|
-
annotations: DraftTimelineAnnotations2.parse(result.draft.annotations),
|
|
8335
|
-
resources: result.draft.resources,
|
|
8336
|
-
model: result.draft.model,
|
|
8337
|
-
reasoningEffort: result.draft.reasoningEffort,
|
|
8338
|
-
latencyMode: result.draft.latencyMode,
|
|
8339
|
-
sourceTurnId: result.draft.sourceTurnId,
|
|
8340
|
-
sourceTurnVersion: result.draft.sourceTurnVersion,
|
|
8341
|
-
updatedAt: result.draft.updatedAt.toISOString()
|
|
8342
|
-
} : null,
|
|
8343
|
-
interruptionCount: result.interruptionCount,
|
|
8344
|
-
replay: result.replay
|
|
8345
|
-
};
|
|
8781
|
+
return {
|
|
8782
|
+
accepted: result.accepted,
|
|
8783
|
+
turn: result.turn,
|
|
8784
|
+
receipt: {
|
|
8785
|
+
id: result.receipt.id,
|
|
8786
|
+
action: result.receipt.action,
|
|
8787
|
+
operationKey: result.receipt.operationKey,
|
|
8788
|
+
targetSessionId: result.receipt.targetSessionId,
|
|
8789
|
+
targetTurnId: result.receipt.targetTurnId,
|
|
8790
|
+
appliedControlRevision: result.receipt.appliedControlRevision,
|
|
8791
|
+
appliedQueueVersion: result.receipt.appliedQueueVersion,
|
|
8792
|
+
appliedTurnVersion: result.receipt.appliedTurnVersion,
|
|
8793
|
+
appliedDraftRevision: result.receipt.appliedDraftRevision,
|
|
8794
|
+
createdAt: result.receipt.createdAt.toISOString()
|
|
8795
|
+
},
|
|
8796
|
+
routing: result.routing,
|
|
8797
|
+
draft: result.draft ? {
|
|
8798
|
+
revision: result.draft.revision,
|
|
8799
|
+
text: result.draft.text,
|
|
8800
|
+
annotations: DraftTimelineAnnotations2.parse(result.draft.annotations),
|
|
8801
|
+
resources: result.draft.resources,
|
|
8802
|
+
model: result.draft.model,
|
|
8803
|
+
reasoningEffort: result.draft.reasoningEffort,
|
|
8804
|
+
latencyMode: result.draft.latencyMode,
|
|
8805
|
+
sourceTurnId: result.draft.sourceTurnId,
|
|
8806
|
+
sourceTurnVersion: result.draft.sourceTurnVersion,
|
|
8807
|
+
updatedAt: result.draft.updatedAt.toISOString()
|
|
8808
|
+
} : null,
|
|
8809
|
+
interruptionCount: result.interruptionCount,
|
|
8810
|
+
replay: result.replay
|
|
8811
|
+
};
|
|
8812
|
+
}
|
|
8813
|
+
async function postUserMessageTurn(input) {
|
|
8814
|
+
const { db, settings, accountId, workspaceId, sessionId } = input;
|
|
8815
|
+
const requestedModel = canonicalConfiguredModel(settings, input.model ?? null) ?? null;
|
|
8816
|
+
const requestedReasoningEffort = input.reasoningEffort ?? null;
|
|
8817
|
+
assertConfiguredModel(settings, requestedModel);
|
|
8818
|
+
const sessionForModelGate = await requireSession2(db, workspaceId, sessionId);
|
|
8819
|
+
const effectiveModelForGate = requestedModel ?? sessionForModelGate.model;
|
|
8820
|
+
const freshWorkspaceCustomModel = requestedModel !== null && isWorkspaceCustomModelId(settings, requestedModel) && requestedModel !== sessionForModelGate.model ? requestedModel : null;
|
|
8821
|
+
await assertWorkspaceModelPolicyAllows(db, settings, workspaceId, effectiveModelForGate);
|
|
8822
|
+
try {
|
|
8823
|
+
assertSessionAllowsProductModel(sessionForModelGate, effectiveModelForGate);
|
|
8824
|
+
} catch (error) {
|
|
8825
|
+
if (error instanceof CodexCompactionV2ProviderLockedError) {
|
|
8826
|
+
throw new HTTPException11(422, { message: error.message, cause: error });
|
|
8827
|
+
}
|
|
8828
|
+
throw error;
|
|
8829
|
+
}
|
|
8830
|
+
const operationKey = input.clientEventId ?? crypto.randomUUID();
|
|
8831
|
+
let result;
|
|
8832
|
+
try {
|
|
8833
|
+
result = await runIdempotentPersistenceTransaction(
|
|
8834
|
+
{
|
|
8835
|
+
stage: "session.prompt.submit",
|
|
8836
|
+
eventTypes: ["user.message", "turn.queued", "session.status.changed"],
|
|
8837
|
+
maxAttempts: 3
|
|
8838
|
+
},
|
|
8839
|
+
async () => await withWorkspaceSubjectSessionActivityRls(
|
|
8840
|
+
db,
|
|
8841
|
+
workspaceId,
|
|
8842
|
+
input.actor ?? accountId,
|
|
8843
|
+
(scoped) => submitHumanPromptInTransaction(scoped, {
|
|
8844
|
+
accountId,
|
|
8845
|
+
workspaceId,
|
|
8846
|
+
sessionId,
|
|
8847
|
+
subjectId: input.actor ?? accountId,
|
|
8848
|
+
...input.actorLabel ? { subjectLabel: input.actorLabel } : {},
|
|
8849
|
+
actor: input.commandActor ?? {
|
|
8850
|
+
type: "human",
|
|
8851
|
+
subjectId: input.actor ?? accountId
|
|
8852
|
+
},
|
|
8853
|
+
operationKey,
|
|
8854
|
+
...input.boundaryRequestHash ? { boundaryRequestHash: input.boundaryRequestHash } : {},
|
|
8855
|
+
delivery: input.delivery ?? "send",
|
|
8856
|
+
controlEtag: input.controlEtag ?? null,
|
|
8857
|
+
expectedDraftRevision: input.expectedDraftRevision ?? null,
|
|
8858
|
+
text: input.text,
|
|
8859
|
+
annotations: input.annotations ?? [],
|
|
8860
|
+
modelContext: input.modelContext ?? null,
|
|
8861
|
+
resources: input.resources,
|
|
8862
|
+
...input.composerDraftResources ? { composerDraftResources: input.composerDraftResources } : {},
|
|
8863
|
+
model: requestedModel,
|
|
8864
|
+
reasoningEffort: requestedReasoningEffort,
|
|
8865
|
+
latencyMode: input.latencyMode ?? null,
|
|
8866
|
+
reasoningEffortFallback: input.reasoningEffortFallback ?? settings.openaiReasoningEffort,
|
|
8867
|
+
turnExecutionPolicy: input.turnExecutionPolicy,
|
|
8868
|
+
source: input.origin === "operator" ? "api" : "user",
|
|
8869
|
+
...input.recordAgentRunUsage !== void 0 ? { recordAgentRunUsage: input.recordAgentRunUsage } : {},
|
|
8870
|
+
personalConnectionDelegations: input.personalConnectionDelegations ?? [],
|
|
8871
|
+
...input.personalResourceAttachment ? {
|
|
8872
|
+
personalResourceAttachment: input.personalResourceAttachment
|
|
8873
|
+
} : {},
|
|
8874
|
+
mcpCredentialUpdates: input.mcpCredentialUpdates ?? [],
|
|
8875
|
+
...freshWorkspaceCustomModel ? {
|
|
8876
|
+
beforeFreshPromptCommit: async (tx) => {
|
|
8877
|
+
const reference = workspaceCustomModelReference(
|
|
8878
|
+
settings,
|
|
8879
|
+
freshWorkspaceCustomModel
|
|
8880
|
+
);
|
|
8881
|
+
if (!reference) {
|
|
8882
|
+
throw new Error("workspace custom model reference disappeared");
|
|
8883
|
+
}
|
|
8884
|
+
const active = reference.providerKind === "openrouter" ? await lockActiveWorkspaceOpenRouterCustomModelForAdmission(tx, {
|
|
8885
|
+
accountId,
|
|
8886
|
+
workspaceId,
|
|
8887
|
+
upstreamModelId: reference.upstreamModelId
|
|
8888
|
+
}) : await lockActiveWorkspaceGatewayCustomModelForAdmission(tx, {
|
|
8889
|
+
accountId,
|
|
8890
|
+
workspaceId,
|
|
8891
|
+
upstreamModelId: reference.upstreamModelId
|
|
8892
|
+
});
|
|
8893
|
+
if (!active) {
|
|
8894
|
+
throw new HTTPException11(422, {
|
|
8895
|
+
message: `model is not available: ${freshWorkspaceCustomModel}`
|
|
8896
|
+
});
|
|
8897
|
+
}
|
|
8898
|
+
}
|
|
8899
|
+
} : {},
|
|
8900
|
+
controlLockTimeoutMs: workspaceControlRequestLockTimeoutMs()
|
|
8901
|
+
})
|
|
8902
|
+
)
|
|
8903
|
+
);
|
|
8904
|
+
} catch (error) {
|
|
8905
|
+
if (error instanceof WorkspaceControlBusyError) {
|
|
8906
|
+
throw error;
|
|
8907
|
+
}
|
|
8908
|
+
if (error instanceof PersonalResourceAttachmentAcceptanceError) {
|
|
8909
|
+
throw new HTTPException11(
|
|
8910
|
+
error.kind === "invalid" ? 422 : error.kind === "forbidden" ? 403 : 409,
|
|
8911
|
+
{ message: error.message, cause: error }
|
|
8912
|
+
);
|
|
8913
|
+
}
|
|
8914
|
+
if (error instanceof QueueCommandConflictError || error instanceof SessionControlConflictError) {
|
|
8915
|
+
throw new HTTPException11(409, { message: error.message });
|
|
8916
|
+
}
|
|
8917
|
+
if (error instanceof Error && error.message.includes("cancelled")) {
|
|
8918
|
+
throw new HTTPException11(409, { message: error.message });
|
|
8919
|
+
}
|
|
8920
|
+
if (error instanceof Error && error.message.startsWith("Unknown session MCP server")) {
|
|
8921
|
+
throw new HTTPException11(422, { message: error.message });
|
|
8922
|
+
}
|
|
8923
|
+
throw error;
|
|
8924
|
+
}
|
|
8925
|
+
return finalizePostUserMessageTurn(input, result);
|
|
8346
8926
|
}
|
|
8347
8927
|
function resolveChildGoalFromAcceptedSnapshot(goal, parentGoalSnapshot) {
|
|
8348
8928
|
const inheritedRootConstraints = parentGoalSnapshot.state === "none" ? [] : parentGoalSnapshot.rootConstraints;
|
|
@@ -8372,9 +8952,56 @@ function resolveSessionCreateVisibility(input) {
|
|
|
8372
8952
|
}
|
|
8373
8953
|
return input.requestedVisibility === "private" ? "user_private" : "workspace_shared";
|
|
8374
8954
|
}
|
|
8375
|
-
async function
|
|
8376
|
-
const
|
|
8955
|
+
async function resolveWorkspaceModelBoundarySettings(deps, grant, workspaceId, modelIds, retainedProductModelId) {
|
|
8956
|
+
const retainedWorkspaceModel = retainedProductModelId?.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX2) === true || retainedProductModelId?.startsWith(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX2) === true;
|
|
8957
|
+
if (deps.catalogSourceSettings) {
|
|
8958
|
+
if (!retainedWorkspaceModel) return deps.settings;
|
|
8959
|
+
}
|
|
8960
|
+
const workspaceModelIds = modelIds.filter(
|
|
8961
|
+
(modelId) => typeof modelId === "string" && (modelId.startsWith(WORKSPACE_GATEWAY_MODEL_ID_PREFIX2) || modelId.startsWith(WORKSPACE_OPENROUTER_MODEL_ID_PREFIX2))
|
|
8962
|
+
);
|
|
8963
|
+
const needsWorkspaceResolution = deps.settings.modelCatalogSource === "database" || workspaceModelIds.length > 0;
|
|
8964
|
+
if (!needsWorkspaceResolution) return deps.settings;
|
|
8965
|
+
return (await resolveWorkspaceCatalogSettings(deps.db, deps.catalogSourceSettings ?? deps.settings, {
|
|
8966
|
+
accountId: grant.accountId,
|
|
8967
|
+
workspaceId,
|
|
8968
|
+
...retainedProductModelId !== void 0 ? { retainedProductModelId } : {}
|
|
8969
|
+
})).settings;
|
|
8970
|
+
}
|
|
8971
|
+
async function withSessionCreateUsageRecording(input) {
|
|
8972
|
+
let usageRecording = "recorded";
|
|
8973
|
+
if (input.startMode !== "realtime") {
|
|
8974
|
+
try {
|
|
8975
|
+
await recordWorkspaceUsage(input.deps, {
|
|
8976
|
+
accountId: input.grant.accountId,
|
|
8977
|
+
workspaceId: input.workspaceId,
|
|
8978
|
+
subjectId: input.grant.subjectId,
|
|
8979
|
+
eventType: "agent_run.created",
|
|
8980
|
+
quantity: 1,
|
|
8981
|
+
unit: "run",
|
|
8982
|
+
sourceResourceType: "session",
|
|
8983
|
+
sourceResourceId: input.createOutcome.session.id,
|
|
8984
|
+
sessionId: input.createOutcome.session.id,
|
|
8985
|
+
initiator: input.createOutcome.session.createdBy,
|
|
8986
|
+
initiatorContext: input.createOutcome.session.createdByContext,
|
|
8987
|
+
origin: input.origin,
|
|
8988
|
+
idempotencyKey: `agent_run.created:${input.workspaceId}:${input.createOutcome.session.id}`
|
|
8989
|
+
});
|
|
8990
|
+
} catch (error) {
|
|
8991
|
+
usageRecording = "failed";
|
|
8992
|
+
reportSessionUsageRecordingFailure(error);
|
|
8993
|
+
}
|
|
8994
|
+
}
|
|
8995
|
+
return { ...input.createOutcome, usageRecording };
|
|
8996
|
+
}
|
|
8997
|
+
async function createSessionForRequestWithOutcome(unresolvedDeps, grant, workspaceId, rawPayload, authorization, agentChildPresentation) {
|
|
8377
8998
|
const payload = CreateSessionRequest.parse(rawPayload);
|
|
8999
|
+
if (hasReservedOpenGeniSlackBotSessionMetadata(payload.metadata)) {
|
|
9000
|
+
throw new HTTPException11(422, {
|
|
9001
|
+
message: `${OPENGENI_SLACK_BOT_SESSION_METADATA_KEY2} is reserved for scheduler routing`
|
|
9002
|
+
});
|
|
9003
|
+
}
|
|
9004
|
+
const db = unresolvedDeps.db;
|
|
8378
9005
|
const visibilityProvided = hasOwnProperty(rawPayload, "visibility");
|
|
8379
9006
|
if (payload.visibility === "private" && !grant.metadata?.["sessionId"]) {
|
|
8380
9007
|
if (!authorization) {
|
|
@@ -8382,39 +9009,17 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8382
9009
|
message: "managed human session required"
|
|
8383
9010
|
});
|
|
8384
9011
|
}
|
|
8385
|
-
await requireManagedHumanPrivateSessionCreate(
|
|
9012
|
+
await requireManagedHumanPrivateSessionCreate(unresolvedDeps, authorization, workspaceId);
|
|
8386
9013
|
if (payload.sandbox === "shared" || typeof payload.sandbox === "object") {
|
|
8387
9014
|
throw new HTTPException11(422, {
|
|
8388
9015
|
message: "Only-me sessions require their own sandbox"
|
|
8389
9016
|
});
|
|
8390
9017
|
}
|
|
8391
9018
|
}
|
|
8392
|
-
if (hasReservedOpenGeniSlackBotSessionMetadata(payload.metadata)) {
|
|
8393
|
-
throw new HTTPException11(422, {
|
|
8394
|
-
message: `${OPENGENI_SLACK_BOT_SESSION_METADATA_KEY2} is reserved for scheduler routing`
|
|
8395
|
-
});
|
|
8396
|
-
}
|
|
8397
|
-
if (payload.idempotencyKey) {
|
|
8398
|
-
const denial = await getSessionSpawnDenialByIdempotencyKey(
|
|
8399
|
-
db,
|
|
8400
|
-
workspaceId,
|
|
8401
|
-
payload.idempotencyKey
|
|
8402
|
-
);
|
|
8403
|
-
if (denial) {
|
|
8404
|
-
throw new SessionSpawnDeniedError(SessionSpawnDenial.parse(denial));
|
|
8405
|
-
}
|
|
8406
|
-
}
|
|
8407
|
-
await requireAtomicPersonalResourceAttachment(
|
|
8408
|
-
deps,
|
|
8409
|
-
authorization,
|
|
8410
|
-
workspaceId,
|
|
8411
|
-
payload.personalResourceAttachment,
|
|
8412
|
-
false
|
|
8413
|
-
);
|
|
8414
9019
|
const parentSessionId = typeof grant.metadata?.["sessionId"] === "string" ? grant.metadata["sessionId"] : null;
|
|
8415
9020
|
if (parentSessionId) {
|
|
8416
9021
|
try {
|
|
8417
|
-
await requireSessionAuthorization(
|
|
9022
|
+
await requireSessionAuthorization(unresolvedDeps, grant, {
|
|
8418
9023
|
sessionId: parentSessionId,
|
|
8419
9024
|
operation: "session.child.create",
|
|
8420
9025
|
surface: "core"
|
|
@@ -8464,6 +9069,102 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8464
9069
|
message: "caller attempt does not belong to the parent session"
|
|
8465
9070
|
});
|
|
8466
9071
|
}
|
|
9072
|
+
const replayManagedHumanSubjectId = creationInitiator.actor ? parentCallingTurn?.initiatingHumanSubjectId ?? (parentCallingTurn?.initiator.kind === "subject" ? parentCallingTurn.initiator.subjectId : null) : authorization?.canonicalManagedHumanSession || grant.principalKind === "human_session" ? grant.subjectId : null;
|
|
9073
|
+
let retainedKeyedShellModel = null;
|
|
9074
|
+
if (payload.idempotencyKey && (effectiveVisibility !== "user_private" || replayManagedHumanSubjectId !== null)) {
|
|
9075
|
+
try {
|
|
9076
|
+
const initializedReplay = await getInitializedSessionCreateReplay(db, {
|
|
9077
|
+
accountId: grant.accountId,
|
|
9078
|
+
workspaceId,
|
|
9079
|
+
subjectId: replayManagedHumanSubjectId ?? grant.subjectId,
|
|
9080
|
+
...replayManagedHumanSubjectId ? { activeManagedHumanSubjectId: replayManagedHumanSubjectId } : {},
|
|
9081
|
+
createIdempotencyKey: payload.idempotencyKey,
|
|
9082
|
+
...payload.requestedSessionId ? { requestedSessionId: payload.requestedSessionId } : {},
|
|
9083
|
+
visibility: effectiveVisibility,
|
|
9084
|
+
variableSetIds: payload.variableSetIds ?? [],
|
|
9085
|
+
initialPersonalResourceAttachmentIntent: payload.personalResourceAttachment ?? null,
|
|
9086
|
+
deferInitialTurn: payload.startMode === "realtime"
|
|
9087
|
+
});
|
|
9088
|
+
if (initializedReplay) {
|
|
9089
|
+
if (initializedReplay.outcome === "denied") {
|
|
9090
|
+
throw new SessionSpawnDeniedError(SessionSpawnDenial.parse(initializedReplay.denial));
|
|
9091
|
+
}
|
|
9092
|
+
if (initializedReplay.outcome === "pending") {
|
|
9093
|
+
retainedKeyedShellModel = initializedReplay.session.model;
|
|
9094
|
+
} else {
|
|
9095
|
+
if (initializedReplay.workflowWakeRevision !== null) {
|
|
9096
|
+
await unresolvedDeps.workflowClient.wakeSessionWorkflow({
|
|
9097
|
+
accountId: grant.accountId,
|
|
9098
|
+
workspaceId,
|
|
9099
|
+
sessionId: initializedReplay.session.id,
|
|
9100
|
+
workflowId: initializedReplay.temporalWorkflowId,
|
|
9101
|
+
wakeRevision: initializedReplay.workflowWakeRevision
|
|
9102
|
+
});
|
|
9103
|
+
}
|
|
9104
|
+
return await withSessionCreateUsageRecording({
|
|
9105
|
+
deps: unresolvedDeps,
|
|
9106
|
+
grant,
|
|
9107
|
+
workspaceId,
|
|
9108
|
+
startMode: payload.startMode,
|
|
9109
|
+
origin: creationInitiator.actor ? "system" : "user",
|
|
9110
|
+
createOutcome: {
|
|
9111
|
+
session: initializedReplay.session,
|
|
9112
|
+
outcome: initializedReplay.changed ? "repaired" : "replayed",
|
|
9113
|
+
replay: !initializedReplay.changed,
|
|
9114
|
+
changed: initializedReplay.changed
|
|
9115
|
+
}
|
|
9116
|
+
});
|
|
9117
|
+
}
|
|
9118
|
+
}
|
|
9119
|
+
} catch (error) {
|
|
9120
|
+
if (error instanceof SessionIdConflictError) {
|
|
9121
|
+
throw new HTTPException11(409, {
|
|
9122
|
+
message: "requested session id is already in use"
|
|
9123
|
+
});
|
|
9124
|
+
}
|
|
9125
|
+
if (error instanceof SessionCreateIdempotencyConflictError) {
|
|
9126
|
+
throw new HTTPException11(409, { message: error.message, cause: error });
|
|
9127
|
+
}
|
|
9128
|
+
throw error;
|
|
9129
|
+
}
|
|
9130
|
+
}
|
|
9131
|
+
let settings = await resolveWorkspaceModelBoundarySettings(
|
|
9132
|
+
unresolvedDeps,
|
|
9133
|
+
grant,
|
|
9134
|
+
workspaceId,
|
|
9135
|
+
[payload.model],
|
|
9136
|
+
retainedKeyedShellModel
|
|
9137
|
+
);
|
|
9138
|
+
let deps = settings === unresolvedDeps.settings ? unresolvedDeps : {
|
|
9139
|
+
...unresolvedDeps,
|
|
9140
|
+
catalogSourceSettings: unresolvedDeps.catalogSourceSettings ?? unresolvedDeps.settings,
|
|
9141
|
+
settings
|
|
9142
|
+
};
|
|
9143
|
+
const { bus, workflowClient, objectStorage } = deps;
|
|
9144
|
+
await requireAtomicPersonalResourceAttachment(
|
|
9145
|
+
deps,
|
|
9146
|
+
authorization,
|
|
9147
|
+
workspaceId,
|
|
9148
|
+
payload.personalResourceAttachment,
|
|
9149
|
+
false
|
|
9150
|
+
);
|
|
9151
|
+
const inheritedModel = parentCallingTurn?.model ?? parentSession?.model ?? settings.openaiModel;
|
|
9152
|
+
const effectiveModelId = payload.model ?? inheritedModel;
|
|
9153
|
+
const effectiveCatalogSettings = await resolveWorkspaceModelBoundarySettings(
|
|
9154
|
+
deps,
|
|
9155
|
+
grant,
|
|
9156
|
+
workspaceId,
|
|
9157
|
+
[effectiveModelId],
|
|
9158
|
+
parentSession ? inheritedModel : null
|
|
9159
|
+
);
|
|
9160
|
+
if (effectiveCatalogSettings !== settings) {
|
|
9161
|
+
deps = {
|
|
9162
|
+
...deps,
|
|
9163
|
+
catalogSourceSettings: deps.catalogSourceSettings ?? settings,
|
|
9164
|
+
settings: effectiveCatalogSettings
|
|
9165
|
+
};
|
|
9166
|
+
settings = effectiveCatalogSettings;
|
|
9167
|
+
}
|
|
8467
9168
|
let effectiveGoal = payload.goal;
|
|
8468
9169
|
if (parentSession && payload.goal) {
|
|
8469
9170
|
try {
|
|
@@ -8480,6 +9181,11 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8480
9181
|
});
|
|
8481
9182
|
}
|
|
8482
9183
|
}
|
|
9184
|
+
const initialAutomaticTitle = parentSession && agentChildPresentation ? automaticTitleForAgentChildCreate(
|
|
9185
|
+
agentChildPresentation,
|
|
9186
|
+
effectiveGoal,
|
|
9187
|
+
payload.initialMessage
|
|
9188
|
+
) : null;
|
|
8483
9189
|
const personalResourceSubjectId = creationInitiator.actor ? (await requireLiveAgentAttemptAuthorization(db, grant, creationInitiator.actor.sessionId)).initiatingHumanSubjectId : grant.subjectId;
|
|
8484
9190
|
const xaiProviderAccountAuthoritySnapshot = parentSession && creationInitiator.actor ? await getSessionTurnXaiProviderAccountAuthoritySnapshot(
|
|
8485
9191
|
db,
|
|
@@ -8609,8 +9315,7 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8609
9315
|
}
|
|
8610
9316
|
channelId = channel.id;
|
|
8611
9317
|
}
|
|
8612
|
-
const
|
|
8613
|
-
const model = canonicalConfiguredModel(settings, payload.model ?? inheritedModel);
|
|
9318
|
+
const model = canonicalConfiguredModel(settings, effectiveModelId);
|
|
8614
9319
|
if (model === null || model === void 0) {
|
|
8615
9320
|
throw new Error("effective session model unexpectedly resolved to null");
|
|
8616
9321
|
}
|
|
@@ -8733,6 +9438,8 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8733
9438
|
const sandboxChoice = payload.sandbox ?? (payload.targetSandboxId ? "new" : parentSessionId ? "shared" : "new");
|
|
8734
9439
|
let sandboxGroupId = null;
|
|
8735
9440
|
let inheritedBackend;
|
|
9441
|
+
let inheritedSandboxOs;
|
|
9442
|
+
let inheritedActiveTarget = null;
|
|
8736
9443
|
const requestedVariableSetIds = variableSets.map((variableSet) => variableSet.id);
|
|
8737
9444
|
const variableSetsMatchGroup = (memberVariableSetIds) => stableJson4(memberVariableSetIds) === stableJson4(requestedVariableSetIds);
|
|
8738
9445
|
const rigVersionMatchesGroup = (memberRigVersionId) => memberRigVersionId === frozenRigVersionId;
|
|
@@ -8768,6 +9475,11 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8768
9475
|
} else {
|
|
8769
9476
|
sandboxGroupId = parent.sandboxGroupId;
|
|
8770
9477
|
inheritedBackend = parent.sandboxBackend;
|
|
9478
|
+
inheritedSandboxOs = parent.sandboxOs;
|
|
9479
|
+
inheritedActiveTarget = parent.activeSandboxId ? {
|
|
9480
|
+
sandboxId: parent.activeSandboxId,
|
|
9481
|
+
workingDir: parent.workingDir
|
|
9482
|
+
} : null;
|
|
8771
9483
|
}
|
|
8772
9484
|
} else if (typeof sandboxChoice === "object") {
|
|
8773
9485
|
const member = await getAnySessionInGroup(db, workspaceId, sandboxChoice.groupId);
|
|
@@ -8804,12 +9516,18 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8804
9516
|
}
|
|
8805
9517
|
sandboxGroupId = sandboxChoice.groupId;
|
|
8806
9518
|
inheritedBackend = member.sandboxBackend;
|
|
9519
|
+
inheritedSandboxOs = member.sandboxOs;
|
|
8807
9520
|
}
|
|
8808
9521
|
if (payload.workingDir !== void 0 && !payload.targetSandboxId) {
|
|
8809
9522
|
throw new HTTPException11(422, {
|
|
8810
9523
|
message: "workingDir requires targetSandboxId (it is the targeted machine's working directory)"
|
|
8811
9524
|
});
|
|
8812
9525
|
}
|
|
9526
|
+
if (inheritedBackend === void 0 && !payload.targetSandboxId && (payload.sandboxBackend ?? settings.sandboxBackend) === "selfhosted") {
|
|
9527
|
+
throw new HTTPException11(422, {
|
|
9528
|
+
message: "selfhosted sessions require targetSandboxId; select an online Connected Machine"
|
|
9529
|
+
});
|
|
9530
|
+
}
|
|
8813
9531
|
let machineHomeBackend;
|
|
8814
9532
|
let machineHomeOs;
|
|
8815
9533
|
if (payload.targetSandboxId && inheritedBackend === void 0 && settings.sandboxOwnershipEnabled && settings.sandboxSelfhostedEnabled) {
|
|
@@ -8832,6 +9550,17 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8832
9550
|
}
|
|
8833
9551
|
}
|
|
8834
9552
|
}
|
|
9553
|
+
const effectiveSandboxBackend = inheritedBackend ?? machineHomeBackend ?? payload.sandboxBackend ?? settings.sandboxBackend;
|
|
9554
|
+
const effectiveSandboxOs = inheritedSandboxOs ?? machineHomeOs;
|
|
9555
|
+
const effectiveSeedTarget = payload.targetSandboxId ? {
|
|
9556
|
+
sandboxId: payload.targetSandboxId,
|
|
9557
|
+
workingDir: payload.workingDir ?? null
|
|
9558
|
+
} : inheritedActiveTarget;
|
|
9559
|
+
if (effectiveSandboxBackend === "selfhosted" && effectiveSeedTarget === null && managedSessionGroupBackend(settings.sandboxBackend, effectiveSandboxBackend) === null) {
|
|
9560
|
+
throw new HTTPException11(422, {
|
|
9561
|
+
message: "self-hosted execution runs on a Connected Machine, but no machine was selected or inherited; connect the parent session to a machine or provide machineTarget"
|
|
9562
|
+
});
|
|
9563
|
+
}
|
|
8835
9564
|
if (payload.startMode !== "realtime") {
|
|
8836
9565
|
await requireLimit(deps, {
|
|
8837
9566
|
accountId: grant.accountId,
|
|
@@ -8868,10 +9597,10 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8868
9597
|
// machine-targeted create (top-level or own-box child) labels the home
|
|
8869
9598
|
// "selfhosted" (machineHomeBackend), overriding the caller/deployment
|
|
8870
9599
|
// default so the row matches where the session actually runs.
|
|
8871
|
-
sandboxBackend:
|
|
9600
|
+
sandboxBackend: effectiveSandboxBackend,
|
|
8872
9601
|
// Mirror the backend relabel on the OS axis: a machine-targeted own-box
|
|
8873
|
-
// create carries a derived OS; shared spawns
|
|
8874
|
-
...
|
|
9602
|
+
// create carries a derived OS; shared spawns inherit the exact parent box.
|
|
9603
|
+
...effectiveSandboxOs ? { sandboxOs: effectiveSandboxOs } : {},
|
|
8875
9604
|
sandboxGroupId,
|
|
8876
9605
|
metadata: payload.metadata,
|
|
8877
9606
|
...creationInitiator.initiator ? { createdBy: creationInitiator.initiator } : {},
|
|
@@ -8887,6 +9616,7 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8887
9616
|
rigVersionId: frozenRigVersionId,
|
|
8888
9617
|
channelId,
|
|
8889
9618
|
goal: effectiveGoal ?? null,
|
|
9619
|
+
initialAutomaticTitle,
|
|
8890
9620
|
// Per-session persona instructions (already trimmed/validated by the
|
|
8891
9621
|
// contracts schema). Persisted on the row; composed system-level at turn
|
|
8892
9622
|
// time. Not surfaced as an event.
|
|
@@ -8898,6 +9628,8 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8898
9628
|
sessionMcpServers: sessionMcpServers.metadata,
|
|
8899
9629
|
personalConnectionDelegations,
|
|
8900
9630
|
initialPersonalResourceAttachmentIntent: payload.personalResourceAttachment ?? null,
|
|
9631
|
+
workspaceCustomModel: isWorkspaceCustomModelId(settings, model),
|
|
9632
|
+
retainWorkspaceCustomModel: parentSession !== null && model === inheritedModel,
|
|
8901
9633
|
...xaiProviderAccountAuthoritySnapshot ? { xaiProviderAccountAuthoritySnapshot } : {},
|
|
8902
9634
|
parentSessionId,
|
|
8903
9635
|
createIdempotencyKey: payload.idempotencyKey ?? null,
|
|
@@ -8908,10 +9640,10 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8908
9640
|
// active-sandbox pointer is seeded race-free inside createAndStartSession
|
|
8909
9641
|
// (after the row exists, before the first turn dispatches). Validation
|
|
8910
9642
|
// (ownership/liveness) lives in swapActiveSandbox; an invalid target 422s.
|
|
8911
|
-
seedTargetSandbox:
|
|
8912
|
-
sandboxId:
|
|
9643
|
+
seedTargetSandbox: effectiveSeedTarget ? {
|
|
9644
|
+
sandboxId: effectiveSeedTarget.sandboxId,
|
|
8913
9645
|
settings,
|
|
8914
|
-
workingDir:
|
|
9646
|
+
workingDir: effectiveSeedTarget.workingDir,
|
|
8915
9647
|
resourceSubjectId: personalResourceSubjectId
|
|
8916
9648
|
} : null,
|
|
8917
9649
|
consumeNewSessionDraft: payload.expectedNewSessionDraftRevision !== void 0 && payload.startMode !== "realtime" ? {
|
|
@@ -8953,207 +9685,322 @@ async function createSessionForRequestWithOutcome(deps, grant, workspaceId, rawP
|
|
|
8953
9685
|
message: error.message,
|
|
8954
9686
|
cause: error
|
|
8955
9687
|
});
|
|
8956
|
-
}
|
|
8957
|
-
if (error instanceof SessionCreateIdempotencyConflictError) {
|
|
8958
|
-
throw new HTTPException11(409, { message: error.message, cause: error });
|
|
8959
|
-
}
|
|
8960
|
-
throw error;
|
|
8961
|
-
}
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
|
|
8965
|
-
await recordWorkspaceUsage(deps, {
|
|
8966
|
-
accountId: grant.accountId,
|
|
8967
|
-
workspaceId,
|
|
8968
|
-
subjectId: grant.subjectId,
|
|
8969
|
-
eventType: "agent_run.created",
|
|
8970
|
-
quantity: 1,
|
|
8971
|
-
unit: "run",
|
|
8972
|
-
sourceResourceType: "session",
|
|
8973
|
-
sourceResourceId: createOutcome.session.id,
|
|
8974
|
-
sessionId: createOutcome.session.id,
|
|
8975
|
-
initiator: createOutcome.session.createdBy,
|
|
8976
|
-
initiatorContext: createOutcome.session.createdByContext,
|
|
8977
|
-
origin: creationInitiator.actor ? "system" : "user",
|
|
8978
|
-
idempotencyKey: `agent_run.created:${workspaceId}:${createOutcome.session.id}`
|
|
8979
|
-
});
|
|
8980
|
-
} catch (error) {
|
|
8981
|
-
usageRecording = "failed";
|
|
8982
|
-
reportSessionUsageRecordingFailure(error);
|
|
8983
|
-
}
|
|
8984
|
-
}
|
|
8985
|
-
return { ...createOutcome, usageRecording };
|
|
8986
|
-
}
|
|
8987
|
-
function reportSessionUsageRecordingFailure(_error) {
|
|
8988
|
-
console.warn(
|
|
8989
|
-
"[sessions] usage recording failed after committed session create; returning committed outcome",
|
|
8990
|
-
{
|
|
8991
|
-
errorClass: "UsageRecordingError",
|
|
8992
|
-
errorCode: "session_create_usage_recording_failed",
|
|
8993
|
-
origin: "core"
|
|
8994
|
-
}
|
|
8995
|
-
);
|
|
8996
|
-
}
|
|
8997
|
-
async function createSessionForRequest(deps, grant, workspaceId, rawPayload, authorization) {
|
|
8998
|
-
return (await createSessionForRequestWithOutcome(deps, grant, workspaceId, rawPayload, authorization)).session;
|
|
8999
|
-
}
|
|
9000
|
-
async function acceptSessionUserMessageWithOutcome(deps, grant, workspaceId, sessionId, input) {
|
|
9001
|
-
const { settings, db, bus, workflowClient, objectStorage } = deps;
|
|
9002
|
-
const delegatedServiceInitiator = serviceInitiatorForGrant(grant);
|
|
9003
|
-
await requireSessionAuthorization(deps, grant, {
|
|
9004
|
-
sessionId,
|
|
9005
|
-
operation: input.delivery === "steer" ? "session.steer" : "session.append",
|
|
9006
|
-
surface: "core"
|
|
9007
|
-
});
|
|
9008
|
-
await requireAtomicPersonalResourceAttachment(
|
|
9009
|
-
deps,
|
|
9010
|
-
input.authorization,
|
|
9011
|
-
workspaceId,
|
|
9012
|
-
input.personalResourceAttachment,
|
|
9013
|
-
true
|
|
9014
|
-
);
|
|
9015
|
-
const existingSession = await requireSession2(db, workspaceId, sessionId);
|
|
9016
|
-
const requestedModel = canonicalConfiguredModel(settings, input.model ?? null) ?? null;
|
|
9017
|
-
const effectiveModel = canonicalConfiguredModel(settings, requestedModel ?? existingSession.model) ?? null;
|
|
9018
|
-
if (effectiveModel === null) {
|
|
9019
|
-
throw new Error("effective follow-up model unexpectedly resolved to null");
|
|
9020
|
-
}
|
|
9021
|
-
try {
|
|
9022
|
-
assertSessionAllowsProductModel(existingSession, effectiveModel);
|
|
9023
|
-
} catch (error) {
|
|
9024
|
-
if (error instanceof CodexCompactionV2ProviderLockedError) {
|
|
9025
|
-
throw new HTTPException11(422, { message: error.message, cause: error });
|
|
9026
|
-
}
|
|
9027
|
-
throw error;
|
|
9028
|
-
}
|
|
9029
|
-
const sessionReasoningEffort = existingSession.reasoningEffort;
|
|
9030
|
-
const effectiveReasoningEffort = input.reasoningEffort ?? sessionReasoningEffort;
|
|
9031
|
-
const sessionLatencyMode = existingSession.latencyMode;
|
|
9032
|
-
const effectiveLatencyMode = input.latencyMode ?? sessionLatencyMode;
|
|
9033
|
-
const turnExecutionPolicy = resolveTurnExecutionPolicyV1(settings, {
|
|
9034
|
-
modelId: effectiveModel,
|
|
9035
|
-
requestedModelId: input.model ?? null,
|
|
9036
|
-
modelSource: input.model == null ? "session" : "explicit",
|
|
9037
|
-
reasoningEffort: effectiveReasoningEffort,
|
|
9038
|
-
reasoningSource: input.reasoningEffort == null ? "session" : "explicit",
|
|
9039
|
-
latencyMode: effectiveLatencyMode,
|
|
9040
|
-
latencyModeSource: input.latencyMode == null ? "session" : "explicit"
|
|
9041
|
-
});
|
|
9042
|
-
const requestedResources = normalizeResources(input.resources ?? []);
|
|
9043
|
-
const composerDraftResources = input.composerDraftResources ? normalizeResources(input.composerDraftResources) : void 0;
|
|
9044
|
-
if (composerDraftResources) {
|
|
9045
|
-
const acceptedResources = new Set(requestedResources.map((resource) => stableJson4(resource)));
|
|
9046
|
-
const unacceptedDraftResource = composerDraftResources.find(
|
|
9047
|
-
(resource) => !acceptedResources.has(stableJson4(resource))
|
|
9048
|
-
);
|
|
9049
|
-
if (unacceptedDraftResource) {
|
|
9050
|
-
throw new HTTPException11(422, {
|
|
9051
|
-
message: "composer draft resources must be included in the accepted resource set"
|
|
9052
|
-
});
|
|
9053
|
-
}
|
|
9054
|
-
}
|
|
9055
|
-
const annotations = await validateSubmittedTimelineAnnotations(
|
|
9056
|
-
db,
|
|
9057
|
-
workspaceId,
|
|
9058
|
-
sessionId,
|
|
9059
|
-
input.annotations ?? []
|
|
9060
|
-
);
|
|
9061
|
-
await requireLimit(deps, {
|
|
9062
|
-
accountId: grant.accountId,
|
|
9063
|
-
workspaceId,
|
|
9064
|
-
action: "agent_run:create",
|
|
9065
|
-
quantity: 1,
|
|
9066
|
-
model: effectiveModel
|
|
9067
|
-
});
|
|
9068
|
-
if (requestedResources.some((resource) => resource.kind === "file") && !objectStorage) {
|
|
9069
|
-
throw new HTTPException11(503, {
|
|
9070
|
-
message: "object storage is not configured"
|
|
9071
|
-
});
|
|
9072
|
-
}
|
|
9073
|
-
await validateFileResources(
|
|
9074
|
-
db,
|
|
9075
|
-
grant.accountId,
|
|
9076
|
-
workspaceId,
|
|
9077
|
-
grant.subjectId,
|
|
9078
|
-
requestedResources
|
|
9079
|
-
);
|
|
9080
|
-
await validateGitHubRepositorySelection(db, workspaceId, [
|
|
9081
|
-
...existingSession.resources,
|
|
9082
|
-
...requestedResources
|
|
9083
|
-
]);
|
|
9084
|
-
const mcpCredentialUpdates = validateSessionMcpCredentialUpdates({
|
|
9085
|
-
settings,
|
|
9086
|
-
grant,
|
|
9087
|
-
session: existingSession,
|
|
9088
|
-
updates: input.mcpCredentialUpdates ?? []
|
|
9089
|
-
});
|
|
9090
|
-
const connectionDelegationSource = personalConnectionDelegationSourceForGrant(grant);
|
|
9091
|
-
const inheritedPersonalConnectionDelegations = connectionDelegationSource.kind === "turn" ? await getSessionTurnPersonalConnectionDelegations2(
|
|
9092
|
-
db,
|
|
9093
|
-
workspaceId,
|
|
9094
|
-
connectionDelegationSource.sessionId,
|
|
9095
|
-
connectionDelegationSource.turnId
|
|
9096
|
-
) : null;
|
|
9097
|
-
const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(
|
|
9098
|
-
db,
|
|
9099
|
-
workspaceId,
|
|
9100
|
-
settings,
|
|
9101
|
-
inheritedPersonalConnectionDelegations ? {
|
|
9102
|
-
personalConnectionDelegations: inheritedPersonalConnectionDelegations
|
|
9103
|
-
} : { subjectId: grant.subjectId }
|
|
9104
|
-
);
|
|
9105
|
-
const personalConnectionDelegations = await freezePersonalConnectionDelegations({
|
|
9106
|
-
db,
|
|
9688
|
+
}
|
|
9689
|
+
if (error instanceof SessionCreateIdempotencyConflictError) {
|
|
9690
|
+
throw new HTTPException11(409, { message: error.message, cause: error });
|
|
9691
|
+
}
|
|
9692
|
+
throw error;
|
|
9693
|
+
}
|
|
9694
|
+
return await withSessionCreateUsageRecording({
|
|
9695
|
+
deps,
|
|
9696
|
+
grant,
|
|
9107
9697
|
workspaceId,
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
source: connectionDelegationSource,
|
|
9112
|
-
targetSessionId: sessionId,
|
|
9113
|
-
googleDrivePublicationEnabled: existingSession.firstPartyMcpTools.includes("editable_artifact_export") && existingSession.firstPartyMcpTools.includes("editable_artifact_export_status") && (!existingSession.firstPartyMcpPermissions?.length || existingSession.firstPartyMcpPermissions.includes("artifacts:read") && existingSession.firstPartyMcpPermissions.includes("artifacts:publish")),
|
|
9114
|
-
atlassianEnabled: existingSession.firstPartyMcpTools.some((tool) => tool.startsWith("atlassian_")) && (!existingSession.firstPartyMcpPermissions?.length || existingSession.firstPartyMcpPermissions.includes("connections:read")),
|
|
9115
|
-
...input.connectionAuthorities ? { authoritySelections: input.connectionAuthorities } : {}
|
|
9698
|
+
startMode: payload.startMode,
|
|
9699
|
+
origin: creationInitiator.actor ? "system" : "user",
|
|
9700
|
+
createOutcome
|
|
9116
9701
|
});
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9702
|
+
}
|
|
9703
|
+
function reportSessionUsageRecordingFailure(_error) {
|
|
9704
|
+
console.warn(
|
|
9705
|
+
"[sessions] usage recording failed after committed session create; returning committed outcome",
|
|
9706
|
+
{
|
|
9707
|
+
errorClass: "UsageRecordingError",
|
|
9708
|
+
errorCode: "session_create_usage_recording_failed",
|
|
9709
|
+
origin: "core"
|
|
9710
|
+
}
|
|
9711
|
+
);
|
|
9712
|
+
}
|
|
9713
|
+
async function createSessionForRequest(deps, grant, workspaceId, rawPayload, authorization) {
|
|
9714
|
+
return (await createSessionForRequestWithOutcome(deps, grant, workspaceId, rawPayload, authorization)).session;
|
|
9715
|
+
}
|
|
9716
|
+
function sessionPromptBoundaryRequestHash(input) {
|
|
9717
|
+
return `prompt-boundary-v1:${canonicalSessionCommandHash({
|
|
9718
|
+
delivery: input.delivery,
|
|
9719
|
+
controlEtag: input.controlEtag,
|
|
9720
|
+
expectedDraftRevision: input.expectedDraftRevision,
|
|
9721
|
+
text: input.text,
|
|
9722
|
+
annotations: input.annotations,
|
|
9723
|
+
modelContext: input.modelContext,
|
|
9724
|
+
resources: input.resources,
|
|
9725
|
+
composerDraftResourcesProvided: input.composerDraftResources !== void 0,
|
|
9726
|
+
composerDraftResources: input.composerDraftResources ?? [],
|
|
9727
|
+
model: input.model,
|
|
9728
|
+
reasoningEffort: input.reasoningEffort,
|
|
9729
|
+
latencyMode: input.latencyMode,
|
|
9730
|
+
source: input.source,
|
|
9731
|
+
mcpCredentialUpdates: input.mcpCredentialUpdates,
|
|
9732
|
+
connectionAuthorities: input.connectionAuthorities ?? [],
|
|
9733
|
+
personalResourceAttachment: input.personalResourceAttachment ?? null,
|
|
9734
|
+
...input.commandActor.type === "service" ? {
|
|
9735
|
+
serviceInitiator: {
|
|
9736
|
+
subjectId: input.commandActor.subjectId,
|
|
9737
|
+
subjectLabel: input.commandActor.subjectLabel ?? null,
|
|
9738
|
+
context: input.commandActor.context ?? {}
|
|
9739
|
+
}
|
|
9740
|
+
} : {}
|
|
9741
|
+
})}`;
|
|
9742
|
+
}
|
|
9743
|
+
async function acceptSessionUserMessageWithOutcome(deps, grant, workspaceId, sessionId, input) {
|
|
9744
|
+
const { db, bus, workflowClient, objectStorage } = deps;
|
|
9745
|
+
const delegatedServiceInitiator = serviceInitiatorForGrant(grant);
|
|
9746
|
+
const delivery = input.delivery ?? "send";
|
|
9747
|
+
const source = delegatedServiceInitiator || input.origin === "operator" ? "api" : "user";
|
|
9748
|
+
const commandActor = delegatedServiceInitiator ? {
|
|
9749
|
+
type: "service",
|
|
9750
|
+
subjectId: delegatedServiceInitiator.initiator.subjectId,
|
|
9751
|
+
...delegatedServiceInitiator.initiator.label ? { subjectLabel: delegatedServiceInitiator.initiator.label } : {},
|
|
9752
|
+
context: delegatedServiceInitiator.context
|
|
9753
|
+
} : { type: "human", subjectId: grant.subjectId };
|
|
9754
|
+
await requireSessionAuthorization(deps, grant, {
|
|
9124
9755
|
sessionId,
|
|
9756
|
+
operation: delivery === "steer" ? "session.steer" : "session.append",
|
|
9757
|
+
surface: "core"
|
|
9758
|
+
});
|
|
9759
|
+
const requestedResources = normalizeResources(input.resources ?? []);
|
|
9760
|
+
const composerDraftResources = input.composerDraftResources ? normalizeResources(input.composerDraftResources) : void 0;
|
|
9761
|
+
const boundaryRequestHash = input.clientEventId ? sessionPromptBoundaryRequestHash({
|
|
9762
|
+
delivery,
|
|
9763
|
+
controlEtag: input.controlEtag ?? null,
|
|
9764
|
+
expectedDraftRevision: input.expectedDraftRevision ?? null,
|
|
9125
9765
|
text: input.text,
|
|
9126
|
-
annotations,
|
|
9766
|
+
annotations: input.annotations ?? [],
|
|
9127
9767
|
modelContext: input.modelContext ?? null,
|
|
9128
9768
|
resources: requestedResources,
|
|
9129
9769
|
...composerDraftResources ? { composerDraftResources } : {},
|
|
9130
9770
|
model: input.model ?? null,
|
|
9131
9771
|
reasoningEffort: input.reasoningEffort ?? null,
|
|
9132
9772
|
latencyMode: input.latencyMode ?? null,
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9136
|
-
personalConnectionDelegations,
|
|
9773
|
+
source,
|
|
9774
|
+
mcpCredentialUpdates: input.mcpCredentialUpdates ?? [],
|
|
9775
|
+
...input.connectionAuthorities ? { connectionAuthorities: input.connectionAuthorities } : {},
|
|
9137
9776
|
...input.personalResourceAttachment ? { personalResourceAttachment: input.personalResourceAttachment } : {},
|
|
9138
|
-
|
|
9139
|
-
|
|
9140
|
-
|
|
9141
|
-
|
|
9142
|
-
|
|
9143
|
-
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9777
|
+
commandActor
|
|
9778
|
+
}) : null;
|
|
9779
|
+
if (input.clientEventId && boundaryRequestHash) {
|
|
9780
|
+
const replay = await withWorkspaceSubjectSessionActivityRls(
|
|
9781
|
+
db,
|
|
9782
|
+
workspaceId,
|
|
9783
|
+
grant.subjectId,
|
|
9784
|
+
async (scopedDb) => await replaySubmittedHumanPromptFromBoundaryReceipt(scopedDb, {
|
|
9785
|
+
workspaceId,
|
|
9786
|
+
sessionId,
|
|
9787
|
+
subjectId: grant.subjectId,
|
|
9788
|
+
actor: commandActor,
|
|
9789
|
+
operationKey: input.clientEventId,
|
|
9790
|
+
delivery,
|
|
9791
|
+
boundaryRequestHash,
|
|
9792
|
+
expectedDraftRevision: input.expectedDraftRevision ?? null
|
|
9793
|
+
})
|
|
9794
|
+
);
|
|
9795
|
+
if (replay) {
|
|
9796
|
+
return finalizePostUserMessageTurn(
|
|
9797
|
+
{
|
|
9798
|
+
db,
|
|
9799
|
+
bus,
|
|
9800
|
+
workflowClient,
|
|
9801
|
+
accountId: grant.accountId,
|
|
9802
|
+
workspaceId,
|
|
9803
|
+
sessionId,
|
|
9804
|
+
delivery,
|
|
9805
|
+
...deps.schedulePromptPostCommit ? { schedulePostCommit: deps.schedulePromptPostCommit } : {}
|
|
9806
|
+
},
|
|
9807
|
+
replay
|
|
9808
|
+
);
|
|
9809
|
+
}
|
|
9810
|
+
}
|
|
9811
|
+
try {
|
|
9812
|
+
await requireAtomicPersonalResourceAttachment(
|
|
9813
|
+
deps,
|
|
9814
|
+
input.authorization,
|
|
9815
|
+
workspaceId,
|
|
9816
|
+
input.personalResourceAttachment,
|
|
9817
|
+
true
|
|
9818
|
+
);
|
|
9819
|
+
const existingSession = await requireSession2(db, workspaceId, sessionId);
|
|
9820
|
+
const settings = await resolveWorkspaceModelBoundarySettings(
|
|
9821
|
+
deps,
|
|
9822
|
+
grant,
|
|
9823
|
+
workspaceId,
|
|
9824
|
+
[input.model ?? existingSession.model],
|
|
9825
|
+
existingSession.model
|
|
9826
|
+
);
|
|
9827
|
+
if (settings !== deps.settings) {
|
|
9828
|
+
deps = {
|
|
9829
|
+
...deps,
|
|
9830
|
+
catalogSourceSettings: deps.catalogSourceSettings ?? deps.settings,
|
|
9831
|
+
settings
|
|
9832
|
+
};
|
|
9833
|
+
}
|
|
9834
|
+
const requestedModel = canonicalConfiguredModel(settings, input.model ?? null) ?? null;
|
|
9835
|
+
const effectiveModel = canonicalConfiguredModel(settings, requestedModel ?? existingSession.model) ?? null;
|
|
9836
|
+
if (effectiveModel === null) {
|
|
9837
|
+
throw new Error("effective follow-up model unexpectedly resolved to null");
|
|
9838
|
+
}
|
|
9839
|
+
await assertWorkspaceModelPolicyAllows(db, settings, workspaceId, requestedModel);
|
|
9840
|
+
try {
|
|
9841
|
+
assertSessionAllowsProductModel(existingSession, effectiveModel);
|
|
9842
|
+
} catch (error) {
|
|
9843
|
+
if (error instanceof CodexCompactionV2ProviderLockedError) {
|
|
9844
|
+
throw new HTTPException11(422, { message: error.message, cause: error });
|
|
9148
9845
|
}
|
|
9149
|
-
|
|
9150
|
-
|
|
9151
|
-
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9846
|
+
throw error;
|
|
9847
|
+
}
|
|
9848
|
+
const sessionReasoningEffort = existingSession.reasoningEffort;
|
|
9849
|
+
const effectiveReasoningEffort = input.reasoningEffort ?? sessionReasoningEffort;
|
|
9850
|
+
const sessionLatencyMode = existingSession.latencyMode;
|
|
9851
|
+
const effectiveLatencyMode = input.latencyMode ?? sessionLatencyMode;
|
|
9852
|
+
const turnExecutionPolicy = resolveTurnExecutionPolicyV1(settings, {
|
|
9853
|
+
modelId: effectiveModel,
|
|
9854
|
+
requestedModelId: input.model ?? null,
|
|
9855
|
+
modelSource: input.model == null ? "session" : "explicit",
|
|
9856
|
+
reasoningEffort: effectiveReasoningEffort,
|
|
9857
|
+
reasoningSource: input.reasoningEffort == null ? "session" : "explicit",
|
|
9858
|
+
latencyMode: effectiveLatencyMode,
|
|
9859
|
+
latencyModeSource: input.latencyMode == null ? "session" : "explicit"
|
|
9860
|
+
});
|
|
9861
|
+
if (composerDraftResources) {
|
|
9862
|
+
const acceptedResources = new Set(requestedResources.map((resource) => stableJson4(resource)));
|
|
9863
|
+
const unacceptedDraftResource = composerDraftResources.find(
|
|
9864
|
+
(resource) => !acceptedResources.has(stableJson4(resource))
|
|
9865
|
+
);
|
|
9866
|
+
if (unacceptedDraftResource) {
|
|
9867
|
+
throw new HTTPException11(422, {
|
|
9868
|
+
message: "composer draft resources must be included in the accepted resource set"
|
|
9869
|
+
});
|
|
9870
|
+
}
|
|
9871
|
+
}
|
|
9872
|
+
const annotations = await validateSubmittedTimelineAnnotations(
|
|
9873
|
+
db,
|
|
9874
|
+
workspaceId,
|
|
9875
|
+
sessionId,
|
|
9876
|
+
input.annotations ?? []
|
|
9877
|
+
);
|
|
9878
|
+
await requireLimit(deps, {
|
|
9879
|
+
accountId: grant.accountId,
|
|
9880
|
+
workspaceId,
|
|
9881
|
+
action: "agent_run:create",
|
|
9882
|
+
quantity: 1,
|
|
9883
|
+
model: effectiveModel
|
|
9884
|
+
});
|
|
9885
|
+
if (requestedResources.some((resource) => resource.kind === "file") && !objectStorage) {
|
|
9886
|
+
throw new HTTPException11(503, {
|
|
9887
|
+
message: "object storage is not configured"
|
|
9888
|
+
});
|
|
9889
|
+
}
|
|
9890
|
+
await validateFileResources(
|
|
9891
|
+
db,
|
|
9892
|
+
grant.accountId,
|
|
9893
|
+
workspaceId,
|
|
9894
|
+
grant.subjectId,
|
|
9895
|
+
requestedResources
|
|
9896
|
+
);
|
|
9897
|
+
await validateGitHubRepositorySelection(db, workspaceId, [
|
|
9898
|
+
...existingSession.resources,
|
|
9899
|
+
...requestedResources
|
|
9900
|
+
]);
|
|
9901
|
+
const mcpCredentialUpdates = validateSessionMcpCredentialUpdates({
|
|
9902
|
+
settings,
|
|
9903
|
+
grant,
|
|
9904
|
+
session: existingSession,
|
|
9905
|
+
updates: input.mcpCredentialUpdates ?? []
|
|
9906
|
+
});
|
|
9907
|
+
const connectionDelegationSource = personalConnectionDelegationSourceForGrant(grant);
|
|
9908
|
+
const inheritedPersonalConnectionDelegations = connectionDelegationSource.kind === "turn" ? await getSessionTurnPersonalConnectionDelegations2(
|
|
9909
|
+
db,
|
|
9910
|
+
workspaceId,
|
|
9911
|
+
connectionDelegationSource.sessionId,
|
|
9912
|
+
connectionDelegationSource.turnId
|
|
9913
|
+
) : null;
|
|
9914
|
+
const runtimeSettings = await settingsWithEnabledCapabilityMcpServers(
|
|
9915
|
+
db,
|
|
9916
|
+
workspaceId,
|
|
9917
|
+
settings,
|
|
9918
|
+
inheritedPersonalConnectionDelegations ? {
|
|
9919
|
+
personalConnectionDelegations: inheritedPersonalConnectionDelegations
|
|
9920
|
+
} : { subjectId: grant.subjectId }
|
|
9921
|
+
);
|
|
9922
|
+
const personalConnectionDelegations = await freezePersonalConnectionDelegations({
|
|
9923
|
+
db,
|
|
9924
|
+
workspaceId,
|
|
9925
|
+
settings: runtimeSettings,
|
|
9926
|
+
tools: existingSession.tools,
|
|
9927
|
+
resources: [...existingSession.resources, ...requestedResources],
|
|
9928
|
+
source: connectionDelegationSource,
|
|
9929
|
+
targetSessionId: sessionId,
|
|
9930
|
+
googleDrivePublicationEnabled: existingSession.firstPartyMcpTools.includes("editable_artifact_export") && existingSession.firstPartyMcpTools.includes("editable_artifact_export_status") && (!existingSession.firstPartyMcpPermissions?.length || existingSession.firstPartyMcpPermissions.includes("artifacts:read") && existingSession.firstPartyMcpPermissions.includes("artifacts:publish")),
|
|
9931
|
+
atlassianEnabled: existingSession.firstPartyMcpTools.some((tool) => tool.startsWith("atlassian_")) && (!existingSession.firstPartyMcpPermissions?.length || existingSession.firstPartyMcpPermissions.includes("connections:read")),
|
|
9932
|
+
...input.connectionAuthorities ? { authoritySelections: input.connectionAuthorities } : {}
|
|
9933
|
+
});
|
|
9934
|
+
const { accepted, turn, draft, receipt: receipt2, routing, interruptionCount, replay } = await postUserMessageTurn({
|
|
9935
|
+
db,
|
|
9936
|
+
bus,
|
|
9937
|
+
workflowClient,
|
|
9938
|
+
settings,
|
|
9939
|
+
accountId: grant.accountId,
|
|
9940
|
+
workspaceId,
|
|
9941
|
+
sessionId,
|
|
9942
|
+
text: input.text,
|
|
9943
|
+
annotations,
|
|
9944
|
+
modelContext: input.modelContext ?? null,
|
|
9945
|
+
resources: requestedResources,
|
|
9946
|
+
...composerDraftResources ? { composerDraftResources } : {},
|
|
9947
|
+
model: input.model ?? null,
|
|
9948
|
+
reasoningEffort: input.reasoningEffort ?? null,
|
|
9949
|
+
latencyMode: input.latencyMode ?? null,
|
|
9950
|
+
reasoningEffortFallback: sessionReasoningEffort,
|
|
9951
|
+
turnExecutionPolicy,
|
|
9952
|
+
mcpCredentialUpdates,
|
|
9953
|
+
personalConnectionDelegations,
|
|
9954
|
+
...input.personalResourceAttachment ? { personalResourceAttachment: input.personalResourceAttachment } : {},
|
|
9955
|
+
delivery,
|
|
9956
|
+
origin: source === "api" ? "operator" : "human",
|
|
9957
|
+
actor: grant.subjectId,
|
|
9958
|
+
...grant.subjectLabel ? { actorLabel: grant.subjectLabel } : {},
|
|
9959
|
+
commandActor,
|
|
9960
|
+
...boundaryRequestHash ? { boundaryRequestHash } : {},
|
|
9961
|
+
...input.controlEtag !== void 0 ? { controlEtag: input.controlEtag } : {},
|
|
9962
|
+
...input.expectedDraftRevision !== void 0 ? { expectedDraftRevision: input.expectedDraftRevision } : {},
|
|
9963
|
+
...input.clientEventId ? { clientEventId: input.clientEventId } : {},
|
|
9964
|
+
recordAgentRunUsage: true,
|
|
9965
|
+
...deps.schedulePromptPostCommit ? { schedulePostCommit: deps.schedulePromptPostCommit } : {}
|
|
9966
|
+
});
|
|
9967
|
+
return { accepted, turn, draft, receipt: receipt2, routing, interruptionCount, replay };
|
|
9968
|
+
} catch (error) {
|
|
9969
|
+
if (input.clientEventId && boundaryRequestHash) {
|
|
9970
|
+
const replay = await withWorkspaceSubjectSessionActivityRls(
|
|
9971
|
+
db,
|
|
9972
|
+
workspaceId,
|
|
9973
|
+
grant.subjectId,
|
|
9974
|
+
async (scopedDb) => await replaySubmittedHumanPromptFromBoundaryReceipt(scopedDb, {
|
|
9975
|
+
workspaceId,
|
|
9976
|
+
sessionId,
|
|
9977
|
+
subjectId: grant.subjectId,
|
|
9978
|
+
actor: commandActor,
|
|
9979
|
+
operationKey: input.clientEventId,
|
|
9980
|
+
delivery,
|
|
9981
|
+
boundaryRequestHash,
|
|
9982
|
+
expectedDraftRevision: input.expectedDraftRevision ?? null,
|
|
9983
|
+
serializeOperation: true
|
|
9984
|
+
})
|
|
9985
|
+
);
|
|
9986
|
+
if (replay) {
|
|
9987
|
+
return finalizePostUserMessageTurn(
|
|
9988
|
+
{
|
|
9989
|
+
db,
|
|
9990
|
+
bus,
|
|
9991
|
+
workflowClient,
|
|
9992
|
+
accountId: grant.accountId,
|
|
9993
|
+
workspaceId,
|
|
9994
|
+
sessionId,
|
|
9995
|
+
delivery,
|
|
9996
|
+
...deps.schedulePromptPostCommit ? { schedulePostCommit: deps.schedulePromptPostCommit } : {}
|
|
9997
|
+
},
|
|
9998
|
+
replay
|
|
9999
|
+
);
|
|
10000
|
+
}
|
|
10001
|
+
}
|
|
10002
|
+
throw error;
|
|
10003
|
+
}
|
|
9157
10004
|
}
|
|
9158
10005
|
async function acceptSessionUserMessage(deps, grant, workspaceId, sessionId, input) {
|
|
9159
10006
|
const { accepted, turn, receipt: receipt2, routing, interruptionCount, replay } = await acceptSessionUserMessageWithOutcome(deps, grant, workspaceId, sessionId, input);
|
|
@@ -9478,6 +10325,26 @@ function scheduledTaskToolsProvided(rawPayload) {
|
|
|
9478
10325
|
agentConfig && typeof agentConfig === "object" && Object.prototype.hasOwnProperty.call(agentConfig, "tools")
|
|
9479
10326
|
);
|
|
9480
10327
|
}
|
|
10328
|
+
function workspaceCustomModelCommitGuard(input) {
|
|
10329
|
+
const reference = workspaceCustomModelReference(input.settings, input.modelId);
|
|
10330
|
+
if (!reference) return void 0;
|
|
10331
|
+
return async (tx) => {
|
|
10332
|
+
const active = reference.providerKind === "openrouter" ? await lockActiveWorkspaceOpenRouterCustomModelForAdmission2(tx, {
|
|
10333
|
+
accountId: input.accountId,
|
|
10334
|
+
workspaceId: input.workspaceId,
|
|
10335
|
+
upstreamModelId: reference.upstreamModelId
|
|
10336
|
+
}) : await lockActiveWorkspaceGatewayCustomModelForAdmission2(tx, {
|
|
10337
|
+
accountId: input.accountId,
|
|
10338
|
+
workspaceId: input.workspaceId,
|
|
10339
|
+
upstreamModelId: reference.upstreamModelId
|
|
10340
|
+
});
|
|
10341
|
+
if (!active) {
|
|
10342
|
+
throw new HTTPException12(422, {
|
|
10343
|
+
message: `model is not available: ${input.modelId}`
|
|
10344
|
+
});
|
|
10345
|
+
}
|
|
10346
|
+
};
|
|
10347
|
+
}
|
|
9481
10348
|
function scheduledConnectionSurfaceEligibility(settings, target) {
|
|
9482
10349
|
const tools = target?.firstPartyMcpTools ?? resolveFirstPartyMcpToolPolicy2(settings).default;
|
|
9483
10350
|
const permissions = target?.firstPartyMcpPermissions?.length ? target.firstPartyMcpPermissions : DEFAULT_FIRST_PARTY_MCP_PERMISSIONS2;
|
|
@@ -9513,6 +10380,15 @@ async function createValidatedScheduledTask(input) {
|
|
|
9513
10380
|
rigId: input.payload.rigId,
|
|
9514
10381
|
agentConfig
|
|
9515
10382
|
});
|
|
10383
|
+
if (!knowledgeAction) {
|
|
10384
|
+
await validateScheduledTaskMachineTarget({
|
|
10385
|
+
settings: input.settings,
|
|
10386
|
+
db: input.db,
|
|
10387
|
+
grant: input.grant,
|
|
10388
|
+
runMode: input.payload.runMode,
|
|
10389
|
+
agentConfig
|
|
10390
|
+
});
|
|
10391
|
+
}
|
|
9516
10392
|
if (!knowledgeAction && input.payload.variableSetId) {
|
|
9517
10393
|
await validateVariableSetAttachment(
|
|
9518
10394
|
{ settings: input.settings, db: input.db },
|
|
@@ -9560,6 +10436,12 @@ async function createValidatedScheduledTask(input) {
|
|
|
9560
10436
|
workspaceId: input.grant.workspaceId,
|
|
9561
10437
|
subjectId: input.grant.subjectId
|
|
9562
10438
|
});
|
|
10439
|
+
const beforeCreateCommit = !knowledgeAction && input.payload.runMode !== "existing_session" ? workspaceCustomModelCommitGuard({
|
|
10440
|
+
settings: input.settings,
|
|
10441
|
+
accountId: input.grant.accountId,
|
|
10442
|
+
workspaceId: input.grant.workspaceId,
|
|
10443
|
+
modelId: agentConfig.model ?? input.settings.openaiModel
|
|
10444
|
+
}) : void 0;
|
|
9563
10445
|
return await withScheduledTaskAuthorityWriteErrors(
|
|
9564
10446
|
() => createScheduledTask(input.db, {
|
|
9565
10447
|
id,
|
|
@@ -9581,7 +10463,8 @@ async function createValidatedScheduledTask(input) {
|
|
|
9581
10463
|
targetSessionId: target?.id ?? null,
|
|
9582
10464
|
variableSetId: input.payload.variableSetId ?? null,
|
|
9583
10465
|
rigId: input.payload.rigId ?? null,
|
|
9584
|
-
metadata: input.payload.metadata
|
|
10466
|
+
metadata: input.payload.metadata,
|
|
10467
|
+
...beforeCreateCommit ? { beforeCreateCommit } : {}
|
|
9585
10468
|
})
|
|
9586
10469
|
);
|
|
9587
10470
|
}
|
|
@@ -9695,6 +10578,59 @@ async function validateScheduledTaskTarget(input) {
|
|
|
9695
10578
|
}
|
|
9696
10579
|
return session;
|
|
9697
10580
|
}
|
|
10581
|
+
async function validateScheduledTaskMachineTarget(input) {
|
|
10582
|
+
const machineTarget = input.agentConfig.machineTarget;
|
|
10583
|
+
if (!machineTarget) {
|
|
10584
|
+
if (input.runMode !== "existing_session" && (input.agentConfig.sandboxBackend ?? input.settings.sandboxBackend) === "selfhosted") {
|
|
10585
|
+
throw new HTTPException12(422, {
|
|
10586
|
+
message: "self-hosted scheduled tasks require a Connected Machine; select a machine before saving"
|
|
10587
|
+
});
|
|
10588
|
+
}
|
|
10589
|
+
return null;
|
|
10590
|
+
}
|
|
10591
|
+
if (input.runMode === "existing_session") {
|
|
10592
|
+
throw new HTTPException12(422, {
|
|
10593
|
+
message: "machineTarget cannot be used with an existing-session target"
|
|
10594
|
+
});
|
|
10595
|
+
}
|
|
10596
|
+
if (!input.settings.sandboxOwnershipEnabled || !input.settings.sandboxSelfhostedEnabled) {
|
|
10597
|
+
throw new HTTPException12(422, {
|
|
10598
|
+
message: "Connected Machines are not enabled for scheduled tasks in this deployment"
|
|
10599
|
+
});
|
|
10600
|
+
}
|
|
10601
|
+
const access = {
|
|
10602
|
+
accountId: input.grant.accountId,
|
|
10603
|
+
workspaceId: input.grant.workspaceId,
|
|
10604
|
+
subjectId: input.grant.subjectId
|
|
10605
|
+
};
|
|
10606
|
+
const sandbox = await getSandbox4(input.db, access, machineTarget.targetSandboxId);
|
|
10607
|
+
if (!sandbox || sandbox.kind !== "selfhosted" || !sandbox.enrollmentId) {
|
|
10608
|
+
throw new HTTPException12(422, {
|
|
10609
|
+
message: "the selected Connected Machine is unavailable"
|
|
10610
|
+
});
|
|
10611
|
+
}
|
|
10612
|
+
if (sandbox.scope === "user") {
|
|
10613
|
+
throw new HTTPException12(422, {
|
|
10614
|
+
message: "personal Connected Machines cannot run unattended schedules; select a workspace or organization machine"
|
|
10615
|
+
});
|
|
10616
|
+
}
|
|
10617
|
+
const enrollment = input.requireOnline ? await getLiveEnrollmentConnection3(input.db, access, sandbox.enrollmentId) : await getEnrollment3(input.db, access, sandbox.enrollmentId);
|
|
10618
|
+
if (!enrollment || enrollment.status !== "active") {
|
|
10619
|
+
throw new HTTPException12(422, {
|
|
10620
|
+
message: input.requireOnline ? "the selected Connected Machine is offline" : "the selected Connected Machine is unavailable"
|
|
10621
|
+
});
|
|
10622
|
+
}
|
|
10623
|
+
if (input.requireOnline && !enrollment.workspaceRoot) {
|
|
10624
|
+
throw new HTTPException12(422, {
|
|
10625
|
+
message: "the selected Connected Machine has not reported a workspace root; reconnect it with a current agent"
|
|
10626
|
+
});
|
|
10627
|
+
}
|
|
10628
|
+
return {
|
|
10629
|
+
sandboxId: sandbox.id,
|
|
10630
|
+
enrollmentId: sandbox.enrollmentId,
|
|
10631
|
+
sandboxOs: enrollment.os
|
|
10632
|
+
};
|
|
10633
|
+
}
|
|
9698
10634
|
function scheduledTaskForGrant(task, grant) {
|
|
9699
10635
|
if (hasPermission(grant.permissions, "sessions:control") || task.targetSessionId === null) {
|
|
9700
10636
|
return task;
|
|
@@ -9854,6 +10790,15 @@ async function validatedScheduledTaskUpdate(input) {
|
|
|
9854
10790
|
const nextAgentConfig = update.agentConfig ?? input.existing.agentConfig;
|
|
9855
10791
|
const authorityTargetChanged = nextRunMode !== input.existing.runMode || nextTargetSessionId !== input.existing.targetSessionId || input.payload.variableSetId !== void 0 && input.payload.variableSetId !== input.existing.variableSetId || input.payload.rigId !== void 0 && input.payload.rigId !== input.existing.rigId;
|
|
9856
10792
|
const materialExecutionChange = authorityTargetChanged || input.payload.connectionAuthorities !== void 0 || !isDeepStrictEqual(nextAgentConfig, input.existing.agentConfig) || input.payload.action !== void 0 && !isDeepStrictEqual(input.payload.action, input.existing.action) || input.payload.schedule !== void 0 && !isDeepStrictEqual(input.payload.schedule, input.existing.schedule) || input.payload.overlapPolicy !== void 0 && input.payload.overlapPolicy !== input.existing.overlapPolicy || input.payload.metadata !== void 0 && !isDeepStrictEqual(input.payload.metadata, input.existing.metadata) || input.existing.status === "paused" && input.payload.status === "active";
|
|
10793
|
+
if (materialExecutionChange && nextRunMode !== "existing_session") {
|
|
10794
|
+
const beforeUpdateCommit = workspaceCustomModelCommitGuard({
|
|
10795
|
+
settings: input.settings,
|
|
10796
|
+
accountId: input.existing.accountId,
|
|
10797
|
+
workspaceId: input.existing.workspaceId,
|
|
10798
|
+
modelId: nextAgentConfig.model ?? input.settings.openaiModel
|
|
10799
|
+
});
|
|
10800
|
+
if (beforeUpdateCommit) update.beforeUpdateCommit = beforeUpdateCommit;
|
|
10801
|
+
}
|
|
9857
10802
|
const existingXaiAuthority = await getScheduledTaskXaiProviderAccountAuthoritySnapshot(
|
|
9858
10803
|
input.db,
|
|
9859
10804
|
input.existing.workspaceId,
|
|
@@ -9966,6 +10911,13 @@ async function validatedScheduledTaskUpdate(input) {
|
|
|
9966
10911
|
rigId: input.payload.rigId !== void 0 ? input.payload.rigId : input.existing.rigId,
|
|
9967
10912
|
agentConfig: update.agentConfig ?? input.existing.agentConfig
|
|
9968
10913
|
});
|
|
10914
|
+
await validateScheduledTaskMachineTarget({
|
|
10915
|
+
settings: input.settings,
|
|
10916
|
+
db: input.db,
|
|
10917
|
+
grant: input.grant,
|
|
10918
|
+
runMode: nextRunMode,
|
|
10919
|
+
agentConfig: update.agentConfig ?? input.existing.agentConfig
|
|
10920
|
+
});
|
|
9969
10921
|
if (input.payload.targetSessionId !== void 0 || input.existing.runMode === "existing_session" || nextRunMode === "existing_session" || input.existing.runMode === "reusable_session" && nextRunMode !== "reusable_session") {
|
|
9970
10922
|
update.targetSessionId = nextTargetSessionId;
|
|
9971
10923
|
}
|
|
@@ -11008,6 +11960,7 @@ function denied(reason) {
|
|
|
11008
11960
|
|
|
11009
11961
|
// src/domain/memory-slack-delivery.ts
|
|
11010
11962
|
import {
|
|
11963
|
+
correctWorkspaceMemory,
|
|
11011
11964
|
enqueueMemorySlackPublication,
|
|
11012
11965
|
getCurrentMemorySlackPublicationConfiguration,
|
|
11013
11966
|
getWorkspaceMemorySlackPublicationSnapshot,
|
|
@@ -11021,6 +11974,25 @@ async function saveWorkspaceMemoryWithSlackPublication(db, input, publication, e
|
|
|
11021
11974
|
return { ...result, slackPublication };
|
|
11022
11975
|
});
|
|
11023
11976
|
}
|
|
11977
|
+
async function correctWorkspaceMemoryWithSlackPublication(db, input, publication, embedder) {
|
|
11978
|
+
return await withWorkspaceRls(db, input.workspaceId, async (scopedDb) => {
|
|
11979
|
+
const result = await correctWorkspaceMemory(scopedDb, input, embedder);
|
|
11980
|
+
if (!publication || result.action !== "superseded" || !result.replacement) {
|
|
11981
|
+
return { ...result, slackPublication: { decision: null, enqueue: null } };
|
|
11982
|
+
}
|
|
11983
|
+
const replacement = await requiredSnapshot(scopedDb, input.workspaceId, result.replacement.id);
|
|
11984
|
+
const slackPublication = await evaluateAndEnqueue(scopedDb, {
|
|
11985
|
+
accountId: input.accountId,
|
|
11986
|
+
workspaceId: input.workspaceId,
|
|
11987
|
+
snapshot: replacement,
|
|
11988
|
+
changeKind: "corrected",
|
|
11989
|
+
relatedMemoryId: result.memory.id,
|
|
11990
|
+
occurredAt: result.replacement.updatedAt,
|
|
11991
|
+
publication
|
|
11992
|
+
});
|
|
11993
|
+
return { ...result, slackPublication };
|
|
11994
|
+
});
|
|
11995
|
+
}
|
|
11024
11996
|
async function publishSavedMemoryMutation(db, input, result, publication) {
|
|
11025
11997
|
if (result.updated || result.deduped && !result.superseded) {
|
|
11026
11998
|
return { decision: null, enqueue: null };
|
|
@@ -11405,7 +12377,13 @@ import {
|
|
|
11405
12377
|
writeCompanyBrainGovernedProposal
|
|
11406
12378
|
} from "@opengeni/db";
|
|
11407
12379
|
import { createHash as createHash7 } from "crypto";
|
|
11408
|
-
var DEFAULT_AUTOMATIC_LEARNING_DESTINATIONS = ["preference"];
|
|
12380
|
+
var DEFAULT_AUTOMATIC_LEARNING_DESTINATIONS = ["preference", "instruction_policy"];
|
|
12381
|
+
function dispatchBestEffortGovernedLearningNotification(notify) {
|
|
12382
|
+
try {
|
|
12383
|
+
void notify().catch(() => void 0);
|
|
12384
|
+
} catch {
|
|
12385
|
+
}
|
|
12386
|
+
}
|
|
11409
12387
|
function createCompanyBrainGovernedWriteRouter(options) {
|
|
11410
12388
|
const authority = options.authority ?? writeCompanyBrainGovernedProposal;
|
|
11411
12389
|
return {
|
|
@@ -11566,15 +12544,14 @@ function createCompanyBrainLearningPolicyRouter(options) {
|
|
|
11566
12544
|
learningFailure: classifyLearningFailure("activation", error)
|
|
11567
12545
|
});
|
|
11568
12546
|
}
|
|
11569
|
-
|
|
11570
|
-
|
|
12547
|
+
dispatchBestEffortGovernedLearningNotification(
|
|
12548
|
+
() => notifyActivation({
|
|
11571
12549
|
db: options.db,
|
|
11572
12550
|
receipt: activation,
|
|
11573
12551
|
sessionId: attempt.sessionId,
|
|
11574
12552
|
attemptId: attempt.attemptId
|
|
11575
|
-
})
|
|
11576
|
-
|
|
11577
|
-
}
|
|
12553
|
+
})
|
|
12554
|
+
);
|
|
11578
12555
|
return CompanyBrainLearningPolicyRouteReceipt.parse({
|
|
11579
12556
|
operationId: request.operationId,
|
|
11580
12557
|
workspaceId: attempt.workspaceId,
|
|
@@ -12020,15 +12997,14 @@ function createRememberRouter(options) {
|
|
|
12020
12997
|
}
|
|
12021
12998
|
}
|
|
12022
12999
|
if (!activation) throw asRememberFailure(lastFailure);
|
|
12023
|
-
|
|
12024
|
-
|
|
13000
|
+
dispatchBestEffortGovernedLearningNotification(
|
|
13001
|
+
() => notifyActivation({
|
|
12025
13002
|
db: options.db,
|
|
12026
13003
|
receipt: activation,
|
|
12027
13004
|
sessionId: attempt.sessionId,
|
|
12028
13005
|
attemptId: attempt.attemptId
|
|
12029
|
-
})
|
|
12030
|
-
|
|
12031
|
-
}
|
|
13006
|
+
})
|
|
13007
|
+
);
|
|
12032
13008
|
return RememberConfirmReceipt.parse({
|
|
12033
13009
|
status: "activated",
|
|
12034
13010
|
operationId: request.operationId,
|
|
@@ -12848,7 +13824,9 @@ function resolveMemberSubjectId(userId) {
|
|
|
12848
13824
|
function assertWorkspaceMemberRemovable(input) {
|
|
12849
13825
|
const { members, subjectId, callerSubjectId } = input;
|
|
12850
13826
|
if (subjectId === callerSubjectId) {
|
|
12851
|
-
throw new HTTPException13(409, {
|
|
13827
|
+
throw new HTTPException13(409, {
|
|
13828
|
+
message: "you cannot remove your own membership"
|
|
13829
|
+
});
|
|
12852
13830
|
}
|
|
12853
13831
|
const target = members.find((member) => member.subjectId === subjectId);
|
|
12854
13832
|
if (!target) {
|
|
@@ -12865,9 +13843,28 @@ function assertWorkspaceMemberRemovable(input) {
|
|
|
12865
13843
|
}
|
|
12866
13844
|
}
|
|
12867
13845
|
}
|
|
13846
|
+
function assertWorkspaceMemberUpdateAllowed(input) {
|
|
13847
|
+
const { members, subjectId, callerSubjectId, nextPermissions } = input;
|
|
13848
|
+
if (subjectId === callerSubjectId) {
|
|
13849
|
+
throw new HTTPException13(409, {
|
|
13850
|
+
message: "you cannot change your own workspace access"
|
|
13851
|
+
});
|
|
13852
|
+
}
|
|
13853
|
+
const target = members.find((member) => member.subjectId === subjectId);
|
|
13854
|
+
if (!target) {
|
|
13855
|
+
throw new HTTPException13(404, { message: "member not found" });
|
|
13856
|
+
}
|
|
13857
|
+
if (memberCanAdminister(target) && !memberCanAdminister({ permissions: nextPermissions }) && !members.some((member) => member.subjectId !== subjectId && memberCanAdminister(member))) {
|
|
13858
|
+
throw new HTTPException13(409, {
|
|
13859
|
+
message: "the workspace must keep at least one administrator"
|
|
13860
|
+
});
|
|
13861
|
+
}
|
|
13862
|
+
}
|
|
12868
13863
|
function assertWorkspaceDeletable(input) {
|
|
12869
13864
|
if (input.workspaceCountForAccount <= 1) {
|
|
12870
|
-
throw new HTTPException13(409, {
|
|
13865
|
+
throw new HTTPException13(409, {
|
|
13866
|
+
message: "cannot delete the account's only workspace"
|
|
13867
|
+
});
|
|
12871
13868
|
}
|
|
12872
13869
|
if (input.activeSessionCount > 0) {
|
|
12873
13870
|
throw new HTTPException13(409, {
|
|
@@ -13125,9 +14122,9 @@ import {
|
|
|
13125
14122
|
} from "@opengeni/contracts";
|
|
13126
14123
|
import {
|
|
13127
14124
|
getNewSessionDraftInTransaction,
|
|
13128
|
-
getEnrollment as
|
|
14125
|
+
getEnrollment as getEnrollment4,
|
|
13129
14126
|
getRig as getRig6,
|
|
13130
|
-
getSandbox as
|
|
14127
|
+
getSandbox as getSandbox5,
|
|
13131
14128
|
getVariableSet as getVariableSet4,
|
|
13132
14129
|
NewSessionDraftAccessError,
|
|
13133
14130
|
newSessionDraftToolsProvided,
|
|
@@ -13220,8 +14217,8 @@ async function hydrateNewSessionDraft(deps, grant, workspaceId, row) {
|
|
|
13220
14217
|
if (!rig?.activeVersion) delete options.rigId;
|
|
13221
14218
|
}
|
|
13222
14219
|
if (options.targetSandboxId) {
|
|
13223
|
-
const sandbox = await
|
|
13224
|
-
const enrollment = sandbox?.enrollmentId ? await
|
|
14220
|
+
const sandbox = await getSandbox5(deps.db, workspaceId, options.targetSandboxId);
|
|
14221
|
+
const enrollment = sandbox?.enrollmentId ? await getEnrollment4(deps.db, workspaceId, sandbox.enrollmentId) : null;
|
|
13225
14222
|
if (!sandbox || sandbox.kind !== "selfhosted" || !enrollment || enrollment.status !== "active") {
|
|
13226
14223
|
delete options.targetSandboxId;
|
|
13227
14224
|
delete options.workingDir;
|
|
@@ -14118,6 +15115,7 @@ async function saveHumanComposerDraft(deps, context, input) {
|
|
|
14118
15115
|
// src/application/user-resource-grants.ts
|
|
14119
15116
|
import {
|
|
14120
15117
|
issueSelfUserResourceGrant,
|
|
15118
|
+
issueSelfLocalConnectionUseGrant,
|
|
14121
15119
|
listSelfUserResourceAuthorities,
|
|
14122
15120
|
revokeSelfUserResourceGrant,
|
|
14123
15121
|
sessionTenancyProductActivated as sessionTenancyProductActivated3,
|
|
@@ -14144,7 +15142,11 @@ async function requireOwnerProductGate(deps, authorization, workspaceId, permiss
|
|
|
14144
15142
|
}
|
|
14145
15143
|
}
|
|
14146
15144
|
function requireOwnerAuthority(authorization, workspaceId, permissions) {
|
|
14147
|
-
|
|
15145
|
+
if (!authorization.canonicalLocalHumanSession) {
|
|
15146
|
+
requireCanonicalManagedHuman(authorization, workspaceId);
|
|
15147
|
+
} else if (!authorization.contextIntegrity || authorization.authenticatedSubjectId !== authorization.grant.subjectId || authorization.grant.workspaceId !== workspaceId) {
|
|
15148
|
+
throw new SessionTenancyManagedHumanRequiredError();
|
|
15149
|
+
}
|
|
14148
15150
|
for (const permission of permissions) requirePermission(authorization.grant, permission);
|
|
14149
15151
|
}
|
|
14150
15152
|
async function listManagedHumanUserResourceAuthorities(deps, authorization, workspaceId, input) {
|
|
@@ -14161,6 +15163,23 @@ async function listManagedHumanUserResourceAuthorities(deps, authorization, work
|
|
|
14161
15163
|
}
|
|
14162
15164
|
async function issueManagedHumanUserResourceGrant(deps, authorization, workspaceId, authorityId, request, authorizationSurface = "core") {
|
|
14163
15165
|
const modePermissions = request.mode === "session" ? ["sessions:control"] : ["sessions:create"];
|
|
15166
|
+
if (authorization.canonicalLocalHumanSession) {
|
|
15167
|
+
requireOwnerAuthority(authorization, workspaceId, [
|
|
15168
|
+
...ISSUE_PERMISSIONS[request.resourceKind],
|
|
15169
|
+
"sessions:create"
|
|
15170
|
+
]);
|
|
15171
|
+
if (request.resourceKind !== "connection" || request.mode !== "always") {
|
|
15172
|
+
throw new SessionTenancyManagedHumanRequiredError();
|
|
15173
|
+
}
|
|
15174
|
+
return await issueSelfLocalConnectionUseGrant(deps.db, {
|
|
15175
|
+
accountId: authorization.grant.accountId,
|
|
15176
|
+
workspaceId,
|
|
15177
|
+
subjectId: authorization.grant.subjectId,
|
|
15178
|
+
authorityId,
|
|
15179
|
+
context: request.context,
|
|
15180
|
+
workspaceSharedAcknowledged: request.workspaceSharedAcknowledged
|
|
15181
|
+
});
|
|
15182
|
+
}
|
|
14164
15183
|
await requireOwnerProductGate(deps, authorization, workspaceId, [
|
|
14165
15184
|
...ISSUE_PERMISSIONS[request.resourceKind],
|
|
14166
15185
|
...modePermissions
|
|
@@ -14280,6 +15299,7 @@ export {
|
|
|
14280
15299
|
MEMORY_SLACK_PROJECTION_MAX_UTF8_BYTES,
|
|
14281
15300
|
MEMORY_SLACK_PROJECTION_VERSION,
|
|
14282
15301
|
MEMORY_SLACK_SUMMARY_MAX_UTF8_BYTES,
|
|
15302
|
+
MODEL_CREDENTIAL_READINESS_OBSERVATION_MAX_AGE_MS,
|
|
14283
15303
|
ManagedAuthActorLeaseOutcomeUnknownError,
|
|
14284
15304
|
MathEditableArtifactOutboxRandom,
|
|
14285
15305
|
OPENGENI_PR_REVIEW_AGENT_INSTRUCTIONS,
|
|
@@ -14317,6 +15337,7 @@ export {
|
|
|
14317
15337
|
acceptSessionUserMessage,
|
|
14318
15338
|
acceptSessionUserMessageWithOutcome,
|
|
14319
15339
|
accessGrantAuthorizationFromContext,
|
|
15340
|
+
accountScopedApiKeyWorkspaceAuthority,
|
|
14320
15341
|
activateRigVersionForApi,
|
|
14321
15342
|
apiIntegrationsMatchingDelegations,
|
|
14322
15343
|
appendRigSetupCommand,
|
|
@@ -14344,6 +15365,7 @@ export {
|
|
|
14344
15365
|
assertVideoGenerationTransition,
|
|
14345
15366
|
assertWorkspaceDeletable,
|
|
14346
15367
|
assertWorkspaceMemberRemovable,
|
|
15368
|
+
assertWorkspaceMemberUpdateAllowed,
|
|
14347
15369
|
assertWorkspaceModelPolicyAllows,
|
|
14348
15370
|
authorizedAtlassianConnectionsForGrant,
|
|
14349
15371
|
authorizedSocialConnectionsForGrant,
|
|
@@ -14374,6 +15396,7 @@ export {
|
|
|
14374
15396
|
controlHumanSessionWorkstreamWithOutcome,
|
|
14375
15397
|
controlHumanWorkspace,
|
|
14376
15398
|
conversationDeliveryNextAction,
|
|
15399
|
+
correctWorkspaceMemoryWithSlackPublication,
|
|
14377
15400
|
createAndStartSession,
|
|
14378
15401
|
createAndStartSessionWithOutcome,
|
|
14379
15402
|
createCatalogItem,
|
|
@@ -14405,6 +15428,7 @@ export {
|
|
|
14405
15428
|
directRetainedProcessMatchesBackend,
|
|
14406
15429
|
disableCapability,
|
|
14407
15430
|
discoverMcpRegistryCapabilities,
|
|
15431
|
+
dispatchBestEffortGovernedLearningNotification,
|
|
14408
15432
|
editHumanQueuePrompt,
|
|
14409
15433
|
editableArtifactActorKey,
|
|
14410
15434
|
editableArtifactAuthorizationRevisionPortFromPostgres,
|
|
@@ -14442,6 +15466,7 @@ export {
|
|
|
14442
15466
|
fikenConnectionMetadata,
|
|
14443
15467
|
filenameForMimeType,
|
|
14444
15468
|
forkManagedHumanSession,
|
|
15469
|
+
freezeAgentChildAutomaticTitleInCreatorContext,
|
|
14445
15470
|
freezePersonalConnectionDelegations,
|
|
14446
15471
|
getActorNewSessionDraft,
|
|
14447
15472
|
getAutomationAdapter,
|
|
@@ -14465,6 +15490,7 @@ export {
|
|
|
14465
15490
|
hasReservedOpenGeniSlackBotSessionMetadata,
|
|
14466
15491
|
hashEditableArtifactCreateRequest,
|
|
14467
15492
|
hashEditableArtifactImportRequest,
|
|
15493
|
+
initialAutomaticTitleForSessionStart,
|
|
14468
15494
|
inlinePackSkillInstall,
|
|
14469
15495
|
insightsSessionLabel,
|
|
14470
15496
|
inspectEditableArtifactLiveWireEnvelope,
|
|
@@ -14476,6 +15502,9 @@ export {
|
|
|
14476
15502
|
isTerminalVideoGenerationState,
|
|
14477
15503
|
isTrustedScheduledSlackBotSession,
|
|
14478
15504
|
isUserMember,
|
|
15505
|
+
isWorkspaceCustomModelId,
|
|
15506
|
+
isWorkspaceGatewayCustomModelId,
|
|
15507
|
+
isWorkspaceOpenRouterCustomModelId,
|
|
14479
15508
|
issueManagedHumanUserResourceGrant,
|
|
14480
15509
|
legacySandboxRuntimeFromPacks,
|
|
14481
15510
|
listCapabilityPacks,
|
|
@@ -14486,6 +15515,8 @@ export {
|
|
|
14486
15515
|
listRigVersionsForApi,
|
|
14487
15516
|
listWorkspaceCapabilityPacks,
|
|
14488
15517
|
loadRigDefaultVariableSetEnvironment,
|
|
15518
|
+
managedSessionGroupBackend,
|
|
15519
|
+
managedSessionGroupOs,
|
|
14489
15520
|
manualScheduledTaskTriggerUsageKey,
|
|
14490
15521
|
manualScheduledTaskTriggerWorkflowId,
|
|
14491
15522
|
markManagedAuthRequestActorTransitionApplied,
|
|
@@ -14494,6 +15525,7 @@ export {
|
|
|
14494
15525
|
mergeResourceRefs,
|
|
14495
15526
|
mergeRigDefaultVariableSetEnvironment,
|
|
14496
15527
|
mergeToolRefs,
|
|
15528
|
+
modelFundingForAdmission,
|
|
14497
15529
|
moveHumanQueuePrompt,
|
|
14498
15530
|
nativeConnectionCapabilityRecommendations,
|
|
14499
15531
|
normalizeConversationActor,
|
|
@@ -14557,6 +15589,7 @@ export {
|
|
|
14557
15589
|
requireAccessGrantAuthorization,
|
|
14558
15590
|
requireAccountAdminAuthorizationStamp,
|
|
14559
15591
|
requireAutomationAdapter,
|
|
15592
|
+
requireCanonicalLocalAccountAdministrator,
|
|
14560
15593
|
requireCanonicalManagedHuman,
|
|
14561
15594
|
requireEnvironmentEncryption,
|
|
14562
15595
|
requireFreshAccessGrant,
|
|
@@ -14575,6 +15608,7 @@ export {
|
|
|
14575
15608
|
requireVariableSetEncryption,
|
|
14576
15609
|
requireVariableSetForApi,
|
|
14577
15610
|
resolveCapabilityPack,
|
|
15611
|
+
resolveCatalogSettings,
|
|
14578
15612
|
resolveChildGoalFromAcceptedSnapshot,
|
|
14579
15613
|
resolveCodexAppsCredentialIdForRun,
|
|
14580
15614
|
resolveFikenDefaultCompanySlug,
|
|
@@ -14587,8 +15621,11 @@ export {
|
|
|
14587
15621
|
resolveSessionSandboxRuntime,
|
|
14588
15622
|
resolveSessionToolPolicy,
|
|
14589
15623
|
resolveSkillImport,
|
|
15624
|
+
resolveWorkspaceCatalogSettings,
|
|
14590
15625
|
resolveWorkspaceLegacyRuntimePacks,
|
|
15626
|
+
resolveWorkspaceModelSelection,
|
|
14591
15627
|
restoreScheduledTask,
|
|
15628
|
+
retainedProcessBackgroundSettlement,
|
|
14592
15629
|
revokeManagedHumanUserResourceGrant,
|
|
14593
15630
|
rigActorForGrant,
|
|
14594
15631
|
rigProviderImageBuildRequestId,
|
|
@@ -14653,6 +15690,7 @@ export {
|
|
|
14653
15690
|
validateManagedAuthRequestActorLease,
|
|
14654
15691
|
validateMcpCapabilityConnection,
|
|
14655
15692
|
validateOpenGeniSlackBotConnectionSelection,
|
|
15693
|
+
validateScheduledTaskMachineTarget,
|
|
14656
15694
|
validateScheduledTaskTarget,
|
|
14657
15695
|
validateToolRefs,
|
|
14658
15696
|
validateToolRefsForSessionPolicy,
|
|
@@ -14672,6 +15710,7 @@ export {
|
|
|
14672
15710
|
withScheduledTaskAuthorityWriteErrors,
|
|
14673
15711
|
withWorkspaceDefaultMcpTools,
|
|
14674
15712
|
workflowIdForSession,
|
|
15713
|
+
workspaceCustomModelReference,
|
|
14675
15714
|
workspaceSessionToolPolicyDefaultServerIds,
|
|
14676
15715
|
workspaceSessionToolPolicyServerIds,
|
|
14677
15716
|
wrapChannelABoxWithRouting
|