First Release of Claw3D (#11)
Co-authored-by: iamlukethedev <iamlukethedev@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,288 @@
|
||||
import { beforeEach, describe, expect, it, vi } from "vitest";
|
||||
|
||||
import type { AgentStoreSeed } from "@/features/agents/state/store";
|
||||
import type { GatewayModelPolicySnapshot } from "@/lib/gateway/models";
|
||||
import type { StudioSettingsPatch } from "@/lib/studio/settings";
|
||||
|
||||
vi.mock("@/features/agents/operations/agentFleetHydration", () => ({
|
||||
hydrateAgentFleetFromGateway: vi.fn(),
|
||||
}));
|
||||
|
||||
import { hydrateAgentFleetFromGateway } from "@/features/agents/operations/agentFleetHydration";
|
||||
import {
|
||||
executeStudioBootstrapLoadCommands,
|
||||
executeStudioFocusedPatchCommands,
|
||||
executeStudioFocusedPreferenceLoadCommands,
|
||||
runStudioBootstrapLoadOperation,
|
||||
runStudioFocusFilterPersistenceOperation,
|
||||
runStudioFocusedPreferenceLoadOperation,
|
||||
runStudioFocusedSelectionPersistenceOperation,
|
||||
type StudioBootstrapLoadCommand,
|
||||
} from "@/features/agents/operations/studioBootstrapOperation";
|
||||
|
||||
const hydrateAgentFleetFromGatewayMock = vi.mocked(hydrateAgentFleetFromGateway);
|
||||
|
||||
describe("studioBootstrapOperation", () => {
|
||||
beforeEach(() => {
|
||||
hydrateAgentFleetFromGatewayMock.mockReset();
|
||||
});
|
||||
|
||||
it("builds bootstrap commands from hydrated fleet result", async () => {
|
||||
const seeds: AgentStoreSeed[] = [
|
||||
{
|
||||
agentId: "agent-1",
|
||||
name: "Agent One",
|
||||
sessionKey: "agent:agent-1:main",
|
||||
},
|
||||
{
|
||||
agentId: "agent-2",
|
||||
name: "Agent Two",
|
||||
sessionKey: "agent:agent-2:main",
|
||||
},
|
||||
];
|
||||
const snapshot = { config: {} } as GatewayModelPolicySnapshot;
|
||||
hydrateAgentFleetFromGatewayMock.mockResolvedValue({
|
||||
seeds,
|
||||
sessionCreatedAgentIds: ["agent-1"],
|
||||
sessionSettingsSyncedAgentIds: ["agent-1"],
|
||||
summaryPatches: [{ agentId: "agent-2", patch: { latestPreview: "hello" } }],
|
||||
suggestedSelectedAgentId: "agent-2",
|
||||
configSnapshot: snapshot,
|
||||
});
|
||||
|
||||
const commands = await runStudioBootstrapLoadOperation({
|
||||
client: { call: async () => null },
|
||||
gatewayUrl: "https://gateway.test",
|
||||
cachedConfigSnapshot: null,
|
||||
loadStudioSettings: async () => null,
|
||||
isDisconnectLikeError: () => false,
|
||||
preferredSelectedAgentId: "agent-1",
|
||||
hasCurrentSelection: false,
|
||||
});
|
||||
|
||||
expect(commands).toEqual([
|
||||
{ kind: "set-gateway-config-snapshot", snapshot },
|
||||
{
|
||||
kind: "hydrate-agents",
|
||||
seeds,
|
||||
initialSelectedAgentId: "agent-1",
|
||||
},
|
||||
{
|
||||
kind: "mark-session-created",
|
||||
agentId: "agent-1",
|
||||
sessionSettingsSynced: true,
|
||||
},
|
||||
{
|
||||
kind: "apply-summary-patch",
|
||||
agentId: "agent-2",
|
||||
patch: { latestPreview: "hello" },
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("returns set-error command when fleet hydration fails", async () => {
|
||||
hydrateAgentFleetFromGatewayMock.mockRejectedValue(new Error("load failed"));
|
||||
|
||||
const commands = await runStudioBootstrapLoadOperation({
|
||||
client: { call: async () => null },
|
||||
gatewayUrl: "https://gateway.test",
|
||||
cachedConfigSnapshot: null,
|
||||
loadStudioSettings: async () => null,
|
||||
isDisconnectLikeError: () => false,
|
||||
preferredSelectedAgentId: null,
|
||||
hasCurrentSelection: false,
|
||||
});
|
||||
|
||||
expect(commands).toEqual([{ kind: "set-error", message: "load failed" }]);
|
||||
});
|
||||
|
||||
it("executes bootstrap commands with injected callbacks", () => {
|
||||
const commands: StudioBootstrapLoadCommand[] = [
|
||||
{
|
||||
kind: "set-gateway-config-snapshot",
|
||||
snapshot: { config: {} } as GatewayModelPolicySnapshot,
|
||||
},
|
||||
{
|
||||
kind: "hydrate-agents",
|
||||
seeds: [{ agentId: "agent-1", name: "Agent One", sessionKey: "s1" }],
|
||||
initialSelectedAgentId: "agent-1",
|
||||
},
|
||||
{
|
||||
kind: "mark-session-created",
|
||||
agentId: "agent-1",
|
||||
sessionSettingsSynced: true,
|
||||
},
|
||||
{
|
||||
kind: "apply-summary-patch",
|
||||
agentId: "agent-1",
|
||||
patch: { latestPreview: "preview" },
|
||||
},
|
||||
{
|
||||
kind: "set-error",
|
||||
message: "failed",
|
||||
},
|
||||
];
|
||||
|
||||
const setGatewayConfigSnapshot = vi.fn();
|
||||
const hydrateAgents = vi.fn();
|
||||
const dispatchUpdateAgent = vi.fn();
|
||||
const setError = vi.fn();
|
||||
|
||||
executeStudioBootstrapLoadCommands({
|
||||
commands,
|
||||
setGatewayConfigSnapshot,
|
||||
hydrateAgents,
|
||||
dispatchUpdateAgent,
|
||||
setError,
|
||||
});
|
||||
|
||||
expect(setGatewayConfigSnapshot).toHaveBeenCalledTimes(1);
|
||||
expect(hydrateAgents).toHaveBeenCalledWith(
|
||||
[{ agentId: "agent-1", name: "Agent One", sessionKey: "s1" }],
|
||||
"agent-1"
|
||||
);
|
||||
expect(dispatchUpdateAgent).toHaveBeenCalledWith("agent-1", {
|
||||
sessionCreated: true,
|
||||
sessionSettingsSynced: true,
|
||||
});
|
||||
expect(dispatchUpdateAgent).toHaveBeenCalledWith("agent-1", { latestPreview: "preview" });
|
||||
expect(setError).toHaveBeenCalledWith("failed");
|
||||
});
|
||||
|
||||
it("loads focused preference and emits restore commands", async () => {
|
||||
const commands = await runStudioFocusedPreferenceLoadOperation({
|
||||
gatewayUrl: "https://gateway.test",
|
||||
loadStudioSettings: async () => ({
|
||||
version: 1,
|
||||
gateway: null,
|
||||
focused: {
|
||||
"https://gateway.test": {
|
||||
mode: "focused",
|
||||
selectedAgentId: "agent-9",
|
||||
filter: "running",
|
||||
},
|
||||
},
|
||||
avatars: {},
|
||||
deskAssignments: {},
|
||||
analytics: {},
|
||||
voiceReplies: {},
|
||||
}),
|
||||
isFocusFilterTouched: () => false,
|
||||
});
|
||||
|
||||
expect(commands).toEqual([
|
||||
{
|
||||
kind: "set-preferred-selected-agent-id",
|
||||
agentId: "agent-9",
|
||||
},
|
||||
{
|
||||
kind: "set-focus-filter",
|
||||
filter: "all",
|
||||
},
|
||||
{
|
||||
kind: "set-focused-preferences-loaded",
|
||||
value: true,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("skips focused preference restore when user touched filter during load", async () => {
|
||||
const commands = await runStudioFocusedPreferenceLoadOperation({
|
||||
gatewayUrl: "https://gateway.test",
|
||||
loadStudioSettings: async () => ({
|
||||
version: 1,
|
||||
gateway: null,
|
||||
focused: {
|
||||
"https://gateway.test": {
|
||||
mode: "focused",
|
||||
selectedAgentId: "agent-9",
|
||||
filter: "running",
|
||||
},
|
||||
},
|
||||
avatars: {},
|
||||
deskAssignments: {},
|
||||
analytics: {},
|
||||
voiceReplies: {},
|
||||
}),
|
||||
isFocusFilterTouched: () => true,
|
||||
});
|
||||
|
||||
expect(commands).toEqual([
|
||||
{
|
||||
kind: "set-focused-preferences-loaded",
|
||||
value: true,
|
||||
},
|
||||
]);
|
||||
});
|
||||
|
||||
it("returns focused preference load error command on failure", async () => {
|
||||
const commands = await runStudioFocusedPreferenceLoadOperation({
|
||||
gatewayUrl: "https://gateway.test",
|
||||
loadStudioSettings: async () => {
|
||||
throw new Error("settings failed");
|
||||
},
|
||||
isFocusFilterTouched: () => false,
|
||||
});
|
||||
|
||||
expect(commands[0]).toMatchObject({
|
||||
kind: "log-error",
|
||||
message: "Failed to load focused preference.",
|
||||
});
|
||||
expect(commands[1]).toEqual({
|
||||
kind: "set-focused-preferences-loaded",
|
||||
value: true,
|
||||
});
|
||||
});
|
||||
|
||||
it("executes focused preference load commands", () => {
|
||||
const setFocusedPreferencesLoaded = vi.fn();
|
||||
const setPreferredSelectedAgentId = vi.fn();
|
||||
const setFocusFilter = vi.fn();
|
||||
const logError = vi.fn();
|
||||
|
||||
executeStudioFocusedPreferenceLoadCommands({
|
||||
commands: [
|
||||
{ kind: "set-focused-preferences-loaded", value: false },
|
||||
{ kind: "set-preferred-selected-agent-id", agentId: "agent-1" },
|
||||
{ kind: "set-focus-filter", filter: "approvals" },
|
||||
{ kind: "log-error", message: "failed", error: new Error("boom") },
|
||||
],
|
||||
setFocusedPreferencesLoaded,
|
||||
setPreferredSelectedAgentId,
|
||||
setFocusFilter,
|
||||
logError,
|
||||
});
|
||||
|
||||
expect(setFocusedPreferencesLoaded).toHaveBeenCalledWith(false);
|
||||
expect(setPreferredSelectedAgentId).toHaveBeenCalledWith("agent-1");
|
||||
expect(setFocusFilter).toHaveBeenCalledWith("approvals");
|
||||
expect(logError).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it("plans focused persistence patch commands and executes scheduler", () => {
|
||||
const filterCommands = runStudioFocusFilterPersistenceOperation({
|
||||
gatewayUrl: "https://gateway.test",
|
||||
focusFilterTouched: true,
|
||||
focusFilter: "running",
|
||||
});
|
||||
const selectionCommands = runStudioFocusedSelectionPersistenceOperation({
|
||||
gatewayUrl: "https://gateway.test",
|
||||
status: "connected",
|
||||
focusedPreferencesLoaded: true,
|
||||
agentsLoadedOnce: true,
|
||||
selectedAgentId: "agent-2",
|
||||
});
|
||||
|
||||
const schedulePatch = vi.fn();
|
||||
executeStudioFocusedPatchCommands({
|
||||
commands: [...filterCommands, ...selectionCommands],
|
||||
schedulePatch,
|
||||
});
|
||||
|
||||
expect(schedulePatch).toHaveBeenCalledTimes(2);
|
||||
const firstCall = schedulePatch.mock.calls[0] as [StudioSettingsPatch, number];
|
||||
const secondCall = schedulePatch.mock.calls[1] as [StudioSettingsPatch, number];
|
||||
expect(firstCall[1]).toBe(300);
|
||||
expect(secondCall[1]).toBe(300);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user