@opengeni/config 0.21.0-canary.0 → 0.22.5-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/index.d.ts +14 -2
- package/dist/index.js +88 -19
- package/dist/index.js.map +1 -1
- package/package.json +4 -4
- package/src/index.ts +102 -18
package/dist/index.d.ts
CHANGED
|
@@ -273,6 +273,8 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
273
273
|
variable_set_get_variable: "variable_set_get_variable";
|
|
274
274
|
variable_set_list: "variable_set_list";
|
|
275
275
|
variable_set_set_variable: "variable_set_set_variable";
|
|
276
|
+
work_claim_release: "work_claim_release";
|
|
277
|
+
work_claim_upsert: "work_claim_upsert";
|
|
276
278
|
x_accounts_list: "x_accounts_list";
|
|
277
279
|
x_mentions_live: "x_mentions_live";
|
|
278
280
|
x_post_reply: "x_post_reply";
|
|
@@ -417,6 +419,8 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
417
419
|
variable_set_get_variable: "variable_set_get_variable";
|
|
418
420
|
variable_set_list: "variable_set_list";
|
|
419
421
|
variable_set_set_variable: "variable_set_set_variable";
|
|
422
|
+
work_claim_release: "work_claim_release";
|
|
423
|
+
work_claim_upsert: "work_claim_upsert";
|
|
420
424
|
x_accounts_list: "x_accounts_list";
|
|
421
425
|
x_mentions_live: "x_mentions_live";
|
|
422
426
|
x_post_reply: "x_post_reply";
|
|
@@ -426,6 +430,10 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
426
430
|
}>>>>;
|
|
427
431
|
streamTokenSecret: z.ZodOptional<z.ZodString>;
|
|
428
432
|
streamControlEnabled: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
433
|
+
workDiscoveryEnabled: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
434
|
+
workClaimMutationsEnabled: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
435
|
+
workDiscoveryHumanAdvisoriesEnabled: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
436
|
+
workDiscoveryAutomaticNudgesEnabled: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
429
437
|
ogtoolPackageSpec: z.ZodOptional<z.ZodString>;
|
|
430
438
|
environmentsEncryptionKey: z.ZodOptional<z.ZodString>;
|
|
431
439
|
integrationsEnabled: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
@@ -586,6 +594,8 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
586
594
|
modalImageId: z.ZodOptional<z.ZodString>;
|
|
587
595
|
modalImageRegistrySecret: z.ZodOptional<z.ZodString>;
|
|
588
596
|
modalTimeoutSeconds: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
597
|
+
modalSandboxCpu: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
598
|
+
modalSandboxMemoryMiB: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
|
|
589
599
|
modalTokenId: z.ZodOptional<z.ZodString>;
|
|
590
600
|
modalTokenSecret: z.ZodOptional<z.ZodString>;
|
|
591
601
|
modalEnvironment: z.ZodOptional<z.ZodString>;
|
|
@@ -600,8 +610,6 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
600
610
|
sandboxTerminalEnabled: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
601
611
|
streamResolutionWidth: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
602
612
|
streamResolutionHeight: z.ZodDefault<z.ZodCoercedNumber<unknown>>;
|
|
603
|
-
computerUseEnabled: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
604
|
-
computerUseReadOnly: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
605
613
|
recordingEnabled: z.ZodDefault<z.ZodPreprocess<z.ZodBoolean>>;
|
|
606
614
|
recordingDefaultCodec: z.ZodDefault<z.ZodEnum<{
|
|
607
615
|
"h264-mp4": "h264-mp4";
|
|
@@ -770,6 +778,10 @@ declare const SettingsSchema: z.ZodObject<{
|
|
|
770
778
|
betterAuthAllowedHosts: z.ZodDefault<z.ZodString>;
|
|
771
779
|
betterAuthCookieDomain: z.ZodOptional<z.ZodString>;
|
|
772
780
|
betterAuthTrustedOrigins: z.ZodDefault<z.ZodString>;
|
|
781
|
+
managedAuthGoogleClientId: z.ZodOptional<z.ZodString>;
|
|
782
|
+
managedAuthGoogleClientSecret: z.ZodOptional<z.ZodString>;
|
|
783
|
+
managedAuthGithubClientId: z.ZodOptional<z.ZodString>;
|
|
784
|
+
managedAuthGithubClientSecret: z.ZodOptional<z.ZodString>;
|
|
773
785
|
managedAuthSessionSetMode: z.ZodDefault<z.ZodEnum<{
|
|
774
786
|
broker: "broker";
|
|
775
787
|
dual: "dual";
|
package/dist/index.js
CHANGED
|
@@ -304,6 +304,21 @@ var SettingsSchema = z.object({
|
|
|
304
304
|
// holder of stream:control gets 403 until this flips. Keeps stream:control a
|
|
305
305
|
// declared-but-inert permission so later hardening is a flag flip.
|
|
306
306
|
streamControlEnabled: EnvBoolean.default(false),
|
|
307
|
+
// Provider-neutral advisory work discovery rollout. Disabling this keeps
|
|
308
|
+
// ordinary session listings available while rejecting relevance discovery
|
|
309
|
+
// and omitting claim evidence from their compact projections.
|
|
310
|
+
workDiscoveryEnabled: EnvBoolean.default(true),
|
|
311
|
+
// Exact-attempt claim mutations are independently reversible. Turning this
|
|
312
|
+
// off removes the first-party mutation tools; durable claims and lifecycle
|
|
313
|
+
// settlement evidence remain readable.
|
|
314
|
+
workClaimMutationsEnabled: EnvBoolean.default(true),
|
|
315
|
+
// Human presentation is a separate rollout stage from the read API. The
|
|
316
|
+
// topology response carries this decision so clients can hide advisory UI
|
|
317
|
+
// without inventing authorization or ownership semantics.
|
|
318
|
+
workDiscoveryHumanAdvisoriesEnabled: EnvBoolean.default(true),
|
|
319
|
+
// Automatic overlap nudges are deliberately unshipped and default OFF until
|
|
320
|
+
// an evaluated precision threshold and operator runbook approve them.
|
|
321
|
+
workDiscoveryAutomaticNudgesEnabled: EnvBoolean.default(false),
|
|
307
322
|
// Optional release-coherent bootstrap hint for custom rigs/connected machines
|
|
308
323
|
// that do not carry the stock-image ogtool binary. Exact stable versions only:
|
|
309
324
|
// the agent must never guess a tag or silently install `latest`.
|
|
@@ -636,6 +651,13 @@ var SettingsSchema = z.object({
|
|
|
636
651
|
// larger timeout—is what lets a session outlive one finite provider box.
|
|
637
652
|
// Knob: OPENGENI_MODAL_TIMEOUT_SECONDS.
|
|
638
653
|
modalTimeoutSeconds: z.coerce.number().int().positive().max(86400).default(86400),
|
|
654
|
+
// Optional provider reservations for every new Modal sandbox. CPU is measured
|
|
655
|
+
// in physical cores and may be fractional; memory is measured in MiB. Leave
|
|
656
|
+
// both unset to preserve Modal's provider defaults. The Agents adapter stores
|
|
657
|
+
// the resolved values in its session state so snapshot replacement and exact
|
|
658
|
+
// resume cannot silently change the reservation.
|
|
659
|
+
modalSandboxCpu: z.coerce.number().positive().optional(),
|
|
660
|
+
modalSandboxMemoryMiB: z.coerce.number().int().positive().optional(),
|
|
639
661
|
modalTokenId: z.string().optional(),
|
|
640
662
|
modalTokenSecret: z.string().optional(),
|
|
641
663
|
modalEnvironment: z.string().optional(),
|
|
@@ -673,8 +695,8 @@ var SettingsSchema = z.object({
|
|
|
673
695
|
// cell advertises mode "interactive" — the noVNC viewer can drive mouse+keyboard
|
|
674
696
|
// into :0 (x11vnc runs without -viewonly). Turn it OFF for a genuinely read-only
|
|
675
697
|
// deployment: the cell reports mode "read-only" and the client disables the
|
|
676
|
-
// "Take control" affordance.
|
|
677
|
-
//
|
|
698
|
+
// "Take control" affordance. This gates the HUMAN viewer plane; agent
|
|
699
|
+
// interaction is authorized through managed ComputerSession tools.
|
|
678
700
|
sandboxDesktopInteractive: EnvBoolean.default(true),
|
|
679
701
|
// REAL PTY terminal toggle (P5.t): gates the ttyd pty-ws plane (7681) the API
|
|
680
702
|
// mints over the SAME tunnel as the desktop. Defaults ON — the interactive
|
|
@@ -688,13 +710,7 @@ var SettingsSchema = z.object({
|
|
|
688
710
|
// down→up restart. Defaults match the proven spike geometry (1280x800).
|
|
689
711
|
streamResolutionWidth: z.coerce.number().int().positive().default(1280),
|
|
690
712
|
streamResolutionHeight: z.coerce.number().int().positive().default(800),
|
|
691
|
-
//
|
|
692
|
-
// scrot). Gated by sandboxDesktopEnabled + a desktop-capable backend in
|
|
693
|
-
// buildAgentCapabilities; computerUseReadOnly:false is the agent-driver default
|
|
694
|
-
// (it must click/type — the human viewer plane is the read-only one).
|
|
695
|
-
computerUseEnabled: EnvBoolean.default(true),
|
|
696
|
-
computerUseReadOnly: EnvBoolean.default(false),
|
|
697
|
-
// P4.3 recording loop: ffmpeg x11grab of :0 → mp4/webm → @opengeni/storage.
|
|
713
|
+
// Recording loop: ffmpeg x11grab of :0 → mp4/webm → @opengeni/storage.
|
|
698
714
|
// recordingMaxBytes caps the in-memory finalize buffer (≤ storage single-PUT);
|
|
699
715
|
// recordingMaxSeconds is the ffmpeg -t hard ceiling (bounds a multi-day turn).
|
|
700
716
|
recordingEnabled: EnvBoolean.default(true),
|
|
@@ -1050,6 +1066,10 @@ var SettingsSchema = z.object({
|
|
|
1050
1066
|
betterAuthAllowedHosts: z.string().default(""),
|
|
1051
1067
|
betterAuthCookieDomain: z.string().optional(),
|
|
1052
1068
|
betterAuthTrustedOrigins: z.string().default(""),
|
|
1069
|
+
managedAuthGoogleClientId: z.string().optional(),
|
|
1070
|
+
managedAuthGoogleClientSecret: z.string().optional(),
|
|
1071
|
+
managedAuthGithubClientId: z.string().optional(),
|
|
1072
|
+
managedAuthGithubClientSecret: z.string().optional(),
|
|
1053
1073
|
// Rolling browser login-slot compatibility. Repository/deployment default is
|
|
1054
1074
|
// deliberately legacy; changing to broker is an operator-authorized rollout.
|
|
1055
1075
|
managedAuthSessionSetMode: z.enum(["legacy", "dual", "broker"]).default("legacy"),
|
|
@@ -1740,6 +1760,14 @@ function getSettings() {
|
|
|
1740
1760
|
allowedFirstPartyMcpTools: optional("OPENGENI_ALLOWED_FIRST_PARTY_MCP_TOOLS"),
|
|
1741
1761
|
streamTokenSecret: optional("OPENGENI_STREAM_TOKEN_SECRET"),
|
|
1742
1762
|
streamControlEnabled: optional("OPENGENI_STREAM_CONTROL_ENABLED"),
|
|
1763
|
+
workDiscoveryEnabled: optional("OPENGENI_WORK_DISCOVERY_ENABLED"),
|
|
1764
|
+
workClaimMutationsEnabled: optional("OPENGENI_WORK_CLAIM_MUTATIONS_ENABLED"),
|
|
1765
|
+
workDiscoveryHumanAdvisoriesEnabled: optional(
|
|
1766
|
+
"OPENGENI_WORK_DISCOVERY_HUMAN_ADVISORIES_ENABLED"
|
|
1767
|
+
),
|
|
1768
|
+
workDiscoveryAutomaticNudgesEnabled: optional(
|
|
1769
|
+
"OPENGENI_WORK_DISCOVERY_AUTOMATIC_NUDGES_ENABLED"
|
|
1770
|
+
),
|
|
1743
1771
|
ogtoolPackageSpec: optional("OPENGENI_OGTOOL_PACKAGE_SPEC"),
|
|
1744
1772
|
environmentsEncryptionKey: optional("OPENGENI_ENVIRONMENTS_ENCRYPTION_KEY"),
|
|
1745
1773
|
integrationsEnabled: optional("OPENGENI_INTEGRATIONS_ENABLED"),
|
|
@@ -1892,6 +1920,8 @@ function getSettings() {
|
|
|
1892
1920
|
modalImageId: optional("OPENGENI_MODAL_IMAGE_ID"),
|
|
1893
1921
|
modalImageRegistrySecret: optional("OPENGENI_MODAL_IMAGE_REGISTRY_SECRET"),
|
|
1894
1922
|
modalTimeoutSeconds: optional("OPENGENI_MODAL_TIMEOUT_SECONDS"),
|
|
1923
|
+
modalSandboxCpu: optional("OPENGENI_MODAL_SANDBOX_CPU"),
|
|
1924
|
+
modalSandboxMemoryMiB: optional("OPENGENI_MODAL_SANDBOX_MEMORY_MIB"),
|
|
1895
1925
|
modalTokenId: optional("OPENGENI_MODAL_TOKEN_ID"),
|
|
1896
1926
|
modalTokenSecret: optional("OPENGENI_MODAL_TOKEN_SECRET"),
|
|
1897
1927
|
modalEnvironment: optional("OPENGENI_MODAL_ENVIRONMENT"),
|
|
@@ -1902,8 +1932,6 @@ function getSettings() {
|
|
|
1902
1932
|
sandboxTerminalEnabled: optional("OPENGENI_SANDBOX_TERMINAL_ENABLED"),
|
|
1903
1933
|
streamResolutionWidth: optional("OPENGENI_STREAM_RESOLUTION_WIDTH"),
|
|
1904
1934
|
streamResolutionHeight: optional("OPENGENI_STREAM_RESOLUTION_HEIGHT"),
|
|
1905
|
-
computerUseEnabled: optional("OPENGENI_COMPUTER_USE_ENABLED"),
|
|
1906
|
-
computerUseReadOnly: optional("OPENGENI_COMPUTER_USE_READONLY"),
|
|
1907
1935
|
recordingEnabled: optional("OPENGENI_RECORDING_ENABLED"),
|
|
1908
1936
|
workspaceCaptureEnabled: optional("OPENGENI_WORKSPACE_CAPTURE"),
|
|
1909
1937
|
recordingDefaultCodec: optional("OPENGENI_RECORDING_DEFAULT_CODEC"),
|
|
@@ -2059,6 +2087,10 @@ function getSettings() {
|
|
|
2059
2087
|
betterAuthAllowedHosts: optional("OPENGENI_BETTER_AUTH_ALLOWED_HOSTS"),
|
|
2060
2088
|
betterAuthCookieDomain: optional("OPENGENI_BETTER_AUTH_COOKIE_DOMAIN"),
|
|
2061
2089
|
betterAuthTrustedOrigins: optional("OPENGENI_BETTER_AUTH_TRUSTED_ORIGINS"),
|
|
2090
|
+
managedAuthGoogleClientId: optional("OPENGENI_MANAGED_AUTH_GOOGLE_CLIENT_ID"),
|
|
2091
|
+
managedAuthGoogleClientSecret: optional("OPENGENI_MANAGED_AUTH_GOOGLE_CLIENT_SECRET"),
|
|
2092
|
+
managedAuthGithubClientId: optional("OPENGENI_MANAGED_AUTH_GITHUB_CLIENT_ID"),
|
|
2093
|
+
managedAuthGithubClientSecret: optional("OPENGENI_MANAGED_AUTH_GITHUB_CLIENT_SECRET"),
|
|
2062
2094
|
managedAuthSessionSetMode: optional("OPENGENI_MANAGED_AUTH_SESSION_SET_MODE"),
|
|
2063
2095
|
resendApiKey: optional("OPENGENI_RESEND_API_KEY"),
|
|
2064
2096
|
emailFrom: optional("OPENGENI_EMAIL_FROM"),
|
|
@@ -2674,8 +2706,9 @@ function canonicalJson(value) {
|
|
|
2674
2706
|
};
|
|
2675
2707
|
return JSON.stringify(normalize(value));
|
|
2676
2708
|
}
|
|
2677
|
-
function definitionVersionFor(model, provider) {
|
|
2709
|
+
function definitionVersionFor(model, provider, options = {}) {
|
|
2678
2710
|
const requestMetadata = staticRequestMetadataForDigest(provider);
|
|
2711
|
+
const includeWireProfile = options.includeWireProfile ?? true;
|
|
2679
2712
|
const digestInput = canonicalJson({
|
|
2680
2713
|
schemaVersion: model.schemaVersion,
|
|
2681
2714
|
id: model.id,
|
|
@@ -2684,7 +2717,7 @@ function definitionVersionFor(model, provider) {
|
|
|
2684
2717
|
provider: {
|
|
2685
2718
|
adapterKind: provider.kind,
|
|
2686
2719
|
wireApi: provider.api,
|
|
2687
|
-
wireProfile: provider.wireProfile,
|
|
2720
|
+
...includeWireProfile ? { wireProfile: provider.wireProfile } : {},
|
|
2688
2721
|
baseUrl: provider.baseUrl ?? null,
|
|
2689
2722
|
defaultHeaders: requestMetadata.headers,
|
|
2690
2723
|
defaultQuery: requestMetadata.query
|
|
@@ -2698,6 +2731,11 @@ function definitionVersionFor(model, provider) {
|
|
|
2698
2731
|
});
|
|
2699
2732
|
return `sha256:${createHash("sha256").update("opengeni:model-definition:v1\n", "utf8").update(digestInput, "utf8").digest("hex")}`;
|
|
2700
2733
|
}
|
|
2734
|
+
function legacyImplicitOpenAiDefinitionVersionFor(model, provider) {
|
|
2735
|
+
if (provider.wireProfile !== "openai") return null;
|
|
2736
|
+
const { definitionVersion: _definitionVersion, ...modelWithoutVersion } = model;
|
|
2737
|
+
return definitionVersionFor(modelWithoutVersion, provider, { includeWireProfile: false });
|
|
2738
|
+
}
|
|
2701
2739
|
function builtinProviderId(settings) {
|
|
2702
2740
|
return settings.openaiProvider === "azure" ? "azure" : "openai";
|
|
2703
2741
|
}
|
|
@@ -3080,7 +3118,12 @@ function assertTurnExecutionPolicyMatchesConfigV1(settings, policy, expected) {
|
|
|
3080
3118
|
if (!resolved) {
|
|
3081
3119
|
throw new Error("Turn execution policy model is no longer configured");
|
|
3082
3120
|
}
|
|
3083
|
-
const
|
|
3121
|
+
const legacyImplicitOpenAiDefinitionVersion = legacyImplicitOpenAiDefinitionVersionFor(
|
|
3122
|
+
resolved.model,
|
|
3123
|
+
resolved.provider
|
|
3124
|
+
);
|
|
3125
|
+
const definitionVersionMatches = parsed.definitionVersion === resolved.model.definitionVersion || parsed.definitionVersion === legacyImplicitOpenAiDefinitionVersion;
|
|
3126
|
+
const mismatched = parsed.providerId !== resolved.provider.id || parsed.upstreamModelId !== resolved.model.upstreamModelId || parsed.wireApi !== resolved.model.api || !definitionVersionMatches || canonicalJson(parsed.credentialSource) !== canonicalJson(resolved.model.credentialSource) || canonicalJson(parsed.billing) !== canonicalJson(resolved.model.billing);
|
|
3084
3127
|
if (mismatched) {
|
|
3085
3128
|
throw new Error("Turn execution policy does not match the current provider definition");
|
|
3086
3129
|
}
|
|
@@ -3868,6 +3911,37 @@ function validateSettings(settings) {
|
|
|
3868
3911
|
);
|
|
3869
3912
|
}
|
|
3870
3913
|
}
|
|
3914
|
+
if (Boolean(settings.managedAuthGoogleClientId) !== Boolean(settings.managedAuthGoogleClientSecret)) {
|
|
3915
|
+
throw new Error(
|
|
3916
|
+
"OPENGENI_MANAGED_AUTH_GOOGLE_CLIENT_ID and OPENGENI_MANAGED_AUTH_GOOGLE_CLIENT_SECRET must be configured together"
|
|
3917
|
+
);
|
|
3918
|
+
}
|
|
3919
|
+
if (Boolean(settings.managedAuthGithubClientId) !== Boolean(settings.managedAuthGithubClientSecret)) {
|
|
3920
|
+
throw new Error(
|
|
3921
|
+
"OPENGENI_MANAGED_AUTH_GITHUB_CLIENT_ID and OPENGENI_MANAGED_AUTH_GITHUB_CLIENT_SECRET must be configured together"
|
|
3922
|
+
);
|
|
3923
|
+
}
|
|
3924
|
+
const managedSocialAuthConfigured = Boolean(
|
|
3925
|
+
settings.managedAuthGoogleClientId || settings.managedAuthGithubClientId
|
|
3926
|
+
);
|
|
3927
|
+
if (managedSocialAuthConfigured) {
|
|
3928
|
+
if (settings.productAccessMode !== "managed") {
|
|
3929
|
+
throw new Error(
|
|
3930
|
+
"Managed Google/GitHub authentication requires OPENGENI_PRODUCT_ACCESS_MODE=managed"
|
|
3931
|
+
);
|
|
3932
|
+
}
|
|
3933
|
+
const publicOrigin = canonicalPublicOrigin(settings.publicBaseUrl);
|
|
3934
|
+
if (!publicOrigin) {
|
|
3935
|
+
throw new Error(
|
|
3936
|
+
"OPENGENI_PUBLIC_BASE_URL must be a credential-free HTTP(S) origin when managed social authentication is configured"
|
|
3937
|
+
);
|
|
3938
|
+
}
|
|
3939
|
+
if (!publicOrigin.startsWith("https://") && !["local", "test"].includes(settings.environment)) {
|
|
3940
|
+
throw new Error(
|
|
3941
|
+
"OPENGENI_PUBLIC_BASE_URL must use https when managed social authentication is configured outside local/test"
|
|
3942
|
+
);
|
|
3943
|
+
}
|
|
3944
|
+
}
|
|
3871
3945
|
environmentsEncryptionKeyBytes(settings);
|
|
3872
3946
|
if (settings.integrationsEnabled) {
|
|
3873
3947
|
if (settings.productAccessMode === "managed" && !settings.publicBaseUrl) {
|
|
@@ -3924,11 +3998,6 @@ function validateSettings(settings) {
|
|
|
3924
3998
|
"OPENGENI_INTEGRATIONS_ENABLED=true is required when personal GitHub OAuth is enabled"
|
|
3925
3999
|
);
|
|
3926
4000
|
}
|
|
3927
|
-
if (settings.productAccessMode !== "managed") {
|
|
3928
|
-
throw new Error(
|
|
3929
|
-
"OPENGENI_GITHUB_PERSONAL_OAUTH_ENABLED=true requires OPENGENI_PRODUCT_ACCESS_MODE=managed"
|
|
3930
|
-
);
|
|
3931
|
-
}
|
|
3932
4001
|
if (!settings.githubPersonalOauthClientId || !settings.githubPersonalOauthClientSecret) {
|
|
3933
4002
|
throw new Error(
|
|
3934
4003
|
"personal GitHub OAuth requires OPENGENI_GITHUB_PERSONAL_OAUTH_CLIENT_ID and OPENGENI_GITHUB_PERSONAL_OAUTH_CLIENT_SECRET"
|