@opengeni/config 0.8.1 → 0.9.3
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 +14 -0
- package/dist/index.js +59 -0
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +72 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeni/config",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.3",
|
|
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": {
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
36
|
"@opengeni/codex": "^0.2.9",
|
|
37
|
-
"@opengeni/contracts": "^0.
|
|
37
|
+
"@opengeni/contracts": "^0.30.0",
|
|
38
38
|
"zod": "^4.2.1"
|
|
39
39
|
},
|
|
40
40
|
"engines": {
|
package/src/index.ts
CHANGED
|
@@ -218,6 +218,20 @@ const SettingsSchema = z.object({
|
|
|
218
218
|
observabilityMetricsEnabled: EnvBoolean.default(true),
|
|
219
219
|
observabilityOtlpEndpoint: z.string().url().optional(),
|
|
220
220
|
observabilityOtlpHeaders: z.string().default(""),
|
|
221
|
+
analyticsEnabled: EnvBoolean.default(false),
|
|
222
|
+
analyticsConsentRequired: EnvBoolean.default(true),
|
|
223
|
+
analyticsReoClientId: z
|
|
224
|
+
.string()
|
|
225
|
+
.max(128)
|
|
226
|
+
.regex(/^[A-Za-z0-9_-]+$/u)
|
|
227
|
+
.optional(),
|
|
228
|
+
analyticsPosthogProjectKey: z.string().min(1).max(256).optional(),
|
|
229
|
+
analyticsPosthogHost: z.string().url().max(2_048).optional(),
|
|
230
|
+
analyticsGa4MeasurementId: z
|
|
231
|
+
.string()
|
|
232
|
+
.max(32)
|
|
233
|
+
.regex(/^G-[A-Z0-9]+$/u)
|
|
234
|
+
.optional(),
|
|
221
235
|
publicBaseUrl: z.string().url().optional(),
|
|
222
236
|
// Browser origin when the web app and API use separate origins in local
|
|
223
237
|
// development. Production normally leaves this unset and uses publicBaseUrl.
|
|
@@ -275,6 +289,9 @@ const SettingsSchema = z.object({
|
|
|
275
289
|
// Undefined is meaningful: the migration boundary persists the product
|
|
276
290
|
// default of 3 when no deployment override is supplied.
|
|
277
291
|
maxNestedAgentDepth: z.coerce.number().int().nonnegative().max(MAX_NESTED_AGENT_DEPTH).optional(),
|
|
292
|
+
// Operator OAuth apps for first-party social connectors, keyed by provider
|
|
293
|
+
// id ("x", "reddit"): {"x":{"clientId":"...","clientSecret":"..."}}.
|
|
294
|
+
socialOauthClientsJson: z.string().default("{}"),
|
|
278
295
|
// Session goal guard rails. Goals are designed for runs that legitimately
|
|
279
296
|
// span days, so length is bounded by pathology detection (no-progress
|
|
280
297
|
// streaks, budget exhaustion), never by count. goalMaxAutoContinuations is
|
|
@@ -1571,6 +1588,12 @@ export function getSettings(): Settings {
|
|
|
1571
1588
|
optional("OPENGENI_OTEL_EXPORTER_OTLP_ENDPOINT") ?? optional("OTEL_EXPORTER_OTLP_ENDPOINT"),
|
|
1572
1589
|
observabilityOtlpHeaders:
|
|
1573
1590
|
optional("OPENGENI_OTEL_EXPORTER_OTLP_HEADERS") ?? optional("OTEL_EXPORTER_OTLP_HEADERS"),
|
|
1591
|
+
analyticsEnabled: optional("OPENGENI_ANALYTICS_ENABLED"),
|
|
1592
|
+
analyticsConsentRequired: optional("OPENGENI_ANALYTICS_CONSENT_REQUIRED"),
|
|
1593
|
+
analyticsReoClientId: optional("OPENGENI_ANALYTICS_REO_CLIENT_ID"),
|
|
1594
|
+
analyticsPosthogProjectKey: optional("OPENGENI_ANALYTICS_POSTHOG_PROJECT_KEY"),
|
|
1595
|
+
analyticsPosthogHost: optional("OPENGENI_ANALYTICS_POSTHOG_HOST"),
|
|
1596
|
+
analyticsGa4MeasurementId: optional("OPENGENI_ANALYTICS_GA4_MEASUREMENT_ID"),
|
|
1574
1597
|
publicBaseUrl: optional("OPENGENI_PUBLIC_BASE_URL"),
|
|
1575
1598
|
webBaseUrl: optional("OPENGENI_WEB_BASE_URL"),
|
|
1576
1599
|
agentReleasesBaseUrl: optional("OPENGENI_AGENT_RELEASES_BASE_URL"),
|
|
@@ -1600,6 +1623,7 @@ export function getSettings(): Settings {
|
|
|
1600
1623
|
googleDriveClientId: optional("OPENGENI_GOOGLE_DRIVE_CLIENT_ID"),
|
|
1601
1624
|
googleDriveClientSecret: optional("OPENGENI_GOOGLE_DRIVE_CLIENT_SECRET"),
|
|
1602
1625
|
maxNestedAgentDepth: optional("OPENGENI_MAX_NESTED_AGENT_DEPTH"),
|
|
1626
|
+
socialOauthClientsJson: optional("OPENGENI_SOCIAL_OAUTH_CLIENTS_JSON"),
|
|
1603
1627
|
goalMaxAutoContinuations: optional("OPENGENI_GOAL_MAX_AUTO_CONTINUATIONS"),
|
|
1604
1628
|
goalNoProgressLimit: optional("OPENGENI_GOAL_NO_PROGRESS_LIMIT"),
|
|
1605
1629
|
agentMaxModelCallsPerTurn: optional("OPENGENI_AGENT_MAX_MODEL_CALLS_PER_TURN"),
|
|
@@ -3627,6 +3651,53 @@ export function parseIntegrationsOauthClientsJson(
|
|
|
3627
3651
|
return out;
|
|
3628
3652
|
}
|
|
3629
3653
|
|
|
3654
|
+
export const SocialOAuthClientConfigSchema = z.object({
|
|
3655
|
+
clientId: z.string().min(1),
|
|
3656
|
+
clientSecret: z.string().min(1).optional(),
|
|
3657
|
+
});
|
|
3658
|
+
export type SocialOAuthClientConfig = z.infer<typeof SocialOAuthClientConfigSchema>;
|
|
3659
|
+
|
|
3660
|
+
const SOCIAL_OAUTH_PROVIDER_IDS = ["x", "reddit"] as const;
|
|
3661
|
+
|
|
3662
|
+
export function parseSocialOauthClientsJson(
|
|
3663
|
+
raw: string | undefined,
|
|
3664
|
+
): Partial<Record<(typeof SOCIAL_OAUTH_PROVIDER_IDS)[number], SocialOAuthClientConfig>> {
|
|
3665
|
+
if (!raw?.trim() || raw.trim() === "{}") {
|
|
3666
|
+
return {};
|
|
3667
|
+
}
|
|
3668
|
+
let parsed: unknown;
|
|
3669
|
+
try {
|
|
3670
|
+
parsed = JSON.parse(raw);
|
|
3671
|
+
} catch (error) {
|
|
3672
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3673
|
+
throw new Error(`OPENGENI_SOCIAL_OAUTH_CLIENTS_JSON must be valid JSON: ${message}`, {
|
|
3674
|
+
cause: error,
|
|
3675
|
+
});
|
|
3676
|
+
}
|
|
3677
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
|
|
3678
|
+
throw new Error(
|
|
3679
|
+
"OPENGENI_SOCIAL_OAUTH_CLIENTS_JSON must be a JSON object keyed by social provider id",
|
|
3680
|
+
);
|
|
3681
|
+
}
|
|
3682
|
+
const out: Partial<Record<(typeof SOCIAL_OAUTH_PROVIDER_IDS)[number], SocialOAuthClientConfig>> =
|
|
3683
|
+
{};
|
|
3684
|
+
for (const [key, value] of Object.entries(parsed)) {
|
|
3685
|
+
if (!SOCIAL_OAUTH_PROVIDER_IDS.includes(key as (typeof SOCIAL_OAUTH_PROVIDER_IDS)[number])) {
|
|
3686
|
+
throw new Error(
|
|
3687
|
+
`OPENGENI_SOCIAL_OAUTH_CLIENTS_JSON provider ${key} is not supported (expected: ${SOCIAL_OAUTH_PROVIDER_IDS.join(", ")})`,
|
|
3688
|
+
);
|
|
3689
|
+
}
|
|
3690
|
+
const result = SocialOAuthClientConfigSchema.safeParse(value);
|
|
3691
|
+
if (!result.success) {
|
|
3692
|
+
throw new Error(
|
|
3693
|
+
`OPENGENI_SOCIAL_OAUTH_CLIENTS_JSON client for ${key} is invalid: ${result.error.message}`,
|
|
3694
|
+
);
|
|
3695
|
+
}
|
|
3696
|
+
out[key as (typeof SOCIAL_OAUTH_PROVIDER_IDS)[number]] = result.data;
|
|
3697
|
+
}
|
|
3698
|
+
return out;
|
|
3699
|
+
}
|
|
3700
|
+
|
|
3630
3701
|
export function parseStaticUsageLimitsJson(raw: string): StaticUsageLimitsConfig {
|
|
3631
3702
|
if (!raw.trim() || raw.trim() === "{}") {
|
|
3632
3703
|
return {};
|
|
@@ -3912,6 +3983,7 @@ function validateSettings(settings: Settings): void {
|
|
|
3912
3983
|
}
|
|
3913
3984
|
}
|
|
3914
3985
|
parseIntegrationsOauthClientsJson(settings.integrationsOauthClientsJson);
|
|
3986
|
+
parseSocialOauthClientsJson(settings.socialOauthClientsJson);
|
|
3915
3987
|
if (
|
|
3916
3988
|
settings.productAccessMode === "configured" &&
|
|
3917
3989
|
!["local", "test"].includes(settings.environment) &&
|