mirror of
https://github.com/openclaw/openclaw.git
synced 2026-04-18 04:31:10 +00:00
test: move spawn and doctor coverage to owners
This commit is contained in:
@@ -96,6 +96,47 @@ describe("discord doctor", () => {
|
||||
).toEqual(["Moved channels.discord.streamMode → channels.discord.streaming.mode (block)."]);
|
||||
});
|
||||
|
||||
it("moves account voice.tts.edge into providers.microsoft", () => {
|
||||
const normalize = discordDoctor.normalizeCompatibilityConfig;
|
||||
expect(normalize).toBeDefined();
|
||||
if (!normalize) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = normalize({
|
||||
cfg: {
|
||||
channels: {
|
||||
discord: {
|
||||
accounts: {
|
||||
main: {
|
||||
voice: {
|
||||
tts: {
|
||||
edge: {
|
||||
voice: "en-US-JennyNeural",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
} as never,
|
||||
});
|
||||
|
||||
expect(result.changes).toContain(
|
||||
"Moved channels.discord.accounts.main.voice.tts.edge → channels.discord.accounts.main.voice.tts.providers.microsoft.",
|
||||
);
|
||||
const mainTts = result.config.channels?.discord?.accounts?.main?.voice?.tts as
|
||||
| Record<string, unknown>
|
||||
| undefined;
|
||||
expect(mainTts?.providers).toEqual({
|
||||
microsoft: {
|
||||
voice: "en-US-JennyNeural",
|
||||
},
|
||||
});
|
||||
expect(mainTts?.edge).toBeUndefined();
|
||||
});
|
||||
|
||||
it("finds numeric id entries across discord scopes", () => {
|
||||
const cfg = {
|
||||
channels: {
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
import { beforeEach, describe, expect, it } from "vitest";
|
||||
import "./test-helpers/fast-core-tools.js";
|
||||
import {
|
||||
getCallGatewayMock,
|
||||
getSessionsSpawnTool,
|
||||
setSessionsSpawnConfigOverride,
|
||||
} from "./openclaw-tools.subagents.sessions-spawn.test-harness.js";
|
||||
import { subagentRuns } from "./subagent-registry-memory.js";
|
||||
import { listRunsForRequesterFromRuns } from "./subagent-registry-queries.js";
|
||||
|
||||
function listSubagentRunsForRequester(requesterSessionKey: string) {
|
||||
return listRunsForRequesterFromRuns(subagentRuns, requesterSessionKey);
|
||||
}
|
||||
|
||||
describe("sessions_spawn requesterOrigin threading", () => {
|
||||
const spawnAndReadRequesterRun = async (opts?: { agentThreadId?: number }) => {
|
||||
const tool = await getSessionsSpawnTool({
|
||||
agentSessionKey: "main",
|
||||
agentChannel: "telegram",
|
||||
agentTo: "telegram:123",
|
||||
...(opts?.agentThreadId === undefined ? {} : { agentThreadId: opts.agentThreadId }),
|
||||
});
|
||||
const result = await tool.execute("call", {
|
||||
task: "do thing",
|
||||
runTimeoutSeconds: 1,
|
||||
});
|
||||
expect(result.details).toMatchObject({ status: "accepted", runId: "run-1" });
|
||||
|
||||
const runs = listSubagentRunsForRequester("main");
|
||||
expect(runs).toHaveLength(1);
|
||||
return runs[0];
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
const callGatewayMock = getCallGatewayMock();
|
||||
subagentRuns.clear();
|
||||
callGatewayMock.mockClear();
|
||||
setSessionsSpawnConfigOverride({
|
||||
session: {
|
||||
mainKey: "main",
|
||||
scope: "per-sender",
|
||||
},
|
||||
});
|
||||
|
||||
callGatewayMock.mockImplementation(async (opts: unknown) => {
|
||||
const req = opts as { method?: string };
|
||||
if (req.method === "agent") {
|
||||
return { runId: "run-1", status: "accepted", acceptedAt: 1 };
|
||||
}
|
||||
// Prevent background announce flow by returning a non-terminal status.
|
||||
if (req.method === "agent.wait") {
|
||||
return { runId: "run-1", status: "running" };
|
||||
}
|
||||
return {};
|
||||
});
|
||||
});
|
||||
|
||||
it("captures threadId in requesterOrigin", async () => {
|
||||
const run = await spawnAndReadRequesterRun({ agentThreadId: 42 });
|
||||
expect(run?.requesterOrigin).toMatchObject({
|
||||
channel: "telegram",
|
||||
to: "telegram:123",
|
||||
threadId: 42,
|
||||
});
|
||||
});
|
||||
|
||||
it("stores requesterOrigin without threadId when none is provided", async () => {
|
||||
const run = await spawnAndReadRequesterRun();
|
||||
expect(run?.requesterOrigin?.threadId).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -107,6 +107,7 @@ describe("spawnSubagentDirect seam flow", () => {
|
||||
agentChannel: "discord",
|
||||
agentAccountId: "acct-1",
|
||||
agentTo: "user-1",
|
||||
agentThreadId: 42,
|
||||
workspaceDir: "/tmp/requester-workspace",
|
||||
},
|
||||
);
|
||||
@@ -132,7 +133,7 @@ describe("spawnSubagentDirect seam flow", () => {
|
||||
channel: "discord",
|
||||
accountId: "acct-1",
|
||||
to: "user-1",
|
||||
threadId: undefined,
|
||||
threadId: 42,
|
||||
},
|
||||
task: "inspect the spawn seam",
|
||||
cleanup: "keep",
|
||||
@@ -162,6 +163,44 @@ describe("spawnSubagentDirect seam flow", () => {
|
||||
expect(operations.indexOf("gateway:agent")).toBeGreaterThan(operations.indexOf("store:update"));
|
||||
});
|
||||
|
||||
it("omits requesterOrigin threadId when no requester thread is provided", async () => {
|
||||
hoisted.callGatewayMock.mockImplementation(async (request: { method?: string }) => {
|
||||
if (request.method === "agent") {
|
||||
return { runId: "run-1" };
|
||||
}
|
||||
if (request.method?.startsWith("sessions.")) {
|
||||
return { ok: true };
|
||||
}
|
||||
return {};
|
||||
});
|
||||
installSessionStoreCaptureMock(hoisted.updateSessionStoreMock);
|
||||
|
||||
const result = await spawnSubagentDirect(
|
||||
{
|
||||
task: "inspect unthreaded spawn",
|
||||
model: "openai-codex/gpt-5.4",
|
||||
},
|
||||
{
|
||||
agentSessionKey: "agent:main:main",
|
||||
agentChannel: "discord",
|
||||
agentAccountId: "acct-1",
|
||||
agentTo: "user-1",
|
||||
},
|
||||
);
|
||||
|
||||
expect(result.status).toBe("accepted");
|
||||
expect(hoisted.registerSubagentRunMock).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
requesterOrigin: expect.objectContaining({
|
||||
channel: "discord",
|
||||
accountId: "acct-1",
|
||||
to: "user-1",
|
||||
threadId: undefined,
|
||||
}),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("pins admin-only methods to operator.admin and preserves least-privilege for others (#59428)", async () => {
|
||||
const capturedCalls: Array<{ method?: string; scopes?: string[] }> = [];
|
||||
|
||||
|
||||
@@ -1,12 +1,22 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import type { OpenClawConfig } from "../../../config/types.js";
|
||||
import { applyLegacyDoctorMigrations } from "./legacy-config-compat.js";
|
||||
import { LEGACY_CONFIG_MIGRATIONS_RUNTIME_TTS } from "./legacy-config-migrations.runtime.tts.js";
|
||||
|
||||
function migrateLegacyConfig(raw: unknown): {
|
||||
config: OpenClawConfig | null;
|
||||
changes: string[];
|
||||
} {
|
||||
const { next, changes } = applyLegacyDoctorMigrations(raw);
|
||||
if (!raw || typeof raw !== "object") {
|
||||
return { config: null, changes: [] };
|
||||
}
|
||||
const next = structuredClone(raw) as Record<string, unknown>;
|
||||
const changes: string[] = [];
|
||||
for (const migration of LEGACY_CONFIG_MIGRATIONS_RUNTIME_TTS) {
|
||||
migration.apply(next, changes);
|
||||
}
|
||||
if (changes.length === 0) {
|
||||
return { config: null, changes };
|
||||
}
|
||||
return { config: next as OpenClawConfig | null, changes };
|
||||
}
|
||||
|
||||
@@ -38,41 +48,6 @@ describe("legacy migrate provider-shaped config", () => {
|
||||
});
|
||||
});
|
||||
|
||||
it("moves channels.discord.accounts.<id>.voice.tts.edge into providers.microsoft", () => {
|
||||
const res = migrateLegacyConfig({
|
||||
channels: {
|
||||
discord: {
|
||||
accounts: {
|
||||
main: {
|
||||
voice: {
|
||||
tts: {
|
||||
edge: {
|
||||
voice: "en-US-JennyNeural",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(res.changes).toContain(
|
||||
"Moved channels.discord.accounts.main.voice.tts.edge → channels.discord.accounts.main.voice.tts.providers.microsoft.",
|
||||
);
|
||||
const mainTts = (
|
||||
res.config?.channels?.discord?.accounts as
|
||||
| Record<string, { voice?: { tts?: Record<string, unknown> } }>
|
||||
| undefined
|
||||
)?.main?.voice?.tts;
|
||||
expect(mainTts?.providers).toEqual({
|
||||
microsoft: {
|
||||
voice: "en-US-JennyNeural",
|
||||
},
|
||||
});
|
||||
expect(mainTts?.edge).toBeUndefined();
|
||||
});
|
||||
|
||||
it("moves plugins.entries.voice-call.config.tts.<provider> keys into providers", () => {
|
||||
const res = migrateLegacyConfig({
|
||||
plugins: {
|
||||
|
||||
Reference in New Issue
Block a user