test: cover identity defaults and pi flags

This commit is contained in:
Peter Steinberger
2025-12-14 04:39:36 +00:00
parent 969c7d1c8e
commit 7c677c5057
2 changed files with 192 additions and 0 deletions

View File

@@ -10,6 +10,8 @@ describe("pi agent helpers", () => {
bodyIndex: 1,
isNewSession: true,
sessionId: "sess",
provider: "anthropic",
model: "claude-opus-4-5",
sendSystemOnce: false,
systemSent: false,
identityPrefix: "IDENT",
@@ -18,6 +20,10 @@ describe("pi agent helpers", () => {
expect(built).toContain("-p");
expect(built).toContain("--mode");
expect(built).toContain("json");
expect(built).toContain("--provider");
expect(built).toContain("anthropic");
expect(built).toContain("--model");
expect(built).toContain("claude-opus-4-5");
expect(built.at(-1)).toContain("IDENT");
const builtNoIdentity = piSpec.buildArgs({
@@ -25,6 +31,8 @@ describe("pi agent helpers", () => {
bodyIndex: 1,
isNewSession: false,
sessionId: "sess",
provider: "anthropic",
model: "claude-opus-4-5",
sendSystemOnce: true,
systemSent: true,
identityPrefix: "IDENT",
@@ -33,6 +41,50 @@ describe("pi agent helpers", () => {
expect(builtNoIdentity.at(-1)).toBe("hi");
});
it("injects provider/model for pi invocations only and avoids duplicates", () => {
const base = piSpec.buildArgs({
argv: ["pi", "hello"],
bodyIndex: 1,
isNewSession: true,
sendSystemOnce: false,
systemSent: false,
format: "json",
});
expect(base.filter((a) => a === "--provider").length).toBe(1);
expect(base).toContain("anthropic");
expect(base.filter((a) => a === "--model").length).toBe(1);
expect(base).toContain("claude-opus-4-5");
const already = piSpec.buildArgs({
argv: [
"pi",
"--provider",
"anthropic",
"--model",
"claude-opus-4-5",
"hi",
],
bodyIndex: 5,
isNewSession: true,
sendSystemOnce: false,
systemSent: false,
format: "json",
});
expect(already.filter((a) => a === "--provider").length).toBe(1);
expect(already.filter((a) => a === "--model").length).toBe(1);
const nonPi = piSpec.buildArgs({
argv: ["echo", "hi"],
bodyIndex: 1,
isNewSession: true,
sendSystemOnce: false,
systemSent: false,
format: "json",
});
expect(nonPi).not.toContain("--provider");
expect(nonPi).not.toContain("--model");
});
it("parses final assistant message and preserves usage meta", () => {
const stdout = [
'{"type":"message_start","message":{"role":"assistant"}}',

140
src/config/config.test.ts Normal file
View File

@@ -0,0 +1,140 @@
import fs from "node:fs/promises";
import os from "node:os";
import path from "node:path";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
async function withTempHome<T>(fn: (home: string) => Promise<T>): Promise<T> {
const base = await fs.mkdtemp(path.join(os.tmpdir(), "clawdis-config-"));
const previousHome = process.env.HOME;
process.env.HOME = base;
try {
return await fn(base);
} finally {
process.env.HOME = previousHome;
await fs.rm(base, { recursive: true, force: true });
}
}
describe("config identity defaults", () => {
let previousHome: string | undefined;
beforeEach(() => {
previousHome = process.env.HOME;
});
afterEach(() => {
process.env.HOME = previousHome;
});
it("derives responsePrefix, mentionPatterns, and sessionIntro when identity is set", async () => {
await withTempHome(async (home) => {
const configDir = path.join(home, ".clawdis");
await fs.mkdir(configDir, { recursive: true });
await fs.writeFile(
path.join(configDir, "clawdis.json"),
JSON.stringify(
{
identity: { name: "Samantha", theme: "helpful sloth", emoji: "🦥" },
inbound: {
reply: {
mode: "command",
command: ["pi", "--mode", "rpc", "x"],
session: {},
},
},
},
null,
2,
),
"utf-8",
);
vi.resetModules();
const { loadConfig } = await import("./config.js");
const cfg = loadConfig();
expect(cfg.inbound?.responsePrefix).toBe("🦥");
expect(cfg.inbound?.groupChat?.mentionPatterns).toEqual([
"\\b@?Samantha\\b",
]);
expect(cfg.inbound?.reply?.session?.sessionIntro).toContain(
"You are Samantha.",
);
expect(cfg.inbound?.reply?.session?.sessionIntro).toContain(
"Theme: helpful sloth.",
);
expect(cfg.inbound?.reply?.session?.sessionIntro).toContain(
"Your emoji is 🦥.",
);
});
});
it("does not override explicit values", async () => {
await withTempHome(async (home) => {
const configDir = path.join(home, ".clawdis");
await fs.mkdir(configDir, { recursive: true });
await fs.writeFile(
path.join(configDir, "clawdis.json"),
JSON.stringify(
{
identity: {
name: "Samantha Sloth",
theme: "space lobster",
emoji: "🦞",
},
inbound: {
responsePrefix: "✅",
groupChat: { mentionPatterns: ["@clawd"] },
reply: {
mode: "command",
command: ["pi", "--mode", "rpc", "x"],
session: { sessionIntro: "Explicit intro" },
},
},
},
null,
2,
),
"utf-8",
);
vi.resetModules();
const { loadConfig } = await import("./config.js");
const cfg = loadConfig();
expect(cfg.inbound?.responsePrefix).toBe("✅");
expect(cfg.inbound?.groupChat?.mentionPatterns).toEqual(["@clawd"]);
expect(cfg.inbound?.reply?.session?.sessionIntro).toBe("Explicit intro");
});
});
it("does not synthesize inbound.reply when it is absent", async () => {
await withTempHome(async (home) => {
const configDir = path.join(home, ".clawdis");
await fs.mkdir(configDir, { recursive: true });
await fs.writeFile(
path.join(configDir, "clawdis.json"),
JSON.stringify(
{
identity: { name: "Samantha", theme: "helpful sloth", emoji: "🦥" },
inbound: {},
},
null,
2,
),
"utf-8",
);
vi.resetModules();
const { loadConfig } = await import("./config.js");
const cfg = loadConfig();
expect(cfg.inbound?.responsePrefix).toBe("🦥");
expect(cfg.inbound?.groupChat?.mentionPatterns).toEqual([
"\\b@?Samantha\\b",
]);
expect(cfg.inbound?.reply).toBeUndefined();
});
});
});