mirror of
https://github.com/modelstudioai/cli.git
synced 2026-09-14 19:49:23 +08:00
d24104f7dc
包名 @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 通过。
69 lines
2.9 KiB
TypeScript
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"]);
|
|
});
|
|
});
|