Initialize repository with harness code and assets
Initial import of all source code, config, and README assets: the packages workspace (cli, core, server, web, docs, landing, skills), build scripts, tooling config, and CI workflows. Includes the data-layout revision made on this branch: the local data root defaults to ~/.penguin/data (PENGUIN_HOME still overrides; the installer keeps its binaries in ~/.penguin), and every Agent lives under <project>/agents/<agent>/ — path helpers, the three agent-enumeration scans, the system prompt, built-in Skills, tests and docs all follow the new layout. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018ihk8iQuo3kv2aPjAYEPuR
This commit is contained in:
1 parent
056bed7aeb
commit
45bfae6e94
543 files changed
+92949
No files matched your search
@@ -0,0 +1,90 @@
|
||||
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { afterEach, describe, expect, it } from "vitest";
|
||||
import { applyLanguageToRc, resolveShellRc, upsertBlock } from "../src/lang-config.js";
|
||||
|
||||
describe("resolveShellRc", () => {
|
||||
it("maps zsh / bash / fish to their startup files and syntax", () => {
|
||||
const zsh = resolveShellRc("/bin/zsh", "/home/u");
|
||||
expect(zsh.kind).toBe("zsh");
|
||||
expect(zsh.rcPath).toBe("/home/u/.zshrc");
|
||||
expect(zsh.body("zh")).toBe("export PENGUIN_LANG=zh");
|
||||
|
||||
const bash = resolveShellRc("/usr/bin/bash", "/home/u");
|
||||
expect(bash.kind).toBe("bash");
|
||||
expect(bash.rcPath).toBe("/home/u/.bashrc");
|
||||
|
||||
const fish = resolveShellRc("/usr/local/bin/fish", "/home/u");
|
||||
expect(fish.kind).toBe("fish");
|
||||
expect(fish.rcPath).toBe("/home/u/.config/fish/config.fish");
|
||||
expect(fish.body("en")).toBe("set -gx PENGUIN_LANG en");
|
||||
});
|
||||
|
||||
it("falls back to ~/.profile for an unknown shell", () => {
|
||||
const rc = resolveShellRc(undefined, "/home/u");
|
||||
expect(rc.kind).toBe("unknown");
|
||||
expect(rc.rcPath).toBe("/home/u/.profile");
|
||||
});
|
||||
});
|
||||
|
||||
describe("upsertBlock", () => {
|
||||
it("appends a marked block when none exists", () => {
|
||||
const out = upsertBlock("export PATH=/x\n", "export PENGUIN_LANG=zh");
|
||||
expect(out).toContain("export PATH=/x");
|
||||
expect(out).toContain("# >>> PenguinHarness PENGUIN_LANG >>>");
|
||||
expect(out).toContain("export PENGUIN_LANG=zh");
|
||||
expect(out).toContain("# <<< PenguinHarness PENGUIN_LANG <<<");
|
||||
});
|
||||
|
||||
it("replaces the block in place and is idempotent", () => {
|
||||
const first = upsertBlock("", "export PENGUIN_LANG=zh");
|
||||
const second = upsertBlock(first, "export PENGUIN_LANG=en");
|
||||
// Only one block remains, with its content replaced by the latest value.
|
||||
expect(second.match(/PenguinHarness PENGUIN_LANG/g)?.length).toBe(2); // begin + end markers
|
||||
expect(second).toContain("export PENGUIN_LANG=en");
|
||||
expect(second).not.toContain("export PENGUIN_LANG=zh");
|
||||
// Writing the same value again is stable (the block does not keep growing).
|
||||
const third = upsertBlock(second, "export PENGUIN_LANG=en");
|
||||
expect(third).toBe(second);
|
||||
});
|
||||
|
||||
it("preserves surrounding content when replacing", () => {
|
||||
const base = "line1\n" + upsertBlock("", "export PENGUIN_LANG=zh") + "line2\n";
|
||||
const out = upsertBlock(base, "export PENGUIN_LANG=en");
|
||||
expect(out.startsWith("line1\n")).toBe(true);
|
||||
expect(out.endsWith("line2\n")).toBe(true);
|
||||
expect(out).toContain("export PENGUIN_LANG=en");
|
||||
});
|
||||
});
|
||||
|
||||
describe("applyLanguageToRc", () => {
|
||||
let home: string;
|
||||
afterEach(async () => {
|
||||
await rm(home, { recursive: true, force: true });
|
||||
});
|
||||
|
||||
it("writes the export line to the resolved startup file", async () => {
|
||||
home = await mkdtemp(join(tmpdir(), "penguin-lang-"));
|
||||
const { rcPath, kind } = await applyLanguageToRc("zh", { shell: "/bin/zsh", home });
|
||||
expect(kind).toBe("zsh");
|
||||
expect(rcPath).toBe(join(home, ".zshrc"));
|
||||
const content = await readFile(rcPath, "utf8");
|
||||
expect(content).toContain("export PENGUIN_LANG=zh");
|
||||
|
||||
// Switching the language again updates the file in place instead of appending.
|
||||
await applyLanguageToRc("en", { shell: "/bin/zsh", home });
|
||||
const updated = await readFile(rcPath, "utf8");
|
||||
expect(updated).toContain("export PENGUIN_LANG=en");
|
||||
expect(updated).not.toContain("export PENGUIN_LANG=zh");
|
||||
expect(updated.match(/# >>> PenguinHarness/g)?.length).toBe(1);
|
||||
});
|
||||
|
||||
it("creates nested config dir for fish", async () => {
|
||||
home = await mkdtemp(join(tmpdir(), "penguin-lang-"));
|
||||
const { rcPath } = await applyLanguageToRc("en", { shell: "/usr/bin/fish", home });
|
||||
expect(rcPath).toBe(join(home, ".config", "fish", "config.fish"));
|
||||
const content = await readFile(rcPath, "utf8");
|
||||
expect(content).toContain("set -gx PENGUIN_LANG en");
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user