Files
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

77 lines
2.0 KiB
TypeScript

import {
createContext,
useContext,
useMemo,
type JSX,
type ReactNode
} from "react";
import type {
AgentGUIObservationGap,
AgentGUIObservationGapSource
} from "../../types";
import { useEngineSelector } from "../engine/useEngineSelector";
const AgentObservationGapSourceContext =
createContext<AgentGUIObservationGapSource | null>(null);
export function AgentObservationGapSourceProvider({
children,
source
}: {
children: ReactNode;
source?: AgentGUIObservationGapSource | null;
}): JSX.Element {
return (
<AgentObservationGapSourceContext.Provider value={source ?? null}>
{children}
</AgentObservationGapSourceContext.Provider>
);
}
export function useAgentObservationGap(
agentSessionId: string | null | undefined,
turnId: string | null | undefined,
explicitSource?: AgentGUIObservationGapSource | null
): AgentGUIObservationGap | null {
const contextSource = useContext(AgentObservationGapSourceContext);
const source = explicitSource === undefined ? contextSource : explicitSource;
const binding = useMemo(
() => ({
getSnapshot: () => {
const normalizedAgentSessionId = agentSessionId?.trim() ?? "";
const normalizedTurnId = turnId?.trim() ?? "";
return normalizedAgentSessionId && normalizedTurnId
? (source?.getObservationGap(
normalizedAgentSessionId,
normalizedTurnId
) ?? null)
: null;
},
subscribe: (listener: () => void) =>
source?.subscribe(listener) ?? (() => undefined)
}),
[agentSessionId, source, turnId]
);
return useEngineSelector(
binding,
identityObservationGap,
observationGapsEqual
);
}
function identityObservationGap(
gap: AgentGUIObservationGap | null
): AgentGUIObservationGap | null {
return gap;
}
function observationGapsEqual(
left: AgentGUIObservationGap | null,
right: AgentGUIObservationGap | null
): boolean {
return (
left?.startedAtUnixMs === right?.startedAtUnixMs &&
left?.presentationState === right?.presentationState
);
}