Files
pikasTech-HWLAB/internal/cloud/code-agent-contract.mjs
T
2026-05-24 14:53:14 +08:00

478 lines
18 KiB
JavaScript

import { ENVIRONMENT_DEV } from "../protocol/index.mjs";
export const DEV_CODE_AGENT_PROVIDER_CONTRACT = Object.freeze({
contractVersion: "v1",
environment: ENVIRONMENT_DEV,
codeAgentProvider: "codex-stdio",
runtimeProvider: "openai-responses",
backend: "hwlab-cloud-api/codex-app-server-stdio",
fallbackBackend: "hwlab-cloud-api/openai-responses",
model: "gpt-5.5",
requiredEnv: Object.freeze([
"OPENAI_API_KEY",
"HWLAB_CODE_AGENT_OPENAI_BASE_URL"
]),
secretRefs: Object.freeze([
Object.freeze({
env: "OPENAI_API_KEY",
secretName: "hwlab-code-agent-provider",
secretKey: "openai-api-key"
})
]),
egress: Object.freeze({
env: "HWLAB_CODE_AGENT_OPENAI_BASE_URL",
target: "dev-egress-proxy",
defaultBaseUrl: "http://172.26.26.227:17680/v1/responses",
forbiddenDirectBaseUrl: "https://api.openai.com/v1/responses",
reason: "DEV cloud-api pods must use the D601 egress/proxy path for OpenAI Responses."
}),
codexHome: Object.freeze({
path: "/codex-home",
configMapName: "hwlab-code-agent-codex-config",
configKey: "config.toml",
secretName: "hwlab-code-agent-codex-auth",
authKey: "auth.json",
mountContract: "writable emptyDir CODEX_HOME with read-only config.toml/auth.json file mounts"
}),
noProxyRequired: Object.freeze([
"hyueapi.com",
".hyueapi.com",
"hyui.com",
".hyui.com",
"127.0.0.1",
"localhost",
"::1",
"api.minimaxi.com",
".minimaxi.com"
]),
forbidden: Object.freeze({
prodAllowed: false,
secretPlaintextAllowed: false,
directPublicOpenAiFromDevPod: false
})
});
export function codeAgentSecretRefPlaceholder() {
const ref = DEV_CODE_AGENT_PROVIDER_CONTRACT.secretRefs[0];
return `secretRef:${ref.secretName}/${ref.secretKey}`;
}
export function inspectCodeAgentProviderManifestRefs({ deployEnv = {}, workloadEnv = {} } = {}) {
const contract = DEV_CODE_AGENT_PROVIDER_CONTRACT;
const secretRef = contract.secretRefs[0];
const expectedSecretRef = codeAgentSecretRefPlaceholder();
const requiredRuntimeEnv = codeAgentRequiredRuntimeEnv();
const expectedValues = {
HWLAB_CODE_AGENT_PROVIDER: contract.codeAgentProvider,
HWLAB_CODE_AGENT_MODEL: contract.model,
[contract.egress.env]: contract.egress.defaultBaseUrl,
CODEX_HOME: contract.codexHome.path,
NO_PROXY: contract.noProxyRequired.join(","),
no_proxy: contract.noProxyRequired.join(","),
[secretRef.env]: expectedSecretRef
};
const workloadInspection = inspectCodeAgentProviderWorkloadEnv(workloadEnv);
const missingDeployEnv = requiredRuntimeEnv.filter((name) => !Object.hasOwn(deployEnv ?? {}, name));
const deployMismatches = requiredRuntimeEnv
.filter((name) => Object.hasOwn(deployEnv ?? {}, name) && !Object.is(deployEnv[name], expectedValues[name]))
.map((name) => ({
name,
expected: name === secretRef.env ? expectedSecretRef : expectedValues[name],
redacted: name === secretRef.env || name === contract.egress.env
}));
const missingSecretRefs = [];
if (deployEnv?.[secretRef.env] !== expectedSecretRef || workloadInspection.secretRef.present !== true) {
missingSecretRefs.push(`${secretRef.secretName}/${secretRef.secretKey}`);
}
const missingEgressContract = [];
if (deployEnv?.[contract.egress.env] !== contract.egress.defaultBaseUrl || workloadInspection.egress.matchesDevProxy !== true) {
missingEgressContract.push(`${contract.egress.env} must use ${contract.egress.target}`);
}
if (
isForbiddenDirectOpenAiBaseUrl(deployEnv?.[contract.egress.env]) ||
workloadInspection.egress.directPublicOpenAi === true
) {
missingEgressContract.push(`${contract.egress.env} must not point directly at public api.openai.com`);
}
const missingCodexHomeContract = [];
if (deployEnv?.CODEX_HOME !== contract.codexHome.path || workloadInspection.codexHome.present !== true) {
missingCodexHomeContract.push(`CODEX_HOME must be ${contract.codexHome.path}`);
}
if (workloadInspection.codexHome.configMapPresent !== true) {
missingCodexHomeContract.push(`${contract.codexHome.configMapName}/${contract.codexHome.configKey}`);
}
if (workloadInspection.codexHome.authSecretPresent !== true) {
missingCodexHomeContract.push(`${contract.codexHome.secretName}/${contract.codexHome.authKey}`);
}
const missingNoProxyContract = [...new Set([
...noProxyMissing(deployEnv?.NO_PROXY, contract.noProxyRequired),
...noProxyMissing(deployEnv?.no_proxy, contract.noProxyRequired),
...workloadInspection.noProxy.missing
])];
const ready =
missingDeployEnv.length === 0 &&
deployMismatches.length === 0 &&
workloadInspection.ready === true &&
missingSecretRefs.length === 0 &&
missingEgressContract.length === 0 &&
missingCodexHomeContract.length === 0 &&
missingNoProxyContract.length === 0;
return {
contractVersion: contract.contractVersion,
environment: contract.environment,
provider: contract.codeAgentProvider,
runtimeProvider: contract.runtimeProvider,
backend: contract.backend,
model: contract.model,
status: ready ? "pass" : "blocked",
ready,
requiredEnv: requiredRuntimeEnv.map((name) => ({
name,
deployPresent: Object.hasOwn(deployEnv ?? {}, name),
workloadPresent: workloadInspection.requiredEnv.find((entry) => entry.name === name)?.present === true,
redacted: name === secretRef.env || name === contract.egress.env,
source: name === secretRef.env ? "k8s-secret-ref" : "runtime-env"
})),
secretRef: {
env: secretRef.env,
secretName: secretRef.secretName,
secretKey: secretRef.secretKey,
deployPlaceholderPresent: deployEnv?.[secretRef.env] === expectedSecretRef,
workloadSecretRefPresent: workloadInspection.secretRef.present === true,
present: deployEnv?.[secretRef.env] === expectedSecretRef && workloadInspection.secretRef.present === true,
redacted: true
},
egress: {
env: contract.egress.env,
target: contract.egress.target,
deployPresent: Boolean(deployEnv?.[contract.egress.env]),
workloadPresent: workloadInspection.egress.present,
deployMatchesDevProxy: deployEnv?.[contract.egress.env] === contract.egress.defaultBaseUrl,
workloadMatchesDevProxy: workloadInspection.egress.matchesDevProxy,
directPublicOpenAi:
isForbiddenDirectOpenAiBaseUrl(deployEnv?.[contract.egress.env]) ||
workloadInspection.egress.directPublicOpenAi === true,
valueRedacted: true
},
missingDeployEnv,
missingWorkloadEnv: workloadInspection.missingEnv,
deployMismatches,
workloadMismatches: workloadInspection.mismatchedEnv,
missingSecretRefs,
missingEgressContract,
missingCodexHomeContract,
missingNoProxyContract,
codexHome: workloadInspection.codexHome,
noProxy: workloadInspection.noProxy,
secretMaterialRead: false,
valuesRedacted: true,
providerConnected: false,
fixtureEvidence: false
};
}
export function inspectCodeAgentProviderWorkloadEnv(workloadEnv = {}) {
const contract = DEV_CODE_AGENT_PROVIDER_CONTRACT;
const secretRef = contract.secretRefs[0];
const requiredRuntimeEnv = codeAgentRequiredRuntimeEnv();
const expectedValues = {
HWLAB_CODE_AGENT_PROVIDER: contract.codeAgentProvider,
HWLAB_CODE_AGENT_MODEL: contract.model,
[contract.egress.env]: contract.egress.defaultBaseUrl,
CODEX_HOME: contract.codexHome.path,
NO_PROXY: contract.noProxyRequired.join(","),
no_proxy: contract.noProxyRequired.join(",")
};
const requiredEnv = requiredRuntimeEnv.map((name) => {
const entry = getEnvEntry(workloadEnv, name);
return {
name,
present: Boolean(entry),
redacted: name === secretRef.env || name === contract.egress.env,
source: name === secretRef.env ? "k8s-secret-ref" : "runtime-env"
};
});
const missingEnv = requiredEnv.filter((entry) => !entry.present).map((entry) => entry.name);
const mismatchedEnv = [];
for (const [name, expected] of Object.entries(expectedValues)) {
const entry = getEnvEntry(workloadEnv, name);
if (entry && !Object.is(envEntryValue(entry), expected)) {
mismatchedEnv.push({
name,
expected,
redacted: name === contract.egress.env
});
}
}
const secretKeyRef = envEntrySecretKeyRef(getEnvEntry(workloadEnv, secretRef.env));
const secretPresent =
secretKeyRef?.name === secretRef.secretName &&
secretKeyRef?.key === secretRef.secretKey;
const baseUrl = envEntryValue(getEnvEntry(workloadEnv, contract.egress.env));
const directPublicOpenAi = isForbiddenDirectOpenAiBaseUrl(baseUrl);
const matchesDevProxy = baseUrl === contract.egress.defaultBaseUrl;
const codexHomePresent = envEntryValue(getEnvEntry(workloadEnv, "CODEX_HOME")) === contract.codexHome.path;
const noProxyMissingEntries = [...new Set([
...noProxyMissing(envEntryValue(getEnvEntry(workloadEnv, "NO_PROXY")), contract.noProxyRequired),
...noProxyMissing(envEntryValue(getEnvEntry(workloadEnv, "no_proxy")), contract.noProxyRequired)
])];
const codexHome = inspectCodexHomeWorkloadMounts(workloadEnv);
const ready =
missingEnv.length === 0 &&
mismatchedEnv.length === 0 &&
secretPresent &&
matchesDevProxy &&
!directPublicOpenAi &&
codexHome.present === true &&
codexHome.configMapPresent === true &&
codexHome.authSecretPresent === true &&
noProxyMissingEntries.length === 0;
return {
contractVersion: contract.contractVersion,
environment: contract.environment,
provider: contract.codeAgentProvider,
runtimeProvider: contract.runtimeProvider,
backend: contract.backend,
model: contract.model,
status: ready ? "pass" : "blocked",
ready,
requiredEnv,
missingEnv,
mismatchedEnv,
secretRef: {
env: secretRef.env,
secretName: secretRef.secretName,
secretKey: secretRef.secretKey,
present: secretPresent,
redacted: true
},
egress: {
env: contract.egress.env,
target: contract.egress.target,
present: Boolean(baseUrl),
matchesDevProxy,
directPublicOpenAi,
valueRedacted: true
},
codexHome: {
...codexHome,
present: codexHomePresent && codexHome.present === true
},
noProxy: {
required: [...contract.noProxyRequired],
missing: noProxyMissingEntries,
present: noProxyMissingEntries.length === 0
},
secretMaterialRead: false,
valuesRedacted: true,
providerConnected: false
};
}
export function buildCodeAgentProviderManifestPlaceholder() {
const contract = DEV_CODE_AGENT_PROVIDER_CONTRACT;
return {
contractVersion: contract.contractVersion,
environment: contract.environment,
provider: contract.codeAgentProvider,
runtimeProvider: contract.runtimeProvider,
backend: contract.backend,
model: contract.model,
requiredEnv: [...contract.requiredEnv],
secretRefs: contract.secretRefs.map((item) => ({ ...item })),
egress: { ...contract.egress },
codexHome: { ...contract.codexHome },
noProxyRequired: [...contract.noProxyRequired],
fixtureEvidence: {
providerConnected: false,
summary: "This manifest contract records provider env names, Secret/ConfigMap reference names, DEV egress policy, and Codex app-server mount policy only. It is not live provider evidence."
}
};
}
export function inspectCodeAgentProviderEnv(env = {}) {
const contract = DEV_CODE_AGENT_PROVIDER_CONTRACT;
const missingEnv = contract.requiredEnv.filter((name) => !hasEnvValue(env, name));
const secretRef = contract.secretRefs[0];
const baseUrl = firstNonEmpty(env.HWLAB_CODE_AGENT_OPENAI_BASE_URL);
const directPublicOpenAi =
baseUrl === contract.egress.forbiddenDirectBaseUrl ||
/^https:\/\/api\.openai\.com\/v1\/responses\/?$/u.test(baseUrl);
const egressReady = Boolean(baseUrl) && !directPublicOpenAi;
const noProxyReady = noProxyMissing(env.NO_PROXY, contract.noProxyRequired).length === 0 &&
noProxyMissing(env.no_proxy, contract.noProxyRequired).length === 0;
const codexHomeReady = firstNonEmpty(env.CODEX_HOME) === contract.codexHome.path;
const ready = missingEnv.length === 0 && egressReady && codexHomeReady && noProxyReady;
return {
contractVersion: contract.contractVersion,
environment: contract.environment,
provider: contract.runtimeProvider,
model: firstNonEmpty(env.HWLAB_CODE_AGENT_MODEL, contract.model),
backend: contract.backend,
status: ready ? "available" : "blocked",
ready,
requiredEnv: contract.requiredEnv.map((name) => ({
name,
present: hasEnvValue(env, name),
redacted: name === secretRef.env,
source: name === secretRef.env ? "k8s-secret-ref" : "runtime-env"
})),
missingEnv,
secretRefs: [
{
env: secretRef.env,
secretName: secretRef.secretName,
secretKey: secretRef.secretKey,
present: hasEnvValue(env, secretRef.env),
envInjected: hasEnvValue(env, secretRef.env),
secretPresent: "not_observed_by_runtime",
secretKeyPresent: "not_observed_by_runtime",
redacted: true
}
],
egress: {
env: contract.egress.env,
present: hasEnvValue(env, contract.egress.env),
target: contract.egress.target,
baseUrlConfigured: Boolean(baseUrl),
directPublicOpenAi,
ready: egressReady,
valueRedacted: true
},
codexHome: {
path: contract.codexHome.path,
present: codexHomeReady,
configRef: `${contract.codexHome.configMapName}/${contract.codexHome.configKey}`,
authRef: `${contract.codexHome.secretName}/${contract.codexHome.authKey}`,
secretMaterialRead: false,
valuesRedacted: true
},
noProxy: {
required: [...contract.noProxyRequired],
missing: [...new Set([
...noProxyMissing(env.NO_PROXY, contract.noProxyRequired),
...noProxyMissing(env.no_proxy, contract.noProxyRequired)
])],
present: noProxyReady
},
safety: {
devOnly: true,
prodAllowed: contract.forbidden.prodAllowed,
secretsRead: false,
secretMaterialRead: false,
valuesRedacted: true,
directPublicOpenAiFromDevPod: directPublicOpenAi
},
blocker: ready ? null : codeAgentProviderBlocker({ missingEnv, directPublicOpenAi, baseUrl })
};
}
function codeAgentProviderBlocker({ missingEnv, directPublicOpenAi, baseUrl }) {
if (directPublicOpenAi) {
return "DEV Code Agent OpenAI base URL points at public api.openai.com instead of the DEV egress/proxy path";
}
if (!baseUrl) {
return "DEV Code Agent OpenAI base URL is missing; provider calls must use the DEV egress/proxy path";
}
return `Code Agent provider runtime config is missing ${missingEnv.join(", ")}`;
}
function hasEnvValue(env, name) {
return typeof env?.[name] === "string" && env[name].trim().length > 0;
}
function firstNonEmpty(...values) {
for (const value of values) {
if (typeof value === "string" && value.trim()) return value.trim();
}
return "";
}
function codeAgentRequiredRuntimeEnv() {
return [
"HWLAB_CODE_AGENT_PROVIDER",
"HWLAB_CODE_AGENT_MODEL",
...DEV_CODE_AGENT_PROVIDER_CONTRACT.requiredEnv
];
}
function getEnvEntry(env, name) {
if (!env) return undefined;
if (env instanceof Map) return env.get(name);
if (Array.isArray(env)) return env.find((entry) => entry?.name === name);
return env[name];
}
function envEntryValue(entry) {
if (typeof entry === "string") return entry;
if (entry && typeof entry === "object" && Object.hasOwn(entry, "value")) return entry.value;
return undefined;
}
function envEntrySecretKeyRef(entry) {
if (!entry || typeof entry !== "object") return null;
return entry.valueFrom?.secretKeyRef ?? null;
}
function inspectCodexHomeWorkloadMounts(workloadEnv = {}) {
const contract = DEV_CODE_AGENT_PROVIDER_CONTRACT;
const volumeMounts = Array.isArray(workloadEnv.__volumeMounts) ? workloadEnv.__volumeMounts : [];
const volumes = Array.isArray(workloadEnv.__volumes) ? workloadEnv.__volumes : [];
const homeMount = volumeMounts.find((entry) => entry?.name === "hwlab-code-agent-codex-home" && entry?.mountPath === contract.codexHome.path);
const configMount = volumeMounts.find((entry) =>
entry?.name === "hwlab-code-agent-codex-config" &&
entry?.mountPath === `${contract.codexHome.path}/${contract.codexHome.configKey}` &&
entry?.subPath === contract.codexHome.configKey &&
entry?.readOnly === true
);
const authMount = volumeMounts.find((entry) =>
entry?.name === "hwlab-code-agent-codex-auth" &&
entry?.mountPath === `${contract.codexHome.path}/${contract.codexHome.authKey}` &&
entry?.subPath === contract.codexHome.authKey &&
entry?.readOnly === true
);
const configVolume = volumes.find((entry) =>
entry?.name === "hwlab-code-agent-codex-config" &&
entry?.configMap?.name === contract.codexHome.configMapName &&
(entry.configMap.items ?? []).some((item) => item?.key === contract.codexHome.configKey && item?.path === contract.codexHome.configKey)
);
const authVolume = volumes.find((entry) =>
entry?.name === "hwlab-code-agent-codex-auth" &&
entry?.secret?.secretName === contract.codexHome.secretName &&
(entry.secret.items ?? []).some((item) => item?.key === contract.codexHome.authKey && item?.path === contract.codexHome.authKey)
);
return {
path: contract.codexHome.path,
present: Boolean(homeMount),
writableHomeMountPresent: Boolean(homeMount),
configMapPresent: Boolean(configMount && configVolume),
authSecretPresent: Boolean(authMount && authVolume),
configMapName: contract.codexHome.configMapName,
secretName: contract.codexHome.secretName,
mountContract: contract.codexHome.mountContract,
secretMaterialRead: false,
valuesRedacted: true
};
}
function noProxyMissing(value, required) {
const entries = new Set(String(value ?? "")
.split(/[,;\s]+/u)
.map((item) => item.trim().toLowerCase())
.filter(Boolean));
return required.filter((item) => !entries.has(String(item).toLowerCase()));
}
function isForbiddenDirectOpenAiBaseUrl(value) {
const baseUrl = firstNonEmpty(value);
return (
baseUrl === DEV_CODE_AGENT_PROVIDER_CONTRACT.egress.forbiddenDirectBaseUrl ||
/^https:\/\/api\.openai\.com\/v1\/responses\/?$/u.test(baseUrl)
);
}