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
86 lines
2.4 KiB
TypeScript
86 lines
2.4 KiB
TypeScript
import { useMemo, type ReactNode } from "react";
|
|
import type { AgentSessionEngine } from "@tutti-os/agent-activity-core";
|
|
import type {
|
|
AgentGUIAgentDirectoryPort,
|
|
AgentGUIAgentDirectorySnapshot
|
|
} from "../types.ts";
|
|
import { useEngineSelector } from "../shared/engine/useEngineSelector.ts";
|
|
import {
|
|
agentGuiWorkbenchConversationIdentitiesEqual,
|
|
resolveAgentGuiWorkbenchConversationIdentity
|
|
} from "./conversationIdentity.ts";
|
|
import {
|
|
AgentGuiWorkbenchHeader,
|
|
type AgentGuiWorkbenchHeaderProps
|
|
} from "./header.ts";
|
|
import type {
|
|
AgentGuiWorkbenchProvider,
|
|
AgentGuiWorkbenchState
|
|
} from "./types.ts";
|
|
|
|
interface AgentGuiWorkbenchReactiveHeaderProps extends Omit<
|
|
AgentGuiWorkbenchHeaderProps,
|
|
| "agentTitle"
|
|
| "conversationIconUrl"
|
|
| "conversationTitle"
|
|
| "conversationTitleDisplayPrompt"
|
|
| "hasConversation"
|
|
> {
|
|
agentDirectory: AgentGUIAgentDirectoryPort;
|
|
dockIconUrls?: Partial<Record<AgentGuiWorkbenchProvider, string>>;
|
|
sessionEngine: AgentSessionEngine;
|
|
workbenchState: AgentGuiWorkbenchState | null;
|
|
}
|
|
|
|
export function AgentGuiWorkbenchReactiveHeader({
|
|
agentDirectory,
|
|
dockIconUrls,
|
|
sessionEngine,
|
|
workbenchState,
|
|
...headerProps
|
|
}: AgentGuiWorkbenchReactiveHeaderProps): ReactNode {
|
|
const directoryStore = useMemo(
|
|
() => ({
|
|
getSnapshot: () => agentDirectory.getSnapshot(),
|
|
subscribe: (
|
|
listener: (snapshot: AgentGUIAgentDirectorySnapshot) => void
|
|
) =>
|
|
agentDirectory.subscribe(() => {
|
|
listener(agentDirectory.getSnapshot());
|
|
})
|
|
}),
|
|
[agentDirectory]
|
|
);
|
|
const agents = useEngineSelector(
|
|
directoryStore,
|
|
(snapshot) => snapshot.agents,
|
|
Object.is
|
|
);
|
|
const conversationIdentity = useEngineSelector(
|
|
sessionEngine,
|
|
(engineState) =>
|
|
resolveAgentGuiWorkbenchConversationIdentity({
|
|
agents,
|
|
dockIconUrls,
|
|
engineState,
|
|
workbenchState
|
|
}),
|
|
agentGuiWorkbenchConversationIdentitiesEqual
|
|
);
|
|
|
|
return (
|
|
<AgentGuiWorkbenchHeader
|
|
{...headerProps}
|
|
agentTitle={conversationIdentity?.agentTitle}
|
|
conversationIconUrl={
|
|
conversationIdentity?.iconUrl ?? headerProps.conversationIconFallbackUrl
|
|
}
|
|
conversationTitle={conversationIdentity?.title}
|
|
conversationTitleDisplayPrompt={conversationIdentity?.titleDisplayPrompt}
|
|
hasConversation={Boolean(
|
|
workbenchState?.lastActiveAgentSessionId?.trim()
|
|
)}
|
|
/>
|
|
);
|
|
}
|