Skip to main content
Gremorie

Reasoning

Bloco de pensamento recolhível que abre durante o streaming, rastreia a duração e fecha discretamente ao terminar.

Visão geral

Reasoning expõe a chain-of-thought do modelo sem dominar a resposta. Ele abre automaticamente enquanto isStreaming é true, mede os segundos decorridos, e então se recolhe sozinho um segundo depois que o streaming termina. O trigger alterna entre um Shimmer ("Thinking...") e a duração registrada ("Thought for N seconds").

Use dentro de MessageContent para turnos do assistant cujo modelo expõe um trace de reasoning (o-series, Claude extended thinking, DeepSeek R1, etc.).

Preview

Ocioso

The user wants to add a registry item. I need to:

  1. Confirm the package the primitive lives in.
  2. Check registry.json for the existing schema.
  3. Add the item with registryDependencies pointing at its peers.
'use client';import { Reasoning, ReasoningContent, ReasoningTrigger } from '@gremorie/rx-ai';const REASONING_TEXT = `The user wants to add a registry item. I need to:1. Confirm the package the primitive lives in.2. Check registry.json for the existing schema.3. Add the item with registryDependencies pointing at its peers.`;export function ReasoningPreview() {  return (    <Reasoning isStreaming={false} defaultOpen>      <ReasoningTrigger />      <ReasoningContent>{REASONING_TEXT}</ReasoningContent>    </Reasoning>  );}

Streaming

Considering whether to recommend rx-tool or rx-task for this case...

'use client';import { Reasoning, ReasoningContent, ReasoningTrigger } from '@gremorie/rx-ai';export function ReasoningStreamingPreview() {  return (    <Reasoning isStreaming defaultOpen>      <ReasoningTrigger />      <ReasoningContent>        Considering whether to recommend rx-tool or rx-task for this case...      </ReasoningContent>    </Reasoning>  );}

Expandido

The user wants to add a registry item. I need to:

  1. Confirm the package the primitive lives in.
  2. Check registry.json for the existing schema.
  3. Add the item with registryDependencies pointing at its peers.
'use client';import { Reasoning, ReasoningContent, ReasoningTrigger } from '@gremorie/rx-ai';const REASONING_TEXT = `The user wants to add a registry item. I need to:1. Confirm the package the primitive lives in.2. Check registry.json for the existing schema.3. Add the item with registryDependencies pointing at its peers.`;export function ReasoningExpandedPreview() {  return (    <Reasoning isStreaming={false} defaultOpen>      <ReasoningTrigger />      <ReasoningContent>{REASONING_TEXT}</ReasoningContent>    </Reasoning>  );}

Anatomia

Reasoning
├─ ReasoningTrigger   label "Thinking…" (faz shimmer durante o streaming)
└─ ReasoningContent   o texto de reasoning recolhível

Instalação

bash npx gremorie@latest add rx-reasoning
bash pnpm dlx gremorie@latest add rx-reasoning
bash yarn dlx gremorie@latest add rx-reasoning
bash bunx --bun gremorie@latest add rx-reasoning

Uso

import {
  Reasoning,
  ReasoningTrigger,
  ReasoningContent,
} from "@gremorie/rx-ai";

export function Example({ status, thinking }) {
  return (
    <Reasoning isStreaming={status === "streaming"}>
      <ReasoningTrigger />
      <ReasoningContent>{thinking}</ReasoningContent>
    </Reasoning>
  );
}
import { Component, input } from "@angular/core";
import {
  Reasoning,
  ReasoningTrigger,
  ReasoningContent,
} from "@gremorie/ng-ai";

@Component({
selector: "app-example",
standalone: true,
imports: [Reasoning, ReasoningTrigger, ReasoningContent],
template: `     <reasoning [isStreaming]="status() === 'streaming'">
      <reasoning-trigger />
      <reasoning-content [text]="thinking()" />
    </reasoning>
  `,
})
export class ExampleComponent {
readonly status = input<"idle" | "streaming" | "done">("idle");
readonly thinking = input<string>("");
}

