fix: 对齐NapCat自动化入口默认值
This commit is contained in:
parent
6fc5e65986
commit
fc750ddcf1
@ -44,6 +44,7 @@ pnpm run workstream-closeout -- --title "发布闭环" --verification "Jenkins S
|
|||||||
pnpm run napcat-upstream-audit -- --artifact-root .kt-workspace/test-artifacts/napcat-upstream-sync
|
pnpm run napcat-upstream-audit -- --artifact-root .kt-workspace/test-artifacts/napcat-upstream-sync
|
||||||
pnpm run napcat-sync-candidate-review
|
pnpm run napcat-sync-candidate-review
|
||||||
pnpm run napcat-runtime-release-readiness
|
pnpm run napcat-runtime-release-readiness
|
||||||
|
pnpm run napcat-remote-dev-handoff
|
||||||
pnpm run nas-codex-bootstrap
|
pnpm run nas-codex-bootstrap
|
||||||
pnpm run napcat-device-profile-check
|
pnpm run napcat-device-profile-check
|
||||||
pnpm run cleanup-history -- --dry-run
|
pnpm run cleanup-history -- --dry-run
|
||||||
@ -126,6 +127,7 @@ pnpm run admin-login -- --url http://127.0.0.1:5999/#/auth/login
|
|||||||
| `pnpm run napcat-upstream-audit` | 默认 dry-run 输出 NapCatQQ 上游 release 审计分类、只读 Git 命令和 artifact 路径;显式 `--execute --use-codex` 才运行 Codex。 |
|
| `pnpm run napcat-upstream-audit` | 默认 dry-run 输出 NapCatQQ 上游 release 审计分类、只读 Git 命令和 artifact 路径;显式 `--execute --use-codex` 才运行 Codex。 |
|
||||||
| `pnpm run napcat-sync-candidate-review` | 输出 sync candidate review 的 prompt/context/只读命令骨架,不执行 Codex 或 Git 写操作。 |
|
| `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-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;真实安装、同步和 systemd 接入留给后续实现。 |
|
| `pnpm run nas-codex-bootstrap` | 输出可信 NAS Codex bootstrap dry-run plan;真实安装、同步和 systemd 接入留给后续实现。 |
|
||||||
| `pnpm run napcat-device-profile-check` | 静态检查 API NapCat 设备身份护栏,防止回退到未知设备风险配置。 |
|
| `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 deploy-observation` | 默认 dry-run 输出只读 NAS 观测命令;传 `--execute` 时执行 Jenkins/K8s/health/smoke 观测并写入 `.kt-workspace/test-artifacts/deploy-observation`。 |
|
||||||
|
|||||||
@ -10,6 +10,7 @@
|
|||||||
"deploy-observation": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --deploy-observation",
|
"deploy-observation": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --deploy-observation",
|
||||||
"global-review": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --global-review",
|
"global-review": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --global-review",
|
||||||
"napcat-device-profile-check": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-device-profile-check",
|
"napcat-device-profile-check": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-device-profile-check",
|
||||||
|
"napcat-remote-dev-handoff": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-remote-dev-handoff",
|
||||||
"napcat-runtime-release-readiness": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-runtime-release-readiness",
|
"napcat-runtime-release-readiness": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-runtime-release-readiness",
|
||||||
"napcat-sync-candidate-review": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-sync-candidate-review",
|
"napcat-sync-candidate-review": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-sync-candidate-review",
|
||||||
"napcat-upstream-audit": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-upstream-audit",
|
"napcat-upstream-audit": "node --import ./node_modules/tsx/dist/loader.mjs src/server.ts --napcat-upstream-audit",
|
||||||
|
|||||||
@ -28,6 +28,7 @@ import {
|
|||||||
buildNapcatSyncCandidateReview,
|
buildNapcatSyncCandidateReview,
|
||||||
buildNapcatUpstreamAudit,
|
buildNapcatUpstreamAudit,
|
||||||
buildNasCodexBootstrapPlan,
|
buildNasCodexBootstrapPlan,
|
||||||
|
napcatAutomationDefaults,
|
||||||
} from './tools/napcatAutomation.js';
|
} from './tools/napcatAutomation.js';
|
||||||
import { buildCommitPlan, buildComponentWorkflow, buildDbSyncPlan, buildFinishTask, buildPushPlan, buildRemoteHealthCheck } from './tools/workflow.js';
|
import { buildCommitPlan, buildComponentWorkflow, buildDbSyncPlan, buildFinishTask, buildPushPlan, buildRemoteHealthCheck } from './tools/workflow.js';
|
||||||
import { workstreamReusablePatternValues } from './core/constants.js';
|
import { workstreamReusablePatternValues } from './core/constants.js';
|
||||||
@ -395,16 +396,18 @@ export function registerTools(server: McpServer): void {
|
|||||||
createCandidateBranch: z.boolean().default(false),
|
createCandidateBranch: z.boolean().default(false),
|
||||||
dryMergeConflict: z.boolean().default(false),
|
dryMergeConflict: z.boolean().default(false),
|
||||||
execute: z.boolean().default(false),
|
execute: z.boolean().default(false),
|
||||||
forkBranch: z.string().default('HEAD'),
|
forkBranch: z.string().default(napcatAutomationDefaults.forkBranch),
|
||||||
forkPatchFiles: z.array(z.string()).default([]),
|
forkPatchFiles: z.array(z.string()).default([]),
|
||||||
forkRepo: z.string().default('KTeam/NapCatQQ'),
|
forkRepo: z.string().default(napcatAutomationDefaults.forkRepo),
|
||||||
lastAcceptedUpstreamBase: z.string().default('origin/main'),
|
lastAcceptedUpstreamBase: z
|
||||||
|
.string()
|
||||||
|
.default(napcatAutomationDefaults.lastAcceptedUpstreamBase),
|
||||||
outputSchemaPath: z.string().optional(),
|
outputSchemaPath: z.string().optional(),
|
||||||
upstreamChangedFiles: z.array(z.string()).default([]),
|
upstreamChangedFiles: z.array(z.string()).default([]),
|
||||||
upstreamReleaseTag: z.string().default('upstream/main'),
|
upstreamReleaseTag: z.string().default(napcatAutomationDefaults.upstreamReleaseRef),
|
||||||
upstreamRepo: z.string().default('NapNeko/NapCatQQ'),
|
upstreamRepo: z.string().default(napcatAutomationDefaults.upstreamRepo),
|
||||||
useCodex: z.boolean().default(false),
|
useCodex: z.boolean().default(false),
|
||||||
workspaceRoot: z.string().default('/vol1/docker/kt-codex/workspace/KT'),
|
workspaceRoot: z.string().default(napcatAutomationDefaults.workspaceRoot),
|
||||||
},
|
},
|
||||||
title: 'KT NapCat Upstream Audit',
|
title: 'KT NapCat Upstream Audit',
|
||||||
},
|
},
|
||||||
@ -420,15 +423,17 @@ export function registerTools(server: McpServer): void {
|
|||||||
artifactRoot: z
|
artifactRoot: z
|
||||||
.string()
|
.string()
|
||||||
.default('.kt-workspace/test-artifacts/napcat-automation/sync-candidate-review'),
|
.default('.kt-workspace/test-artifacts/napcat-automation/sync-candidate-review'),
|
||||||
candidateBranch: z.string().default('napcat-upstream-sync/candidate'),
|
candidateBranch: z.string().default(napcatAutomationDefaults.candidateBranch),
|
||||||
execute: z.boolean().default(false),
|
execute: z.boolean().default(false),
|
||||||
forkBranch: z.string().default('dev'),
|
forkBranch: z.string().default(napcatAutomationDefaults.forkBranch),
|
||||||
forkRepo: z.string().default('KTeam/NapCatQQ'),
|
forkRepo: z.string().default(napcatAutomationDefaults.forkRepo),
|
||||||
lastAcceptedUpstreamBase: z.string().default('origin/main'),
|
lastAcceptedUpstreamBase: z
|
||||||
upstreamReleaseTag: z.string().default('upstream/main'),
|
.string()
|
||||||
upstreamRepo: z.string().default('NapNeko/NapCatQQ'),
|
.default(napcatAutomationDefaults.lastAcceptedUpstreamBase),
|
||||||
|
upstreamReleaseTag: z.string().default(napcatAutomationDefaults.upstreamReleaseRef),
|
||||||
|
upstreamRepo: z.string().default(napcatAutomationDefaults.upstreamRepo),
|
||||||
useCodex: z.boolean().default(false),
|
useCodex: z.boolean().default(false),
|
||||||
workspaceRoot: z.string().default('/vol1/docker/kt-codex/workspace/KT'),
|
workspaceRoot: z.string().default(napcatAutomationDefaults.workspaceRoot),
|
||||||
},
|
},
|
||||||
title: 'KT NapCat Sync Candidate Review',
|
title: 'KT NapCat Sync Candidate Review',
|
||||||
},
|
},
|
||||||
@ -441,20 +446,20 @@ export function registerTools(server: McpServer): void {
|
|||||||
description:
|
description:
|
||||||
'生成 NapCat runtime release readiness dry-run prompt、上下文和只读检查骨架;不自动构建镜像、不调用 kubectl、不发布。',
|
'生成 NapCat runtime release readiness dry-run prompt、上下文和只读检查骨架;不自动构建镜像、不调用 kubectl、不发布。',
|
||||||
inputSchema: {
|
inputSchema: {
|
||||||
apiImageTag: z.string().default('main-<jenkins-build>'),
|
apiImageTag: z.string().default(napcatAutomationDefaults.apiImageTag),
|
||||||
artifactRoot: z
|
artifactRoot: z
|
||||||
.string()
|
.string()
|
||||||
.default('.kt-workspace/test-artifacts/napcat-automation/runtime-release-readiness'),
|
.default('.kt-workspace/test-artifacts/napcat-automation/runtime-release-readiness'),
|
||||||
candidateBranch: z.string().default('napcat-upstream-sync/candidate'),
|
candidateBranch: z.string().default(napcatAutomationDefaults.candidateBranch),
|
||||||
execute: z.boolean().default(false),
|
execute: z.boolean().default(false),
|
||||||
forkBranch: z.string().default('dev'),
|
forkBranch: z.string().default(napcatAutomationDefaults.forkBranch),
|
||||||
forkRepo: z.string().default('KTeam/NapCatQQ'),
|
forkRepo: z.string().default(napcatAutomationDefaults.forkRepo),
|
||||||
napcatImageTag: z.string().default('kt-napcat-desktop-cn:desktop-cn'),
|
napcatImageTag: z.string().default(napcatAutomationDefaults.runtimeImageTag),
|
||||||
profile: z.string().default('desktop-cn'),
|
profile: z.string().default(napcatAutomationDefaults.runtimeProfile),
|
||||||
upstreamReleaseTag: z.string().default('upstream/main'),
|
upstreamReleaseTag: z.string().default(napcatAutomationDefaults.upstreamReleaseRef),
|
||||||
upstreamRepo: z.string().default('NapNeko/NapCatQQ'),
|
upstreamRepo: z.string().default(napcatAutomationDefaults.upstreamRepo),
|
||||||
useCodex: z.boolean().default(false),
|
useCodex: z.boolean().default(false),
|
||||||
workspaceRoot: z.string().default('/vol1/docker/kt-codex/workspace/KT'),
|
workspaceRoot: z.string().default(napcatAutomationDefaults.workspaceRoot),
|
||||||
},
|
},
|
||||||
title: 'KT NapCat Runtime Release Readiness',
|
title: 'KT NapCat Runtime Release Readiness',
|
||||||
},
|
},
|
||||||
@ -470,15 +475,15 @@ export function registerTools(server: McpServer): void {
|
|||||||
artifactRoot: z
|
artifactRoot: z
|
||||||
.string()
|
.string()
|
||||||
.default('.kt-workspace/test-artifacts/napcat-automation/remote-dev-handoff'),
|
.default('.kt-workspace/test-artifacts/napcat-automation/remote-dev-handoff'),
|
||||||
candidateBranch: z.string().default('napcat-upstream-sync/candidate'),
|
candidateBranch: z.string().default(napcatAutomationDefaults.candidateBranch),
|
||||||
execute: z.boolean().default(false),
|
execute: z.boolean().default(false),
|
||||||
forkBranch: z.string().default('dev'),
|
forkBranch: z.string().default(napcatAutomationDefaults.forkBranch),
|
||||||
forkRepo: z.string().default('KTeam/NapCatQQ'),
|
forkRepo: z.string().default(napcatAutomationDefaults.forkRepo),
|
||||||
targetHost: z.string().default('nas'),
|
targetHost: z.string().default(napcatAutomationDefaults.targetHost),
|
||||||
upstreamReleaseTag: z.string().default('upstream/main'),
|
upstreamReleaseTag: z.string().default(napcatAutomationDefaults.upstreamReleaseRef),
|
||||||
upstreamRepo: z.string().default('NapNeko/NapCatQQ'),
|
upstreamRepo: z.string().default(napcatAutomationDefaults.upstreamRepo),
|
||||||
useCodex: z.boolean().default(false),
|
useCodex: z.boolean().default(false),
|
||||||
workspaceRoot: z.string().default('/vol1/docker/kt-codex/workspace/KT'),
|
workspaceRoot: z.string().default(napcatAutomationDefaults.workspaceRoot),
|
||||||
},
|
},
|
||||||
title: 'KT NapCat Remote Dev Handoff',
|
title: 'KT NapCat Remote Dev Handoff',
|
||||||
},
|
},
|
||||||
@ -494,10 +499,10 @@ export function registerTools(server: McpServer): void {
|
|||||||
artifactRoot: z
|
artifactRoot: z
|
||||||
.string()
|
.string()
|
||||||
.default('.kt-workspace/test-artifacts/napcat-automation/nas-codex-bootstrap'),
|
.default('.kt-workspace/test-artifacts/napcat-automation/nas-codex-bootstrap'),
|
||||||
codexHome: z.string().default('/vol1/docker/kt-codex/home/.codex'),
|
codexHome: z.string().default(napcatAutomationDefaults.codexHome),
|
||||||
execute: z.boolean().default(false),
|
execute: z.boolean().default(false),
|
||||||
serviceName: z.string().default('kt-codex-automation'),
|
serviceName: z.string().default(napcatAutomationDefaults.bootstrapServiceName),
|
||||||
workspaceRoot: z.string().default('/vol1/docker/kt-codex/workspace/KT'),
|
workspaceRoot: z.string().default(napcatAutomationDefaults.workspaceRoot),
|
||||||
},
|
},
|
||||||
title: 'KT NAS Codex Bootstrap Plan',
|
title: 'KT NAS Codex Bootstrap Plan',
|
||||||
},
|
},
|
||||||
|
|||||||
108
src/selfTest.ts
108
src/selfTest.ts
@ -5,6 +5,7 @@ import {
|
|||||||
parseNasCodexBootstrapCliArgs,
|
parseNasCodexBootstrapCliArgs,
|
||||||
parseDeployObservationCliArgs,
|
parseDeployObservationCliArgs,
|
||||||
parseGlobalReviewCliArgs,
|
parseGlobalReviewCliArgs,
|
||||||
|
parseNapcatRemoteDevHandoffCliArgs,
|
||||||
parseNapcatRuntimeReleaseReadinessCliArgs,
|
parseNapcatRuntimeReleaseReadinessCliArgs,
|
||||||
parseNapcatSyncCandidateReviewCliArgs,
|
parseNapcatSyncCandidateReviewCliArgs,
|
||||||
parseNapcatUpstreamAuditCliArgs,
|
parseNapcatUpstreamAuditCliArgs,
|
||||||
@ -46,9 +47,15 @@ import {
|
|||||||
} from "./tools/napcatAutomation.types.js";
|
} from "./tools/napcatAutomation.types.js";
|
||||||
import {
|
import {
|
||||||
buildNapcatCodexExecCommand,
|
buildNapcatCodexExecCommand,
|
||||||
|
buildNapcatRemoteDevHandoff,
|
||||||
|
buildNapcatRuntimeReleaseReadiness,
|
||||||
|
buildNapcatSyncCandidateReview,
|
||||||
buildNapcatUpstreamAudit,
|
buildNapcatUpstreamAudit,
|
||||||
|
buildNasCodexBootstrapPlan,
|
||||||
classifyNapcatUpstreamAudit,
|
classifyNapcatUpstreamAudit,
|
||||||
|
napcatAutomationDefaults,
|
||||||
} from "./tools/napcatAutomation.js";
|
} from "./tools/napcatAutomation.js";
|
||||||
|
import { registerTools } from "./registerTools.js";
|
||||||
import {
|
import {
|
||||||
loadNapcatAutomationPrompt,
|
loadNapcatAutomationPrompt,
|
||||||
type NapcatAutomationPromptName,
|
type NapcatAutomationPromptName,
|
||||||
@ -128,6 +135,11 @@ export async function runSelfTest(): Promise<void> {
|
|||||||
"server",
|
"server",
|
||||||
"--napcat-runtime-release-readiness",
|
"--napcat-runtime-release-readiness",
|
||||||
]);
|
]);
|
||||||
|
const napcatRemoteHandoffCli = parseNapcatRemoteDevHandoffCliArgs([
|
||||||
|
"node",
|
||||||
|
"server",
|
||||||
|
"--napcat-remote-dev-handoff",
|
||||||
|
]);
|
||||||
const nasBootstrapCli = parseNasCodexBootstrapCliArgs([
|
const nasBootstrapCli = parseNasCodexBootstrapCliArgs([
|
||||||
"node",
|
"node",
|
||||||
"server",
|
"server",
|
||||||
@ -136,10 +148,85 @@ export async function runSelfTest(): Promise<void> {
|
|||||||
if (
|
if (
|
||||||
napcatCandidateCli.execute ||
|
napcatCandidateCli.execute ||
|
||||||
napcatRuntimeCli.execute ||
|
napcatRuntimeCli.execute ||
|
||||||
|
napcatRemoteHandoffCli.execute ||
|
||||||
nasBootstrapCli.execute
|
nasBootstrapCli.execute
|
||||||
) {
|
) {
|
||||||
throw new Error("NapCat auxiliary CLI dry-run default self-check failed");
|
throw new Error("NapCat auxiliary CLI dry-run default self-check failed");
|
||||||
}
|
}
|
||||||
|
const napcatCandidateDefaults = buildNapcatSyncCandidateReview({}).context;
|
||||||
|
const napcatRuntimeDefaults = buildNapcatRuntimeReleaseReadiness({}).context;
|
||||||
|
const napcatRemoteDefaults = buildNapcatRemoteDevHandoff({}).context;
|
||||||
|
const nasBootstrapDefaults = buildNasCodexBootstrapPlan({}).context;
|
||||||
|
if (
|
||||||
|
napcatCandidateDefaults.candidateBranch !==
|
||||||
|
napcatAutomationDefaults.candidateBranch ||
|
||||||
|
napcatCandidateDefaults.forkBranch !== napcatAutomationDefaults.forkBranch ||
|
||||||
|
napcatCandidateDefaults.forkRepo !== napcatAutomationDefaults.forkRepo ||
|
||||||
|
napcatCandidateDefaults.lastAcceptedUpstreamBase !==
|
||||||
|
napcatAutomationDefaults.lastAcceptedUpstreamBase ||
|
||||||
|
napcatCandidateDefaults.upstreamReleaseTag !==
|
||||||
|
napcatAutomationDefaults.upstreamReleaseRef ||
|
||||||
|
napcatCandidateDefaults.upstreamRepo !== napcatAutomationDefaults.upstreamRepo ||
|
||||||
|
napcatCandidateDefaults.workspaceRoot !==
|
||||||
|
napcatAutomationDefaults.workspaceRoot
|
||||||
|
) {
|
||||||
|
throw new Error("NapCat candidate review default alignment self-check failed");
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
napcatRuntimeDefaults.apiImageTag !==
|
||||||
|
napcatAutomationDefaults.apiImageTag ||
|
||||||
|
napcatRuntimeDefaults.candidateBranch !==
|
||||||
|
napcatAutomationDefaults.candidateBranch ||
|
||||||
|
napcatRuntimeDefaults.forkBranch !== napcatAutomationDefaults.forkBranch ||
|
||||||
|
napcatRuntimeDefaults.forkRepo !== napcatAutomationDefaults.forkRepo ||
|
||||||
|
napcatRuntimeDefaults.napcatImageTag !==
|
||||||
|
napcatAutomationDefaults.runtimeImageTag ||
|
||||||
|
napcatRuntimeDefaults.profile !== napcatAutomationDefaults.runtimeProfile ||
|
||||||
|
napcatRuntimeDefaults.upstreamReleaseTag !==
|
||||||
|
napcatAutomationDefaults.upstreamReleaseRef ||
|
||||||
|
napcatRuntimeDefaults.workspaceRoot !==
|
||||||
|
napcatAutomationDefaults.workspaceRoot
|
||||||
|
) {
|
||||||
|
throw new Error("NapCat runtime readiness default alignment self-check failed");
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
napcatRemoteDefaults.candidateBranch !==
|
||||||
|
napcatAutomationDefaults.candidateBranch ||
|
||||||
|
napcatRemoteDefaults.forkBranch !== napcatAutomationDefaults.forkBranch ||
|
||||||
|
napcatRemoteDefaults.forkRepo !== napcatAutomationDefaults.forkRepo ||
|
||||||
|
napcatRemoteDefaults.targetHost !== napcatAutomationDefaults.targetHost ||
|
||||||
|
napcatRemoteDefaults.upstreamReleaseTag !==
|
||||||
|
napcatAutomationDefaults.upstreamReleaseRef ||
|
||||||
|
napcatRemoteDefaults.workspaceRoot !== napcatAutomationDefaults.workspaceRoot
|
||||||
|
) {
|
||||||
|
throw new Error("NapCat remote handoff default alignment self-check failed");
|
||||||
|
}
|
||||||
|
if (
|
||||||
|
nasBootstrapDefaults.codexHome !== napcatAutomationDefaults.codexHome ||
|
||||||
|
nasBootstrapDefaults.serviceName !==
|
||||||
|
napcatAutomationDefaults.bootstrapServiceName ||
|
||||||
|
nasBootstrapDefaults.workspaceRoot !== napcatAutomationDefaults.workspaceRoot
|
||||||
|
) {
|
||||||
|
throw new Error("NAS Codex bootstrap default alignment self-check failed");
|
||||||
|
}
|
||||||
|
const packageJson = JSON.parse(
|
||||||
|
readFileSync(resolveInsideRoot("mcp/ktWorkflow/package.json"), "utf8"),
|
||||||
|
) as { scripts?: Record<string, string> };
|
||||||
|
if (!packageJson.scripts?.["napcat-remote-dev-handoff"]) {
|
||||||
|
throw new Error("NapCat remote handoff npm script self-check failed");
|
||||||
|
}
|
||||||
|
const registeredByFakeServer: string[] = [];
|
||||||
|
const fakeMcpServer = {
|
||||||
|
/**
|
||||||
|
* Records registered MCP tool names so self-test proves the actual registerTools surface, not only the constants list.
|
||||||
|
* @param name - MCP tool name passed by `registerTools`.
|
||||||
|
* @returns Nothing; the name is appended to `registeredByFakeServer`.
|
||||||
|
*/
|
||||||
|
registerTool(name: string): void {
|
||||||
|
registeredByFakeServer.push(name);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
registerTools(fakeMcpServer as never);
|
||||||
for (const toolName of [
|
for (const toolName of [
|
||||||
"kt_napcat_upstream_audit",
|
"kt_napcat_upstream_audit",
|
||||||
"kt_napcat_sync_candidate_review",
|
"kt_napcat_sync_candidate_review",
|
||||||
@ -150,6 +237,9 @@ export async function runSelfTest(): Promise<void> {
|
|||||||
if (!registeredToolNames.includes(toolName)) {
|
if (!registeredToolNames.includes(toolName)) {
|
||||||
throw new Error(`NapCat MCP tool registry self-check failed: ${toolName}`);
|
throw new Error(`NapCat MCP tool registry self-check failed: ${toolName}`);
|
||||||
}
|
}
|
||||||
|
if (!registeredByFakeServer.includes(toolName)) {
|
||||||
|
throw new Error(`NapCat MCP registerTools self-check failed: ${toolName}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (parseNapcatAutomationClassification("manual-review") !== "manual-review") {
|
if (parseNapcatAutomationClassification("manual-review") !== "manual-review") {
|
||||||
throw new Error("NapCat classification parser self-check failed");
|
throw new Error("NapCat classification parser self-check failed");
|
||||||
@ -175,6 +265,24 @@ export async function runSelfTest(): Promise<void> {
|
|||||||
"NapCat upstream audit dry-run artifact plan self-check failed",
|
"NapCat upstream audit dry-run artifact plan self-check failed",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
const dryRunAuditDefaultCommands = dryRunAudit.commands.map(
|
||||||
|
(item) => item.command,
|
||||||
|
);
|
||||||
|
if (
|
||||||
|
dryRunAuditDefaultCommands.some((command) =>
|
||||||
|
command.includes("FORK_BRANCH:-HEAD"),
|
||||||
|
) ||
|
||||||
|
!dryRunAuditDefaultCommands.some((command) =>
|
||||||
|
command.includes(`FORK_BRANCH:-${napcatAutomationDefaults.forkBranch}`),
|
||||||
|
) ||
|
||||||
|
!dryRunAuditDefaultCommands.some((command) =>
|
||||||
|
command.includes(
|
||||||
|
`UPSTREAM_RELEASE_REF:-${napcatAutomationDefaults.upstreamReleaseRef}`,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
throw new Error("NapCat upstream audit command default alignment self-check failed");
|
||||||
|
}
|
||||||
const codexCommand = buildNapcatCodexExecCommand({
|
const codexCommand = buildNapcatCodexExecCommand({
|
||||||
artifactRoot: "/vol1/docker/kt-codex/artifacts/smoke",
|
artifactRoot: "/vol1/docker/kt-codex/artifacts/smoke",
|
||||||
contextPacketPath:
|
contextPacketPath:
|
||||||
|
|||||||
@ -100,10 +100,22 @@ const napcatNasCodexArtifactRoot = '/vol1/docker/kt-codex/artifacts';
|
|||||||
const napcatLocalArtifactRoot = '.kt-workspace/test-artifacts';
|
const napcatLocalArtifactRoot = '.kt-workspace/test-artifacts';
|
||||||
const napcatAutomationSkeletonArtifactRoot =
|
const napcatAutomationSkeletonArtifactRoot =
|
||||||
'.kt-workspace/test-artifacts/napcat-automation';
|
'.kt-workspace/test-artifacts/napcat-automation';
|
||||||
const defaultNapcatForkRepo = 'KTeam/NapCatQQ';
|
|
||||||
const defaultNapcatUpstreamRepo = 'NapNeko/NapCatQQ';
|
export const napcatAutomationDefaults = {
|
||||||
const defaultNapcatCandidateBranch = 'napcat-upstream-sync/candidate';
|
apiImageTag: 'main-<jenkins-build>',
|
||||||
const defaultNapcatWorkspaceRoot = '/vol1/docker/kt-codex/workspace/KT';
|
bootstrapServiceName: 'kt-codex-automation',
|
||||||
|
candidateBranch: 'napcat-upstream-sync/candidate',
|
||||||
|
codexHome: '/vol1/docker/kt-codex/home/.codex',
|
||||||
|
forkBranch: 'dev',
|
||||||
|
forkRepo: 'KTeam/NapCatQQ',
|
||||||
|
lastAcceptedUpstreamBase: 'origin/main',
|
||||||
|
runtimeImageTag: 'kt-napcat-desktop-cn:desktop-cn',
|
||||||
|
runtimeProfile: 'desktop-cn',
|
||||||
|
targetHost: 'nas',
|
||||||
|
upstreamReleaseRef: 'upstream/main',
|
||||||
|
upstreamRepo: 'NapNeko/NapCatQQ',
|
||||||
|
workspaceRoot: '/vol1/docker/kt-codex/workspace/KT',
|
||||||
|
} as const;
|
||||||
|
|
||||||
interface NapcatPromptSkeletonConfig {
|
interface NapcatPromptSkeletonConfig {
|
||||||
artifactSlug: string;
|
artifactSlug: string;
|
||||||
@ -189,14 +201,14 @@ export function buildNapcatSyncCandidateReview(
|
|||||||
input: NapcatSyncCandidateReviewInput,
|
input: NapcatSyncCandidateReviewInput,
|
||||||
) {
|
) {
|
||||||
const context = {
|
const context = {
|
||||||
candidateBranch: input.candidateBranch ?? defaultNapcatCandidateBranch,
|
candidateBranch: input.candidateBranch ?? napcatAutomationDefaults.candidateBranch,
|
||||||
forkBranch: input.forkBranch ?? 'dev',
|
forkBranch: input.forkBranch ?? napcatAutomationDefaults.forkBranch,
|
||||||
forkRepo: input.forkRepo ?? defaultNapcatForkRepo,
|
forkRepo: input.forkRepo ?? napcatAutomationDefaults.forkRepo,
|
||||||
lastAcceptedUpstreamBase:
|
lastAcceptedUpstreamBase:
|
||||||
input.lastAcceptedUpstreamBase ?? 'LAST_ACCEPTED_UPSTREAM_BASE',
|
input.lastAcceptedUpstreamBase ?? napcatAutomationDefaults.lastAcceptedUpstreamBase,
|
||||||
upstreamReleaseTag: input.upstreamReleaseTag ?? 'UPSTREAM_RELEASE_REF',
|
upstreamReleaseTag: input.upstreamReleaseTag ?? napcatAutomationDefaults.upstreamReleaseRef,
|
||||||
upstreamRepo: input.upstreamRepo ?? defaultNapcatUpstreamRepo,
|
upstreamRepo: input.upstreamRepo ?? napcatAutomationDefaults.upstreamRepo,
|
||||||
workspaceRoot: input.workspaceRoot ?? defaultNapcatWorkspaceRoot,
|
workspaceRoot: input.workspaceRoot ?? napcatAutomationDefaults.workspaceRoot,
|
||||||
};
|
};
|
||||||
|
|
||||||
return buildNapcatPromptSkeleton({
|
return buildNapcatPromptSkeleton({
|
||||||
@ -209,13 +221,13 @@ export function buildNapcatSyncCandidateReview(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
command:
|
command:
|
||||||
'git log --oneline --decorate -n 20 "${CANDIDATE_BRANCH:-napcat-upstream-sync/candidate}"',
|
`git log --oneline --decorate -n 20 "\${CANDIDATE_BRANCH:-${napcatAutomationDefaults.candidateBranch}}"`,
|
||||||
description: 'Inspect recent candidate commits without changing refs.',
|
description: 'Inspect recent candidate commits without changing refs.',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command:
|
command:
|
||||||
'git diff --stat "${LAST_ACCEPTED_UPSTREAM_BASE:-origin/main}..${CANDIDATE_BRANCH:-napcat-upstream-sync/candidate}"',
|
`git diff --stat "\${LAST_ACCEPTED_UPSTREAM_BASE:-${napcatAutomationDefaults.lastAcceptedUpstreamBase}}..\${CANDIDATE_BRANCH:-${napcatAutomationDefaults.candidateBranch}}"`,
|
||||||
description: 'Summarize candidate file churn for human review.',
|
description: 'Summarize candidate file churn for human review.',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
},
|
},
|
||||||
@ -239,13 +251,14 @@ export function buildNapcatRuntimeReleaseReadiness(
|
|||||||
input: NapcatRuntimeReleaseReadinessInput,
|
input: NapcatRuntimeReleaseReadinessInput,
|
||||||
) {
|
) {
|
||||||
const context = {
|
const context = {
|
||||||
apiImageTag: input.apiImageTag ?? 'main-<jenkins-build>',
|
apiImageTag: input.apiImageTag ?? napcatAutomationDefaults.apiImageTag,
|
||||||
candidateBranch: input.candidateBranch ?? defaultNapcatCandidateBranch,
|
candidateBranch: input.candidateBranch ?? napcatAutomationDefaults.candidateBranch,
|
||||||
forkRepo: input.forkRepo ?? defaultNapcatForkRepo,
|
forkBranch: input.forkBranch ?? napcatAutomationDefaults.forkBranch,
|
||||||
napcatImageTag: input.napcatImageTag ?? 'kt-napcat-desktop-cn:<profile>',
|
forkRepo: input.forkRepo ?? napcatAutomationDefaults.forkRepo,
|
||||||
profile: input.profile ?? 'desktop-cn',
|
napcatImageTag: input.napcatImageTag ?? napcatAutomationDefaults.runtimeImageTag,
|
||||||
upstreamReleaseTag: input.upstreamReleaseTag ?? 'UPSTREAM_RELEASE_REF',
|
profile: input.profile ?? napcatAutomationDefaults.runtimeProfile,
|
||||||
workspaceRoot: input.workspaceRoot ?? defaultNapcatWorkspaceRoot,
|
upstreamReleaseTag: input.upstreamReleaseTag ?? napcatAutomationDefaults.upstreamReleaseRef,
|
||||||
|
workspaceRoot: input.workspaceRoot ?? napcatAutomationDefaults.workspaceRoot,
|
||||||
};
|
};
|
||||||
|
|
||||||
return buildNapcatPromptSkeleton({
|
return buildNapcatPromptSkeleton({
|
||||||
@ -288,11 +301,12 @@ export function buildNapcatRemoteDevHandoff(
|
|||||||
input: NapcatRemoteDevHandoffInput,
|
input: NapcatRemoteDevHandoffInput,
|
||||||
) {
|
) {
|
||||||
const context = {
|
const context = {
|
||||||
candidateBranch: input.candidateBranch ?? defaultNapcatCandidateBranch,
|
candidateBranch: input.candidateBranch ?? napcatAutomationDefaults.candidateBranch,
|
||||||
forkRepo: input.forkRepo ?? defaultNapcatForkRepo,
|
forkBranch: input.forkBranch ?? napcatAutomationDefaults.forkBranch,
|
||||||
targetHost: input.targetHost ?? 'nas',
|
forkRepo: input.forkRepo ?? napcatAutomationDefaults.forkRepo,
|
||||||
upstreamReleaseTag: input.upstreamReleaseTag ?? 'UPSTREAM_RELEASE_REF',
|
targetHost: input.targetHost ?? napcatAutomationDefaults.targetHost,
|
||||||
workspaceRoot: input.workspaceRoot ?? defaultNapcatWorkspaceRoot,
|
upstreamReleaseTag: input.upstreamReleaseTag ?? napcatAutomationDefaults.upstreamReleaseRef,
|
||||||
|
workspaceRoot: input.workspaceRoot ?? napcatAutomationDefaults.workspaceRoot,
|
||||||
};
|
};
|
||||||
|
|
||||||
return buildNapcatPromptSkeleton({
|
return buildNapcatPromptSkeleton({
|
||||||
@ -329,9 +343,9 @@ export function buildNasCodexBootstrapPlan(input: NasCodexBootstrapPlanInput) {
|
|||||||
input.artifactRoot?.trim() ||
|
input.artifactRoot?.trim() ||
|
||||||
`${napcatAutomationSkeletonArtifactRoot}/nas-codex-bootstrap`;
|
`${napcatAutomationSkeletonArtifactRoot}/nas-codex-bootstrap`;
|
||||||
const context = {
|
const context = {
|
||||||
codexHome: input.codexHome ?? '/vol1/docker/kt-codex/home/.codex',
|
codexHome: input.codexHome ?? napcatAutomationDefaults.codexHome,
|
||||||
serviceName: input.serviceName ?? 'kt-codex-automation',
|
serviceName: input.serviceName ?? napcatAutomationDefaults.bootstrapServiceName,
|
||||||
workspaceRoot: input.workspaceRoot ?? defaultNapcatWorkspaceRoot,
|
workspaceRoot: input.workspaceRoot ?? napcatAutomationDefaults.workspaceRoot,
|
||||||
};
|
};
|
||||||
const requestedExecute = input.execute === true;
|
const requestedExecute = input.execute === true;
|
||||||
|
|
||||||
@ -532,7 +546,7 @@ function assertSafeNapcatCodexArtifactRoot(artifactRoot: string): void {
|
|||||||
* @returns The configured workspace root or the stabilized NAS kt-codex workspace path.
|
* @returns The configured workspace root or the stabilized NAS kt-codex workspace path.
|
||||||
*/
|
*/
|
||||||
function resolveNapcatCodexWorkspaceRoot(workspaceRoot?: string): string {
|
function resolveNapcatCodexWorkspaceRoot(workspaceRoot?: string): string {
|
||||||
return workspaceRoot?.trim() || '/vol1/docker/kt-codex/workspace/KT';
|
return workspaceRoot?.trim() || napcatAutomationDefaults.workspaceRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1028,19 +1042,19 @@ export function buildNapcatUpstreamAudit(
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
command:
|
command:
|
||||||
'git diff --name-only "${LAST_ACCEPTED_UPSTREAM_BASE:-origin/main}..${UPSTREAM_RELEASE_REF:-upstream/main}"',
|
`git diff --name-only "\${LAST_ACCEPTED_UPSTREAM_BASE:-${napcatAutomationDefaults.lastAcceptedUpstreamBase}}..\${UPSTREAM_RELEASE_REF:-${napcatAutomationDefaults.upstreamReleaseRef}}"`,
|
||||||
description: 'List upstream release files changed since the last accepted base.',
|
description: 'List upstream release files changed since the last accepted base.',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command:
|
command:
|
||||||
'git diff --name-only "${LAST_ACCEPTED_UPSTREAM_BASE:-origin/main}..HEAD"',
|
`git diff --name-only "\${LAST_ACCEPTED_UPSTREAM_BASE:-${napcatAutomationDefaults.lastAcceptedUpstreamBase}}..\${FORK_BRANCH:-${napcatAutomationDefaults.forkBranch}}"`,
|
||||||
description: 'List KT fork patch files for deterministic overlap checks.',
|
description: 'List KT fork patch files for deterministic overlap checks.',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
command:
|
command:
|
||||||
'git merge-tree "${FORK_BRANCH:-HEAD}" "${UPSTREAM_RELEASE_REF:-upstream/main}"',
|
`git merge-tree "\${FORK_BRANCH:-${napcatAutomationDefaults.forkBranch}}" "\${UPSTREAM_RELEASE_REF:-${napcatAutomationDefaults.upstreamReleaseRef}}"`,
|
||||||
description: 'Probe the dry merge shape without updating the worktree or refs.',
|
description: 'Probe the dry merge shape without updating the worktree or refs.',
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user