forked from openclaw/openclaw
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocker-entrypoint.mjs
More file actions
122 lines (118 loc) 路 3.8 KB
/
Copy pathdocker-entrypoint.mjs
File metadata and controls
122 lines (118 loc) 路 3.8 KB
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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
// Image activation owns unattended retained-volume repair; ordinary CLI startup only admits state.
import { spawn } from "node:child_process";
import fs from "node:fs";
import os from "node:os";
import path from "node:path";
import { fileURLToPath } from "node:url";
import { getCommandOptionsWithRootOptions } from "./cli-root-options.mjs";
import {
GATEWAY_RUN_BOOLEAN_FLAGS,
GATEWAY_RUN_VALUE_FLAGS,
isForegroundGatewayRunArgv,
} from "./gateway-run-argv.mjs";
const root = path.dirname(fileURLToPath(import.meta.url));
const command = process.argv.slice(2);
function executable(name) {
const candidates = name.includes(path.sep)
? [path.resolve(name)]
: (process.env.PATH ?? "").split(path.delimiter).map((dir) => path.resolve(dir, name));
for (const candidate of candidates) {
try {
fs.accessSync(candidate, fs.constants.X_OK);
if (fs.statSync(candidate).isFile()) {
return fs.realpathSync(candidate);
}
} catch {
// Match normal PATH lookup; exec reports an unavailable command below.
}
}
return undefined;
}
function gatewayInvocation(program) {
if (!command.length) {
throw new Error("Docker entrypoint requires a command");
}
let argv;
if (program === fs.realpathSync(process.execPath) && command[1]) {
let entry;
try {
entry = fs.realpathSync(command[1]);
} catch {
return undefined;
}
if (
!["openclaw.mjs", "dist/index.js", "dist/entry.js", "dist/entry.mjs"].some(
(file) => entry === path.join(root, file),
)
) {
return undefined;
}
argv = [process.execPath, entry, ...command.slice(2)];
} else if (program === path.join(root, "openclaw.mjs")) {
argv = [process.execPath, program, ...command.slice(1)];
} else {
return undefined;
}
if (!isForegroundGatewayRunArgv(argv)) {
return undefined;
}
const options = getCommandOptionsWithRootOptions(argv, {
commandPath: ["gateway"],
booleanFlags: [...GATEWAY_RUN_BOOLEAN_FLAGS],
valueFlags: [...GATEWAY_RUN_VALUE_FLAGS],
mode: "command-path",
});
// Reset owns deletion before initialization; do not migrate state it will discard.
return options && !options.commandOptions.includes("--reset") ? options : undefined;
}
try {
const program = command[0] && executable(command[0]);
if (!program) {
console.error("OpenClaw container activation command was not found");
process.exit(127);
}
const invocation = gatewayInvocation(program);
if (invocation) {
let interrupted;
let child;
for (const signal of ["SIGTERM", "SIGINT", "SIGHUP", "SIGQUIT"]) {
process.on(signal, () => {
interrupted ??= signal;
// Doctor's maintenance barriers own INT/TERM; HUP/QUIT must use that drain too.
child?.kill(signal === "SIGHUP" || signal === "SIGQUIT" ? "SIGTERM" : signal);
});
}
child = spawn(
process.execPath,
[
path.join(root, "openclaw.mjs"),
...invocation.rootOptions,
"doctor",
"--fix",
"--non-interactive",
],
{ stdio: "inherit", env: process.env },
);
let failure;
child.on("error", (error) => {
failure = error;
});
const outcome = await new Promise((resolve) =>
child.once("close", (code, signal) => resolve({ code, signal })),
);
if (failure) {
throw failure;
}
const signal = interrupted ?? outcome.signal;
if (signal || outcome.code !== 0) {
process.exit(signal ? 128 + os.constants.signals[signal] : (outcome.code ?? 1));
}
}
// Replace the adapter so tini continues to supervise the original command directly.
process.execve(program, command, process.env);
} catch (error) {
console.error(
`OpenClaw container activation failed: ${error instanceof Error ? error.message : String(error)}`,
);
process.exitCode = 1;
}