File size: 2,781 Bytes
f778c12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import {
  cloneEnvWithPlatformSemantics,
  createConfigRuntimeEnv,
} from "../../config/config-env-vars.js";
import {
  ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS_ENV,
  formatFutureConfigActionBlock,
  resolveFutureConfigActionBlock,
} from "../../config/future-version-guard.js";
// Gateway-specific future-config actions shared by pre-bootstrap and runtime startup.
import type { ConfigFileSnapshot, OpenClawConfig } from "../../config/types.js";
import type { RuntimeEnv } from "../../runtime.js";
import type { GatewayRunOpts } from "./run-options.js";

export type GatewayRunPreBootstrapOptions = Pick<GatewayRunOpts, "force" | "reset">;

type GatewayRunFutureConfigGuardParams = {
  opts: GatewayRunPreBootstrapOptions;
  snapshot?: ConfigFileSnapshot | null;
  config?: Pick<OpenClawConfig, "env" | "meta"> | null;
};

function resolveGatewayRunFutureConfigBlock(params: GatewayRunFutureConfigGuardParams) {
  const processServiceMode = Boolean(process.env.OPENCLAW_SERVICE_MARKER?.trim());
  const candidateConfig =
    params.config ??
    (params.snapshot?.valid ? (params.snapshot.sourceConfig ?? params.snapshot.config) : undefined);
  const candidateServiceMode =
    !params.opts.reset &&
    Boolean(
      candidateConfig
        ? createConfigRuntimeEnv(candidateConfig, process.env).OPENCLAW_SERVICE_MARKER?.trim()
        : undefined,
    );
  const serviceMode = processServiceMode || candidateServiceMode;
  // Reset runs before service/force startup, while ordinary startup now runs state migrations.
  const futureAction = params.opts.reset
    ? { action: "reset the dev gateway state", exitCode: 1 }
    : serviceMode
      ? { action: "start the gateway service", exitCode: 78 }
      : params.opts.force
        ? { action: "force-kill gateway port listeners", exitCode: 1 }
        : { action: "run automatic gateway startup migrations", exitCode: 1 };
  const guardEnv = serviceMode ? cloneEnvWithPlatformSemantics(process.env) : process.env;
  if (serviceMode) {
    delete guardEnv[ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS_ENV];
  }
  const block = resolveFutureConfigActionBlock({
    action: futureAction.action,
    snapshot: params.snapshot,
    config: params.config,
    env: guardEnv,
  });
  return block ? { block, exitCode: futureAction.exitCode, serviceMode } : null;
}

export function enforceGatewayRunFutureConfigGuard(
  params: GatewayRunFutureConfigGuardParams & { runtime: RuntimeEnv },
): boolean {
  const resolved = resolveGatewayRunFutureConfigBlock(params);
  if (!resolved) {
    return true;
  }
  if (resolved.serviceMode) {
    delete process.env[ALLOW_OLDER_BINARY_DESTRUCTIVE_ACTIONS_ENV];
  }
  params.runtime.error(formatFutureConfigActionBlock(resolved.block));
  params.runtime.exit(resolved.exitCode);
  return false;
}