@afffun/codexbot 1.0.96 → 1.0.98
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
package/src/auth_service.mjs
CHANGED
|
@@ -42,25 +42,46 @@ function mapAuthModeToCodexArgs(mode) {
|
|
|
42
42
|
function buildProjectionScript(layout) {
|
|
43
43
|
const controlDir = trim(layout.codexHomeDir);
|
|
44
44
|
const agentHomeDir = trim(layout.agentHomeDir);
|
|
45
|
+
const agentUser = trim(layout.agentUser);
|
|
46
|
+
const agentGroup = trim(layout.agentGroup);
|
|
45
47
|
if (!controlDir || !agentHomeDir) return '';
|
|
46
48
|
const agentDir = path.join(agentHomeDir, '.codex');
|
|
47
49
|
const lines = [
|
|
48
50
|
'set -euo pipefail',
|
|
49
51
|
`control_dir=${JSON.stringify(controlDir)}`,
|
|
52
|
+
`agent_home_dir=${JSON.stringify(agentHomeDir)}`,
|
|
50
53
|
`agent_dir=${JSON.stringify(agentDir)}`,
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
'
|
|
54
|
+
`agent_user=${JSON.stringify(agentUser)}`,
|
|
55
|
+
`agent_group=${JSON.stringify(agentGroup)}`,
|
|
56
|
+
'parent_gid="$(stat -c \'%g\' "$agent_home_dir" 2>/dev/null || true)"',
|
|
57
|
+
'if [[ ! -d "$agent_dir" ]]; then',
|
|
54
58
|
' mkdir -p "$agent_dir"',
|
|
55
59
|
'fi',
|
|
60
|
+
'if [[ "$(id -u)" == "0" && -n "$agent_user" && -n "$agent_group" ]]; then',
|
|
61
|
+
' chown "$agent_user:$agent_group" "$agent_dir" 2>/dev/null || true',
|
|
62
|
+
'elif [[ -n "$agent_group" ]]; then',
|
|
63
|
+
' chgrp "$agent_group" "$agent_dir" 2>/dev/null || true',
|
|
64
|
+
'elif [[ -n "$parent_gid" ]]; then',
|
|
65
|
+
' chgrp "$parent_gid" "$agent_dir" 2>/dev/null || true',
|
|
66
|
+
'fi',
|
|
67
|
+
'chmod 2770 "$agent_dir" 2>/dev/null || chmod 0770 "$agent_dir" 2>/dev/null || true',
|
|
56
68
|
];
|
|
57
69
|
for (const entry of PROJECTED_FILES) {
|
|
58
70
|
lines.push(`src="$control_dir/${entry.name}"`);
|
|
59
71
|
lines.push(`dst="$agent_dir/${entry.name}"`);
|
|
60
72
|
lines.push('if [[ -f "$src" ]]; then');
|
|
61
73
|
lines.push(' rm -f "$dst"');
|
|
62
|
-
lines.push('
|
|
63
|
-
lines.push(`
|
|
74
|
+
lines.push(' if [[ "$(id -u)" == "0" && -n "$agent_user" && -n "$agent_group" ]]; then');
|
|
75
|
+
lines.push(` install -D -m ${entry.mode} -o "$agent_user" -g "$agent_group" "$src" "$dst"`);
|
|
76
|
+
lines.push(' else');
|
|
77
|
+
lines.push(' cp "$src" "$dst"');
|
|
78
|
+
lines.push(' if [[ -n "$agent_group" ]]; then');
|
|
79
|
+
lines.push(' chgrp "$agent_group" "$dst" 2>/dev/null || true');
|
|
80
|
+
lines.push(' elif [[ -n "$parent_gid" ]]; then');
|
|
81
|
+
lines.push(' chgrp "$parent_gid" "$dst" 2>/dev/null || true');
|
|
82
|
+
lines.push(' fi');
|
|
83
|
+
lines.push(` chmod ${entry.mode} "$dst"`);
|
|
84
|
+
lines.push(' fi');
|
|
64
85
|
lines.push('fi');
|
|
65
86
|
}
|
|
66
87
|
return lines.join('\n');
|
|
@@ -116,7 +137,15 @@ export function createNpmDistributionAuthService(deps = {}) {
|
|
|
116
137
|
const projectionScript = buildProjectionScript(layout);
|
|
117
138
|
if (projectionScript) {
|
|
118
139
|
const projectionArgs = ['-u', layout.controlUser, 'env', `CODEX_HOME=${layout.codexHomeDir}`, `PATH=${pathModule.dirname(layout.codexBinPath)}:${processImpl.env.PATH || ''}`, 'bash', '-lc', projectionScript];
|
|
119
|
-
if (isRoot
|
|
140
|
+
if (isRoot) {
|
|
141
|
+
await runChild(spawnFn, 'bash', ['-lc', projectionScript], {
|
|
142
|
+
env: {
|
|
143
|
+
...processImpl.env,
|
|
144
|
+
CODEX_HOME: layout.codexHomeDir,
|
|
145
|
+
PATH: `${pathModule.dirname(layout.codexBinPath)}:${processImpl.env.PATH || ''}`,
|
|
146
|
+
},
|
|
147
|
+
});
|
|
148
|
+
} else if (!(currentUser && currentUser === layout.controlUser)) {
|
|
120
149
|
await runChild(spawnFn, 'sudo', projectionArgs);
|
|
121
150
|
} else {
|
|
122
151
|
await runChild(spawnFn, 'bash', ['-lc', projectionScript], {
|
package/src/entrypoint.mjs
CHANGED
|
@@ -68,7 +68,11 @@ function renderUsage() {
|
|
|
68
68
|
|
|
69
69
|
export async function runCodexbotCli(argv = [], deps = {}) {
|
|
70
70
|
const logger = deps.logger || console;
|
|
71
|
-
const
|
|
71
|
+
const packageVersion = readPackageVersion();
|
|
72
|
+
const installService = deps.installService || createNpmDistributionInstallService({
|
|
73
|
+
logger,
|
|
74
|
+
cliVersion: packageVersion,
|
|
75
|
+
});
|
|
72
76
|
const activationService = deps.activationService || createNpmDistributionActivationService({ logger });
|
|
73
77
|
const authService = deps.authService || createNpmDistributionAuthService({ logger });
|
|
74
78
|
const cli = parseCliArgs(argv);
|
|
@@ -77,7 +81,6 @@ export async function runCodexbotCli(argv = [], deps = {}) {
|
|
|
77
81
|
return 0;
|
|
78
82
|
}
|
|
79
83
|
if (cli.action === 'version') {
|
|
80
|
-
const packageVersion = readPackageVersion();
|
|
81
84
|
let installedVersion = '';
|
|
82
85
|
try {
|
|
83
86
|
installedVersion = authService.resolveInstalledVersion({});
|
package/src/install_service.mjs
CHANGED
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
} from './config_service.mjs';
|
|
10
10
|
import { createNpmDistributionActivationService } from './activation_service.mjs';
|
|
11
11
|
import { createNpmDistributionInstallSeedService } from './install_seed_service.mjs';
|
|
12
|
+
import { compareVersionLike } from './version_compare_service.mjs';
|
|
12
13
|
|
|
13
14
|
function trim(value, fallback = '') {
|
|
14
15
|
const text = String(value ?? '').trim();
|
|
@@ -102,6 +103,55 @@ function runChild(spawnFn, command, args, options = {}) {
|
|
|
102
103
|
});
|
|
103
104
|
}
|
|
104
105
|
|
|
106
|
+
async function readJsonResponse(response) {
|
|
107
|
+
const text = await response.text();
|
|
108
|
+
try {
|
|
109
|
+
return text ? JSON.parse(text) : {};
|
|
110
|
+
} catch {
|
|
111
|
+
return {};
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function buildMinimumCliVersionMessage({
|
|
116
|
+
currentCliVersion,
|
|
117
|
+
minimumCliVersion,
|
|
118
|
+
manifestVersion,
|
|
119
|
+
channel,
|
|
120
|
+
} = {}) {
|
|
121
|
+
const lines = [
|
|
122
|
+
`This Codexbot CLI is too old for the current public ${channel || 'stable'} install chain.`,
|
|
123
|
+
`- current CLI: ${trim(currentCliVersion, '(unknown)')}`,
|
|
124
|
+
`- minimum supported CLI: ${trim(minimumCliVersion, '(unknown)')}`,
|
|
125
|
+
];
|
|
126
|
+
if (trim(manifestVersion)) {
|
|
127
|
+
lines.push(`- current public runtime: ${manifestVersion}`);
|
|
128
|
+
}
|
|
129
|
+
lines.push('');
|
|
130
|
+
lines.push('Update the npm CLI first, then retry:');
|
|
131
|
+
lines.push(`- npm install -g @afffun/codexbot@latest`);
|
|
132
|
+
lines.push(`- codexbot install`);
|
|
133
|
+
return lines.join('\n');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
function assertMinimumCliVersion({
|
|
137
|
+
cliVersion = '',
|
|
138
|
+
manifest = null,
|
|
139
|
+
channel = '',
|
|
140
|
+
} = {}) {
|
|
141
|
+
const minCliVersion = trim(manifest?.publicInstall?.minimumCliVersion || manifest?.minimumCliVersion);
|
|
142
|
+
const currentCliVersion = trim(cliVersion);
|
|
143
|
+
if (!minCliVersion || !currentCliVersion) return;
|
|
144
|
+
if (compareVersionLike(currentCliVersion, minCliVersion) >= 0) return;
|
|
145
|
+
const err = new Error(buildMinimumCliVersionMessage({
|
|
146
|
+
currentCliVersion,
|
|
147
|
+
minimumCliVersion: minCliVersion,
|
|
148
|
+
manifestVersion: trim(manifest?.version),
|
|
149
|
+
channel,
|
|
150
|
+
}));
|
|
151
|
+
err.code = 'CLI_VERSION_UNSUPPORTED';
|
|
152
|
+
throw err;
|
|
153
|
+
}
|
|
154
|
+
|
|
105
155
|
export function createNpmDistributionInstallService(deps = {}) {
|
|
106
156
|
const fetchFn = deps.fetchFn || fetch;
|
|
107
157
|
const fsPromises = deps.fsPromises || fs;
|
|
@@ -110,6 +160,7 @@ export function createNpmDistributionInstallService(deps = {}) {
|
|
|
110
160
|
const spawnFn = deps.spawnFn || spawn;
|
|
111
161
|
const processImpl = deps.processImpl || process;
|
|
112
162
|
const logger = deps.logger || console;
|
|
163
|
+
const cliVersion = trim(deps.cliVersion);
|
|
113
164
|
const installSeedService = deps.installSeedService || createNpmDistributionInstallSeedService({
|
|
114
165
|
fsPromises,
|
|
115
166
|
osModule,
|
|
@@ -195,6 +246,23 @@ export function createNpmDistributionInstallService(deps = {}) {
|
|
|
195
246
|
});
|
|
196
247
|
await writeResponseToFile(keyResponse, tempKeyPath, fsPromises);
|
|
197
248
|
}
|
|
249
|
+
if (distributionMode === 'install') {
|
|
250
|
+
logger.log('==> Fetch manifest');
|
|
251
|
+
const manifestResponse = await ensureOkResponse(await fetchFn(urls.manifestUrl, { headers }), {
|
|
252
|
+
label: 'manifest',
|
|
253
|
+
installBaseUrl: urls.installBaseUrl,
|
|
254
|
+
channel: urls.channel,
|
|
255
|
+
updateBaseUrl: urls.updateBaseUrl,
|
|
256
|
+
authTokenPresent: Boolean(authToken),
|
|
257
|
+
distributionMode,
|
|
258
|
+
});
|
|
259
|
+
const manifestPayload = await readJsonResponse(manifestResponse);
|
|
260
|
+
assertMinimumCliVersion({
|
|
261
|
+
cliVersion,
|
|
262
|
+
manifest: manifestPayload,
|
|
263
|
+
channel: urls.channel,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
198
266
|
|
|
199
267
|
const remoteMode = distributionMode === 'install' ? 'auto' : trim(mode, 'auto');
|
|
200
268
|
const args = [
|
|
@@ -7,6 +7,9 @@ const SPLIT_DEFAULTS = Object.freeze({
|
|
|
7
7
|
appDir: '/usr/local/lib/codexbot',
|
|
8
8
|
controlEnvFile: '/etc/codexbot/control.env',
|
|
9
9
|
controlUser: 'codexbotd',
|
|
10
|
+
controlGroup: 'codexbotd',
|
|
11
|
+
agentUser: 'codexagent',
|
|
12
|
+
agentGroup: 'codexagent',
|
|
10
13
|
codexHomeDir: '/var/lib/codexbot/control/home/.codex',
|
|
11
14
|
agentHomeDir: '/var/lib/codexbot/agent/home',
|
|
12
15
|
});
|
|
@@ -16,6 +19,9 @@ const LEGACY_DEFAULTS = Object.freeze({
|
|
|
16
19
|
appDir: '/home/codexbot/codexbot-telegram',
|
|
17
20
|
controlEnvFile: '/home/codexbot/codexbot-telegram/.env',
|
|
18
21
|
controlUser: 'codexbot',
|
|
22
|
+
controlGroup: 'codexbot',
|
|
23
|
+
agentUser: 'codexbot',
|
|
24
|
+
agentGroup: 'codexbot',
|
|
19
25
|
codexHomeDir: '/home/codexbot/codexbot-home/.codex',
|
|
20
26
|
agentHomeDir: '',
|
|
21
27
|
});
|
|
@@ -67,6 +73,9 @@ export function resolveInstalledControlLayout({
|
|
|
67
73
|
const fileEnv = readEnvFile(fsSync, envFile);
|
|
68
74
|
const resolvedAppDir = pathModule.resolve(trim(appDir || fileEnv.CODEXBOT_APP_DIR || fileEnv.CODEXBOT_SYSTEM_ROOT, defaults.appDir));
|
|
69
75
|
const resolvedControlUser = trim(controlUser || fileEnv.CODEXBOT_CONTROL_USER, defaults.controlUser);
|
|
76
|
+
const resolvedControlGroup = trim(fileEnv.CODEXBOT_CONTROL_GROUP, defaults.controlGroup);
|
|
77
|
+
const resolvedAgentUser = trim(fileEnv.CODEXBOT_AGENT_USER, defaults.agentUser);
|
|
78
|
+
const resolvedAgentGroup = trim(fileEnv.CODEXBOT_AGENT_GROUP, defaults.agentGroup);
|
|
70
79
|
const resolvedCodexHomeDir = pathModule.resolve(trim(
|
|
71
80
|
codexHomeDir
|
|
72
81
|
|| fileEnv.CODEXBOT_CONTROL_CODEX_HOME_DIR
|
|
@@ -83,6 +92,9 @@ export function resolveInstalledControlLayout({
|
|
|
83
92
|
appDir: resolvedAppDir,
|
|
84
93
|
controlEnvFile: envFile,
|
|
85
94
|
controlUser: resolvedControlUser,
|
|
95
|
+
controlGroup: resolvedControlGroup,
|
|
96
|
+
agentUser: resolvedAgentUser,
|
|
97
|
+
agentGroup: resolvedAgentGroup,
|
|
86
98
|
codexHomeDir: resolvedCodexHomeDir,
|
|
87
99
|
agentHomeDir: resolvedAgentHomeDir,
|
|
88
100
|
codexBinPath,
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
function trimText(value) {
|
|
2
|
+
return String(value || '').trim();
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
function tokenizeVersionLike(value) {
|
|
6
|
+
return trimText(value)
|
|
7
|
+
.split(/[.\-+_]/g)
|
|
8
|
+
.map((item) => item.trim())
|
|
9
|
+
.filter(Boolean)
|
|
10
|
+
.map((item) => (/^\d+$/.test(item) ? Number.parseInt(item, 10) : item.toLowerCase()));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function compareVersionLike(a, b) {
|
|
14
|
+
const left = tokenizeVersionLike(a);
|
|
15
|
+
const right = tokenizeVersionLike(b);
|
|
16
|
+
const limit = Math.max(left.length, right.length);
|
|
17
|
+
for (let index = 0; index < limit; index += 1) {
|
|
18
|
+
const lv = left[index] ?? 0;
|
|
19
|
+
const rv = right[index] ?? 0;
|
|
20
|
+
if (typeof lv === 'number' && typeof rv === 'number') {
|
|
21
|
+
if (lv < rv) return -1;
|
|
22
|
+
if (lv > rv) return 1;
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
const ls = String(lv);
|
|
26
|
+
const rs = String(rv);
|
|
27
|
+
if (ls < rs) return -1;
|
|
28
|
+
if (ls > rs) return 1;
|
|
29
|
+
}
|
|
30
|
+
return 0;
|
|
31
|
+
}
|