Files
pikasTech-HWLAB/scripts/src/code-agent-response-contract.mjs
T
2026-05-23 03:57:09 +00:00

304 lines
11 KiB
JavaScript

const trustedLiveProviders = new Set(["openai-responses", "codex-cli"]);
const untrustedProviderPattern = /\b(?:echo|mock|fixture|stub|sample)\b/iu;
const blockedCodeAgentUiLabels = new Set(["发送失败", "服务受阻", "BLOCKED 凭证缺口"]);
export function classifyCodeAgentChatReadiness(payload, { realDevLive = false, httpStatus = null } = {}) {
const providerBlock = classifyCodeAgentProviderBlock(payload, { httpStatus });
if (providerBlock.blocked) {
return {
status: "blocked",
level: providerBlock.level,
blocker: providerBlock.blocker,
devLiveReplyPass: false,
reason: providerBlock.reason,
...(providerBlock.providerStatus != null ? { providerStatus: providerBlock.providerStatus } : {})
};
}
const assistantReply = typeof payload?.reply?.content === "string" ? payload.reply.content.trim() : "";
if (payload?.status === "completed" && assistantReply) {
const evidence = inspectRealCompletionEvidence(payload);
if (!evidence.ok) {
return {
status: "blocked",
level: realDevLive ? "BLOCKED/untrusted-completion" : "SOURCE",
blocker: "untrusted-completion",
devLiveReplyPass: false,
reason: `completed response is missing real provider/model/trace/conversation evidence or looks like echo/mock/stub: ${evidence.reason}`
};
}
if (realDevLive) {
return {
status: "pass",
level: "#143 DEV-LIVE reply pass",
blocker: null,
devLiveReplyPass: true,
reason: "real DEV /v1/agent/chat completed with a non-empty assistant reply"
};
}
return {
status: "blocked",
level: "SOURCE",
blocker: "not-dev-live",
devLiveReplyPass: false,
reason: "mock, fixture, local stub, or source-only completion cannot be counted as #143 DEV-LIVE reply pass"
};
}
const suffix = httpStatus ? ` (HTTP ${httpStatus})` : "";
return {
status: "blocked",
level: "BLOCKED",
blocker: "runtime",
devLiveReplyPass: false,
reason: `Code Agent chat did not produce a completed non-empty assistant reply${suffix}`
};
}
export function classifyCodeAgentProviderBlock(payload, { httpStatus = null } = {}) {
const payloadStatus = stringOrNull(payload?.status);
const errorCode = stringOrNull(payload?.error?.code);
const availabilityStatus = stringOrNull(payload?.availability?.status);
const missingEnv = Array.isArray(payload?.error?.missingEnv)
? payload.error.missingEnv.filter((item) => typeof item === "string")
: [];
const providerStatus = numericStatus(payload?.error?.providerStatus);
const responseStatus = numericStatus(httpStatus);
const providerHttpBlocked = isHttpNon2xxStatus(providerStatus);
const responseHttpBlocked = isHttpNon2xxStatus(responseStatus);
const httpBlocked = providerHttpBlocked || responseHttpBlocked;
const blockingHttpStatus = providerHttpBlocked ? providerStatus : responseHttpBlocked ? responseStatus : providerStatus ?? responseStatus;
const providerUnavailable =
errorCode === "provider_unavailable" ||
availabilityStatus === "blocked" ||
payloadStatus === "blocked" ||
httpBlocked;
if (!providerUnavailable) {
return { blocked: false };
}
if (httpBlocked) {
return {
blocked: true,
level: "BLOCKED/provider",
blocker: "provider-upstream",
providerStatus: blockingHttpStatus,
missingEnv,
reason: `Code Agent HTTP non-2xx status ${blockingHttpStatus} means the upstream response is blocked, not completed`
};
}
if (missingEnv.includes("OPENAI_API_KEY")) {
return {
blocked: true,
level: "BLOCKED/credential",
blocker: "credential",
providerStatus: blockingHttpStatus,
missingEnv,
reason: "provider_unavailable with missing OPENAI_API_KEY means the provider credential contract is incomplete"
};
}
if (missingEnv.includes("HWLAB_CODE_AGENT_OPENAI_BASE_URL")) {
return {
blocked: true,
level: "BLOCKED/provider-config",
blocker: "provider-config",
providerStatus: blockingHttpStatus,
missingEnv,
reason: "provider_unavailable with missing HWLAB_CODE_AGENT_OPENAI_BASE_URL means the provider egress/base-url contract is incomplete"
};
}
return {
blocked: true,
level: "BLOCKED/provider",
blocker: "provider-unavailable",
providerStatus: blockingHttpStatus,
missingEnv,
reason: "provider_unavailable or availability.status=blocked means the provider path is blocked, not completed"
};
}
export function summarizeCodeAgentPayload(payload, { httpStatus = null, traceId = null } = {}) {
const providerBlock = classifyCodeAgentProviderBlock(payload, { httpStatus });
const hasObjectPayload = payload && typeof payload === "object" && !Array.isArray(payload);
if (!hasObjectPayload) {
if (!providerBlock.blocked) return null;
return {
status: "failed",
sourceKind: null,
evidenceLevel: null,
provider: "unknown",
model: "unknown",
backend: "unknown",
traceId: traceId || "unknown",
hasReply: false,
error: {
code: "provider_unavailable",
missingEnv: [],
missingCommands: [],
providerStatus: providerBlock.providerStatus
}
};
}
const error = normalizeCodeAgentError(payload.error);
const assistantReply = typeof payload.reply?.content === "string" ? payload.reply.content.trim() : "";
const provider = stringOrNull(payload.provider) ?? (providerBlock.blocked ? "unknown" : null);
const model = stringOrNull(payload.model) ?? (providerBlock.blocked ? "unknown" : null);
const backend = stringOrNull(payload.backend) ?? (providerBlock.blocked ? "unknown" : null);
const observedTraceId = stringOrNull(payload.traceId) ?? traceId ?? (providerBlock.blocked ? "unknown" : null);
if (providerBlock.blocked) {
const blockedError = error
? {
...error,
code: error.code ?? "provider_unavailable",
providerStatus: error.providerStatus ?? providerBlock.providerStatus
}
: {
code: "provider_unavailable",
missingEnv: providerBlock.missingEnv ?? [],
missingCommands: [],
providerStatus: providerBlock.providerStatus
};
return {
status: "failed",
sourceKind: stringOrNull(payload.sourceKind),
evidenceLevel: stringOrNull(payload.evidenceLevel),
provider,
model,
backend,
traceId: observedTraceId,
hasReply: false,
error: blockedError
};
}
return {
status: stringOrNull(payload.status),
sourceKind: stringOrNull(payload.sourceKind),
evidenceLevel: stringOrNull(payload.evidenceLevel),
provider,
model,
backend,
traceId: observedTraceId,
hasReply: assistantReply.length > 0,
error
};
}
export function classifyCodeAgentBrowserJourney({ responseSummary, httpOk = false, httpStatus = null, ui = null } = {}) {
const providerBlock = classifyCodeAgentProviderBlock(responseSummary, { httpStatus });
const uiCompleted = ui?.agentChatStatus === "DEV-LIVE 回复" || ui?.agentChatStatus === "已回复" || ui?.completedMessageVisible === true;
const uiFailed = ui?.failedMessageVisible === true || blockedCodeAgentUiLabels.has(ui?.agentChatStatus);
const evidence = inspectSanitizedCompletionEvidence(responseSummary);
const backendCompleted =
httpOk &&
responseSummary?.status === "completed" &&
responseSummary?.hasReply === true &&
responseSummary.error === null &&
evidence.ok;
if (backendCompleted && uiCompleted && !uiFailed) {
return {
status: "pass",
blocker: null,
reason: "completed Code Agent payload over HTTP 2xx with real provider/backend/model/trace/reply evidence and completed UI state"
};
}
if (providerBlock.blocked) {
return {
status: "blocked",
blocker: providerBlock.blocker,
reason: providerBlock.reason,
...(providerBlock.providerStatus != null ? { providerStatus: providerBlock.providerStatus } : {})
};
}
if (responseSummary?.status === "completed") {
return {
status: "blocked",
blocker: "untrusted-completion",
reason: `Code Agent completed-looking payload was not paired with HTTP success, completed UI, and real provider evidence: ${evidence.reason}`
};
}
return {
status: "blocked",
blocker: "runtime",
reason: "Code Agent browser journey did not produce a completed non-error response"
};
}
export function inspectRealCompletionEvidence(payload) {
const provider = String(payload?.provider ?? "").trim().toLowerCase();
const backend = String(payload?.backend ?? "").trim().toLowerCase();
const missing = [];
if (!payload?.conversationId && !payload?.sessionId) missing.push("conversationId");
if (!payload?.traceId) missing.push("traceId");
if (!payload?.messageId) missing.push("messageId");
if (!payload?.provider) missing.push("provider");
if (!payload?.model) missing.push("model");
if (!payload?.backend) missing.push("backend");
if (missing.length > 0) {
return { ok: false, reason: `missing ${missing.join(",")}` };
}
if (!trustedLiveProviders.has(provider)) {
return { ok: false, reason: `provider ${payload.provider} is not an accepted real provider` };
}
if (untrustedProviderPattern.test(`${provider} ${backend}`)) {
return { ok: false, reason: `provider/backend looks non-real: ${payload.provider}/${payload.backend}` };
}
return { ok: true, reason: "provider/model/trace/conversation evidence present" };
}
export function normalizeCodeAgentError(error) {
if (!error || typeof error !== "object") return null;
return {
code: stringOrNull(error.code),
missingEnv: Array.isArray(error.missingEnv) ? error.missingEnv.filter((item) => typeof item === "string") : [],
missingCommands: Array.isArray(error.missingCommands) ? error.missingCommands.filter((item) => typeof item === "string") : [],
providerStatus: numericStatus(error.providerStatus)
};
}
export function isHttpNon2xxStatus(value) {
const status = numericStatus(value);
return status !== null && (status < 200 || status > 299);
}
function inspectSanitizedCompletionEvidence(summary) {
const provider = String(summary?.provider ?? "").trim().toLowerCase();
const backend = String(summary?.backend ?? "").trim().toLowerCase();
const missing = [];
if (!summary?.provider) missing.push("provider");
if (!summary?.model) missing.push("model");
if (!summary?.backend) missing.push("backend");
if (!summary?.traceId) missing.push("traceId");
if (summary?.hasReply !== true) missing.push("reply");
if (missing.length > 0) {
return { ok: false, reason: `missing ${missing.join(",")}` };
}
if (!trustedLiveProviders.has(provider)) {
return { ok: false, reason: `provider ${summary.provider} is not an accepted real provider` };
}
if (untrustedProviderPattern.test(`${provider} ${backend}`)) {
return { ok: false, reason: `provider/backend looks non-real: ${summary.provider}/${summary.backend}` };
}
return { ok: true, reason: "real provider/backend/model/trace/reply evidence present" };
}
function stringOrNull(value) {
return typeof value === "string" && value.trim().length > 0 ? value.trim() : null;
}
function numericStatus(value) {
if (typeof value !== "number" || !Number.isInteger(value)) return null;
return value;
}