forked from EduCraft/curriculum-project-hub
feat(hub): built-in PBank 题库 capability + role tools (v0.0.42)
Register pbank as an ADR-0027 external capability with org-scoped username/password envelopes, readiness via /login, and in-process cph_hub MCP tools (search/get/get_many) that materialize sources under the run workspace. Extend the capability secret payload for docmind vs pbank kinds, admin capabilities UI, role tool umbrella `pbank`, and the pbank-problem-report skill. Credentials never reach the Agent process.
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import {
|
||||
extractProblemId,
|
||||
normalizePbankBaseUrl,
|
||||
pbankRightsFromCredential,
|
||||
} from "../../src/capability/pbankClient.js";
|
||||
import type { PbankCapabilitySecretPayload } from "../../src/capability/types.js";
|
||||
import { claudeSdkToolConfigForRole, cphHubMcpToolsForRole } from "../../src/agent/roleTools.js";
|
||||
|
||||
describe("pbank client helpers", () => {
|
||||
it("extracts problem UUID from bare id and URL", () => {
|
||||
const id = "01234567-89ab-4def-8abc-0123456789ab";
|
||||
expect(extractProblemId(id)).toBe(id);
|
||||
expect(extractProblemId(`https://pbank.paradigm-edu.net/problem/${id}`)).toBe(id);
|
||||
expect(extractProblemId(`https://pbank.example/x?id=${id}`)).toBe(id);
|
||||
});
|
||||
|
||||
it("normalizes base URL trailing slashes", () => {
|
||||
expect(normalizePbankBaseUrl("https://pbank.paradigm-edu.net/api/")).toBe(
|
||||
"https://pbank.paradigm-edu.net/api",
|
||||
);
|
||||
expect(normalizePbankBaseUrl("")).toBe("https://pbank.paradigm-edu.net/api");
|
||||
});
|
||||
|
||||
it("marks derivative use from operator rights status", () => {
|
||||
const owned: PbankCapabilitySecretPayload = {
|
||||
schemaVersion: 1,
|
||||
kind: "pbank",
|
||||
baseUrl: "https://pbank.paradigm-edu.net/api",
|
||||
username: "u",
|
||||
password: "p",
|
||||
rightsStatus: "owned",
|
||||
};
|
||||
expect(pbankRightsFromCredential(owned).derivativeUseAllowed).toBe(true);
|
||||
|
||||
const unknown: PbankCapabilitySecretPayload = {
|
||||
...owned,
|
||||
rightsStatus: "unknown",
|
||||
};
|
||||
expect(pbankRightsFromCredential(unknown).derivativeUseAllowed).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe("role tool mapping for pbank", () => {
|
||||
it("maps umbrella pbank role tool to three MCP tools", () => {
|
||||
expect(cphHubMcpToolsForRole(["pbank"])).toEqual([
|
||||
"pbank_search_problems",
|
||||
"pbank_get_problem",
|
||||
"pbank_get_many_problems",
|
||||
]);
|
||||
const cfg = claudeSdkToolConfigForRole(["pbank", "Read"]);
|
||||
expect(cfg.tools).toContain("Read");
|
||||
expect(cfg.allowedTools).toContain("mcp__cph_hub__pbank_search_problems");
|
||||
expect(cfg.allowedTools).toContain("mcp__cph_hub__pbank_get_problem");
|
||||
expect(cfg.allowedTools).toContain("mcp__cph_hub__pbank_get_many_problems");
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user