mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
fix(ci): heal current main blockers
This commit is contained in:
@@ -23,7 +23,7 @@ function memberLabel(state: APIVoiceState): string | undefined {
|
||||
);
|
||||
}
|
||||
|
||||
export async function appendDiscordVoiceParticipantContext(params: {
|
||||
async function appendDiscordVoiceParticipantContext(params: {
|
||||
context: DiscordVoiceIngressContext | null;
|
||||
client: Client;
|
||||
entry: VoiceSessionEntry;
|
||||
|
||||
@@ -66,7 +66,6 @@ const rawSqliteAllowPathGroups = {
|
||||
"src/infra/state-migrations.storage.ts",
|
||||
"src/infra/state-migrations.cron-run-logs.ts",
|
||||
"src/infra/state-migrations.debug-proxy.ts",
|
||||
"src/infra/state-migrations.task-sidecar-rows.ts",
|
||||
],
|
||||
"shared database stores with direct DatabaseSync access": ["src/proxy-capture/store.sqlite.ts"],
|
||||
"Kysely-backed stores that own a DatabaseSync boundary": [
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import type { CallToolResult } from "@modelcontextprotocol/sdk/types.js";
|
||||
import { expectDefined } from "@openclaw/normalization-core";
|
||||
import { validateToolArguments } from "openclaw/plugin-sdk/llm";
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { getPluginToolMeta } from "../plugins/tools.js";
|
||||
import {
|
||||
buildBundleMcpToolsFromCatalog,
|
||||
@@ -14,33 +14,11 @@ import type { McpCatalogTool } from "./agent-bundle-mcp-types.js";
|
||||
import type { McpToolCatalogDiagnostic } from "./agent-bundle-mcp-types.js";
|
||||
import type { SessionMcpRuntime } from "./agent-bundle-mcp-types.js";
|
||||
import { applyEmbeddedAttemptToolsAllow } from "./embedded-agent-runner/run/attempt-tool-construction-plan.js";
|
||||
|
||||
const mcpAppMocks = vi.hoisted(() => ({ fetchMcpAppView: vi.fn() }));
|
||||
|
||||
vi.mock("./mcp-ui-resource.js", () => ({
|
||||
fetchMcpAppView: mcpAppMocks.fetchMcpAppView,
|
||||
buildMcpAppCanvasPayload: (view: {
|
||||
viewId: string;
|
||||
title: string;
|
||||
serverName: string;
|
||||
toolName: string;
|
||||
uiResourceUri: string;
|
||||
toolCallId?: string;
|
||||
resultMetaState?: "unavailable";
|
||||
}) => ({
|
||||
kind: "canvas",
|
||||
view: { id: view.viewId, title: view.title },
|
||||
presentation: { target: "assistant_message", sandbox: "scripts" },
|
||||
mcpApp: {
|
||||
viewId: view.viewId,
|
||||
serverName: view.serverName,
|
||||
toolName: view.toolName,
|
||||
uiResourceUri: view.uiResourceUri,
|
||||
...(view.toolCallId ? { toolCallId: view.toolCallId } : {}),
|
||||
...(view.resultMetaState ? { resultMetaState: view.resultMetaState } : {}),
|
||||
},
|
||||
}),
|
||||
}));
|
||||
import {
|
||||
getMcpAppViewLease,
|
||||
MCP_APP_RESOURCE_MIME_TYPE,
|
||||
testing as mcpUiResourceTesting,
|
||||
} from "./mcp-ui-resource.js";
|
||||
|
||||
function expectTextContentBlock(block: unknown, text: string) {
|
||||
const content = block as { type?: string; text?: string } | undefined;
|
||||
@@ -114,8 +92,8 @@ function makeToolRuntime(
|
||||
}
|
||||
|
||||
describe("createBundleMcpToolRuntime", () => {
|
||||
beforeEach(() => {
|
||||
mcpAppMocks.fetchMcpAppView.mockReset();
|
||||
afterEach(() => {
|
||||
mcpUiResourceTesting.clearViewStore();
|
||||
});
|
||||
|
||||
it("keeps app-only MCP tools out of the model tool catalog", async () => {
|
||||
@@ -164,14 +142,6 @@ describe("createBundleMcpToolRuntime", () => {
|
||||
});
|
||||
|
||||
it("attaches app previews without converting typed image results to text", async () => {
|
||||
mcpAppMocks.fetchMcpAppView.mockResolvedValue({
|
||||
viewId: "cv_app",
|
||||
title: "Demo UI",
|
||||
serverName: "demo",
|
||||
toolName: "show",
|
||||
uiResourceUri: "ui://demo/app",
|
||||
toolCallId: "call-1",
|
||||
});
|
||||
const tool: McpCatalogTool = {
|
||||
serverName: "demo",
|
||||
safeServerName: "demo",
|
||||
@@ -189,6 +159,15 @@ describe("createBundleMcpToolRuntime", () => {
|
||||
},
|
||||
});
|
||||
sessionRuntime.mcpAppsEnabled = true;
|
||||
sessionRuntime.readResource = async () => ({
|
||||
contents: [
|
||||
{
|
||||
uri: "ui://demo/app",
|
||||
mimeType: MCP_APP_RESOURCE_MIME_TYPE,
|
||||
text: "<html>demo</html>",
|
||||
},
|
||||
],
|
||||
});
|
||||
const materialized = await materializeBundleMcpToolsForRun({ runtime: sessionRuntime });
|
||||
materialized.restrictAppTools?.(materialized.tools);
|
||||
|
||||
@@ -200,7 +179,7 @@ describe("createBundleMcpToolRuntime", () => {
|
||||
expect(result.details).toMatchObject({
|
||||
mcpAppPreview: {
|
||||
mcpApp: {
|
||||
viewId: "cv_app",
|
||||
viewId: expect.stringMatching(/^mcp-app-/u),
|
||||
serverName: "demo",
|
||||
toolName: "show",
|
||||
uiResourceUri: "ui://demo/app",
|
||||
@@ -209,12 +188,14 @@ describe("createBundleMcpToolRuntime", () => {
|
||||
},
|
||||
},
|
||||
});
|
||||
expect(mcpAppMocks.fetchMcpAppView).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
toolCallId: "call-1",
|
||||
allowedAppToolNames: new Set(["show"]),
|
||||
}),
|
||||
);
|
||||
const viewId = (result.details as { mcpAppPreview?: { mcpApp?: { viewId?: string } } })
|
||||
.mcpAppPreview?.mcpApp?.viewId;
|
||||
expect(
|
||||
getMcpAppViewLease(
|
||||
expectDefined(viewId, "MCP App preview view id test invariant"),
|
||||
sessionRuntime,
|
||||
)?.allowedAppToolNames,
|
||||
).toEqual(new Set(["show"]));
|
||||
});
|
||||
|
||||
it("materializes bundle MCP tools and executes them", async () => {
|
||||
|
||||
@@ -20,7 +20,7 @@ type BeforeAgentRunSession = {
|
||||
agent: { state: { messages: AgentMessage[] } };
|
||||
};
|
||||
|
||||
export type BeforeAgentRunBlockOutcome = {
|
||||
type BeforeAgentRunBlockOutcome = {
|
||||
blockedBy: string;
|
||||
promptError: Error;
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ import { resetConfigRuntimeState } from "../config/config.js";
|
||||
import { loadCronStore, saveCronStore } from "../cron/store.js";
|
||||
import type { GuardedFetchOptions } from "../infra/net/fetch-guard.js";
|
||||
import { peekSystemEvents } from "../infra/system-events.js";
|
||||
import { getGatewayProcessInstanceId } from "./process-instance.js";
|
||||
import type { GatewayCronState } from "./server-cron.js";
|
||||
import {
|
||||
connectOk,
|
||||
@@ -1540,7 +1541,12 @@ describe("gateway server cron", () => {
|
||||
|
||||
const secondRunRes = await rpcReq(ws, "cron.run", { id: "busy-job", mode: "force" }, 1_000);
|
||||
expect(secondRunRes.ok).toBe(true);
|
||||
expect(secondRunRes.payload).toEqual({ ok: true, ran: false, reason: "already-running" });
|
||||
expect(secondRunRes.payload).toEqual({
|
||||
ok: true,
|
||||
ran: false,
|
||||
reason: "already-running",
|
||||
processInstanceId: getGatewayProcessInstanceId(),
|
||||
});
|
||||
expect(cronIsolatedRun).toHaveBeenCalledTimes(1);
|
||||
|
||||
const finishedRun = waitForCronEvent(
|
||||
@@ -1585,7 +1591,12 @@ describe("gateway server cron", () => {
|
||||
try {
|
||||
const runRes = await rpcReq(ws, "cron.run", { id: "future-job", mode: "due" }, 1_000);
|
||||
expect(runRes.ok).toBe(true);
|
||||
expect(runRes.payload).toEqual({ ok: true, ran: false, reason: "not-due" });
|
||||
expect(runRes.payload).toEqual({
|
||||
ok: true,
|
||||
ran: false,
|
||||
reason: "not-due",
|
||||
processInstanceId: getGatewayProcessInstanceId(),
|
||||
});
|
||||
expect(cronIsolatedRun).not.toHaveBeenCalled();
|
||||
} finally {
|
||||
await cleanupCronTestRun({ ws, server, prevSkipCron });
|
||||
|
||||
Reference in New Issue
Block a user