Files
penguin-harness/packages/cli/test/config-format.test.ts
T
Yaowei Zheng 45bfae6e94 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
2026-07-19 14:06:53 +08:00

69 lines
2.7 KiB
TypeScript

/**
* Unit tests for `config model list` rendering: provider and model_id are separate
* columns (stored fields as-is, with the default model marked `*` before the provider
* column; the request column was removed along with concatenated storage); vision falls
* back to the catalog matched by the (provider, model_id) pair; api_key is masked
* inline; fully empty columns are omitted automatically.
*/
import { describe, expect, it } from "vitest";
import type { ProjectConfig } from "@prismshadow/penguin-core";
import { formatModelRows } from "../src/commands/config.js";
describe("formatModelRows", () => {
const cfg: ProjectConfig = {
default_model: { provider: "anthropic", model_id: "claude-sonnet-4-6" },
models: [
{
provider: "anthropic",
model_id: "claude-sonnet-4-6",
context_window: 1000000,
pricing: { unit: "usd_per_mtok", cache_read: 0.3, cache_write: 3.75, output: 15 },
},
{
provider: "custom",
model_id: "my-proxy-model",
client_type: "openai",
vision: false,
api_key: "sk-test-abcd-1234",
},
],
};
it("provider 与 model_id 双列展示;预置模型 vision 经目录成对匹配,默认模型以 * 标记", () => {
const lines = formatModelRows(cfg);
expect(lines).toHaveLength(2);
expect(lines[0]).toMatch(/^\* anthropic\s+claude-sonnet-4-6\s+vision=Y/);
expect(lines[0]).toContain("price=0.3/3.75/15");
// The request column was removed; no <provider>/<id> concatenation appears anymore.
expect(lines[0]).not.toContain("request=");
expect(lines[0]).not.toContain("anthropic/claude-sonnet-4-6");
});
it("自定义模型 vision 按标注(显式 false 记 -);内联 api_key 掩码显示", () => {
const lines = formatModelRows(cfg);
expect(lines[1]).toMatch(/^ {2}custom\s+my-proxy-model\s+vision=-/);
expect(lines[1]).toContain("client_type=openai");
expect(lines[1]).toContain("api_key=****1234");
expect(lines[1]).not.toContain("sk-test-abcd-1234");
});
it("同名 model_id 双 provider 并存时各占一行,默认标记只落在成对命中的那行", () => {
const lines = formatModelRows({
default_model: { provider: "deepseek", model_id: "m1" },
models: [
{ provider: "deepseek", model_id: "m1" },
{ provider: "siliconflow", model_id: "m1" },
],
});
expect(lines[0]).toMatch(/^\* deepseek\s+m1\s+vision=Y/);
expect(lines[1]).toMatch(/^ {2}siliconflow\s+m1\s+vision=Y/);
});
it("无标注按「缺省=支持」记 Y;全空列省略", () => {
const lines = formatModelRows({
models: [{ provider: "custom", model_id: "m1" }],
});
expect(lines[0]).toBe(" custom m1 vision=Y api_key=-");
});
});