fix(ci): stabilize windows tests
This commit is contained in:
@@ -327,14 +327,14 @@ export async function handleDirectiveOnly(params: {
|
|||||||
aliasIndex,
|
aliasIndex,
|
||||||
allowedModelKeys,
|
allowedModelKeys,
|
||||||
allowedModelCatalog,
|
allowedModelCatalog,
|
||||||
resetModelOverride,
|
resetModelOverride,
|
||||||
initialModelLabel,
|
initialModelLabel,
|
||||||
formatModelSwitchEvent,
|
formatModelSwitchEvent,
|
||||||
currentThinkLevel,
|
currentThinkLevel,
|
||||||
currentVerboseLevel,
|
currentVerboseLevel,
|
||||||
currentReasoningLevel,
|
currentReasoningLevel,
|
||||||
currentElevatedLevel,
|
currentElevatedLevel,
|
||||||
} = params;
|
} = params;
|
||||||
|
|
||||||
if (directives.hasModelDirective) {
|
if (directives.hasModelDirective) {
|
||||||
const modelDirective = directives.rawModelDirective?.trim().toLowerCase();
|
const modelDirective = directives.rawModelDirective?.trim().toLowerCase();
|
||||||
|
|||||||
@@ -7,11 +7,33 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|||||||
async function withTempHome<T>(fn: (home: string) => Promise<T>): Promise<T> {
|
async function withTempHome<T>(fn: (home: string) => Promise<T>): Promise<T> {
|
||||||
const base = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-config-"));
|
const base = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-config-"));
|
||||||
const previousHome = process.env.HOME;
|
const previousHome = process.env.HOME;
|
||||||
|
const previousUserProfile = process.env.USERPROFILE;
|
||||||
|
const previousHomeDrive = process.env.HOMEDRIVE;
|
||||||
|
const previousHomePath = process.env.HOMEPATH;
|
||||||
process.env.HOME = base;
|
process.env.HOME = base;
|
||||||
|
process.env.USERPROFILE = base;
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
const parsed = path.parse(base);
|
||||||
|
process.env.HOMEDRIVE = parsed.root.replace(/\\$/, "");
|
||||||
|
process.env.HOMEPATH = base.slice(Math.max(parsed.root.length - 1, 0));
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
return await fn(base);
|
return await fn(base);
|
||||||
} finally {
|
} finally {
|
||||||
process.env.HOME = previousHome;
|
process.env.HOME = previousHome;
|
||||||
|
process.env.USERPROFILE = previousUserProfile;
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
if (previousHomeDrive === undefined) {
|
||||||
|
delete process.env.HOMEDRIVE;
|
||||||
|
} else {
|
||||||
|
process.env.HOMEDRIVE = previousHomeDrive;
|
||||||
|
}
|
||||||
|
if (previousHomePath === undefined) {
|
||||||
|
delete process.env.HOMEPATH;
|
||||||
|
} else {
|
||||||
|
process.env.HOMEPATH = previousHomePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
await fs.rm(base, { recursive: true, force: true });
|
await fs.rm(base, { recursive: true, force: true });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -402,7 +424,7 @@ describe("Nix integration (U3, U5, U9)", () => {
|
|||||||
{ CLAWDBOT_STATE_DIR: "/custom/state/dir" },
|
{ CLAWDBOT_STATE_DIR: "/custom/state/dir" },
|
||||||
async () => {
|
async () => {
|
||||||
const { STATE_DIR_CLAWDBOT } = await import("./config.js");
|
const { STATE_DIR_CLAWDBOT } = await import("./config.js");
|
||||||
expect(STATE_DIR_CLAWDBOT).toBe("/custom/state/dir");
|
expect(STATE_DIR_CLAWDBOT).toBe(path.resolve("/custom/state/dir"));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -412,7 +434,9 @@ describe("Nix integration (U3, U5, U9)", () => {
|
|||||||
{ CLAWDBOT_CONFIG_PATH: undefined, CLAWDBOT_STATE_DIR: undefined },
|
{ CLAWDBOT_CONFIG_PATH: undefined, CLAWDBOT_STATE_DIR: undefined },
|
||||||
async () => {
|
async () => {
|
||||||
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
||||||
expect(CONFIG_PATH_CLAWDBOT).toMatch(/\.clawdbot\/clawdbot\.json$/);
|
expect(CONFIG_PATH_CLAWDBOT).toMatch(
|
||||||
|
/\.clawdbot[\\/]clawdbot\.json$/,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -435,7 +459,9 @@ describe("Nix integration (U3, U5, U9)", () => {
|
|||||||
},
|
},
|
||||||
async () => {
|
async () => {
|
||||||
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
const { CONFIG_PATH_CLAWDBOT } = await import("./config.js");
|
||||||
expect(CONFIG_PATH_CLAWDBOT).toBe("/custom/state/clawdbot.json");
|
expect(CONFIG_PATH_CLAWDBOT).toBe(
|
||||||
|
path.join(path.resolve("/custom/state"), "clawdbot.json"),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import path from "node:path";
|
||||||
import { describe, expect, it } from "vitest";
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
import { resolveOAuthDir, resolveOAuthPath } from "./paths.js";
|
import { resolveOAuthDir, resolveOAuthPath } from "./paths.js";
|
||||||
@@ -9,9 +10,11 @@ describe("oauth paths", () => {
|
|||||||
CLAWDBOT_STATE_DIR: "/custom/state",
|
CLAWDBOT_STATE_DIR: "/custom/state",
|
||||||
} as NodeJS.ProcessEnv;
|
} as NodeJS.ProcessEnv;
|
||||||
|
|
||||||
expect(resolveOAuthDir(env, "/custom/state")).toBe("/custom/oauth");
|
expect(resolveOAuthDir(env, "/custom/state")).toBe(
|
||||||
|
path.resolve("/custom/oauth"),
|
||||||
|
);
|
||||||
expect(resolveOAuthPath(env, "/custom/state")).toBe(
|
expect(resolveOAuthPath(env, "/custom/state")).toBe(
|
||||||
"/custom/oauth/oauth.json",
|
path.join(path.resolve("/custom/oauth"), "oauth.json"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -21,10 +24,10 @@ describe("oauth paths", () => {
|
|||||||
} as NodeJS.ProcessEnv;
|
} as NodeJS.ProcessEnv;
|
||||||
|
|
||||||
expect(resolveOAuthDir(env, "/custom/state")).toBe(
|
expect(resolveOAuthDir(env, "/custom/state")).toBe(
|
||||||
"/custom/state/credentials",
|
path.join("/custom/state", "credentials"),
|
||||||
);
|
);
|
||||||
expect(resolveOAuthPath(env, "/custom/state")).toBe(
|
expect(resolveOAuthPath(env, "/custom/state")).toBe(
|
||||||
"/custom/state/credentials/oauth.json",
|
path.join("/custom/state", "credentials", "oauth.json"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -138,7 +138,9 @@ describe("sessions", () => {
|
|||||||
{ CLAWDBOT_STATE_DIR: "/custom/state" } as NodeJS.ProcessEnv,
|
{ CLAWDBOT_STATE_DIR: "/custom/state" } as NodeJS.ProcessEnv,
|
||||||
() => "/home/ignored",
|
() => "/home/ignored",
|
||||||
);
|
);
|
||||||
expect(dir).toBe("/custom/state/agents/main/sessions");
|
expect(dir).toBe(
|
||||||
|
path.join(path.resolve("/custom/state"), "agents", "main", "sessions"),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("falls back to CLAWDIS_STATE_DIR for session transcripts dir", () => {
|
it("falls back to CLAWDIS_STATE_DIR for session transcripts dir", () => {
|
||||||
@@ -146,7 +148,9 @@ describe("sessions", () => {
|
|||||||
{ CLAWDIS_STATE_DIR: "/legacy/state" } as NodeJS.ProcessEnv,
|
{ CLAWDIS_STATE_DIR: "/legacy/state" } as NodeJS.ProcessEnv,
|
||||||
() => "/home/ignored",
|
() => "/home/ignored",
|
||||||
);
|
);
|
||||||
expect(dir).toBe("/legacy/state/agents/main/sessions");
|
expect(dir).toBe(
|
||||||
|
path.join(path.resolve("/legacy/state"), "agents", "main", "sessions"),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("includes topic ids in session transcript filenames", () => {
|
it("includes topic ids in session transcript filenames", () => {
|
||||||
@@ -155,7 +159,13 @@ describe("sessions", () => {
|
|||||||
try {
|
try {
|
||||||
const sessionFile = resolveSessionTranscriptPath("sess-1", "main", 123);
|
const sessionFile = resolveSessionTranscriptPath("sess-1", "main", 123);
|
||||||
expect(sessionFile).toBe(
|
expect(sessionFile).toBe(
|
||||||
"/custom/state/agents/main/sessions/sess-1-topic-123.jsonl",
|
path.join(
|
||||||
|
path.resolve("/custom/state"),
|
||||||
|
"agents",
|
||||||
|
"main",
|
||||||
|
"sessions",
|
||||||
|
"sess-1-topic-123.jsonl",
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
if (prev === undefined) {
|
if (prev === undefined) {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import path from "node:path";
|
||||||
import { afterEach, describe, expect, it, vi } from "vitest";
|
import { afterEach, describe, expect, it, vi } from "vitest";
|
||||||
|
|
||||||
const fsMocks = vi.hoisted(() => ({
|
const fsMocks = vi.hoisted(() => ({
|
||||||
@@ -22,14 +23,16 @@ afterEach(() => {
|
|||||||
|
|
||||||
describe("resolveGatewayProgramArguments", () => {
|
describe("resolveGatewayProgramArguments", () => {
|
||||||
it("uses realpath-resolved dist entry when running via npx shim", async () => {
|
it("uses realpath-resolved dist entry when running via npx shim", async () => {
|
||||||
process.argv = ["node", "/tmp/.npm/_npx/63c3/node_modules/.bin/clawdbot"];
|
const argv1 = path.resolve(
|
||||||
fsMocks.realpath.mockResolvedValue(
|
"/tmp/.npm/_npx/63c3/node_modules/.bin/clawdbot",
|
||||||
|
);
|
||||||
|
const entryPath = path.resolve(
|
||||||
"/tmp/.npm/_npx/63c3/node_modules/clawdbot/dist/entry.js",
|
"/tmp/.npm/_npx/63c3/node_modules/clawdbot/dist/entry.js",
|
||||||
);
|
);
|
||||||
|
process.argv = ["node", argv1];
|
||||||
|
fsMocks.realpath.mockResolvedValue(entryPath);
|
||||||
fsMocks.access.mockImplementation(async (target: string) => {
|
fsMocks.access.mockImplementation(async (target: string) => {
|
||||||
if (
|
if (target === entryPath) {
|
||||||
target === "/tmp/.npm/_npx/63c3/node_modules/clawdbot/dist/entry.js"
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new Error("missing");
|
throw new Error("missing");
|
||||||
@@ -39,7 +42,7 @@ describe("resolveGatewayProgramArguments", () => {
|
|||||||
|
|
||||||
expect(result.programArguments).toEqual([
|
expect(result.programArguments).toEqual([
|
||||||
process.execPath,
|
process.execPath,
|
||||||
"/tmp/.npm/_npx/63c3/node_modules/clawdbot/dist/entry.js",
|
entryPath,
|
||||||
"gateway-daemon",
|
"gateway-daemon",
|
||||||
"--port",
|
"--port",
|
||||||
"18789",
|
"18789",
|
||||||
@@ -47,12 +50,16 @@ describe("resolveGatewayProgramArguments", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("falls back to node_modules package dist when .bin path is not resolved", async () => {
|
it("falls back to node_modules package dist when .bin path is not resolved", async () => {
|
||||||
process.argv = ["node", "/tmp/.npm/_npx/63c3/node_modules/.bin/clawdbot"];
|
const argv1 = path.resolve(
|
||||||
|
"/tmp/.npm/_npx/63c3/node_modules/.bin/clawdbot",
|
||||||
|
);
|
||||||
|
const indexPath = path.resolve(
|
||||||
|
"/tmp/.npm/_npx/63c3/node_modules/clawdbot/dist/index.js",
|
||||||
|
);
|
||||||
|
process.argv = ["node", argv1];
|
||||||
fsMocks.realpath.mockRejectedValue(new Error("no realpath"));
|
fsMocks.realpath.mockRejectedValue(new Error("no realpath"));
|
||||||
fsMocks.access.mockImplementation(async (target: string) => {
|
fsMocks.access.mockImplementation(async (target: string) => {
|
||||||
if (
|
if (target === indexPath) {
|
||||||
target === "/tmp/.npm/_npx/63c3/node_modules/clawdbot/dist/index.js"
|
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
throw new Error("missing");
|
throw new Error("missing");
|
||||||
@@ -62,7 +69,7 @@ describe("resolveGatewayProgramArguments", () => {
|
|||||||
|
|
||||||
expect(result.programArguments).toEqual([
|
expect(result.programArguments).toEqual([
|
||||||
process.execPath,
|
process.execPath,
|
||||||
"/tmp/.npm/_npx/63c3/node_modules/clawdbot/dist/index.js",
|
indexPath,
|
||||||
"gateway-daemon",
|
"gateway-daemon",
|
||||||
"--port",
|
"--port",
|
||||||
"18789",
|
"18789",
|
||||||
|
|||||||
@@ -17,6 +17,44 @@ import {
|
|||||||
installGatewayTestHooks();
|
installGatewayTestHooks();
|
||||||
|
|
||||||
describe("gateway server models + voicewake", () => {
|
describe("gateway server models + voicewake", () => {
|
||||||
|
const setTempHome = (homeDir: string) => {
|
||||||
|
const prevHome = process.env.HOME;
|
||||||
|
const prevUserProfile = process.env.USERPROFILE;
|
||||||
|
const prevHomeDrive = process.env.HOMEDRIVE;
|
||||||
|
const prevHomePath = process.env.HOMEPATH;
|
||||||
|
process.env.HOME = homeDir;
|
||||||
|
process.env.USERPROFILE = homeDir;
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
const parsed = path.parse(homeDir);
|
||||||
|
process.env.HOMEDRIVE = parsed.root.replace(/\\$/, "");
|
||||||
|
process.env.HOMEPATH = homeDir.slice(Math.max(parsed.root.length - 1, 0));
|
||||||
|
}
|
||||||
|
return () => {
|
||||||
|
if (prevHome === undefined) {
|
||||||
|
delete process.env.HOME;
|
||||||
|
} else {
|
||||||
|
process.env.HOME = prevHome;
|
||||||
|
}
|
||||||
|
if (prevUserProfile === undefined) {
|
||||||
|
delete process.env.USERPROFILE;
|
||||||
|
} else {
|
||||||
|
process.env.USERPROFILE = prevUserProfile;
|
||||||
|
}
|
||||||
|
if (process.platform === "win32") {
|
||||||
|
if (prevHomeDrive === undefined) {
|
||||||
|
delete process.env.HOMEDRIVE;
|
||||||
|
} else {
|
||||||
|
process.env.HOMEDRIVE = prevHomeDrive;
|
||||||
|
}
|
||||||
|
if (prevHomePath === undefined) {
|
||||||
|
delete process.env.HOMEPATH;
|
||||||
|
} else {
|
||||||
|
process.env.HOMEPATH = prevHomePath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
test(
|
test(
|
||||||
"voicewake.get returns defaults and voicewake.set broadcasts",
|
"voicewake.get returns defaults and voicewake.set broadcasts",
|
||||||
{ timeout: 15_000 },
|
{ timeout: 15_000 },
|
||||||
@@ -24,8 +62,7 @@ describe("gateway server models + voicewake", () => {
|
|||||||
const homeDir = await fs.mkdtemp(
|
const homeDir = await fs.mkdtemp(
|
||||||
path.join(os.tmpdir(), "clawdbot-home-"),
|
path.join(os.tmpdir(), "clawdbot-home-"),
|
||||||
);
|
);
|
||||||
const prevHome = process.env.HOME;
|
const restoreHome = setTempHome(homeDir);
|
||||||
process.env.HOME = homeDir;
|
|
||||||
|
|
||||||
const { server, ws } = await startServerWithClient();
|
const { server, ws } = await startServerWithClient();
|
||||||
await connectOk(ws);
|
await connectOk(ws);
|
||||||
@@ -72,18 +109,13 @@ describe("gateway server models + voicewake", () => {
|
|||||||
ws.close();
|
ws.close();
|
||||||
await server.close();
|
await server.close();
|
||||||
|
|
||||||
if (prevHome === undefined) {
|
restoreHome();
|
||||||
delete process.env.HOME;
|
|
||||||
} else {
|
|
||||||
process.env.HOME = prevHome;
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
test("pushes voicewake.changed to nodes on connect and on updates", async () => {
|
test("pushes voicewake.changed to nodes on connect and on updates", async () => {
|
||||||
const homeDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-home-"));
|
const homeDir = await fs.mkdtemp(path.join(os.tmpdir(), "clawdbot-home-"));
|
||||||
const prevHome = process.env.HOME;
|
const restoreHome = setTempHome(homeDir);
|
||||||
process.env.HOME = homeDir;
|
|
||||||
|
|
||||||
bridgeSendEvent.mockClear();
|
bridgeSendEvent.mockClear();
|
||||||
bridgeListConnected.mockReturnValue([{ nodeId: "n1" }]);
|
bridgeListConnected.mockReturnValue([{ nodeId: "n1" }]);
|
||||||
@@ -124,11 +156,7 @@ describe("gateway server models + voicewake", () => {
|
|||||||
ws.close();
|
ws.close();
|
||||||
await server.close();
|
await server.close();
|
||||||
|
|
||||||
if (prevHome === undefined) {
|
restoreHome();
|
||||||
delete process.env.HOME;
|
|
||||||
} else {
|
|
||||||
process.env.HOME = prevHome;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test("models.list returns model catalog", async () => {
|
test("models.list returns model catalog", async () => {
|
||||||
|
|||||||
@@ -49,11 +49,11 @@ describe("brew helpers", () => {
|
|||||||
it("includes Linuxbrew bin/sbin in path candidates", () => {
|
it("includes Linuxbrew bin/sbin in path candidates", () => {
|
||||||
const env: NodeJS.ProcessEnv = { HOMEBREW_PREFIX: "/custom/prefix" };
|
const env: NodeJS.ProcessEnv = { HOMEBREW_PREFIX: "/custom/prefix" };
|
||||||
const dirs = resolveBrewPathDirs({ homeDir: "/home/test", env });
|
const dirs = resolveBrewPathDirs({ homeDir: "/home/test", env });
|
||||||
expect(dirs).toContain("/custom/prefix/bin");
|
expect(dirs).toContain(path.join("/custom/prefix", "bin"));
|
||||||
expect(dirs).toContain("/custom/prefix/sbin");
|
expect(dirs).toContain(path.join("/custom/prefix", "sbin"));
|
||||||
expect(dirs).toContain("/home/linuxbrew/.linuxbrew/bin");
|
expect(dirs).toContain("/home/linuxbrew/.linuxbrew/bin");
|
||||||
expect(dirs).toContain("/home/linuxbrew/.linuxbrew/sbin");
|
expect(dirs).toContain("/home/linuxbrew/.linuxbrew/sbin");
|
||||||
expect(dirs).toContain("/home/test/.linuxbrew/bin");
|
expect(dirs).toContain(path.join("/home/test", ".linuxbrew", "bin"));
|
||||||
expect(dirs).toContain("/home/test/.linuxbrew/sbin");
|
expect(dirs).toContain(path.join("/home/test", ".linuxbrew", "sbin"));
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -51,9 +51,10 @@ describe("control UI assets helpers", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("resolves dist control-ui index path for dist argv1", () => {
|
it("resolves dist control-ui index path for dist argv1", () => {
|
||||||
const argv1 = path.join("/tmp", "pkg", "dist", "index.js");
|
const argv1 = path.resolve("/tmp", "pkg", "dist", "index.js");
|
||||||
|
const distDir = path.dirname(argv1);
|
||||||
expect(resolveControlUiDistIndexPath(argv1)).toBe(
|
expect(resolveControlUiDistIndexPath(argv1)).toBe(
|
||||||
path.join("/tmp", "pkg", "dist", "control-ui", "index.html"),
|
path.join(distDir, "control-ui", "index.html"),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,6 +5,11 @@ import { describe, expect, it, vi } from "vitest";
|
|||||||
import { HEARTBEAT_PROMPT } from "../auto-reply/heartbeat.js";
|
import { HEARTBEAT_PROMPT } from "../auto-reply/heartbeat.js";
|
||||||
import * as replyModule from "../auto-reply/reply.js";
|
import * as replyModule from "../auto-reply/reply.js";
|
||||||
import type { ClawdbotConfig } from "../config/config.js";
|
import type { ClawdbotConfig } from "../config/config.js";
|
||||||
|
import {
|
||||||
|
resolveAgentIdFromSessionKey,
|
||||||
|
resolveMainSessionKey,
|
||||||
|
resolveStorePath,
|
||||||
|
} from "../config/sessions.js";
|
||||||
import {
|
import {
|
||||||
resolveHeartbeatIntervalMs,
|
resolveHeartbeatIntervalMs,
|
||||||
resolveHeartbeatPrompt,
|
resolveHeartbeatPrompt,
|
||||||
@@ -192,15 +197,24 @@ describe("runHeartbeatOnce", () => {
|
|||||||
"{agentId}",
|
"{agentId}",
|
||||||
"sessions.json",
|
"sessions.json",
|
||||||
);
|
);
|
||||||
const storePath = path.join(tmpDir, "agents", "work", "sessions.json");
|
|
||||||
const replySpy = vi.spyOn(replyModule, "getReplyFromConfig");
|
const replySpy = vi.spyOn(replyModule, "getReplyFromConfig");
|
||||||
try {
|
try {
|
||||||
|
const cfg: ClawdbotConfig = {
|
||||||
|
routing: { defaultAgentId: "work" },
|
||||||
|
agent: { heartbeat: { every: "5m" } },
|
||||||
|
whatsapp: { allowFrom: ["*"] },
|
||||||
|
session: { store: storeTemplate },
|
||||||
|
};
|
||||||
|
const sessionKey = resolveMainSessionKey(cfg);
|
||||||
|
const agentId = resolveAgentIdFromSessionKey(sessionKey);
|
||||||
|
const storePath = resolveStorePath(storeTemplate, { agentId });
|
||||||
|
|
||||||
await fs.mkdir(path.dirname(storePath), { recursive: true });
|
await fs.mkdir(path.dirname(storePath), { recursive: true });
|
||||||
await fs.writeFile(
|
await fs.writeFile(
|
||||||
storePath,
|
storePath,
|
||||||
JSON.stringify(
|
JSON.stringify(
|
||||||
{
|
{
|
||||||
"agent:work:main": {
|
[sessionKey]: {
|
||||||
sessionId: "sid",
|
sessionId: "sid",
|
||||||
updatedAt: Date.now(),
|
updatedAt: Date.now(),
|
||||||
lastProvider: "whatsapp",
|
lastProvider: "whatsapp",
|
||||||
@@ -212,13 +226,6 @@ describe("runHeartbeatOnce", () => {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
const cfg: ClawdbotConfig = {
|
|
||||||
routing: { defaultAgentId: "work" },
|
|
||||||
agent: { heartbeat: { every: "5m" } },
|
|
||||||
whatsapp: { allowFrom: ["*"] },
|
|
||||||
session: { store: storeTemplate },
|
|
||||||
};
|
|
||||||
|
|
||||||
replySpy.mockResolvedValue({ text: "Hello from heartbeat" });
|
replySpy.mockResolvedValue({ text: "Hello from heartbeat" });
|
||||||
const sendWhatsApp = vi.fn().mockResolvedValue({
|
const sendWhatsApp = vi.fn().mockResolvedValue({
|
||||||
messageId: "m1",
|
messageId: "m1",
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
import fs from "node:fs/promises";
|
import fs from "node:fs/promises";
|
||||||
|
import os from "node:os";
|
||||||
|
import path from "node:path";
|
||||||
|
|
||||||
import { DisconnectReason } from "@whiskeysockets/baileys";
|
import { DisconnectReason } from "@whiskeysockets/baileys";
|
||||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||||
@@ -7,12 +9,14 @@ vi.useFakeTimers();
|
|||||||
|
|
||||||
const rmMock = vi.spyOn(fs, "rm");
|
const rmMock = vi.spyOn(fs, "rm");
|
||||||
|
|
||||||
|
const authDir = path.join(os.tmpdir(), "wa-creds");
|
||||||
|
|
||||||
vi.mock("../config/config.js", () => ({
|
vi.mock("../config/config.js", () => ({
|
||||||
loadConfig: () =>
|
loadConfig: () =>
|
||||||
({
|
({
|
||||||
whatsapp: {
|
whatsapp: {
|
||||||
accounts: {
|
accounts: {
|
||||||
default: { enabled: true, authDir: "/tmp/wa-creds" },
|
default: { enabled: true, authDir },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}) as never,
|
}) as never,
|
||||||
@@ -29,9 +33,9 @@ vi.mock("./session.js", () => {
|
|||||||
createWaSocket,
|
createWaSocket,
|
||||||
waitForWaConnection,
|
waitForWaConnection,
|
||||||
formatError,
|
formatError,
|
||||||
WA_WEB_AUTH_DIR: "/tmp/wa-creds",
|
WA_WEB_AUTH_DIR: authDir,
|
||||||
logoutWeb: vi.fn(async (params: { authDir?: string }) => {
|
logoutWeb: vi.fn(async (params: { authDir?: string }) => {
|
||||||
await fs.rm(params.authDir ?? "/tmp/wa-creds", {
|
await fs.rm(params.authDir ?? authDir, {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
force: true,
|
force: true,
|
||||||
});
|
});
|
||||||
@@ -75,7 +79,7 @@ describe("loginWeb coverage", () => {
|
|||||||
await expect(
|
await expect(
|
||||||
loginWeb(false, "web", waitForWaConnection as never),
|
loginWeb(false, "web", waitForWaConnection as never),
|
||||||
).rejects.toThrow(/cache cleared/i);
|
).rejects.toThrow(/cache cleared/i);
|
||||||
expect(rmMock).toHaveBeenCalledWith("/tmp/wa-creds", {
|
expect(rmMock).toHaveBeenCalledWith(authDir, {
|
||||||
recursive: true,
|
recursive: true,
|
||||||
force: true,
|
force: true,
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user