吸收数字员工技能远端策略下发
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user