test(gateway): skip codex acp bind when auth is unavailable

This commit is contained in:
Peter Steinberger
2026-04-26 21:42:49 +01:00
parent 7a4574376a
commit 487f8c5d3a

View File

@@ -43,6 +43,10 @@ const DEFAULT_LIVE_CODEX_MODEL = "gpt-5.5";
const DEFAULT_LIVE_PARENT_MODEL = "openai/gpt-5.4";
type LiveAcpAgent = "claude" | "codex" | "droid" | "gemini" | "opencode";
class AcpBindSkipError extends Error {
readonly name = "AcpBindSkipError";
}
function createSlackCurrentConversationBindingRegistry() {
return createTestRegistry([
{
@@ -262,6 +266,16 @@ function isRetryableAcpBindWarmupText(texts: string[]): boolean {
);
}
function isSkippableAcpBindText(params: { liveAgent: LiveAcpAgent; texts: string[] }): boolean {
if (params.liveAgent !== "codex") {
return false;
}
const combined = params.texts.join("\n\n").toLowerCase();
return (
combined.includes("acp_session_init_failed") && combined.includes("authentication required")
);
}
describe("isRetryableAcpBindWarmupText", () => {
it.each([
{
@@ -280,6 +294,23 @@ describe("isRetryableAcpBindWarmupText", () => {
});
});
describe("isSkippableAcpBindText", () => {
it.each([
{
liveAgent: "codex" as const,
texts: ["ACP error (ACP_SESSION_INIT_FAILED): Authentication required"],
expected: true,
},
{
liveAgent: "gemini" as const,
texts: ["ACP error (ACP_SESSION_INIT_FAILED): Authentication required"],
expected: false,
},
])("returns $expected for $liveAgent", ({ liveAgent, texts, expected }) => {
expect(isSkippableAcpBindText({ liveAgent, texts })).toBe(expected);
});
});
function formatAssistantTextPreview(texts: string[], maxChars = 600): string {
const combined = texts.join("\n\n").trim();
if (!combined) {
@@ -362,6 +393,13 @@ async function bindConversationAndWait(params: {
return { mainAssistantTexts, spawnedSessionKey };
}
if (!isRetryableAcpBindWarmupText(mainAssistantTexts)) {
if (isSkippableAcpBindText({ liveAgent: params.liveAgent, texts: mainAssistantTexts })) {
throw new AcpBindSkipError(
`SKIP: ${params.liveAgent} ACP bind unavailable: ${formatAssistantTextPreview(
mainAssistantTexts,
)}`,
);
}
throw new Error(
`bind command did not produce an ACP session: ${formatAssistantTextPreview(mainAssistantTexts)}`,
);
@@ -662,14 +700,24 @@ describeLive("gateway live (ACP bind)", () => {
pinActivePluginChannelRegistry(channelRegistry);
try {
const { mainAssistantTexts, spawnedSessionKey } = await bindConversationAndWait({
client,
sessionKey: originalSessionKey,
liveAgent,
originatingChannel: "slack",
originatingTo: conversationId,
originatingAccountId: accountId,
});
let bindResult: Awaited<ReturnType<typeof bindConversationAndWait>>;
try {
bindResult = await bindConversationAndWait({
client,
sessionKey: originalSessionKey,
liveAgent,
originatingChannel: "slack",
originatingTo: conversationId,
originatingAccountId: accountId,
});
} catch (error) {
if (error instanceof AcpBindSkipError) {
console.error(error.message);
return;
}
throw error;
}
const { mainAssistantTexts, spawnedSessionKey } = bindResult;
logLiveStep("bind command completed");
expect(mainAssistantTexts.join("\n\n")).toContain("Bound this conversation to");
expect(spawnedSessionKey).toMatch(new RegExp(`^agent:${liveAgent}:acp:`));