API

<Reasoning>

PropTypeDefaultDescription
isStreamingbooleanfalseEnquanto true, o bloco abre, o trigger mostra um "Thinking..." com shimmer e o timer de duração corre.
openboolean-Estado de abertura controlado.
defaultOpenbooleantrueEstado de abertura inicial não controlado. O auto-fechamento só dispara quando isto é true.
onOpenChange(open: boolean) => void-Notificação quando o usuário alterna o trigger.
durationnumber-Override externo de duração (segundos). Se omitido, Reasoning a mede a partir das transições de isStreaming.

Estende ComponentProps<typeof Collapsible>.

<ReasoningTrigger>

PropTypeDefaultDescription
getThinkingMessage(isStreaming: boolean, duration?: number) => ReactNodebuiltinCustomiza o label do trigger. O padrão renderiza o Shimmer durante o streaming e "Thought for N seconds" ao terminar.
childrenReactNode-Substitui completamente o conteúdo do trigger (ícone + label + chevron).

<ReasoningContent>

PropTypeDefaultDescription
childrenstring-Markdown renderizado via Streamdown.

useReasoning()

Retorna { isStreaming, isOpen, setIsOpen, duration }. Lança erro quando chamado fora de um limite <Reasoning>.

Composição

  1. <Reasoning> detém o estado de open / streaming / duration e envolve um Collapsible.
  2. <ReasoningTrigger> renderiza o ícone de cérebro + label + chevron e alterna o collapsible.
  3. <ReasoningContent> renderiza o markdown com streaming sob demanda.

Variações

Dentro de uma mensagem do assistant

O pareamento típico - reasoning acima da resposta.

<Message from="assistant">
  <MessageContent>
    <Reasoning isStreaming={status === "streaming"}>
      <ReasoningTrigger />
      <ReasoningContent>{thinking}</ReasoningContent>
    </Reasoning>
    <MessageResponse>{answer}</MessageResponse>
  </MessageContent>
</Message>

Label de trigger customizado

Sobrescreva getThinkingMessage para localizar o texto ou expor metadados do modelo.

<Reasoning isStreaming={isStreaming}>
  <ReasoningTrigger
    getThinkingMessage={(streaming, duration) =>
      streaming ? (
        <Shimmer>Reasoning with o4-mini...</Shimmer>
      ) : (
        <span>Reasoning took {duration ?? '?'}s</span>
      )
    }
  />
  <ReasoningContent>{thinking}</ReasoningContent>
</Reasoning>

Estado de abertura controlado

Quando a casca ao redor decide quando o reasoning está visível (por exemplo, um toggle "Hide reasoning" nas configurações).

const [open, setOpen] = useState(false);

<Reasoning open={open} onOpenChange={setOpen} isStreaming={false} duration={12}>
  <ReasoningTrigger />
  <ReasoningContent>{archivedThinking}</ReasoningContent>
</Reasoning>;

Acessibilidade

  • Teclado: ReasoningTrigger é um CollapsibleTrigger, então alterna com Enter / Space e participa da ordem de Tab.
  • ARIA: o collapsible Radix subjacente conecta aria-expanded e aria-controls no trigger e data-state no content, então leitores de tela anunciam os estados aberto / fechado corretamente.
  • Leitores de tela: o label usa texto vivo ("Thinking..." -> "Thought for N seconds") para que a tecnologia assistiva narre a transição sem precisar de uma região live separada.
  • Movimento reduzido: as animações de recolher / expandir vêm das animações data-state do Tailwind; elas degradam para transições instantâneas quando prefers-reduced-motion: reduce está definido.

Relacionados

  • Message - o pai típico de Reasoning
  • Chain of Thought - reasoning passo a passo quando você tem ações discretas para expor
  • Shimmer - o affordance de loading usado dentro do trigger padrão

On this page