@opengeni/config 0.22.0 → 0.22.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +6 -2
- package/dist/index.js +65 -19
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +79 -18
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/config",
|
|
3
|
-
"version": "0.22.
|
|
3
|
+
"version": "0.22.5",
|
|
4
4
|
"description": "OpenGeni runtime configuration: settings resolution, deployment knobs, and config validation shared across the server packages.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"prepublishOnly": "bash ../../scripts/prepublish-guard"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@opengeni/codex": "^0.2.
|
|
37
|
-
"@opengeni/contracts": "^2.
|
|
36
|
+
"@opengeni/codex": "^0.2.20",
|
|
37
|
+
"@opengeni/contracts": "^2.9.2",
|
|
38
38
|
"@opengeni/xai-subscription": "^0.1.2",
|
|
39
39
|
"zod": "^4.2.1"
|
|
40
40
|
},
|
package/src/index.ts
CHANGED
|
@@ -834,6 +834,13 @@ const SettingsSchema = z.object({
|
|
|
834
834
|
// larger timeout—is what lets a session outlive one finite provider box.
|
|
835
835
|
// Knob: OPENGENI_MODAL_TIMEOUT_SECONDS.
|
|
836
836
|
modalTimeoutSeconds: z.coerce.number().int().positive().max(86_400).default(86_400),
|
|
837
|
+
// Optional provider reservations for every new Modal sandbox. CPU is measured
|
|
838
|
+
// in physical cores and may be fractional; memory is measured in MiB. Leave
|
|
839
|
+
// both unset to preserve Modal's provider defaults. The Agents adapter stores
|
|
840
|
+
// the resolved values in its session state so snapshot replacement and exact
|
|
841
|
+
// resume cannot silently change the reservation.
|
|
842
|
+
modalSandboxCpu: z.coerce.number().positive().optional(),
|
|
843
|
+
modalSandboxMemoryMiB: z.coerce.number().int().positive().optional(),
|
|
837
844
|
modalTokenId: z.string().optional(),
|
|
838
845
|
modalTokenSecret: z.string().optional(),
|
|
839
846
|
modalEnvironment: z.string().optional(),
|
|
@@ -873,8 +880,8 @@ const SettingsSchema = z.object({
|
|
|
873
880
|
// cell advertises mode "interactive" — the noVNC viewer can drive mouse+keyboard
|
|
874
881
|
// into :0 (x11vnc runs without -viewonly). Turn it OFF for a genuinely read-only
|
|
875
882
|
// deployment: the cell reports mode "read-only" and the client disables the
|
|
876
|
-
// "Take control" affordance.
|
|
877
|
-
//
|
|
883
|
+
// "Take control" affordance. This gates the HUMAN viewer plane; agent
|
|
884
|
+
// interaction is authorized through managed ComputerSession tools.
|
|
878
885
|
sandboxDesktopInteractive: EnvBoolean.default(true),
|
|
879
886
|
// REAL PTY terminal toggle (P5.t): gates the ttyd pty-ws plane (7681) the API
|
|
880
887
|
// mints over the SAME tunnel as the desktop. Defaults ON — the interactive
|
|
@@ -888,13 +895,7 @@ const SettingsSchema = z.object({
|
|
|
888
895
|
// down→up restart. Defaults match the proven spike geometry (1280x800).
|
|
889
896
|
streamResolutionWidth: z.coerce.number().int().positive().default(1280),
|
|
890
897
|
streamResolutionHeight: z.coerce.number().int().positive().default(800),
|
|
891
|
-
//
|
|
892
|
-
// scrot). Gated by sandboxDesktopEnabled + a desktop-capable backend in
|
|
893
|
-
// buildAgentCapabilities; computerUseReadOnly:false is the agent-driver default
|
|
894
|
-
// (it must click/type — the human viewer plane is the read-only one).
|
|
895
|
-
computerUseEnabled: EnvBoolean.default(true),
|
|
896
|
-
computerUseReadOnly: EnvBoolean.default(false),
|
|
897
|
-
// P4.3 recording loop: ffmpeg x11grab of :0 → mp4/webm → @opengeni/storage.
|
|
898
|
+
// Recording loop: ffmpeg x11grab of :0 → mp4/webm → @opengeni/storage.
|
|
898
899
|
// recordingMaxBytes caps the in-memory finalize buffer (≤ storage single-PUT);
|
|
899
900
|
// recordingMaxSeconds is the ffmpeg -t hard ceiling (bounds a multi-day turn).
|
|
900
901
|
recordingEnabled: EnvBoolean.default(true),
|
|
@@ -1266,6 +1267,10 @@ const SettingsSchema = z.object({
|
|
|
1266
1267
|
betterAuthAllowedHosts: z.string().default(""),
|
|
1267
1268
|
betterAuthCookieDomain: z.string().optional(),
|
|
1268
1269
|
betterAuthTrustedOrigins: z.string().default(""),
|
|
1270
|
+
managedAuthGoogleClientId: z.string().optional(),
|
|
1271
|
+
managedAuthGoogleClientSecret: z.string().optional(),
|
|
1272
|
+
managedAuthGithubClientId: z.string().optional(),
|
|
1273
|
+
managedAuthGithubClientSecret: z.string().optional(),
|
|
1269
1274
|
// Rolling browser login-slot compatibility. Repository/deployment default is
|
|
1270
1275
|
// deliberately legacy; changing to broker is an operator-authorized rollout.
|
|
1271
1276
|
managedAuthSessionSetMode: z.enum(["legacy", "dual", "broker"]).default("legacy"),
|
|
@@ -2497,6 +2502,8 @@ export function getSettings(): Settings {
|
|
|
2497
2502
|
modalImageId: optional("OPENGENI_MODAL_IMAGE_ID"),
|
|
2498
2503
|
modalImageRegistrySecret: optional("OPENGENI_MODAL_IMAGE_REGISTRY_SECRET"),
|
|
2499
2504
|
modalTimeoutSeconds: optional("OPENGENI_MODAL_TIMEOUT_SECONDS"),
|
|
2505
|
+
modalSandboxCpu: optional("OPENGENI_MODAL_SANDBOX_CPU"),
|
|
2506
|
+
modalSandboxMemoryMiB: optional("OPENGENI_MODAL_SANDBOX_MEMORY_MIB"),
|
|
2500
2507
|
modalTokenId: optional("OPENGENI_MODAL_TOKEN_ID"),
|
|
2501
2508
|
modalTokenSecret: optional("OPENGENI_MODAL_TOKEN_SECRET"),
|
|
2502
2509
|
modalEnvironment: optional("OPENGENI_MODAL_ENVIRONMENT"),
|
|
@@ -2507,8 +2514,6 @@ export function getSettings(): Settings {
|
|
|
2507
2514
|
sandboxTerminalEnabled: optional("OPENGENI_SANDBOX_TERMINAL_ENABLED"),
|
|
2508
2515
|
streamResolutionWidth: optional("OPENGENI_STREAM_RESOLUTION_WIDTH"),
|
|
2509
2516
|
streamResolutionHeight: optional("OPENGENI_STREAM_RESOLUTION_HEIGHT"),
|
|
2510
|
-
computerUseEnabled: optional("OPENGENI_COMPUTER_USE_ENABLED"),
|
|
2511
|
-
computerUseReadOnly: optional("OPENGENI_COMPUTER_USE_READONLY"),
|
|
2512
2517
|
recordingEnabled: optional("OPENGENI_RECORDING_ENABLED"),
|
|
2513
2518
|
workspaceCaptureEnabled: optional("OPENGENI_WORKSPACE_CAPTURE"),
|
|
2514
2519
|
recordingDefaultCodec: optional("OPENGENI_RECORDING_DEFAULT_CODEC"),
|
|
@@ -2664,6 +2669,10 @@ export function getSettings(): Settings {
|
|
|
2664
2669
|
betterAuthAllowedHosts: optional("OPENGENI_BETTER_AUTH_ALLOWED_HOSTS"),
|
|
2665
2670
|
betterAuthCookieDomain: optional("OPENGENI_BETTER_AUTH_COOKIE_DOMAIN"),
|
|
2666
2671
|
betterAuthTrustedOrigins: optional("OPENGENI_BETTER_AUTH_TRUSTED_ORIGINS"),
|
|
2672
|
+
managedAuthGoogleClientId: optional("OPENGENI_MANAGED_AUTH_GOOGLE_CLIENT_ID"),
|
|
2673
|
+
managedAuthGoogleClientSecret: optional("OPENGENI_MANAGED_AUTH_GOOGLE_CLIENT_SECRET"),
|
|
2674
|
+
managedAuthGithubClientId: optional("OPENGENI_MANAGED_AUTH_GITHUB_CLIENT_ID"),
|
|
2675
|
+
managedAuthGithubClientSecret: optional("OPENGENI_MANAGED_AUTH_GITHUB_CLIENT_SECRET"),
|
|
2667
2676
|
managedAuthSessionSetMode: optional("OPENGENI_MANAGED_AUTH_SESSION_SET_MODE"),
|
|
2668
2677
|
resendApiKey: optional("OPENGENI_RESEND_API_KEY"),
|
|
2669
2678
|
emailFrom: optional("OPENGENI_EMAIL_FROM"),
|
|
@@ -3548,8 +3557,10 @@ function canonicalJson(value: unknown): string {
|
|
|
3548
3557
|
function definitionVersionFor(
|
|
3549
3558
|
model: Omit<ConfiguredModel, "definitionVersion">,
|
|
3550
3559
|
provider: ResolvedModelProvider,
|
|
3560
|
+
options: { includeWireProfile?: boolean } = {},
|
|
3551
3561
|
): string {
|
|
3552
3562
|
const requestMetadata = staticRequestMetadataForDigest(provider);
|
|
3563
|
+
const includeWireProfile = options.includeWireProfile ?? true;
|
|
3553
3564
|
const digestInput = canonicalJson({
|
|
3554
3565
|
schemaVersion: model.schemaVersion,
|
|
3555
3566
|
id: model.id,
|
|
@@ -3558,7 +3569,7 @@ function definitionVersionFor(
|
|
|
3558
3569
|
provider: {
|
|
3559
3570
|
adapterKind: provider.kind,
|
|
3560
3571
|
wireApi: provider.api,
|
|
3561
|
-
wireProfile: provider.wireProfile,
|
|
3572
|
+
...(includeWireProfile ? { wireProfile: provider.wireProfile } : {}),
|
|
3562
3573
|
baseUrl: provider.baseUrl ?? null,
|
|
3563
3574
|
defaultHeaders: requestMetadata.headers,
|
|
3564
3575
|
defaultQuery: requestMetadata.query,
|
|
@@ -3576,6 +3587,15 @@ function definitionVersionFor(
|
|
|
3576
3587
|
.digest("hex")}`;
|
|
3577
3588
|
}
|
|
3578
3589
|
|
|
3590
|
+
function legacyImplicitOpenAiDefinitionVersionFor(
|
|
3591
|
+
model: ConfiguredModel,
|
|
3592
|
+
provider: ResolvedModelProvider,
|
|
3593
|
+
): string | null {
|
|
3594
|
+
if (provider.wireProfile !== "openai") return null;
|
|
3595
|
+
const { definitionVersion: _definitionVersion, ...modelWithoutVersion } = model;
|
|
3596
|
+
return definitionVersionFor(modelWithoutVersion, provider, { includeWireProfile: false });
|
|
3597
|
+
}
|
|
3598
|
+
|
|
3579
3599
|
/**
|
|
3580
3600
|
* The built-in provider's stable id: "openai" on the OpenAI platform, "azure"
|
|
3581
3601
|
* on Azure. Exported because the workspace model-policy gate must attribute
|
|
@@ -4157,11 +4177,22 @@ export function assertTurnExecutionPolicyMatchesConfigV1(
|
|
|
4157
4177
|
if (!resolved) {
|
|
4158
4178
|
throw new Error("Turn execution policy model is no longer configured");
|
|
4159
4179
|
}
|
|
4180
|
+
// wireProfile was added to the definition digest after policies already
|
|
4181
|
+
// existed in durable in-flight turns. An omitted profile meant exactly
|
|
4182
|
+
// "openai", so accept that one legacy digest only; Azure and every other
|
|
4183
|
+
// executable-definition change remain fail-closed.
|
|
4184
|
+
const legacyImplicitOpenAiDefinitionVersion = legacyImplicitOpenAiDefinitionVersionFor(
|
|
4185
|
+
resolved.model,
|
|
4186
|
+
resolved.provider,
|
|
4187
|
+
);
|
|
4188
|
+
const definitionVersionMatches =
|
|
4189
|
+
parsed.definitionVersion === resolved.model.definitionVersion ||
|
|
4190
|
+
parsed.definitionVersion === legacyImplicitOpenAiDefinitionVersion;
|
|
4160
4191
|
const mismatched =
|
|
4161
4192
|
parsed.providerId !== resolved.provider.id ||
|
|
4162
4193
|
parsed.upstreamModelId !== resolved.model.upstreamModelId ||
|
|
4163
4194
|
parsed.wireApi !== resolved.model.api ||
|
|
4164
|
-
|
|
4195
|
+
!definitionVersionMatches ||
|
|
4165
4196
|
canonicalJson(parsed.credentialSource) !== canonicalJson(resolved.model.credentialSource) ||
|
|
4166
4197
|
canonicalJson(parsed.billing) !== canonicalJson(resolved.model.billing);
|
|
4167
4198
|
if (mismatched) {
|
|
@@ -5335,6 +5366,41 @@ function validateSettings(settings: Settings): void {
|
|
|
5335
5366
|
);
|
|
5336
5367
|
}
|
|
5337
5368
|
}
|
|
5369
|
+
if (
|
|
5370
|
+
Boolean(settings.managedAuthGoogleClientId) !== Boolean(settings.managedAuthGoogleClientSecret)
|
|
5371
|
+
) {
|
|
5372
|
+
throw new Error(
|
|
5373
|
+
"OPENGENI_MANAGED_AUTH_GOOGLE_CLIENT_ID and OPENGENI_MANAGED_AUTH_GOOGLE_CLIENT_SECRET must be configured together",
|
|
5374
|
+
);
|
|
5375
|
+
}
|
|
5376
|
+
if (
|
|
5377
|
+
Boolean(settings.managedAuthGithubClientId) !== Boolean(settings.managedAuthGithubClientSecret)
|
|
5378
|
+
) {
|
|
5379
|
+
throw new Error(
|
|
5380
|
+
"OPENGENI_MANAGED_AUTH_GITHUB_CLIENT_ID and OPENGENI_MANAGED_AUTH_GITHUB_CLIENT_SECRET must be configured together",
|
|
5381
|
+
);
|
|
5382
|
+
}
|
|
5383
|
+
const managedSocialAuthConfigured = Boolean(
|
|
5384
|
+
settings.managedAuthGoogleClientId || settings.managedAuthGithubClientId,
|
|
5385
|
+
);
|
|
5386
|
+
if (managedSocialAuthConfigured) {
|
|
5387
|
+
if (settings.productAccessMode !== "managed") {
|
|
5388
|
+
throw new Error(
|
|
5389
|
+
"Managed Google/GitHub authentication requires OPENGENI_PRODUCT_ACCESS_MODE=managed",
|
|
5390
|
+
);
|
|
5391
|
+
}
|
|
5392
|
+
const publicOrigin = canonicalPublicOrigin(settings.publicBaseUrl);
|
|
5393
|
+
if (!publicOrigin) {
|
|
5394
|
+
throw new Error(
|
|
5395
|
+
"OPENGENI_PUBLIC_BASE_URL must be a credential-free HTTP(S) origin when managed social authentication is configured",
|
|
5396
|
+
);
|
|
5397
|
+
}
|
|
5398
|
+
if (!publicOrigin.startsWith("https://") && !["local", "test"].includes(settings.environment)) {
|
|
5399
|
+
throw new Error(
|
|
5400
|
+
"OPENGENI_PUBLIC_BASE_URL must use https when managed social authentication is configured outside local/test",
|
|
5401
|
+
);
|
|
5402
|
+
}
|
|
5403
|
+
}
|
|
5338
5404
|
environmentsEncryptionKeyBytes(settings);
|
|
5339
5405
|
if (settings.integrationsEnabled) {
|
|
5340
5406
|
if (settings.productAccessMode === "managed" && !settings.publicBaseUrl) {
|
|
@@ -5401,11 +5467,6 @@ function validateSettings(settings: Settings): void {
|
|
|
5401
5467
|
"OPENGENI_INTEGRATIONS_ENABLED=true is required when personal GitHub OAuth is enabled",
|
|
5402
5468
|
);
|
|
5403
5469
|
}
|
|
5404
|
-
if (settings.productAccessMode !== "managed") {
|
|
5405
|
-
throw new Error(
|
|
5406
|
-
"OPENGENI_GITHUB_PERSONAL_OAUTH_ENABLED=true requires OPENGENI_PRODUCT_ACCESS_MODE=managed",
|
|
5407
|
-
);
|
|
5408
|
-
}
|
|
5409
5470
|
if (!settings.githubPersonalOauthClientId || !settings.githubPersonalOauthClientSecret) {
|
|
5410
5471
|
throw new Error(
|
|
5411
5472
|
"personal GitHub OAuth requires OPENGENI_GITHUB_PERSONAL_OAUTH_CLIENT_ID and OPENGENI_GITHUB_PERSONAL_OAUTH_CLIENT_SECRET",
|