



























@@ -43,6 +43,10 @@ const DEFAULT_LIVE_CODEX_MODEL = "gpt-5.5";
4343const DEFAULT_LIVE_PARENT_MODEL = "openai/gpt-5.4";
4444type LiveAcpAgent = "claude" | "codex" | "droid" | "gemini" | "opencode";
454546+class AcpBindSkipError extends Error {
47+readonly name = "AcpBindSkipError";
48+}
49+4650function createSlackCurrentConversationBindingRegistry() {
4751return createTestRegistry([
4852{
@@ -262,6 +266,16 @@ function isRetryableAcpBindWarmupText(texts: string[]): boolean {
262266);
263267}
264268269+function isSkippableAcpBindText(params: { liveAgent: LiveAcpAgent; texts: string[] }): boolean {
270+if (params.liveAgent !== "codex") {
271+return false;
272+}
273+const combined = params.texts.join("\n\n").toLowerCase();
274+return (
275+combined.includes("acp_session_init_failed") && combined.includes("authentication required")
276+);
277+}
278+265279describe("isRetryableAcpBindWarmupText", () => {
266280it.each([
267281{
@@ -280,6 +294,23 @@ describe("isRetryableAcpBindWarmupText", () => {
280294});
281295});
282296297+describe("isSkippableAcpBindText", () => {
298+it.each([
299+{
300+liveAgent: "codex" as const,
301+texts: ["ACP error (ACP_SESSION_INIT_FAILED): Authentication required"],
302+expected: true,
303+},
304+{
305+liveAgent: "gemini" as const,
306+texts: ["ACP error (ACP_SESSION_INIT_FAILED): Authentication required"],
307+expected: false,
308+},
309+])("returns $expected for $liveAgent", ({ liveAgent, texts, expected }) => {
310+expect(isSkippableAcpBindText({ liveAgent, texts })).toBe(expected);
311+});
312+});
313+283314function formatAssistantTextPreview(texts: string[], maxChars = 600): string {
284315const combined = texts.join("\n\n").trim();
285316if (!combined) {
@@ -362,6 +393,13 @@ async function bindConversationAndWait(params: {
362393return { mainAssistantTexts, spawnedSessionKey };
363394}
364395if (!isRetryableAcpBindWarmupText(mainAssistantTexts)) {
396+if (isSkippableAcpBindText({ liveAgent: params.liveAgent, texts: mainAssistantTexts })) {
397+throw new AcpBindSkipError(
398+`SKIP: ${params.liveAgent} ACP bind unavailable: ${formatAssistantTextPreview(
399+ mainAssistantTexts,
400+ )}`,
401+);
402+}
365403throw new Error(
366404`bind command did not produce an ACP session: ${formatAssistantTextPreview(mainAssistantTexts)}`,
367405);
@@ -662,14 +700,24 @@ describeLive("gateway live (ACP bind)", () => {
662700pinActivePluginChannelRegistry(channelRegistry);
663701664702try {
665-const { mainAssistantTexts, spawnedSessionKey } = await bindConversationAndWait({
666- client,
667-sessionKey: originalSessionKey,
668- liveAgent,
669-originatingChannel: "slack",
670-originatingTo: conversationId,
671-originatingAccountId: accountId,
672-});
703+let bindResult: Awaited<ReturnType<typeof bindConversationAndWait>>;
704+try {
705+bindResult = await bindConversationAndWait({
706+ client,
707+sessionKey: originalSessionKey,
708+ liveAgent,
709+originatingChannel: "slack",
710+originatingTo: conversationId,
711+originatingAccountId: accountId,
712+});
713+} catch (error) {
714+if (error instanceof AcpBindSkipError) {
715+console.error(error.message);
716+return;
717+}
718+throw error;
719+}
720+const { mainAssistantTexts, spawnedSessionKey } = bindResult;
673721logLiveStep("bind command completed");
674722expect(mainAssistantTexts.join("\n\n")).toContain("Bound this conversation to");
675723expect(spawnedSessionKey).toMatch(new RegExp(`^agent:${liveAgent}:acp:`));
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。