@opengeni/config 1.2.2 → 2.0.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/index.d.ts +93 -4
- package/dist/index.js +172 -73
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +243 -123
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
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": "^
|
|
36
|
+
"@opengeni/codex": "^0.2.24",
|
|
37
|
+
"@opengeni/contracts": "^5.0.0",
|
|
38
38
|
"@opengeni/xai-subscription": "^0.1.4",
|
|
39
39
|
"zod": "^4.2.1"
|
|
40
40
|
},
|
package/src/index.ts
CHANGED
|
@@ -197,7 +197,7 @@ export const AGENT_INSTRUCTIONS_CORE_PLACEHOLDER = "{{core}}";
|
|
|
197
197
|
*/
|
|
198
198
|
export const DEFAULT_AGENT_INSTRUCTIONS = [
|
|
199
199
|
"You are an OpenGeni workspace agent.",
|
|
200
|
-
"Follow the user's task and
|
|
200
|
+
"Follow the user's task and the applicable Skill instructions for the current role.",
|
|
201
201
|
"Work inside the sandbox workspace and use filesystem and shell tools when useful.",
|
|
202
202
|
"Repository resources are mounted under repos/<host>/<owner>/<repo> unless the session specifies another collision-free mount path.",
|
|
203
203
|
"File resources are mounted under .opengeni/files/<file-id>/ unless the session specifies another mount path.",
|
|
@@ -285,6 +285,8 @@ const SettingsSchema = z.object({
|
|
|
285
285
|
observabilityMetricsEnabled: EnvBoolean.default(true),
|
|
286
286
|
observabilityOtlpEndpoint: z.string().url().optional(),
|
|
287
287
|
observabilityOtlpHeaders: z.string().default(""),
|
|
288
|
+
observabilityDiagnosticsEndpoint: z.string().url().optional(),
|
|
289
|
+
observabilityDiagnosticsHeaders: z.string().default(""),
|
|
288
290
|
analyticsEnabled: EnvBoolean.default(false),
|
|
289
291
|
analyticsConsentRequired: EnvBoolean.default(true),
|
|
290
292
|
analyticsReoClientId: z
|
|
@@ -484,16 +486,6 @@ const SettingsSchema = z.object({
|
|
|
484
486
|
// into @opengeni/db once at boot.
|
|
485
487
|
// Env: OPENGENI_CHILD_LIFECYCLE_NOTICES_ENABLED.
|
|
486
488
|
childLifecycleNoticesEnabled: EnvBoolean.default(false),
|
|
487
|
-
// Explicit host-owned MCP connection authority is a rolling protocol
|
|
488
|
-
// activation. Keep it off while any API, worker, or browser bundle predates
|
|
489
|
-
// the authority discriminator; enable it only after the whole fleet runs an
|
|
490
|
-
// image that understands host refs. Legacy markerless non-UUID refs remain a
|
|
491
|
-
// separate compatibility lane for already-persisted embedding integrations.
|
|
492
|
-
// Env: OPENGENI_HOST_MCP_AUTHORITY_SOURCE_ADMISSION_ENABLED.
|
|
493
|
-
hostMcpAuthoritySourceAdmissionEnabled: EnvBoolean.default(false),
|
|
494
|
-
// Server-owned per-organization remote MCP resolver configuration. Optional;
|
|
495
|
-
// inline credentials and native provider OAuth do not require this service.
|
|
496
|
-
hostMcpCredentialResolversJson: z.string().optional(),
|
|
497
489
|
// Per-channel and per-DM Slack workspace routing. Default ON. A channel does
|
|
498
490
|
// not count a personal workspace as a candidate, so an organization with one
|
|
499
491
|
// shared workspace resolves it as the sole candidate and never asks; the
|
|
@@ -744,6 +736,7 @@ const SettingsSchema = z.object({
|
|
|
744
736
|
// rotated TO — when EITHER usage window (5h/weekly) is at/over this percent. Default 90 to
|
|
745
737
|
// match the UI danger flip (UsageBar danger at pct >= 90). OPENGENI_CODEX_ROTATION_NEAR_EXHAUSTION_PCT.
|
|
746
738
|
codexRotationNearExhaustionPct: z.coerce.number().int().min(1).max(100).default(90),
|
|
739
|
+
reasoningConfigurationUpdatesEnabled: EnvBoolean.default(false),
|
|
747
740
|
openaiReasoningEffort: ReasoningEffort.default("low"),
|
|
748
741
|
openaiAllowedReasoningEfforts: z.string().default("low,medium,high,xhigh,max"),
|
|
749
742
|
openaiResponsesTransport: z.enum(["http", "websocket"]).default("http"),
|
|
@@ -792,7 +785,7 @@ const SettingsSchema = z.object({
|
|
|
792
785
|
// the verified, self-contained native artifact runtime at its fixed image
|
|
793
786
|
// paths. Disabled by default so arbitrary/custom provider images never make
|
|
794
787
|
// document/spreadsheet/presentation skills appear when their runtime is
|
|
795
|
-
|
|
788
|
+
|
|
796
789
|
// when this base-image contract is enabled.
|
|
797
790
|
sandboxArtifactRuntimeEnabled: EnvBoolean.default(false),
|
|
798
791
|
dockerExposedPorts: z.string().default(""),
|
|
@@ -804,6 +797,9 @@ const SettingsSchema = z.object({
|
|
|
804
797
|
dockerWorkspaceBaseDir: z.string().min(1).optional(),
|
|
805
798
|
modalAppName: z.string().default("opengeni-sandbox"),
|
|
806
799
|
modalImageRef: z.string().optional(),
|
|
800
|
+
// Activate only after descriptor-aware readers, DB fences and the exact
|
|
801
|
+
// native image have passed the supervised-command rollout canary.
|
|
802
|
+
modalCommandSupervisionEnabled: EnvBoolean.default(false),
|
|
807
803
|
// Provider-native immutable Modal image ID for the exact logical
|
|
808
804
|
// `modalImageRef`. When set, the runtime uses ModalImageSelector.fromId and
|
|
809
805
|
// never asks Modal to parse or import the registry ref. The logical ref is
|
|
@@ -1332,6 +1328,124 @@ const SettingsSchema = z.object({
|
|
|
1332
1328
|
});
|
|
1333
1329
|
|
|
1334
1330
|
export type Settings = z.infer<typeof SettingsSchema>;
|
|
1331
|
+
|
|
1332
|
+
// Independently supervised artifact services are not API/agent runtimes. Parse
|
|
1333
|
+
// only their actual capabilities, using the same field schemas as getSettings.
|
|
1334
|
+
const ArtifactServiceSettingsSchema = SettingsSchema.pick({
|
|
1335
|
+
serviceName: true,
|
|
1336
|
+
environment: true,
|
|
1337
|
+
deploymentRevision: true,
|
|
1338
|
+
dbSchema: true,
|
|
1339
|
+
rlsStrategy: true,
|
|
1340
|
+
observabilityStructuredLogs: true,
|
|
1341
|
+
observabilityMetricsEnabled: true,
|
|
1342
|
+
observabilityOtlpEndpoint: true,
|
|
1343
|
+
observabilityOtlpHeaders: true,
|
|
1344
|
+
});
|
|
1345
|
+
const ArtifactOutboxSettingsSchema = ArtifactServiceSettingsSchema.extend({
|
|
1346
|
+
natsUrl: SettingsSchema.shape.natsUrl,
|
|
1347
|
+
selfhostedNatsControlUser: SettingsSchema.shape.selfhostedNatsControlUser,
|
|
1348
|
+
selfhostedNatsControlPassword: SettingsSchema.shape.selfhostedNatsControlPassword,
|
|
1349
|
+
});
|
|
1350
|
+
const ObjectStorageSettingsSchema = SettingsSchema.pick({
|
|
1351
|
+
objectStorageBackend: true,
|
|
1352
|
+
objectStorageEndpoint: true,
|
|
1353
|
+
objectStorageInternalEndpoint: true,
|
|
1354
|
+
objectStorageSandboxEndpoint: true,
|
|
1355
|
+
objectStorageBucket: true,
|
|
1356
|
+
objectStorageRegion: true,
|
|
1357
|
+
objectStorageAccessKeyId: true,
|
|
1358
|
+
objectStorageSecretAccessKey: true,
|
|
1359
|
+
objectStorageForcePathStyle: true,
|
|
1360
|
+
objectStorageAzureConnectionString: true,
|
|
1361
|
+
objectStorageAzureAccountName: true,
|
|
1362
|
+
objectStorageAzureAccountKey: true,
|
|
1363
|
+
objectStorageAzureEndpoint: true,
|
|
1364
|
+
objectStorageGcsProjectId: true,
|
|
1365
|
+
objectStorageGcsCredentialsJson: true,
|
|
1366
|
+
objectStorageGcsKeyFilename: true,
|
|
1367
|
+
objectStorageGcsApiEndpoint: true,
|
|
1368
|
+
});
|
|
1369
|
+
const ArtifactMaterializerSettingsSchema = ArtifactServiceSettingsSchema.extend(
|
|
1370
|
+
ObjectStorageSettingsSchema.shape,
|
|
1371
|
+
);
|
|
1372
|
+
export type ArtifactOutboxSettings = z.infer<typeof ArtifactOutboxSettingsSchema>;
|
|
1373
|
+
export type ObjectStorageSettings = z.infer<typeof ObjectStorageSettingsSchema>;
|
|
1374
|
+
export type ArtifactMaterializerSettings = z.infer<typeof ArtifactMaterializerSettingsSchema>;
|
|
1375
|
+
|
|
1376
|
+
function artifactServiceEnvironment(source: NodeJS.ProcessEnv) {
|
|
1377
|
+
const optional = (name: string) => optionalEnvironmentValue(name, source);
|
|
1378
|
+
return {
|
|
1379
|
+
serviceName: optional("OPENGENI_SERVICE_NAME"),
|
|
1380
|
+
environment: optional("OPENGENI_ENVIRONMENT"),
|
|
1381
|
+
deploymentRevision:
|
|
1382
|
+
optional("OPENGENI_DEPLOYMENT_REVISION") ??
|
|
1383
|
+
optional("SOURCE_VERSION") ??
|
|
1384
|
+
optional("GITHUB_SHA"),
|
|
1385
|
+
dbSchema: optional("OPENGENI_DB_SCHEMA"),
|
|
1386
|
+
rlsStrategy: optional("OPENGENI_RLS_STRATEGY"),
|
|
1387
|
+
observabilityStructuredLogs: optional("OPENGENI_OBSERVABILITY_STRUCTURED_LOGS"),
|
|
1388
|
+
observabilityMetricsEnabled: optional("OPENGENI_OBSERVABILITY_METRICS_ENABLED"),
|
|
1389
|
+
observabilityOtlpEndpoint:
|
|
1390
|
+
optional("OPENGENI_OTEL_EXPORTER_OTLP_ENDPOINT") ?? optional("OTEL_EXPORTER_OTLP_ENDPOINT"),
|
|
1391
|
+
observabilityOtlpHeaders:
|
|
1392
|
+
optional("OPENGENI_OTEL_EXPORTER_OTLP_HEADERS") ?? optional("OTEL_EXPORTER_OTLP_HEADERS"),
|
|
1393
|
+
};
|
|
1394
|
+
}
|
|
1395
|
+
|
|
1396
|
+
export function getArtifactOutboxSettings(
|
|
1397
|
+
source: NodeJS.ProcessEnv = process.env,
|
|
1398
|
+
): ArtifactOutboxSettings {
|
|
1399
|
+
const settings = ArtifactOutboxSettingsSchema.parse({
|
|
1400
|
+
...artifactServiceEnvironment(source),
|
|
1401
|
+
natsUrl: optionalEnvironmentValue("OPENGENI_NATS_URL", source),
|
|
1402
|
+
selfhostedNatsControlUser: optionalEnvironmentValue(
|
|
1403
|
+
"OPENGENI_SELFHOSTED_NATS_CONTROL_USER",
|
|
1404
|
+
source,
|
|
1405
|
+
),
|
|
1406
|
+
selfhostedNatsControlPassword: optionalEnvironmentValue(
|
|
1407
|
+
"OPENGENI_SELFHOSTED_NATS_CONTROL_PASSWORD",
|
|
1408
|
+
source,
|
|
1409
|
+
),
|
|
1410
|
+
});
|
|
1411
|
+
dbSearchPath(settings);
|
|
1412
|
+
if (
|
|
1413
|
+
Boolean(settings.selfhostedNatsControlUser) !== Boolean(settings.selfhostedNatsControlPassword)
|
|
1414
|
+
) {
|
|
1415
|
+
throw new Error("Artifact outbox NATS control user and password must be configured together");
|
|
1416
|
+
}
|
|
1417
|
+
return settings;
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
export function getArtifactMaterializerSettings(
|
|
1421
|
+
source: NodeJS.ProcessEnv = process.env,
|
|
1422
|
+
): ArtifactMaterializerSettings {
|
|
1423
|
+
const optional = (name: string) => optionalEnvironmentValue(name, source);
|
|
1424
|
+
const settings = ArtifactMaterializerSettingsSchema.parse({
|
|
1425
|
+
...artifactServiceEnvironment(source),
|
|
1426
|
+
objectStorageEndpoint: optional("OPENGENI_OBJECT_STORAGE_ENDPOINT"),
|
|
1427
|
+
objectStorageInternalEndpoint: optional("OPENGENI_OBJECT_STORAGE_INTERNAL_ENDPOINT"),
|
|
1428
|
+
objectStorageSandboxEndpoint: optional("OPENGENI_OBJECT_STORAGE_SANDBOX_ENDPOINT"),
|
|
1429
|
+
objectStorageBackend: optional("OPENGENI_OBJECT_STORAGE_BACKEND"),
|
|
1430
|
+
objectStorageBucket: optional("OPENGENI_OBJECT_STORAGE_BUCKET"),
|
|
1431
|
+
objectStorageRegion: optional("OPENGENI_OBJECT_STORAGE_REGION"),
|
|
1432
|
+
objectStorageAccessKeyId: optional("OPENGENI_OBJECT_STORAGE_ACCESS_KEY_ID"),
|
|
1433
|
+
objectStorageSecretAccessKey: optional("OPENGENI_OBJECT_STORAGE_SECRET_ACCESS_KEY"),
|
|
1434
|
+
objectStorageForcePathStyle: optional("OPENGENI_OBJECT_STORAGE_FORCE_PATH_STYLE"),
|
|
1435
|
+
objectStorageAzureConnectionString: optional("OPENGENI_OBJECT_STORAGE_AZURE_CONNECTION_STRING"),
|
|
1436
|
+
objectStorageAzureAccountName: optional("OPENGENI_OBJECT_STORAGE_AZURE_ACCOUNT_NAME"),
|
|
1437
|
+
objectStorageAzureAccountKey: optional("OPENGENI_OBJECT_STORAGE_AZURE_ACCOUNT_KEY"),
|
|
1438
|
+
objectStorageAzureEndpoint: optional("OPENGENI_OBJECT_STORAGE_AZURE_ENDPOINT"),
|
|
1439
|
+
objectStorageGcsProjectId: optional("OPENGENI_OBJECT_STORAGE_GCS_PROJECT_ID"),
|
|
1440
|
+
objectStorageGcsCredentialsJson: optional("OPENGENI_OBJECT_STORAGE_GCS_CREDENTIALS_JSON"),
|
|
1441
|
+
objectStorageGcsKeyFilename: optional("OPENGENI_OBJECT_STORAGE_GCS_KEY_FILENAME"),
|
|
1442
|
+
objectStorageGcsApiEndpoint: optional("OPENGENI_OBJECT_STORAGE_GCS_API_ENDPOINT"),
|
|
1443
|
+
});
|
|
1444
|
+
dbSearchPath(settings);
|
|
1445
|
+
validateObjectStorageSettings(settings);
|
|
1446
|
+
return settings;
|
|
1447
|
+
}
|
|
1448
|
+
|
|
1335
1449
|
export type McpServerConfig = Settings["mcpServers"][number];
|
|
1336
1450
|
|
|
1337
1451
|
export type GoogleDriveProviderRetryOptions = {
|
|
@@ -2826,6 +2940,8 @@ export function getSettings(source: NodeJS.ProcessEnv = process.env): Settings {
|
|
|
2826
2940
|
optional("OPENGENI_OTEL_EXPORTER_OTLP_ENDPOINT") ?? optional("OTEL_EXPORTER_OTLP_ENDPOINT"),
|
|
2827
2941
|
observabilityOtlpHeaders:
|
|
2828
2942
|
optional("OPENGENI_OTEL_EXPORTER_OTLP_HEADERS") ?? optional("OTEL_EXPORTER_OTLP_HEADERS"),
|
|
2943
|
+
observabilityDiagnosticsEndpoint: optional("OPENGENI_OBSERVABILITY_DIAGNOSTICS_ENDPOINT"),
|
|
2944
|
+
observabilityDiagnosticsHeaders: optional("OPENGENI_OBSERVABILITY_DIAGNOSTICS_HEADERS"),
|
|
2829
2945
|
analyticsEnabled: optional("OPENGENI_ANALYTICS_ENABLED"),
|
|
2830
2946
|
analyticsConsentRequired: optional("OPENGENI_ANALYTICS_CONSENT_REQUIRED"),
|
|
2831
2947
|
analyticsReoClientId: optional("OPENGENI_ANALYTICS_REO_CLIENT_ID"),
|
|
@@ -2906,10 +3022,6 @@ export function getSettings(source: NodeJS.ProcessEnv = process.env): Settings {
|
|
|
2906
3022
|
goalIdleBackoffMs: optional("OPENGENI_GOAL_IDLE_BACKOFF_MS"),
|
|
2907
3023
|
goalIdleBackoffMaxMs: optional("OPENGENI_GOAL_IDLE_BACKOFF_MAX_MS"),
|
|
2908
3024
|
childLifecycleNoticesEnabled: optional("OPENGENI_CHILD_LIFECYCLE_NOTICES_ENABLED"),
|
|
2909
|
-
hostMcpAuthoritySourceAdmissionEnabled: optional(
|
|
2910
|
-
"OPENGENI_HOST_MCP_AUTHORITY_SOURCE_ADMISSION_ENABLED",
|
|
2911
|
-
),
|
|
2912
|
-
hostMcpCredentialResolversJson: optional("OPENGENI_HOST_MCP_CREDENTIAL_RESOLVERS_JSON"),
|
|
2913
3025
|
slackWorkspaceRoutingEnabled: optional("OPENGENI_SLACK_WORKSPACE_ROUTING_ENABLED"),
|
|
2914
3026
|
agentMaxModelCallsPerTurn: optional("OPENGENI_AGENT_MAX_MODEL_CALLS_PER_TURN"),
|
|
2915
3027
|
contextWindowTokens: optional("OPENGENI_CONTEXT_WINDOW_TOKENS"),
|
|
@@ -2994,6 +3106,9 @@ export function getSettings(source: NodeJS.ProcessEnv = process.env): Settings {
|
|
|
2994
3106
|
lazyToolSearchEnabled: optional("OPENGENI_LAZY_TOOL_SEARCH_ENABLED"),
|
|
2995
3107
|
codexFleetPolicyShadowEnabled: optional("OPENGENI_CODEX_FLEET_POLICY_SHADOW_ENABLED"),
|
|
2996
3108
|
codexProductSku: optional("OPENGENI_CODEX_PRODUCT_SKU"),
|
|
3109
|
+
reasoningConfigurationUpdatesEnabled: optional(
|
|
3110
|
+
"OPENGENI_REASONING_CONFIGURATION_UPDATES_ENABLED",
|
|
3111
|
+
),
|
|
2997
3112
|
openaiReasoningEffort: optional("OPENGENI_OPENAI_REASONING_EFFORT"),
|
|
2998
3113
|
openaiAllowedReasoningEfforts: optional("OPENGENI_OPENAI_ALLOWED_REASONING_EFFORTS"),
|
|
2999
3114
|
openaiResponsesTransport: optional("OPENGENI_OPENAI_RESPONSES_TRANSPORT"),
|
|
@@ -3017,6 +3132,7 @@ export function getSettings(source: NodeJS.ProcessEnv = process.env): Settings {
|
|
|
3017
3132
|
dockerWorkspaceBaseDir: optional("OPENGENI_DOCKER_WORKSPACE_BASE_DIR"),
|
|
3018
3133
|
modalAppName: optional("OPENGENI_MODAL_APP_NAME"),
|
|
3019
3134
|
modalImageRef: optional("OPENGENI_MODAL_IMAGE_REF") ?? DEFAULT_MODAL_IMAGE_REF,
|
|
3135
|
+
modalCommandSupervisionEnabled: optional("OPENGENI_MODAL_COMMAND_SUPERVISION_ENABLED"),
|
|
3020
3136
|
modalImageId: optional("OPENGENI_MODAL_IMAGE_ID"),
|
|
3021
3137
|
modalImageRegistrySecret: optional("OPENGENI_MODAL_IMAGE_REGISTRY_SECRET"),
|
|
3022
3138
|
modalTimeoutSeconds: optional("OPENGENI_MODAL_TIMEOUT_SECONDS"),
|
|
@@ -5764,6 +5880,7 @@ export function applyGitAuthPointerEnvironment(
|
|
|
5764
5880
|
}
|
|
5765
5881
|
|
|
5766
5882
|
export type StartupRetryOptions = {
|
|
5883
|
+
shouldRetry?: (error: unknown) => boolean;
|
|
5767
5884
|
attempts?: number;
|
|
5768
5885
|
initialDelayMs?: number;
|
|
5769
5886
|
maxDelayMs?: number;
|
|
@@ -5778,7 +5895,7 @@ export type StartupRetryOptions = {
|
|
|
5778
5895
|
|
|
5779
5896
|
export function startupRetryOptions(
|
|
5780
5897
|
settings: Settings,
|
|
5781
|
-
): Required<Omit<StartupRetryOptions, "onRetry">> {
|
|
5898
|
+
): Required<Omit<StartupRetryOptions, "onRetry" | "shouldRetry">> {
|
|
5782
5899
|
return {
|
|
5783
5900
|
attempts: settings.startupDependencyRetryAttempts,
|
|
5784
5901
|
initialDelayMs: settings.startupDependencyRetryInitialDelayMs,
|
|
@@ -5798,7 +5915,7 @@ export async function retryStartupDependency<T>(
|
|
|
5798
5915
|
try {
|
|
5799
5916
|
return await operation();
|
|
5800
5917
|
} catch (error) {
|
|
5801
|
-
if (attempt >= attempts) {
|
|
5918
|
+
if (attempt >= attempts || options.shouldRetry?.(error) === false) {
|
|
5802
5919
|
throw error;
|
|
5803
5920
|
}
|
|
5804
5921
|
const delayMs = Math.min(maxDelayMs, initialDelayMs * 2 ** (attempt - 1));
|
|
@@ -6705,105 +6822,7 @@ function validateSettings(settings: Settings, source: NodeJS.ProcessEnv = proces
|
|
|
6705
6822
|
);
|
|
6706
6823
|
}
|
|
6707
6824
|
}
|
|
6708
|
-
|
|
6709
|
-
settings.objectStorageBackend === "s3-compatible" ||
|
|
6710
|
-
settings.objectStorageBackend === "aws-s3"
|
|
6711
|
-
) {
|
|
6712
|
-
if (
|
|
6713
|
-
Boolean(settings.objectStorageAccessKeyId) !== Boolean(settings.objectStorageSecretAccessKey)
|
|
6714
|
-
) {
|
|
6715
|
-
throw new Error(
|
|
6716
|
-
"OPENGENI_OBJECT_STORAGE_ACCESS_KEY_ID and OPENGENI_OBJECT_STORAGE_SECRET_ACCESS_KEY must both be set or both omitted",
|
|
6717
|
-
);
|
|
6718
|
-
}
|
|
6719
|
-
if (
|
|
6720
|
-
settings.objectStorageBackend === "s3-compatible" &&
|
|
6721
|
-
(settings.objectStorageEndpoint ||
|
|
6722
|
-
settings.objectStorageInternalEndpoint ||
|
|
6723
|
-
settings.objectStorageSandboxEndpoint) &&
|
|
6724
|
-
(!settings.objectStorageAccessKeyId || !settings.objectStorageSecretAccessKey)
|
|
6725
|
-
) {
|
|
6726
|
-
throw new Error(
|
|
6727
|
-
"S3-compatible object storage endpoints require OPENGENI_OBJECT_STORAGE_ACCESS_KEY_ID and OPENGENI_OBJECT_STORAGE_SECRET_ACCESS_KEY",
|
|
6728
|
-
);
|
|
6729
|
-
}
|
|
6730
|
-
if (
|
|
6731
|
-
settings.objectStorageAzureConnectionString ||
|
|
6732
|
-
settings.objectStorageAzureAccountName ||
|
|
6733
|
-
settings.objectStorageAzureAccountKey ||
|
|
6734
|
-
settings.objectStorageAzureEndpoint
|
|
6735
|
-
) {
|
|
6736
|
-
throw new Error(
|
|
6737
|
-
"S3 object storage uses OPENGENI_OBJECT_STORAGE_* S3 settings, not OPENGENI_OBJECT_STORAGE_AZURE_* settings",
|
|
6738
|
-
);
|
|
6739
|
-
}
|
|
6740
|
-
if (
|
|
6741
|
-
settings.objectStorageGcsProjectId ||
|
|
6742
|
-
settings.objectStorageGcsCredentialsJson ||
|
|
6743
|
-
settings.objectStorageGcsKeyFilename ||
|
|
6744
|
-
settings.objectStorageGcsApiEndpoint
|
|
6745
|
-
) {
|
|
6746
|
-
throw new Error(
|
|
6747
|
-
"S3 object storage uses OPENGENI_OBJECT_STORAGE_* S3 settings, not OPENGENI_OBJECT_STORAGE_GCS_* settings",
|
|
6748
|
-
);
|
|
6749
|
-
}
|
|
6750
|
-
} else if (settings.objectStorageBackend === "azure-blob") {
|
|
6751
|
-
if (
|
|
6752
|
-
settings.objectStorageEndpoint ||
|
|
6753
|
-
settings.objectStorageInternalEndpoint ||
|
|
6754
|
-
settings.objectStorageSandboxEndpoint ||
|
|
6755
|
-
settings.objectStorageAccessKeyId ||
|
|
6756
|
-
settings.objectStorageSecretAccessKey
|
|
6757
|
-
) {
|
|
6758
|
-
throw new Error(
|
|
6759
|
-
"Azure Blob storage uses OPENGENI_OBJECT_STORAGE_AZURE_* settings, not S3-compatible object storage settings",
|
|
6760
|
-
);
|
|
6761
|
-
}
|
|
6762
|
-
if (
|
|
6763
|
-
settings.objectStorageGcsProjectId ||
|
|
6764
|
-
settings.objectStorageGcsCredentialsJson ||
|
|
6765
|
-
settings.objectStorageGcsKeyFilename ||
|
|
6766
|
-
settings.objectStorageGcsApiEndpoint
|
|
6767
|
-
) {
|
|
6768
|
-
throw new Error(
|
|
6769
|
-
"Azure Blob storage uses OPENGENI_OBJECT_STORAGE_AZURE_* settings, not OPENGENI_OBJECT_STORAGE_GCS_* settings",
|
|
6770
|
-
);
|
|
6771
|
-
}
|
|
6772
|
-
const hasConnectionString = Boolean(settings.objectStorageAzureConnectionString);
|
|
6773
|
-
const hasSharedKey =
|
|
6774
|
-
Boolean(settings.objectStorageAzureAccountName) &&
|
|
6775
|
-
Boolean(settings.objectStorageAzureAccountKey);
|
|
6776
|
-
if (!hasConnectionString && !hasSharedKey) {
|
|
6777
|
-
throw new Error(
|
|
6778
|
-
"Azure Blob storage requires OPENGENI_OBJECT_STORAGE_AZURE_CONNECTION_STRING or OPENGENI_OBJECT_STORAGE_AZURE_ACCOUNT_NAME plus OPENGENI_OBJECT_STORAGE_AZURE_ACCOUNT_KEY",
|
|
6779
|
-
);
|
|
6780
|
-
}
|
|
6781
|
-
} else {
|
|
6782
|
-
if (
|
|
6783
|
-
settings.objectStorageEndpoint ||
|
|
6784
|
-
settings.objectStorageInternalEndpoint ||
|
|
6785
|
-
settings.objectStorageSandboxEndpoint ||
|
|
6786
|
-
settings.objectStorageAccessKeyId ||
|
|
6787
|
-
settings.objectStorageSecretAccessKey
|
|
6788
|
-
) {
|
|
6789
|
-
throw new Error(
|
|
6790
|
-
"GCS object storage uses OPENGENI_OBJECT_STORAGE_GCS_* settings, not S3-compatible object storage settings",
|
|
6791
|
-
);
|
|
6792
|
-
}
|
|
6793
|
-
if (
|
|
6794
|
-
settings.objectStorageAzureConnectionString ||
|
|
6795
|
-
settings.objectStorageAzureAccountName ||
|
|
6796
|
-
settings.objectStorageAzureAccountKey ||
|
|
6797
|
-
settings.objectStorageAzureEndpoint
|
|
6798
|
-
) {
|
|
6799
|
-
throw new Error(
|
|
6800
|
-
"GCS object storage uses OPENGENI_OBJECT_STORAGE_GCS_* settings, not OPENGENI_OBJECT_STORAGE_AZURE_* settings",
|
|
6801
|
-
);
|
|
6802
|
-
}
|
|
6803
|
-
if (settings.objectStorageGcsCredentialsJson) {
|
|
6804
|
-
parseGcsCredentialsJson(settings.objectStorageGcsCredentialsJson);
|
|
6805
|
-
}
|
|
6806
|
-
}
|
|
6825
|
+
validateObjectStorageSettings(settings);
|
|
6807
6826
|
if (settings.documentChunkOverlap >= settings.documentChunkSize) {
|
|
6808
6827
|
throw new Error(
|
|
6809
6828
|
"OPENGENI_DOCUMENT_CHUNK_OVERLAP must be smaller than OPENGENI_DOCUMENT_CHUNK_SIZE",
|
|
@@ -6832,12 +6851,9 @@ function validateSettings(settings: Settings, source: NodeJS.ProcessEnv = proces
|
|
|
6832
6851
|
throw new Error(`OPENGENI_MCP_SERVERS contains duplicate id ${server.id}`);
|
|
6833
6852
|
}
|
|
6834
6853
|
serverIds.add(server.id);
|
|
6835
|
-
if (
|
|
6836
|
-
server.connectionRef?.authoritySource === "host" &&
|
|
6837
|
-
!settings.hostMcpAuthoritySourceAdmissionEnabled
|
|
6838
|
-
) {
|
|
6854
|
+
if (server.connectionRef?.authoritySource === "host") {
|
|
6839
6855
|
throw new Error(
|
|
6840
|
-
"OPENGENI_MCP_SERVERS host-owned connection refs
|
|
6856
|
+
"OPENGENI_MCP_SERVERS host-owned connection refs are no longer supported; select ordinary native connections",
|
|
6841
6857
|
);
|
|
6842
6858
|
}
|
|
6843
6859
|
}
|
|
@@ -7191,6 +7207,108 @@ export function resolveNatsCalloutConfig(settings: Settings): NatsCalloutConfig
|
|
|
7191
7207
|
return { accountSeed, accountName, user, password };
|
|
7192
7208
|
}
|
|
7193
7209
|
|
|
7210
|
+
function validateObjectStorageSettings(settings: ObjectStorageSettings): void {
|
|
7211
|
+
if (
|
|
7212
|
+
settings.objectStorageBackend === "s3-compatible" ||
|
|
7213
|
+
settings.objectStorageBackend === "aws-s3"
|
|
7214
|
+
) {
|
|
7215
|
+
if (
|
|
7216
|
+
Boolean(settings.objectStorageAccessKeyId) !== Boolean(settings.objectStorageSecretAccessKey)
|
|
7217
|
+
) {
|
|
7218
|
+
throw new Error(
|
|
7219
|
+
"OPENGENI_OBJECT_STORAGE_ACCESS_KEY_ID and OPENGENI_OBJECT_STORAGE_SECRET_ACCESS_KEY must both be set or both omitted",
|
|
7220
|
+
);
|
|
7221
|
+
}
|
|
7222
|
+
if (
|
|
7223
|
+
settings.objectStorageBackend === "s3-compatible" &&
|
|
7224
|
+
(settings.objectStorageEndpoint ||
|
|
7225
|
+
settings.objectStorageInternalEndpoint ||
|
|
7226
|
+
settings.objectStorageSandboxEndpoint) &&
|
|
7227
|
+
(!settings.objectStorageAccessKeyId || !settings.objectStorageSecretAccessKey)
|
|
7228
|
+
) {
|
|
7229
|
+
throw new Error(
|
|
7230
|
+
"S3-compatible object storage endpoints require OPENGENI_OBJECT_STORAGE_ACCESS_KEY_ID and OPENGENI_OBJECT_STORAGE_SECRET_ACCESS_KEY",
|
|
7231
|
+
);
|
|
7232
|
+
}
|
|
7233
|
+
if (
|
|
7234
|
+
settings.objectStorageAzureConnectionString ||
|
|
7235
|
+
settings.objectStorageAzureAccountName ||
|
|
7236
|
+
settings.objectStorageAzureAccountKey ||
|
|
7237
|
+
settings.objectStorageAzureEndpoint
|
|
7238
|
+
) {
|
|
7239
|
+
throw new Error(
|
|
7240
|
+
"S3 object storage uses OPENGENI_OBJECT_STORAGE_* S3 settings, not OPENGENI_OBJECT_STORAGE_AZURE_* settings",
|
|
7241
|
+
);
|
|
7242
|
+
}
|
|
7243
|
+
if (
|
|
7244
|
+
settings.objectStorageGcsProjectId ||
|
|
7245
|
+
settings.objectStorageGcsCredentialsJson ||
|
|
7246
|
+
settings.objectStorageGcsKeyFilename ||
|
|
7247
|
+
settings.objectStorageGcsApiEndpoint
|
|
7248
|
+
) {
|
|
7249
|
+
throw new Error(
|
|
7250
|
+
"S3 object storage uses OPENGENI_OBJECT_STORAGE_* S3 settings, not OPENGENI_OBJECT_STORAGE_GCS_* settings",
|
|
7251
|
+
);
|
|
7252
|
+
}
|
|
7253
|
+
} else if (settings.objectStorageBackend === "azure-blob") {
|
|
7254
|
+
if (
|
|
7255
|
+
settings.objectStorageEndpoint ||
|
|
7256
|
+
settings.objectStorageInternalEndpoint ||
|
|
7257
|
+
settings.objectStorageSandboxEndpoint ||
|
|
7258
|
+
settings.objectStorageAccessKeyId ||
|
|
7259
|
+
settings.objectStorageSecretAccessKey
|
|
7260
|
+
) {
|
|
7261
|
+
throw new Error(
|
|
7262
|
+
"Azure Blob storage uses OPENGENI_OBJECT_STORAGE_AZURE_* settings, not S3-compatible object storage settings",
|
|
7263
|
+
);
|
|
7264
|
+
}
|
|
7265
|
+
if (
|
|
7266
|
+
settings.objectStorageGcsProjectId ||
|
|
7267
|
+
settings.objectStorageGcsCredentialsJson ||
|
|
7268
|
+
settings.objectStorageGcsKeyFilename ||
|
|
7269
|
+
settings.objectStorageGcsApiEndpoint
|
|
7270
|
+
) {
|
|
7271
|
+
throw new Error(
|
|
7272
|
+
"Azure Blob storage uses OPENGENI_OBJECT_STORAGE_AZURE_* settings, not OPENGENI_OBJECT_STORAGE_GCS_* settings",
|
|
7273
|
+
);
|
|
7274
|
+
}
|
|
7275
|
+
const hasConnectionString = Boolean(settings.objectStorageAzureConnectionString);
|
|
7276
|
+
const hasSharedKey =
|
|
7277
|
+
Boolean(settings.objectStorageAzureAccountName) &&
|
|
7278
|
+
Boolean(settings.objectStorageAzureAccountKey);
|
|
7279
|
+
if (!hasConnectionString && !hasSharedKey) {
|
|
7280
|
+
throw new Error(
|
|
7281
|
+
"Azure Blob storage requires OPENGENI_OBJECT_STORAGE_AZURE_CONNECTION_STRING or OPENGENI_OBJECT_STORAGE_AZURE_ACCOUNT_NAME plus OPENGENI_OBJECT_STORAGE_AZURE_ACCOUNT_KEY",
|
|
7282
|
+
);
|
|
7283
|
+
}
|
|
7284
|
+
} else {
|
|
7285
|
+
if (
|
|
7286
|
+
settings.objectStorageEndpoint ||
|
|
7287
|
+
settings.objectStorageInternalEndpoint ||
|
|
7288
|
+
settings.objectStorageSandboxEndpoint ||
|
|
7289
|
+
settings.objectStorageAccessKeyId ||
|
|
7290
|
+
settings.objectStorageSecretAccessKey
|
|
7291
|
+
) {
|
|
7292
|
+
throw new Error(
|
|
7293
|
+
"GCS object storage uses OPENGENI_OBJECT_STORAGE_GCS_* settings, not S3-compatible object storage settings",
|
|
7294
|
+
);
|
|
7295
|
+
}
|
|
7296
|
+
if (
|
|
7297
|
+
settings.objectStorageAzureConnectionString ||
|
|
7298
|
+
settings.objectStorageAzureAccountName ||
|
|
7299
|
+
settings.objectStorageAzureAccountKey ||
|
|
7300
|
+
settings.objectStorageAzureEndpoint
|
|
7301
|
+
) {
|
|
7302
|
+
throw new Error(
|
|
7303
|
+
"GCS object storage uses OPENGENI_OBJECT_STORAGE_GCS_* settings, not OPENGENI_OBJECT_STORAGE_AZURE_* settings",
|
|
7304
|
+
);
|
|
7305
|
+
}
|
|
7306
|
+
if (settings.objectStorageGcsCredentialsJson) {
|
|
7307
|
+
parseGcsCredentialsJson(settings.objectStorageGcsCredentialsJson);
|
|
7308
|
+
}
|
|
7309
|
+
}
|
|
7310
|
+
}
|
|
7311
|
+
|
|
7194
7312
|
/**
|
|
7195
7313
|
* The PRIVILEGED control-plane NATS login (api/worker). Present only when BOTH a
|
|
7196
7314
|
* user and password are set; otherwise null and the bus connects anonymously (local
|
|
@@ -7202,7 +7320,9 @@ export interface NatsControlPlaneAuth {
|
|
|
7202
7320
|
password: string;
|
|
7203
7321
|
}
|
|
7204
7322
|
|
|
7205
|
-
export function resolveNatsControlPlaneAuth(
|
|
7323
|
+
export function resolveNatsControlPlaneAuth(
|
|
7324
|
+
settings: Pick<Settings, "selfhostedNatsControlUser" | "selfhostedNatsControlPassword">,
|
|
7325
|
+
): NatsControlPlaneAuth | null {
|
|
7206
7326
|
const user = settings.selfhostedNatsControlUser?.trim();
|
|
7207
7327
|
const password = settings.selfhostedNatsControlPassword?.trim();
|
|
7208
7328
|
if (!user || !password) {
|