Angular had no counterpart to `useComponent` in react-core and vue, so the only
way to let an agent display one of your components was `registerFrontendTool`
with a handler the component does not need, or `registerRenderToolCall`, which
requires the tool to already exist in the agent.
`FrontendToolConfig.handler` becomes optional, and `#bindClientTool` returns the
config unwrapped when it is absent. Core already has the render-only path: a tool
declaring no handler gets an empty tool result and completes the turn. Binding a
wrapper regardless called `undefined` on the first tool call, and a stub handler
would write a fabricated result into the thread instead.
`registerComponent` is that shape with the model-facing description built for it,
identical to the one react-core and vue build, so the tool reads the same to the
model whichever frontend registered the component. The component stays an
ordinary `ToolRenderer` reading `toolCall().args`.
The tool is declared by the frontend and forwarded over AG-UI, so a display-only
component needs nothing added to the agent, on any framework.
Refs OSS-1034
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rendering activity messages outside of CopilotChatMessageView (custom chat
shells, dashboards, headless setups) currently requires instantiating the
whole message view or copying its private resolution logic. Tool calls
already have a public component for this (RenderToolCalls), activities do
not.
This adds CopilotActivity (<copilot-activity [message] [agentId]>), a
standalone host for a single activity message. CopilotChatMessageView now
delegates to it, so there is one implementation for the activity role. No
behavior change. The renderer resolution moves into an internal
pickActivityRenderer that is not exported.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>