Files
modelstudioai__cli/packages/bailian-kb-dsh/tests/client.test.ts
T
zeyu.fz d24104f7dc feat(kb-dsh): 接入仓库工程约定并改名为公开包 bailian-kb-dsh
包名 @ali/bailian-kb-dsh → bailian-kb-dsh(公开 npm):package.json name +
cordis.patch.yml insert.name + tsdown PLUGIN_ID 三处同步(漏一处即 dsh 运行时崩)。

产物 lib/ → dist/(本仓 .gitignore 忽略 dist 不忽略 lib),连带 main/types/
exports/files/tsdown outDir 同步;.gitignore 补 *.tsbuildinfo。

依赖接 catalog(yaml/typescript/@types/node/vite-plus);测试导入 vitest →
vite-plus/test(全仓统一约定,消掉唯一的 vitest 依赖漂移)。

tsconfig 拆三件套:tsconfig.json 纯类型检查覆盖 src+tests(供 oxlint 自动发现,
含 jsx/DOM),tsconfig.build.json 产出 node 半,tsconfig.web.json 隔离检查 web 半。
补齐 tests 从未被类型检查暴露的一处 partial 输入类型错误。

根 vite.config.ts 新增两条 override:web 半 no-restricted-imports 把 tsdown 构建期
的 bundle purity gate 提前到 lint 期;全包放开 _ 前缀的 no-unused-vars。

文档:新增 docs/agents/dsh-plugin.md,AGENTS.md 项目地图/版本锁步例外/分层边界/
场景索引同步,packages.mjs 注释说明故意不进发布白名单。

格式化(单引号无分号 → 双引号加分号)由 pre-commit 的 vp check --fix 自动完成,
无法单独成 commit,一并纳入。

全仓 vp check 0 error;插件 13 文件 85 测试全绿;build + typecheck 通过。
2026-08-24 11:02:44 +08:00

69 lines
2.9 KiB
TypeScript

import { describe, expect, it, vi } from "vite-plus/test";
import { KbApiError, KbClient } from "../src/client.js";
function makeClient(fetchImpl: typeof fetch) {
return new KbClient({
resolveWorkspaceId: async () => "ws-1",
endpointHost: "cn-beijing.maas.aliyuncs.com",
resolveApiKey: async () => "sk-test",
fetchImpl,
});
}
describe("KbClient.postJson", () => {
it("sends Bearer auth to the workspace endpoint and returns parsed JSON", async () => {
const fetchImpl = vi.fn(async () => new Response(JSON.stringify({ ok: 1 }), { status: 200 }));
const client = makeClient(fetchImpl as unknown as typeof fetch);
const result = await client.postJson<{ ok: number }>("/api/v1/indices/knowledge/search", {
query: "q",
});
expect(result.ok).toBe(1);
const [url, init] = fetchImpl.mock.calls[0] as unknown as [string, RequestInit];
expect(url).toBe("https://ws-1.cn-beijing.maas.aliyuncs.com/api/v1/indices/knowledge/search");
expect((init.headers as Record<string, string>).Authorization).toBe("Bearer sk-test");
expect(init.method).toBe("POST");
});
it("translates a non-2xx into KbApiError with status and a bounded body summary", async () => {
const body = JSON.stringify({ code: "InvalidParameter", message: "agent not found" });
const fetchImpl = vi.fn(async () => new Response(body, { status: 400 }));
const client = makeClient(fetchImpl as unknown as typeof fetch);
const err = await client
.postJson("/api/v1/indices/knowledge/search", {})
.catch((e: unknown) => e);
expect(err).toBeInstanceOf(KbApiError);
expect((err as KbApiError).status).toBe(400);
expect((err as KbApiError).message).toContain("agent not found");
});
it("re-resolves the API key per call (credential hot-swap contract)", async () => {
const resolveApiKey = vi.fn(async () => "sk-test");
const fetchImpl = vi.fn(async () => new Response("{}", { status: 200 }));
const client = new KbClient({
resolveWorkspaceId: async () => "ws-1",
endpointHost: "h",
resolveApiKey,
fetchImpl: fetchImpl as unknown as typeof fetch,
});
await client.postJson("/p", {});
await client.postJson("/p", {});
expect(resolveApiKey).toHaveBeenCalledTimes(2);
});
it("re-resolves the workspace id per call (credential hot-swap contract)", async () => {
let workspaceId = "ws-1";
const fetchImpl = vi.fn(async () => new Response("{}", { status: 200 }));
const client = new KbClient({
resolveWorkspaceId: async () => workspaceId,
endpointHost: "h",
resolveApiKey: async () => "sk-test",
fetchImpl: fetchImpl as unknown as typeof fetch,
});
await client.postJson("/p", {});
workspaceId = "ws-2";
await client.postJson("/p", {});
const urls = fetchImpl.mock.calls.map((call) => (call as unknown as [string])[0]);
expect(urls).toEqual(["https://ws-1.h/p", "https://ws-2.h/p"]);
});
});