fix: 适配NAS Codex nvm运行时

This commit is contained in:
sunlei 2026-06-25 09:41:16 +08:00
parent e2a50f03b3
commit b8b46a04c3
3 changed files with 60 additions and 9 deletions

View File

@ -16,7 +16,7 @@
- 生成接口测试计划:接口改动后输出真实调用命令和统一返回结构断言。
- 生成业务链路测试计划:固化 Admin 登录、博客 CRUD、QQBot 扫码/自动回复、更新登录 SSE、FFLogs 命令、系统日志可视化、Web/Playground 回跳。
- 静态检查 NapCat 设备身份护栏:确认 API 仍保留 QQNT 可见 hostname、实体 OUI 风格 MAC、QQNT `machine-info` 写入、持久化 runtime dir 和 `DB_TIMEZONE` 默认值。
- 生成 NapCatQQ 上游同步与 runtime 发布自动化入口MCP/CLI 默认 dry-run覆盖 upstream audit、sync candidate review、runtime readiness、remote dev handoff 和 NAS Codex bootstrap planupstream audit 在显式 `execute=true``useCodex=true` 时可运行 CodexNAS Codex bootstrap 在显式 `execute=true` 时只返回目录准备和 CLI 包检查/安装计划,不复制 secrets、不写 systemd、不触发发布。
- 生成 NapCatQQ 上游同步与 runtime 发布自动化入口MCP/CLI 默认 dry-run覆盖 upstream audit、sync candidate review、runtime readiness、remote dev handoff 和 NAS Codex bootstrap planupstream audit 在显式 `execute=true``useCodex=true` 时可运行 CodexNAS Codex bootstrap 在显式 `execute=true` 时只返回目录准备、nvm 管理的 Node 22.14.0 / pnpm 10.28.2 / Codex CLI 安装计划,不复制 secrets、不写 systemd、不触发发布。
- 生成卡点固化记录:把超时、卡进程、远程命令误写、重复失败整理成“问题点 / 稳定解法 / 后续入口 / 验证证据”,避免原样重试。
- 生成改动文档同步计划:按变更文件自动提示需要同步的 README、API、AGENTS、docs、Obsidian、skill 和 ktWorkflow 入口。
- 生成多仓库提交/推送计划:按仓库分组、建议提交信息、列出提交和推送前检查。
@ -114,7 +114,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login
| `kt_napcat_sync_candidate_review` | 生成 NapCat sync candidate review 的 prompt/context/只读命令骨架Task 5 不执行 Codex 或 Git 写操作 |
| `kt_napcat_runtime_release_readiness` | 生成 NapCat runtime release readiness 的 prompt/context/只读检查骨架,不自动构建或发布 |
| `kt_napcat_remote_dev_handoff` | 生成 NapCat 自动化远程开发 handoff 的 prompt/context 骨架,不创建线程或同步仓库 |
| `kt_nas_codex_bootstrap_plan` | 生成可信 NAS Codex bootstrap dry-run/execute command planexecute 只规划目录准备和 CLI 包检查/安装,不复制 secrets、不写 systemd |
| `kt_nas_codex_bootstrap_plan` | 生成可信 NAS Codex bootstrap dry-run/execute command planexecute 只规划目录准备和 nvm 管理的 Node/pnpm/Codex 安装,不复制 secrets、不写 systemd |
| `kt_napcat_device_profile_check` | 静态检查 API NapCat 设备身份护栏,覆盖 hostname、MAC、`machine-info`、runtime dir 和 DB timezone |
| `kt_blocker_resolution` | 生成或写入卡点固化记录,提醒停止原样重试 |
| `kt_remote_health_check` | 生成或执行远程只读健康检查命令 |
@ -137,7 +137,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login
| `pnpm run napcat-sync-candidate-review` | 输出 sync candidate review 的 prompt/context/只读命令骨架,不执行 Codex 或 Git 写操作。 |
| `pnpm run napcat-runtime-release-readiness` | 输出 runtime release readiness 的 prompt/context/只读检查骨架,不构建镜像、不调用 kubectl、不发布。 |
| `pnpm run napcat-remote-dev-handoff` | 输出远程开发 handoff 的 prompt/context 骨架,不创建线程、不同步仓库、不执行 Codex。 |
| `pnpm run nas-codex-bootstrap` | 输出可信 NAS Codex bootstrap dry-run plan`--execute` 只生成目录准备和 CLI 包检查/安装命令计划,不真实执行 SSH、不复制 secrets、不写 systemd。 |
| `pnpm run nas-codex-bootstrap` | 输出可信 NAS Codex bootstrap dry-run plan`--execute` 只生成目录准备和 nvm 管理的 Node/pnpm/Codex 安装命令计划,不真实执行 SSH、不复制 secrets、不写 systemd。 |
| `pnpm run napcat-device-profile-check` | 静态检查 API NapCat 设备身份护栏,防止回退到未知设备风险配置。 |
| `pnpm run deploy-observation` | 默认 dry-run 输出只读 NAS 观测命令;传 `--execute` 时执行 Jenkins/K8s/health/smoke 观测并写入 `.kt-workspace/test-artifacts/deploy-observation`。 |
| `pnpm run obsidian-context` | 输出 Obsidian 索引上下文;可传 `--module Admin`、`--query QQBot`、`--max-documents 10`。 |

View File

