fix: 修复 Code Queue PR preflight fallback
This commit is contained in:
+231
-69
@@ -6869,38 +6869,49 @@ function compactPrPreflightCommanderView(record: Record<string, unknown>, option
|
||||
const prCreateDryRun = asRecord(capability?.prCreateDryRun);
|
||||
const unsupportedMergeBoundary = asRecord(capability?.unsupportedMergeBoundary);
|
||||
const commands = prPreflightCommandSet(record, options);
|
||||
const schedulerAuthObserved = tokenCoverage !== null;
|
||||
const schedulerAuthReady = tokenCoverage?.ok === true;
|
||||
const activeRunnerTokenCandidatePresent = activeRunnerDevContainer.ok === true;
|
||||
const failureKind = record.failureKind ?? (schedulerAuthReady ? null : "auth-missing");
|
||||
const degradedReason = record.degradedReason ?? (schedulerAuthReady ? null : "auth-broker-needed");
|
||||
const blockingDisposition = record.blockingDisposition ?? (failureKind === "runner-skills-blocker" ? "runner-capability-degraded" : undefined);
|
||||
const githubTransient = asRecord(record.githubTransient);
|
||||
const transportObservation = asRecord(record.transportObservation);
|
||||
const runtimeObservation = asRecord(record.runtimeObservation);
|
||||
const runtimePreflightObserved = runtimeObservation?.observed === true || record.preflight !== undefined;
|
||||
|
||||
return {
|
||||
ok: record.ok === true,
|
||||
runnerDisposition: record.runnerDisposition ?? (record.ok === true ? "ready" : "infra-blocked"),
|
||||
failureKind,
|
||||
degradedReason,
|
||||
...(blockingDisposition === undefined ? {} : { blockingDisposition }),
|
||||
...(typeof record.message === "string" ? { message: record.message } : {}),
|
||||
...(record.retryable === true ? { retryable: true } : {}),
|
||||
...(typeof record.commanderAction === "string" ? { commanderAction: record.commanderAction } : {}),
|
||||
...(githubTransient === null ? {} : { githubTransient }),
|
||||
summary: {
|
||||
status: record.ok === true ? "ready" : "blocked",
|
||||
schedulerPreflightAuthReady: schedulerAuthReady,
|
||||
status: record.ok === true ? "ready" : failureKind === "runner-skills-blocker" ? "runner-capability-degraded" : "blocked",
|
||||
transportState: transportObservation?.state ?? "primary-ok",
|
||||
runtimePreflightState: runtimeObservation?.state ?? (record.preflight === undefined ? "runtime-preflight-unobserved" : "runtime-preflight-observed"),
|
||||
schedulerPreflightAuthReady: schedulerAuthObserved ? schedulerAuthReady : null,
|
||||
schedulerPreflightScope: tokenCoverage?.scope ?? "scheduler-runner-env",
|
||||
activeRunnerTokenCandidatePresent,
|
||||
activeRunnerScope: activeRunnerDevContainer.scope ?? "current-cli-process",
|
||||
interpretation: schedulerAuthReady
|
||||
interpretation: !runtimePreflightObserved
|
||||
? "runtime preflight was not observed; do not infer scheduler auth or active runner PR capability from this transport failure"
|
||||
: schedulerAuthReady
|
||||
? "scheduler preflight auth is ready; still use active-runner dry-runs before writes"
|
||||
: "scheduler auth is missing for preflight admission only; this does not prove the active runner/dev container cannot create or comment PRs",
|
||||
},
|
||||
schedulerPreflight: {
|
||||
scope: tokenCoverage?.scope ?? "scheduler-runner-env",
|
||||
authReady: schedulerAuthReady,
|
||||
authReady: schedulerAuthObserved ? schedulerAuthReady : null,
|
||||
authSource: tokenCoverage?.source ?? null,
|
||||
credentialSource: tokenCoverage?.credentialSource ?? null,
|
||||
missing: Array.isArray(tokenCoverage?.missing) ? tokenCoverage.missing.map(String) : [],
|
||||
failureKind: schedulerAuthReady ? null : failureKind,
|
||||
degradedReason: schedulerAuthReady ? null : degradedReason,
|
||||
missing: schedulerAuthObserved && Array.isArray(tokenCoverage?.missing) ? tokenCoverage.missing.map(String) : [],
|
||||
failureKind: schedulerAuthObserved ? schedulerAuthReady ? null : failureKind : null,
|
||||
degradedReason: schedulerAuthObserved ? schedulerAuthReady ? null : degradedReason : null,
|
||||
authBroker: authBroker === null ? null : {
|
||||
ok: authBroker.ok ?? schedulerAuthReady,
|
||||
source: authBroker.source ?? null,
|
||||
@@ -6947,6 +6958,8 @@ function compactPrPreflightCommanderView(record: Record<string, unknown>, option
|
||||
recommendedActions: compactRecommendedActions(record),
|
||||
upstream: record.upstream ?? null,
|
||||
controlPlane: record.controlPlane ?? null,
|
||||
transportObservation: transportObservation ?? undefined,
|
||||
runtimeObservation: runtimeObservation ?? undefined,
|
||||
observationGap: record.observationGap ?? undefined,
|
||||
localObservationGap: record.localObservationGap ?? undefined,
|
||||
localObservationSummary: record.localObservationSummary ?? undefined,
|
||||
@@ -7064,6 +7077,188 @@ function maybeFullPrPreflightObservations(options: CodexPrPreflightOptions, loca
|
||||
};
|
||||
}
|
||||
|
||||
function prPreflightRuntimeProxyPath(options: CodexPrPreflightOptions, includeRemote: boolean): string {
|
||||
return codeQueueProxyPath(`/api/runtime-preflight${queryString({
|
||||
remote: includeRemote ? 1 : undefined,
|
||||
pushDryRun: options.pushDryRun ? 1 : undefined,
|
||||
pushDryRunRef: options.pushDryRunRef,
|
||||
prCreateDryRun: options.prCreateDryRun ? 1 : undefined,
|
||||
prCreateDryRunHead: options.prCreateDryRunHead,
|
||||
issue: options.issueNumber,
|
||||
})}`);
|
||||
}
|
||||
|
||||
function runtimePreflightFromResponse(response: unknown): { response: Record<string, unknown>; body: Record<string, unknown>; preflight: Record<string, unknown> } | null {
|
||||
const record = asRecord(response);
|
||||
const body = asRecord(record?.body);
|
||||
const preflight = asRecord(body?.runtimePreflight);
|
||||
if (record?.ok !== true || preflight === null) return null;
|
||||
return { response: record, body: body ?? {}, preflight };
|
||||
}
|
||||
|
||||
function compactTransportErrorText(record: Record<string, unknown> | null, body: Record<string, unknown> | null): string {
|
||||
const candidates = [
|
||||
body?.error,
|
||||
body?.providerError,
|
||||
body?.message,
|
||||
record?.message,
|
||||
record?.commandStderrTail,
|
||||
record?.stderrTail,
|
||||
record?.stdoutTail,
|
||||
];
|
||||
return candidates.find((item): item is string => typeof item === "string" && item.length > 0) ?? "";
|
||||
}
|
||||
|
||||
function compactPrPreflightTransportResponse(path: string, response: unknown): Record<string, unknown> {
|
||||
const record = asRecord(response);
|
||||
const body = responseBody(record);
|
||||
const detail = asRecord(body?.detail) ?? asRecord(body?.details);
|
||||
const text = compactTransportErrorText(record, body);
|
||||
return {
|
||||
path,
|
||||
ok: record?.ok === true,
|
||||
status: responseStatus(record),
|
||||
bodyOk: body?.ok ?? null,
|
||||
stage: typeof body?.stage === "string" ? body.stage : null,
|
||||
serviceId: typeof body?.serviceId === "string" ? body.serviceId : typeof body?.service === "string" ? body.service : null,
|
||||
providerId: typeof body?.providerId === "string" ? body.providerId : null,
|
||||
requestId: typeof body?.requestId === "string" ? body.requestId : null,
|
||||
retryable: body?.retryable ?? detail?.retryable ?? null,
|
||||
runtimePreflightPresent: asRecord(body?.runtimePreflight) !== null,
|
||||
errorPreview: text.length === 0 ? null : compactInlinePreview(text, 240),
|
||||
};
|
||||
}
|
||||
|
||||
function prPreflightRuntimeTransportDegraded(response: unknown): boolean {
|
||||
const record = asRecord(response);
|
||||
if (record?.ok === true) return false;
|
||||
const status = responseStatus(record);
|
||||
const body = responseBody(record);
|
||||
const text = [
|
||||
compactTransportErrorText(record, body),
|
||||
typeof body?.stage === "string" ? body.stage : "",
|
||||
typeof body?.serviceId === "string" ? body.serviceId : "",
|
||||
typeof body?.providerId === "string" ? body.providerId : "",
|
||||
].join(" ").toLowerCase();
|
||||
if (status === 504) return true;
|
||||
return (status === 502 || status === 503)
|
||||
&& /\b(?:http-tunnel-wait|tunnel|timed out|timeout|disconnected|provider|k3sctl-adapter)\b/u.test(text);
|
||||
}
|
||||
|
||||
function prPreflightTransportObservation(
|
||||
state: "transport-degraded" | "transport-blocked",
|
||||
primaryPath: string,
|
||||
primaryResponse: unknown,
|
||||
fallbackPath: string,
|
||||
fallbackResponse: unknown,
|
||||
fallbackUsed: boolean,
|
||||
): Record<string, unknown> {
|
||||
return {
|
||||
state,
|
||||
degraded: true,
|
||||
primary: compactPrPreflightTransportResponse(primaryPath, primaryResponse),
|
||||
fallback: compactPrPreflightTransportResponse(fallbackPath, fallbackResponse),
|
||||
fallbackAttempted: true,
|
||||
fallbackUsed,
|
||||
interpretation: fallbackUsed
|
||||
? "transport degraded on the remote runtime probe; runtime preflight was observed through the lightweight Code Queue runtime path"
|
||||
: "transport blocked on both runtime-preflight observation paths; runner PR capability was not observed",
|
||||
};
|
||||
}
|
||||
|
||||
function prPreflightRuntimeObservation(
|
||||
options: CodexPrPreflightOptions,
|
||||
preflight: Record<string, unknown> | null,
|
||||
source: "primary-runtime-preflight" | "fallback-runtime-preflight" | null,
|
||||
primaryPath: string,
|
||||
fallbackPath: string | null,
|
||||
): Record<string, unknown> {
|
||||
const pull = asRecord(preflight?.pullRequestDelivery);
|
||||
return {
|
||||
state: preflight === null ? "runtime-preflight-unobserved" : "runtime-preflight-observed",
|
||||
observed: preflight !== null,
|
||||
source,
|
||||
remoteProbesRequested: options.remote,
|
||||
remoteProbesObserved: asRecord(pull?.remote) !== null,
|
||||
primaryPath,
|
||||
fallbackPath,
|
||||
};
|
||||
}
|
||||
|
||||
function prPreflightObservedRuntimeResult(
|
||||
options: CodexPrPreflightOptions,
|
||||
response: Record<string, unknown>,
|
||||
preflight: Record<string, unknown>,
|
||||
controlPlaneMode: "local-backend-core" | "remote-frontend",
|
||||
runtimeSource: "primary-runtime-preflight" | "fallback-runtime-preflight",
|
||||
primaryPath: string,
|
||||
fallbackPath: string | null,
|
||||
transportObservation?: Record<string, unknown>,
|
||||
): Record<string, unknown> {
|
||||
const compact = compactPrRuntimePreflight(preflight, options);
|
||||
return compactPrPreflightCommanderView({
|
||||
ok: compact.ok,
|
||||
runnerDisposition: compact.runnerDisposition,
|
||||
blockingDisposition: compact.blockingDisposition,
|
||||
failureKind: compact.failureKind ?? null,
|
||||
degradedReason: compact.degradedReason ?? null,
|
||||
...(compact.retryable === true ? { retryable: true } : {}),
|
||||
...(typeof compact.commanderAction === "string" ? { commanderAction: compact.commanderAction } : {}),
|
||||
...(asRecord(compact.githubTransient) === null ? {} : { githubTransient: compact.githubTransient }),
|
||||
authScopeSummary: compact.authScopeSummary,
|
||||
scopeBoundary: compact.scopeBoundary,
|
||||
activeRunnerDevContainer: compact.activeRunnerDevContainer,
|
||||
recommendedActions: compact.recommendedActions,
|
||||
skillsContract: compact.skillsContract,
|
||||
upstream: { ok: response.ok, status: response.status },
|
||||
controlPlane: {
|
||||
mode: controlPlaneMode,
|
||||
localBackendCoreMissing: false,
|
||||
remoteFallbackUsed: false,
|
||||
transportFallbackUsed: transportObservation?.fallbackUsed === true,
|
||||
},
|
||||
...(transportObservation === undefined ? {} : { transportObservation }),
|
||||
runtimeObservation: prPreflightRuntimeObservation(options, preflight, runtimeSource, primaryPath, fallbackPath),
|
||||
preflight: compact,
|
||||
}, options);
|
||||
}
|
||||
|
||||
function prPreflightTransportBlockedResult(
|
||||
options: CodexPrPreflightOptions,
|
||||
controlPlaneMode: "local-backend-core" | "remote-frontend",
|
||||
primaryPath: string,
|
||||
primaryResponse: unknown,
|
||||
fallbackPath: string,
|
||||
fallbackResponse: unknown,
|
||||
): Record<string, unknown> {
|
||||
const transportObservation = prPreflightTransportObservation("transport-blocked", primaryPath, primaryResponse, fallbackPath, fallbackResponse, false);
|
||||
return compactPrPreflightCommanderView({
|
||||
ok: false,
|
||||
runnerDisposition: "infra-blocked",
|
||||
blockingDisposition: "control-plane-observation-gap",
|
||||
failureKind: "proxy-gap",
|
||||
degradedReason: "runtime-preflight-transport-unavailable",
|
||||
message: "Code Queue runtime preflight could not be observed through either the remote probe path or the lightweight runtime fallback",
|
||||
upstream: {
|
||||
ok: false,
|
||||
status: responseStatus(asRecord(fallbackResponse)) ?? responseStatus(asRecord(primaryResponse)),
|
||||
},
|
||||
controlPlane: {
|
||||
mode: controlPlaneMode,
|
||||
localBackendCoreMissing: false,
|
||||
remoteFallbackUsed: false,
|
||||
transportFallbackUsed: false,
|
||||
},
|
||||
transportObservation,
|
||||
runtimeObservation: prPreflightRuntimeObservation(options, null, null, primaryPath, fallbackPath),
|
||||
commands: {
|
||||
retry: "bun scripts/cli.ts codex pr-preflight --remote",
|
||||
fallbackRaw: "bun scripts/cli.ts microservice proxy code-queue /api/runtime-preflight --raw",
|
||||
fullDetail: "bun scripts/cli.ts codex pr-preflight --remote --full",
|
||||
},
|
||||
}, options);
|
||||
}
|
||||
|
||||
function compactPrRuntimePreflight(preflight: Record<string, unknown>, options: CodexPrPreflightOptions): Record<string, unknown> {
|
||||
const pull = asRecord(preflight.pullRequestDelivery) ?? {};
|
||||
const skills = compactSkillsStatus(preflight.skills);
|
||||
@@ -7116,10 +7311,12 @@ function compactPrRuntimePreflight(preflight: Record<string, unknown>, options:
|
||||
const activeRunnerDevContainer = activeRunnerDevContainerCapability();
|
||||
const authScopeSummary = prPreflightAuthScopeSummary(tokenCoverage, activeRunnerDevContainer);
|
||||
const recommendedActions = prPreflightRecommendedActions(tokenCoverage);
|
||||
const blockingDisposition = failureKind === "runner-skills-blocker" ? "runner-capability-degraded" : undefined;
|
||||
const result: Record<string, unknown> = {
|
||||
ok,
|
||||
failureKind,
|
||||
degradedReason,
|
||||
...(blockingDisposition === undefined ? {} : { blockingDisposition }),
|
||||
checkedAt: preflight.checkedAt ?? pull.checkedAt ?? null,
|
||||
runner: {
|
||||
serviceId: "code-queue",
|
||||
@@ -7344,15 +7541,18 @@ function codeQueuePrPreflight(optionArgs: string[] = [], transport: CodeQueuePrP
|
||||
const options = parsePrPreflightOptions(optionArgs);
|
||||
const config = transport.config ?? null;
|
||||
const fetcher = transport.coreFetch ?? coreInternalFetch;
|
||||
const path = codeQueueProxyPath(`/api/runtime-preflight${queryString({
|
||||
remote: options.remote ? 1 : undefined,
|
||||
pushDryRun: options.pushDryRun ? 1 : undefined,
|
||||
pushDryRunRef: options.pushDryRunRef,
|
||||
prCreateDryRun: options.prCreateDryRun ? 1 : undefined,
|
||||
prCreateDryRunHead: options.prCreateDryRunHead,
|
||||
issue: options.issueNumber,
|
||||
})}`);
|
||||
const localResponse = fetcher(path);
|
||||
const primaryPath = prPreflightRuntimeProxyPath(options, options.remote);
|
||||
const localResponse = fetcher(primaryPath);
|
||||
if (options.remote && prPreflightRuntimeTransportDegraded(localResponse)) {
|
||||
const fallbackPath = prPreflightRuntimeProxyPath(options, false);
|
||||
const fallbackResponse = fetcher(fallbackPath);
|
||||
const fallbackRuntime = runtimePreflightFromResponse(fallbackResponse);
|
||||
if (fallbackRuntime !== null) {
|
||||
const transportObservation = prPreflightTransportObservation("transport-degraded", primaryPath, localResponse, fallbackPath, fallbackResponse, true);
|
||||
return prPreflightObservedRuntimeResult(options, fallbackRuntime.response, fallbackRuntime.preflight, "local-backend-core", "fallback-runtime-preflight", primaryPath, fallbackPath, transportObservation);
|
||||
}
|
||||
return prPreflightTransportBlockedResult(options, "local-backend-core", primaryPath, localResponse, fallbackPath, fallbackResponse);
|
||||
}
|
||||
const localRecord = asRecord(localResponse);
|
||||
const localTargetStackMissing = localRecord?.ok === false
|
||||
&& localRecord.failureKind === "target-stack-not-running"
|
||||
@@ -7495,28 +7695,7 @@ function codeQueuePrPreflight(optionArgs: string[] = [], transport: CodeQueuePrP
|
||||
},
|
||||
};
|
||||
}
|
||||
const compact = compactPrRuntimePreflight(preflight, options);
|
||||
return compactPrPreflightCommanderView({
|
||||
ok: compact.ok,
|
||||
runnerDisposition: compact.runnerDisposition,
|
||||
failureKind: compact.failureKind ?? null,
|
||||
degradedReason: compact.degradedReason ?? null,
|
||||
...(compact.retryable === true ? { retryable: true } : {}),
|
||||
...(typeof compact.commanderAction === "string" ? { commanderAction: compact.commanderAction } : {}),
|
||||
...(asRecord(compact.githubTransient) === null ? {} : { githubTransient: compact.githubTransient }),
|
||||
authScopeSummary: compact.authScopeSummary,
|
||||
scopeBoundary: compact.scopeBoundary,
|
||||
activeRunnerDevContainer: compact.activeRunnerDevContainer,
|
||||
recommendedActions: compact.recommendedActions,
|
||||
skillsContract: compact.skillsContract,
|
||||
upstream: { ok: response.ok, status: response.status },
|
||||
controlPlane: {
|
||||
mode: "local-backend-core",
|
||||
localBackendCoreMissing: false,
|
||||
remoteFallbackUsed: false,
|
||||
},
|
||||
preflight: compact,
|
||||
}, options);
|
||||
return prPreflightObservedRuntimeResult(options, response, preflight, "local-backend-core", "primary-runtime-preflight", primaryPath, null);
|
||||
}
|
||||
|
||||
export function codexPrPreflightQueryForTest(optionArgs: string[], transport: CodeQueuePrPreflightTransport = {}): unknown {
|
||||
@@ -7525,15 +7704,19 @@ export function codexPrPreflightQueryForTest(optionArgs: string[], transport: Co
|
||||
|
||||
export async function codexPrPreflightQueryAsync(optionArgs: string[], fetcher: AsyncCodexResponseFetcher): Promise<unknown> {
|
||||
const options = parsePrPreflightOptions(optionArgs);
|
||||
const path = codeQueueProxyPath(`/api/runtime-preflight${queryString({
|
||||
remote: options.remote ? 1 : undefined,
|
||||
pushDryRun: options.pushDryRun ? 1 : undefined,
|
||||
pushDryRunRef: options.pushDryRunRef,
|
||||
prCreateDryRun: options.prCreateDryRun ? 1 : undefined,
|
||||
prCreateDryRunHead: options.prCreateDryRunHead,
|
||||
issue: options.issueNumber,
|
||||
})}`);
|
||||
const response = asRecord(await fetcher(path));
|
||||
const primaryPath = prPreflightRuntimeProxyPath(options, options.remote);
|
||||
const primaryResponse = await fetcher(primaryPath);
|
||||
if (options.remote && prPreflightRuntimeTransportDegraded(primaryResponse)) {
|
||||
const fallbackPath = prPreflightRuntimeProxyPath(options, false);
|
||||
const fallbackResponse = await fetcher(fallbackPath);
|
||||
const fallbackRuntime = runtimePreflightFromResponse(fallbackResponse);
|
||||
if (fallbackRuntime !== null) {
|
||||
const transportObservation = prPreflightTransportObservation("transport-degraded", primaryPath, primaryResponse, fallbackPath, fallbackResponse, true);
|
||||
return prPreflightObservedRuntimeResult(options, fallbackRuntime.response, fallbackRuntime.preflight, "remote-frontend", "fallback-runtime-preflight", primaryPath, fallbackPath, transportObservation);
|
||||
}
|
||||
return prPreflightTransportBlockedResult(options, "remote-frontend", primaryPath, primaryResponse, fallbackPath, fallbackResponse);
|
||||
}
|
||||
const response = asRecord(primaryResponse);
|
||||
if (response?.ok !== true) throw new Error(upstreamError(response));
|
||||
const body = asRecord(response.body);
|
||||
const preflight = asRecord(body?.runtimePreflight);
|
||||
@@ -7555,28 +7738,7 @@ export async function codexPrPreflightQueryAsync(optionArgs: string[], fetcher:
|
||||
},
|
||||
};
|
||||
}
|
||||
const compact = compactPrRuntimePreflight(preflight, options);
|
||||
return compactPrPreflightCommanderView({
|
||||
ok: compact.ok,
|
||||
runnerDisposition: compact.runnerDisposition,
|
||||
failureKind: compact.failureKind ?? null,
|
||||
degradedReason: compact.degradedReason ?? null,
|
||||
...(compact.retryable === true ? { retryable: true } : {}),
|
||||
...(typeof compact.commanderAction === "string" ? { commanderAction: compact.commanderAction } : {}),
|
||||
...(asRecord(compact.githubTransient) === null ? {} : { githubTransient: compact.githubTransient }),
|
||||
authScopeSummary: compact.authScopeSummary,
|
||||
scopeBoundary: compact.scopeBoundary,
|
||||
activeRunnerDevContainer: compact.activeRunnerDevContainer,
|
||||
recommendedActions: compact.recommendedActions,
|
||||
skillsContract: compact.skillsContract,
|
||||
upstream: { ok: response.ok, status: response.status },
|
||||
controlPlane: {
|
||||
mode: "remote-frontend",
|
||||
localBackendCoreMissing: false,
|
||||
remoteFallbackUsed: false,
|
||||
},
|
||||
preflight: compact,
|
||||
}, options);
|
||||
return prPreflightObservedRuntimeResult(options, response, preflight, "remote-frontend", "primary-runtime-preflight", primaryPath, null);
|
||||
}
|
||||
|
||||
export function codexSubmitRoutingRecommendationForTest(prompt: string, model?: string): SubmitRoutingRecommendation {
|
||||
|
||||
Reference in New Issue
Block a user