From a8367bb0ec1c1ed0f44219e3c7435a85ccccebef Mon Sep 17 00:00:00 2001 From: Peter Steinberger Date: Mon, 16 Mar 2026 06:50:55 +0000 Subject: [PATCH] fix: stabilize ci gate --- ...ent.delivery-target-thread-session.test.ts | 11 +++++++ src/cron/isolated-agent.test-setup.ts | 16 +++++++++- src/infra/bonjour.ts | 30 +++++-------------- src/infra/outbound/channel-adapters.test.ts | 11 ++++++- src/infra/outbound/outbound-policy.test.ts | 11 ++++++- src/infra/outbound/outbound.test.ts | 9 ++++++ 6 files changed, 62 insertions(+), 26 deletions(-) diff --git a/src/cron/isolated-agent.delivery-target-thread-session.test.ts b/src/cron/isolated-agent.delivery-target-thread-session.test.ts index a034d7ab924..51f9c645a03 100644 --- a/src/cron/isolated-agent.delivery-target-thread-session.test.ts +++ b/src/cron/isolated-agent.delivery-target-thread-session.test.ts @@ -1,4 +1,5 @@ import { describe, expect, it, vi } from "vitest"; +import { parseTelegramTarget } from "../../extensions/telegram/src/targets.js"; import type { OpenClawConfig } from "../config/config.js"; // Mock session store so we can control what entries exist. @@ -19,6 +20,16 @@ vi.mock("../channels/plugins/index.js", () => ({ getChannelPlugin: vi.fn(() => ({ meta: { label: "Telegram" }, config: {}, + messaging: { + parseExplicitTarget: ({ raw }: { raw: string }) => { + const target = parseTelegramTarget(raw); + return { + to: target.chatId, + threadId: target.messageThreadId, + chatType: target.chatType === "unknown" ? undefined : target.chatType, + }; + }, + }, outbound: { resolveTarget: ({ to }: { to?: string }) => to ? { ok: true, to } : { ok: false, error: new Error("missing") }, diff --git a/src/cron/isolated-agent.test-setup.ts b/src/cron/isolated-agent.test-setup.ts index bdeb71fbaf4..17093bda0a5 100644 --- a/src/cron/isolated-agent.test-setup.ts +++ b/src/cron/isolated-agent.test-setup.ts @@ -1,5 +1,6 @@ import { vi } from "vitest"; import { signalOutbound, telegramOutbound } from "../../test/channel-outbounds.js"; +import { parseTelegramTarget } from "../../extensions/telegram/src/targets.js"; import { loadModelCatalog } from "../agents/model-catalog.js"; import { runEmbeddedPiAgent } from "../agents/pi-embedded.js"; import { runSubagentAnnounceFlow } from "../agents/subagent-announce.js"; @@ -19,7 +20,20 @@ export function setupIsolatedAgentTurnMocks(params?: { fast?: boolean }): void { createTestRegistry([ { pluginId: "telegram", - plugin: createOutboundTestPlugin({ id: "telegram", outbound: telegramOutbound }), + plugin: createOutboundTestPlugin({ + id: "telegram", + outbound: telegramOutbound, + messaging: { + parseExplicitTarget: ({ raw }) => { + const target = parseTelegramTarget(raw); + return { + to: target.chatId, + threadId: target.messageThreadId, + chatType: target.chatType === "unknown" ? undefined : target.chatType, + }; + }, + }, + }), source: "test", }, { diff --git a/src/infra/bonjour.ts b/src/infra/bonjour.ts index 9e7790e2065..2b500986f33 100644 --- a/src/infra/bonjour.ts +++ b/src/infra/bonjour.ts @@ -48,35 +48,18 @@ function prettifyInstanceName(name: string) { return normalized.replace(/\s+\(OpenClaw\)\s*$/i, "").trim() || normalized; } -type BonjourService = { - advertise: () => Promise; - destroy: () => Promise; - getFQDN: () => string; - getHostname: () => string; - getPort: () => number; - on: (event: string, listener: (...args: unknown[]) => void) => unknown; - serviceState: string; -}; +type BonjourService = import("@homebridge/ciao").CiaoService; +type BonjourResponder = import("@homebridge/ciao").Responder; +type BonjourServiceState = BonjourService["serviceState"]; type BonjourCycle = { - responder: { - createService: (options: { - name: string; - type: string; - protocol: unknown; - port: number; - domain: string; - hostname: string; - txt: Record; - }) => unknown; - shutdown: () => Promise; - }; + responder: BonjourResponder; services: Array<{ label: string; svc: BonjourService }>; cleanupUnhandledRejection?: () => void; }; type ServiceStateTracker = { - state: string; + state: BonjourServiceState | "unknown"; sinceMs: number; }; @@ -271,7 +254,8 @@ export async function startGatewayBonjourAdvertiser( const updateStateTrackers = (services: Array<{ label: string; svc: BonjourService }>) => { const now = Date.now(); for (const { label, svc } of services) { - const nextState = typeof svc.serviceState === "string" ? svc.serviceState : "unknown"; + const nextState: BonjourServiceState | "unknown" = + typeof svc.serviceState === "string" ? svc.serviceState : "unknown"; const current = stateTracker.get(label); if (!current || current.state !== nextState) { stateTracker.set(label, { state: nextState, sinceMs: now }); diff --git a/src/infra/outbound/channel-adapters.test.ts b/src/infra/outbound/channel-adapters.test.ts index d8a01aadb2b..ca39b403226 100644 --- a/src/infra/outbound/channel-adapters.test.ts +++ b/src/infra/outbound/channel-adapters.test.ts @@ -1,9 +1,18 @@ import { Separator, TextDisplay } from "@buape/carbon"; -import { describe, expect, it } from "vitest"; +import { beforeEach, describe, expect, it } from "vitest"; +import { discordPlugin } from "../../../extensions/discord/src/channel.js"; import { DiscordUiContainer } from "../../../extensions/discord/src/ui.js"; +import { setActivePluginRegistry } from "../../plugins/runtime.js"; +import { createTestRegistry } from "../../test-utils/channel-plugins.js"; import { getChannelMessageAdapter } from "./channel-adapters.js"; describe("getChannelMessageAdapter", () => { + beforeEach(() => { + setActivePluginRegistry( + createTestRegistry([{ pluginId: "discord", plugin: discordPlugin, source: "test" }]), + ); + }); + it("returns the default adapter for non-discord channels", () => { expect(getChannelMessageAdapter("telegram")).toEqual({ supportsComponentsV2: false, diff --git a/src/infra/outbound/outbound-policy.test.ts b/src/infra/outbound/outbound-policy.test.ts index fd19649c345..43e71afb923 100644 --- a/src/infra/outbound/outbound-policy.test.ts +++ b/src/infra/outbound/outbound-policy.test.ts @@ -1,5 +1,8 @@ -import { describe, expect, it } from "vitest"; +import { beforeEach, describe, expect, it } from "vitest"; +import { discordPlugin } from "../../../extensions/discord/src/channel.js"; import type { OpenClawConfig } from "../../config/config.js"; +import { setActivePluginRegistry } from "../../plugins/runtime.js"; +import { createTestRegistry } from "../../test-utils/channel-plugins.js"; import { applyCrossContextDecoration, buildCrossContextDecoration, @@ -23,6 +26,12 @@ const discordConfig = { } as OpenClawConfig; describe("outbound policy helpers", () => { + beforeEach(() => { + setActivePluginRegistry( + createTestRegistry([{ pluginId: "discord", plugin: discordPlugin, source: "test" }]), + ); + }); + it("allows cross-provider sends when enabled", () => { const cfg = { ...slackConfig, diff --git a/src/infra/outbound/outbound.test.ts b/src/infra/outbound/outbound.test.ts index 9e58d5c6c05..5c2303d7154 100644 --- a/src/infra/outbound/outbound.test.ts +++ b/src/infra/outbound/outbound.test.ts @@ -2,8 +2,11 @@ import fs from "node:fs"; import os from "node:os"; import path from "node:path"; import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it, vi } from "vitest"; +import { discordPlugin } from "../../../extensions/discord/src/channel.js"; import type { ReplyPayload } from "../../auto-reply/types.js"; import type { OpenClawConfig } from "../../config/config.js"; +import { setActivePluginRegistry } from "../../plugins/runtime.js"; +import { createTestRegistry } from "../../test-utils/channel-plugins.js"; import { typedCases } from "../../test-utils/typed-cases.js"; import { ackDelivery, @@ -39,6 +42,12 @@ import { } from "./payloads.js"; import { runResolveOutboundTargetCoreTests } from "./targets.shared-test.js"; +beforeEach(() => { + setActivePluginRegistry( + createTestRegistry([{ pluginId: "discord", plugin: discordPlugin, source: "test" }]), + ); +}); + describe("delivery-queue", () => { let tmpDir: string; let fixtureRoot = "";