@ -220,6 +220,10 @@ export async function runSelfTest(): Promise<void> {
throw new Error("NAS Codex bootstrap Windows path guard self-check failed");
}
for (const expected of [
"export NVM_DIR=/vol1/docker/kt-codex/runtime/nvm",
'test -s "$NVM_DIR/nvm.sh"',
"nvm --version",
"nvm current",
"node --version",
"corepack --version",
"pnpm --version",
@ -250,7 +254,13 @@ export async function runSelfTest(): Promise<void> {
}
if (
!executeBootstrapCommandText.includes("install -d -m 700 /vol1/docker/kt-codex/home/.codex") ||
!executeBootstrapCommandText.includes("npm install -g @openai/codex")
!executeBootstrapCommandText.includes("install -d -m 755 /vol1/docker/kt-codex/runtime") ||
!executeBootstrapCommandText.includes("git clone https://github.com/nvm-sh/nvm.git \"$NVM_DIR\"") ||
!executeBootstrapCommandText.includes("git -C \"$NVM_DIR\" checkout \"$NVM_TAG\"") ||
!executeBootstrapCommandText.includes("nvm install \"$NODE_VERSION\"") ||
!executeBootstrapCommandText.includes("nvm alias default \"$NODE_VERSION\"") ||
!executeBootstrapCommandText.includes("npm install -g @openai/codex@latest") ||
!executeBootstrapCommandText.includes("ln -sfn \"$target\" \"/usr/local/bin/$cmd\"")
) {
throw new Error("NAS Codex bootstrap execute package plan self-check failed");
}
@ -434,7 +444,7 @@ export async function runSelfTest(): Promise<void> {
for (const expected of [
"CODEX_HOME='/vol1/docker/kt-codex/home/.codex'",
"--cd '/vol1/docker/kt-codex/workspace/KT'",
"--profile-v2 automation",
"--profile automation",
"--sandbox workspace-write",
"--json",
"--ephemeral",

View File

@ -335,6 +335,9 @@ export function buildNapcatRemoteDevHandoff(
interface NasCodexBootstrapContext {
codexHome: string;
nodeVersion: string;
nvmDir: string;
nvmTag: string;
serviceName: string;
workspaceRoot: string;
}
@ -354,6 +357,9 @@ export function buildNasCodexBootstrapPlan(input: NasCodexBootstrapPlanInput) {
input.codexHome,
napcatAutomationDefaults.codexHome,
),
nodeVersion: '22.14.0',
nvmDir: '/vol1/docker/kt-codex/runtime/nvm',
nvmTag: 'v0.40.5',
serviceName: resolveNasBootstrapServiceName(
input.serviceName ?? napcatAutomationDefaults.bootstrapServiceName,
),
@ -481,6 +487,11 @@ function buildNasBootstrapDryRunCommand(
return buildNasBootstrapSshPlanCommand(
[
"printf '%s\\n' '[ktWorkflow] NAS Codex bootstrap dry-run checks'",
`export NVM_DIR=${context.nvmDir}`,
'test -s "$NVM_DIR/nvm.sh"',
'. "$NVM_DIR/nvm.sh"',
'nvm --version',
'nvm current',
'node --version',
'corepack --version',
'pnpm --version',
@ -504,23 +515,53 @@ function buildNasBootstrapExecuteCommand(
context: NasCodexBootstrapContext,
): string {
const workspaceParent = path.posix.dirname(context.workspaceRoot);
const nvmParent = path.posix.dirname(context.nvmDir);
return buildNasBootstrapSshPlanCommand(
[
"printf '%s\\n' '[ktWorkflow] NAS Codex bootstrap execute plan'",
`install -d -m 755 ${workspaceParent}`,
`install -d -m 755 ${nvmParent}`,
`install -d -m 700 ${context.codexHome}`,
`install -d -m 755 ${napcatNasCodexArtifactRoot}`,
'node --version',
`export NVM_DIR=${context.nvmDir}`,
`NVM_TAG=${context.nvmTag}`,
`NODE_VERSION=${context.nodeVersion}`,
'if [ ! -d "$NVM_DIR/.git" ]; then',
' git clone https://github.com/nvm-sh/nvm.git "$NVM_DIR"',
'fi',
'git -C "$NVM_DIR" fetch --tags origin',
'git -C "$NVM_DIR" checkout "$NVM_TAG"',
'. "$NVM_DIR/nvm.sh"',
'nvm install "$NODE_VERSION"',
'nvm alias default "$NODE_VERSION"',
'nvm use "$NODE_VERSION"',
'npm config delete prefix >/dev/null 2>&1 || true',
'corepack --version',
'corepack enable',
'corepack prepare pnpm@10.28.2 --activate',
'pnpm --version',
'git --version',
'docker --version',
'if ! command -v codex >/dev/null 2>&1; then',
' npm install -g @openai/codex',
'npm install -g @openai/codex@latest',
"cat >/etc/profile.d/kt-codex-nvm.sh <<'PROFILE'",
'export NVM_DIR=/vol1/docker/kt-codex/runtime/nvm',
'if [ -s "$NVM_DIR/nvm.sh" ]; then',
' . "$NVM_DIR/nvm.sh"',
' nvm use --silent default >/dev/null 2>&1 || true',
'fi',
'if [ -s "$NVM_DIR/bash_completion" ]; then',
' . "$NVM_DIR/bash_completion"',
'fi',
'PROFILE',
'chmod 644 /etc/profile.d/kt-codex-nvm.sh',
'for cmd in node npm npx corepack pnpm pnpx codex; do',
' target=$(command -v "$cmd")',
' ln -sfn "$target" "/usr/local/bin/$cmd"',
'done',
'nvm --version',
'nvm current',
'node --version',
'codex --version',
`test -d ${context.workspaceRoot}`,
`test -d ${context.codexHome}`,
@ -586,7 +627,7 @@ export function buildNapcatCodexExecCommand(
`CODEX_HOME=${shellQuotePath(codexHome)}`,
'codex --ask-for-approval never exec',
`--cd ${shellQuotePath(input.workspaceRoot)}`,
'--profile-v2 automation',
'--profile automation',
'--sandbox workspace-write',
'--json',
'--ephemeral',