吸收数字员工技能远端策略下发

This commit is contained in:
baiyanyun
2026-06-11 09:04:08 +08:00
parent 751ce45619
commit 8ab3d73fb1
18 changed files with 876 additions and 207 deletions

View File

@@ -137,6 +137,106 @@ describe("digital employee sync service", () => {
});
});
it("pulls remote skill policies and preserves local skill preferences", async () => {
mockState.settings.set("digital_employee_skill_policies_v1", {
version: 1,
local_skills: {
"qimingclaw-acp-session": { enabled: false, updatedAt: "2026-06-07T07:00:00.000Z", source: "local" },
},
});
mockState.fetch.mockResolvedValue(jsonResponse({
success: true,
data: {
skill_policies: {
updated_at: "2026-06-07T08:01:00.000Z",
skills: {
"qimingclaw-mcp-tool-crm-crm-delete": {
enabled: false,
updated_at: "2026-06-07T08:01:00.000Z",
reason: "management_disabled",
},
},
},
},
}));
const { pullDigitalEmployeeSkillPolicies } = await import("./syncService");
const result = await pullDigitalEmployeeSkillPolicies({ force: true });
expect(result).toMatchObject({
ok: true,
endpoint: "https://manage.example.com/api/digital-employee/policies/skills",
policies: {
source: "remote",
remote_updated_at: "2026-06-07T08:01:00.000Z",
last_pulled_at: "2026-06-07T08:00:00.000Z",
last_pull_error: null,
local_skills: {
"qimingclaw-acp-session": expect.objectContaining({ enabled: false, source: "local" }),
},
remote_skills: {
"qimingclaw-mcp-tool-crm-crm-delete": expect.objectContaining({ enabled: false, source: "remote", reason: "management_disabled" }),
},
},
});
expect(mockState.fetch).toHaveBeenCalledWith(
"https://manage.example.com/api/digital-employee/policies/skills",
expect.objectContaining({ method: "GET" }),
);
expect(mockState.settings.get("digital_employee_skill_policies_v1")).toMatchObject(result.policies);
});
it("keeps current skill policies when remote skill policy pull fails", async () => {
mockState.settings.set("digital_employee_skill_policies_v1", {
version: 1,
remote_skills: {
"qimingclaw-computer-control": { enabled: false, updatedAt: "2026-06-07T07:30:00.000Z", source: "remote" },
},
});
mockState.fetch.mockResolvedValue({
ok: false,
status: 503,
text: vi.fn().mockResolvedValue(JSON.stringify({ message: "skill policy service unavailable" })),
} as unknown as Response);
const { pullDigitalEmployeeSkillPolicies } = await import("./syncService");
const result = await pullDigitalEmployeeSkillPolicies({ force: true });
expect(result).toMatchObject({
ok: false,
error: "skill policy service unavailable",
policies: {
remote_skills: {
"qimingclaw-computer-control": expect.objectContaining({ enabled: false, source: "remote" }),
},
last_pulled_at: "2026-06-07T08:00:00.000Z",
last_pull_error: "skill policy service unavailable",
},
});
});
it.each([
["skillPolicies"],
["policies"],
])("pulls remote skill policies from data.%s", async (fieldName) => {
mockState.fetch.mockResolvedValue(jsonResponse({
success: true,
data: {
[fieldName]: {
"qimingclaw-acp-session": false,
},
},
}));
const { pullDigitalEmployeeSkillPolicies } = await import("./syncService");
const result = await pullDigitalEmployeeSkillPolicies({ force: true });
expect(result.policies.remote_skills["qimingclaw-acp-session"]).toEqual(expect.objectContaining({
enabled: false,
source: "remote",
}));
});
it("acquires a remote plan step dispatch lease through the management endpoint", async () => {
mockState.fetch.mockResolvedValue(jsonResponse({
ok: true,