fix(ci): stabilize auto-reply CI tests

This commit is contained in:
Peter Steinberger
2026-04-11 04:09:01 +01:00
parent 44e5b62c27
commit d515009c53
13 changed files with 71 additions and 82 deletions

View File

@@ -407,9 +407,7 @@ describe("DiscordVoiceManager", () => {
await manager.join({ guildId: "g1", channelId: "1001" });
const entry = (manager as unknown as { sessions: Map<string, unknown> }).sessions.get(
"g1",
) as
const entry = (manager as unknown as { sessions: Map<string, unknown> }).sessions.get("g1") as
| {
guildId: string;
channelId: string;

View File

@@ -1,7 +1,4 @@
export function resolveMemorySearchPreflight(params: {
query: string;
hasIndexedContent: boolean;
}):
export function resolveMemorySearchPreflight(params: { query: string; hasIndexedContent: boolean }):
| {
normalizedQuery: string;
shouldInitializeProvider: boolean;

View File

@@ -4,9 +4,9 @@
"description": "OpenClaw Microsoft Teams channel plugin",
"type": "module",
"dependencies": {
"@sinclair/typebox": "0.34.49",
"@microsoft/teams.api": "2.0.7",
"@microsoft/teams.apps": "2.0.7",
"@sinclair/typebox": "0.34.49",
"express": "^5.2.1",
"jsonwebtoken": "^9.0.3",
"jwks-rsa": "^4.0.1"

View File

@@ -1,4 +1,5 @@
import { vi, type Mock } from "vitest";
import { clearAgentHarnesses } from "../harness/registry.js";
type MockResolvedModel = {
model: { provider: string; api: string; id: string; input: unknown[] };
@@ -143,6 +144,7 @@ export function resetCompactSessionStateMocks(): void {
}
export function resetCompactHooksHarnessMocks(): void {
clearAgentHarnesses();
hookRunner.hasHooks.mockReset();
hookRunner.hasHooks.mockReturnValue(false);
hookRunner.runBeforeCompaction.mockReset();
@@ -307,13 +309,10 @@ export async function loadCompactHooksHarness(): Promise<{
resolveSessionLockMaxHoldFromTimeout: vi.fn(() => 0),
}));
vi.doMock("../../context-engine/index.js", () => ({
ensureContextEnginesInitialized: vi.fn(),
resolveContextEngine: resolveContextEngineMock,
}));
vi.doMock("../../context-engine/init.js", () => ({
ensureContextEnginesInitialized: vi.fn(),
}));
vi.doMock("../../context-engine/registry.js", () => ({
resolveContextEngine: resolveContextEngineMock,
}));

View File

@@ -45,15 +45,28 @@ function resolveUserHomeDir(): string | undefined {
}
function compactSkillPaths(skills: Skill[]): Skill[] {
const home = resolveUserHomeDir();
if (!home) return skills;
const prefix = home.endsWith(path.sep) ? home : home + path.sep;
const homes = [resolveHomeDir(), resolveUserHomeDir()]
.filter((home): home is string => !!home)
.map((home) => path.resolve(home))
.filter((home, index, all) => all.indexOf(home) === index)
.sort((a, b) => b.length - a.length);
if (homes.length === 0) return skills;
return skills.map((s) => ({
...s,
filePath: s.filePath.startsWith(prefix) ? "~/" + s.filePath.slice(prefix.length) : s.filePath,
filePath: compactHomePath(s.filePath, homes),
}));
}
function compactHomePath(filePath: string, homes: readonly string[]): string {
for (const home of homes) {
const prefix = home.endsWith(path.sep) ? home : home + path.sep;
if (filePath.startsWith(prefix)) {
return "~/" + filePath.slice(prefix.length);
}
}
return filePath;
}
function isSkillVisibleInAvailableSkillsPrompt(entry: SkillEntry): boolean {
if (entry.exposure) {
return entry.exposure.includeInAvailableSkillsPrompt !== false;

View File

@@ -202,13 +202,10 @@ describe("info command handlers", () => {
});
it("preserves the shared session store path when routing /status", async () => {
const params = buildInfoParams(
"/status",
{
commands: { text: true },
channels: { whatsapp: { allowFrom: ["*"] } },
} as OpenClawConfig,
);
const params = buildInfoParams("/status", {
commands: { text: true },
channels: { whatsapp: { allowFrom: ["*"] } },
} as OpenClawConfig);
params.storePath = "/tmp/target-session-store.json";
const statusResult = await handleStatusCommand(params, true);
@@ -222,13 +219,10 @@ describe("info command handlers", () => {
});
it("prefers the target session entry when routing /status", async () => {
const params = buildInfoParams(
"/status",
{
commands: { text: true },
channels: { whatsapp: { allowFrom: ["*"] } },
} as OpenClawConfig,
);
const params = buildInfoParams("/status", {
commands: { text: true },
channels: { whatsapp: { allowFrom: ["*"] } },
} as OpenClawConfig);
params.sessionEntry = {
sessionId: "wrapper-session",
updatedAt: Date.now(),

View File

@@ -80,13 +80,10 @@ describe("handlePluginCommand", () => {
});
executePluginCommandMock.mockResolvedValue({ text: "from plugin" });
const params = buildPluginParams(
"/card",
{
commands: { text: true },
channels: { whatsapp: { allowFrom: ["*"] } },
} as OpenClawConfig,
);
const params = buildPluginParams("/card", {
commands: { text: true },
channels: { whatsapp: { allowFrom: ["*"] } },
} as OpenClawConfig);
params.sessionEntry = {
sessionId: "wrapper-session",
sessionFile: "/tmp/wrapper-session.jsonl",

View File

@@ -257,13 +257,10 @@ describe("handleCommands reset hooks", () => {
});
it("prefers the target session entry when emitting reset hooks", async () => {
const params = buildResetParams(
"/reset",
{
commands: { text: true },
channels: { whatsapp: { allowFrom: ["*"] } },
} as OpenClawConfig,
);
const params = buildResetParams("/reset", {
commands: { text: true },
channels: { whatsapp: { allowFrom: ["*"] } },
} as OpenClawConfig);
params.sessionEntry = {
sessionId: "wrapper-session",
updatedAt: Date.now(),

View File

@@ -259,8 +259,18 @@ describe("subagents spawn action", () => {
);
spawnSubagentDirectMock.mockClear();
await handleSubagentsSpawnAction(
{
await handleSubagentsSpawnAction({
...buildContext({
requesterKey: "agent:main:target",
sessionEntry: {
sessionId: "wrapper-session",
updatedAt: Date.now(),
groupId: "wrapper-group",
groupChannel: "#wrapper",
space: "wrapper-space",
},
}),
params: {
...buildContext({
requesterKey: "agent:main:target",
sessionEntry: {
@@ -270,30 +280,18 @@ describe("subagents spawn action", () => {
groupChannel: "#wrapper",
space: "wrapper-space",
},
}),
params: {
...buildContext({
requesterKey: "agent:main:target",
sessionEntry: {
sessionId: "wrapper-session",
updatedAt: Date.now(),
groupId: "wrapper-group",
groupChannel: "#wrapper",
space: "wrapper-space",
},
}).params,
sessionStore: {
"agent:main:target": {
sessionId: "target-session",
updatedAt: Date.now(),
groupId: "target-group",
groupChannel: "#target",
space: "target-space",
},
}).params,
sessionStore: {
"agent:main:target": {
sessionId: "target-session",
updatedAt: Date.now(),
groupId: "target-group",
groupChannel: "#target",
space: "target-space",
},
},
},
);
});
expect(spawnSubagentDirectMock).toHaveBeenCalledWith(
expect.anything(),

View File

@@ -1377,9 +1377,9 @@ export function createNestedChannelParsedAllowFromPrompt(params: {
getExistingAllowFrom: ({ cfg }: { cfg: OpenClawConfig }) =>
params.getExistingAllowFrom?.(cfg) ??
(
(cfg.channels?.[params.channel] as Record<string, unknown> | undefined)?.[
params.section
] as { allowFrom?: Array<string | number> } | undefined
(cfg.channels?.[params.channel] as Record<string, unknown> | undefined)?.[params.section] as
| { allowFrom?: Array<string | number> }
| undefined
)?.allowFrom ??
[],
...(params.mergeEntries ? { mergeEntries: params.mergeEntries } : {}),

View File

@@ -166,7 +166,7 @@ function resolveProviderPluginsWithOwnedWebSearch(
registry: PluginManifestRegistry,
): PluginManifestRecord[] {
return registry.plugins
.filter((plugin) => plugin.providers.length > 0)
.filter((plugin) => (plugin.providers?.length ?? 0) > 0)
.filter((plugin) => (plugin.contracts?.webSearchProviders?.length ?? 0) > 0);
}

View File

@@ -2534,9 +2534,7 @@ describe("gateway server sessions", () => {
expect(deleted.ok).toBe(true);
expect(deleted.payload?.deleted).toBe(true);
expect(subagentLifecycleHookMocks.runSubagentEnded).toHaveBeenCalledTimes(1);
const event = (
subagentLifecycleHookMocks.runSubagentEnded.mock.calls as unknown[][]
)[0]?.[0] as
const event = (subagentLifecycleHookMocks.runSubagentEnded.mock.calls as unknown[][])[0]?.[0] as
| { targetKind?: string; targetSessionKey?: string; reason?: string; outcome?: string }
| undefined;
expect(event).toMatchObject({
@@ -2852,9 +2850,7 @@ describe("gateway server sessions", () => {
expect(reset.payload?.key).toBe("agent:main:subagent:worker");
expect(reset.payload?.entry.sessionId).not.toBe("sess-subagent");
expect(subagentLifecycleHookMocks.runSubagentEnded).toHaveBeenCalledTimes(1);
const event = (
subagentLifecycleHookMocks.runSubagentEnded.mock.calls as unknown[][]
)[0]?.[0] as
const event = (subagentLifecycleHookMocks.runSubagentEnded.mock.calls as unknown[][])[0]?.[0] as
| { targetKind?: string; targetSessionKey?: string; reason?: string; outcome?: string }
| undefined;
expect(event).toMatchObject({

View File

@@ -25,9 +25,9 @@ function loadPluginRuntime(): PluginRuntimeModule | null {
}
export function resolveRuntimeTextTransforms(): PluginTextTransforms | undefined {
return mergePluginTextTransforms(
...(loadPluginRuntime()
?.getActivePluginRegistry()
?.textTransforms?.map((entry) => entry.transforms) ?? []),
);
const registry = loadPluginRuntime()?.getActivePluginRegistry();
const pluginTextTransforms = Array.isArray(registry?.textTransforms)
? registry.textTransforms.map((entry) => entry.transforms)
: [];
return mergePluginTextTransforms(...pluginTextTransforms);
}