Files
tutti/packages/agent/gui/agent-gui/agentGuiNode/controller/useAgentGUIInteractionReadiness.spec.tsx
agent-radar 2ed3415fb7
Publish Claude Code Binaries / Stage and publish binaries (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-arm64 (push) Canceled after 0s
Publish Tutti App Runtime / Build darwin-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build linux-amd64 (push) Canceled after 0s
Publish Tutti App Runtime / Build windows-amd64 (push) Canceled after 0s
Sync Tutti Agent Skills / sync (push) Canceled after 0s
Windows Agent Adapters / Test Windows agent adapters (push) Canceled after 0s
Windows Daemon Adapters / Test Windows daemon adapters (push) Canceled after 0s
Publish Tutti App Runtime / Publish runtime catalog (push) Canceled after 0s
源码快照 @ 2026-09-01 (source-only, 剔除非源码素材)
2026-09-01 20:17:27 +08:00

86 lines
2.4 KiB
TypeScript

import { act, renderHook } from "@testing-library/react";
import { describe, expect, it } from "vitest";
import type {
AgentGUIInteractionReadiness,
AgentGUIInteractionReadinessIdentity,
AgentGUIInteractionReadinessSource
} from "../../../types";
import { useAgentGUIInteractionReadiness } from "./useAgentGUIInteractionReadiness";
class FakeInteractionReadinessSource implements AgentGUIInteractionReadinessSource {
private readonly listeners = new Set<() => void>();
private state: AgentGUIInteractionReadiness | null = null;
getInteractionReadiness(
_identity: AgentGUIInteractionReadinessIdentity
): AgentGUIInteractionReadiness | null {
return this.state;
}
subscribe(listener: () => void): () => void {
this.listeners.add(listener);
return () => this.listeners.delete(listener);
}
set(state: AgentGUIInteractionReadiness): void {
this.state = state;
for (const listener of this.listeners) listener();
}
}
describe("useAgentGUIInteractionReadiness", () => {
it("fails closed until the supplied Host source publishes the exact record", () => {
const source = new FakeInteractionReadinessSource();
const identity = {
workspaceId: "workspace-1",
agentSessionId: "session-1",
turnId: "turn-1",
requestId: "request-1"
};
const rendered = renderHook(() =>
useAgentGUIInteractionReadiness({ identity, source })
);
expect(rendered.result.current).toEqual({
status: "blocked",
reason: "synchronizing"
});
act(() => source.set({ status: "ready" }));
expect(rendered.result.current).toEqual({ status: "ready" });
});
it("does not add a gate when the Host omits the capability", () => {
const rendered = renderHook(() =>
useAgentGUIInteractionReadiness({
identity: {
workspaceId: "workspace-1",
agentSessionId: "session-1",
turnId: "turn-1",
requestId: "request-1"
},
source: null
})
);
expect(rendered.result.current).toBeNull();
});
it("fails closed when a presented interaction has no resolvable identity", () => {
const source = new FakeInteractionReadinessSource();
const rendered = renderHook(() =>
useAgentGUIInteractionReadiness({
identity: null,
required: true,
source
})
);
expect(rendered.result.current).toEqual({
status: "blocked",
reason: "synchronizing"
});
});
});