@opengeni/config 0.7.8 → 0.7.11

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@opengeni/config",
3
- "version": "0.7.8",
3
+ "version": "0.7.11",
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.7",
37
- "@opengeni/contracts": "^0.20.1",
37
+ "@opengeni/contracts": "^0.22.0",
38
38
  "zod": "^4.2.1"
39
39
  },
40
40
  "engines": {
package/src/index.ts CHANGED
@@ -265,6 +265,8 @@ const SettingsSchema = z.object({
265
265
  integrationsStateSecret: z.string().optional(),
266
266
  integrationsAllowPrivateNetworkTargets: EnvBoolean.default(false),
267
267
  integrationsOauthClientsJson: z.string().default("{}"),
268
+ slackClientId: z.string().optional(),
269
+ slackClientSecret: z.string().optional(),
268
270
  // Undefined is meaningful: the migration boundary persists the product
269
271
  // default of 3 when no deployment override is supplied.
270
272
  maxNestedAgentDepth: z.coerce.number().int().nonnegative().max(MAX_NESTED_AGENT_DEPTH).optional(),
@@ -1369,6 +1371,8 @@ export function getSettings(): Settings {
1369
1371
  "OPENGENI_INTEGRATIONS_ALLOW_PRIVATE_NETWORK_TARGETS",
1370
1372
  ),
1371
1373
  integrationsOauthClientsJson: optional("OPENGENI_INTEGRATIONS_OAUTH_CLIENTS_JSON"),
1374
+ slackClientId: optional("OPENGENI_SLACK_CLIENT_ID"),
1375
+ slackClientSecret: optional("OPENGENI_SLACK_CLIENT_SECRET"),
1372
1376
  maxNestedAgentDepth: optional("OPENGENI_MAX_NESTED_AGENT_DEPTH"),
1373
1377
  goalMaxAutoContinuations: optional("OPENGENI_GOAL_MAX_AUTO_CONTINUATIONS"),
1374
1378
  goalNoProgressLimit: optional("OPENGENI_GOAL_NO_PROGRESS_LIMIT"),
@@ -2783,9 +2787,14 @@ export function stableSandboxEnvironmentForRun(
2783
2787
  };
2784
2788
  // Backend-aware HOME: a provisioned box (docker + every cloud provider) runs the
2785
2789
  // agent under the descriptor's workspaceRoot. `local` runs in-process as the host
2786
- // unix user (keep its real $HOME); `none` has no box.
2790
+ // unix user (keep its real $HOME); `selfhosted` runs on a user's machine and must
2791
+ // likewise preserve that machine's real HOME; `none` has no box.
2787
2792
  const descriptor = CAPABILITY_DESCRIPTORS[settings.sandboxBackend];
2788
- if (settings.sandboxBackend !== "none" && settings.sandboxBackend !== "local") {
2793
+ if (
2794
+ settings.sandboxBackend !== "none" &&
2795
+ settings.sandboxBackend !== "local" &&
2796
+ settings.sandboxBackend !== "selfhosted"
2797
+ ) {
2789
2798
  environment.HOME ??= descriptor.workspaceRoot;
2790
2799
  }
2791
2800
  // TOKEN-BROKER (B1): the STABLE credential FILE PATHS and CLI wrapper PATH for
@@ -2806,7 +2815,15 @@ export function stableSandboxEnvironmentForRun(
2806
2815
  environment.PATH = prependPathEntry(environment.PATH, environment.OPENGENI_GIT_CLI_WRAPPER_DIR);
2807
2816
  }
2808
2817
  if (settings.toolspaceEnabled) {
2809
- environment.OPENGENI_TOOLSPACE_TOKEN_FILE ??= `${environment.HOME ?? descriptor.workspaceRoot}/.opengeni/toolspace-token`;
2818
+ // Connected Machines do not share one control-plane-known home path. Keep a
2819
+ // stable shell-resolved pointer in the manifest; runtime expands this trusted
2820
+ // marker against the machine's own HOME for seed, renewal, and every command.
2821
+ // Never derive it from the selfhosted descriptor root (`/`), which would try
2822
+ // to write `/.opengeni` as an ordinary machine user.
2823
+ environment.OPENGENI_TOOLSPACE_TOKEN_FILE ??=
2824
+ settings.sandboxBackend === "selfhosted"
2825
+ ? "$HOME/.opengeni/toolspace-token"
2826
+ : `${environment.HOME ?? descriptor.workspaceRoot}/.opengeni/toolspace-token`;
2810
2827
  if (settings.ogtoolPackageSpec) {
2811
2828
  environment.OPENGENI_OGTOOL_PACKAGE_SPEC ??= settings.ogtoolPackageSpec;
2812
2829
  }
@@ -3226,6 +3243,7 @@ function positiveInt(value: unknown): number {
3226
3243
  function ensureBuiltInMcpServers(settings: Settings): Settings["mcpServers"] {
3227
3244
  const existing = settings.mcpServers.filter((server) => server.id !== "opengeni");
3228
3245
  const firstPartyMcpUrl = firstPartyMcpServerUrl(settings);
3246
+ const firstPartyFilesMcpUrl = firstPartyFilesMcpServerUrl(firstPartyMcpUrl);
3229
3247
  const firstPartyDocsMcpUrl = firstPartyDocumentsMcpServerUrl(firstPartyMcpUrl);
3230
3248
  const hasFiles = existing.some((server) => server.id === "files");
3231
3249
  const hasDocs = existing.some((server) => server.id === "docs");
@@ -3253,7 +3271,7 @@ function ensureBuiltInMcpServers(settings: Settings): Settings["mcpServers"] {
3253
3271
  {
3254
3272
  id: "files",
3255
3273
  name: "Files",
3256
- url: firstPartyMcpUrl,
3274
+ url: firstPartyFilesMcpUrl,
3257
3275
  allowedTools: ["files_get_download_url"],
3258
3276
  cacheToolsList: true,
3259
3277
  },
@@ -3329,6 +3347,10 @@ function firstPartyDocumentsMcpServerUrl(mcpUrl: string): string {
3329
3347
  return `${mcpUrl.replace(/\/+$/, "")}/docs`;
3330
3348
  }
3331
3349
 
3350
+ function firstPartyFilesMcpServerUrl(mcpUrl: string): string {
3351
+ return `${mcpUrl.replace(/\/+$/, "")}/files`;
3352
+ }
3353
+
3332
3354
  function validateSettings(settings: Settings): void {
3333
3355
  temporalConnectionOptions(settings);
3334
3356
  if (settings.toolspaceEnabled && !settings.delegationSecret) {
@@ -3381,6 +3403,31 @@ function validateSettings(settings: Settings): void {
3381
3403
  );
3382
3404
  }
3383
3405
  }
3406
+ if (Boolean(settings.slackClientId) !== Boolean(settings.slackClientSecret)) {
3407
+ throw new Error(
3408
+ "OPENGENI_SLACK_CLIENT_ID and OPENGENI_SLACK_CLIENT_SECRET must be configured together",
3409
+ );
3410
+ }
3411
+ if (settings.slackClientId) {
3412
+ if (!settings.publicBaseUrl) {
3413
+ throw new Error(
3414
+ "OPENGENI_PUBLIC_BASE_URL is required when the OpenGeni Slack app is configured",
3415
+ );
3416
+ }
3417
+ if (
3418
+ !settings.publicBaseUrl.startsWith("https://") &&
3419
+ !["local", "test"].includes(settings.environment)
3420
+ ) {
3421
+ throw new Error(
3422
+ "OPENGENI_PUBLIC_BASE_URL must use https when the OpenGeni Slack app is configured outside local/test",
3423
+ );
3424
+ }
3425
+ if (!settings.integrationsStateSecret) {
3426
+ throw new Error(
3427
+ "OPENGENI_INTEGRATIONS_STATE_SECRET is required when the OpenGeni Slack app is configured",
3428
+ );
3429
+ }
3430
+ }
3384
3431
  parseIntegrationsOauthClientsJson(settings.integrationsOauthClientsJson);
3385
3432
  if (
3386
3433
  settings.productAccessMode === "configured" &&