Chat · Components

ChatDebugComponent

ChatDebugComponent provides a docked development panel for inspecting an Agent or AgentWithHistory. It ships from the debug-only secondary entry point so applications can keep debug implementation code out of production bundles unless they explicitly opt in.

Selector: chat-debug

Import:

import { ChatDebugComponent } from '@threadplane/chat/debug';

Basic Usage

import { Component, ChangeDetectionStrategy, signal } from '@angular/core';
import { injectAgent, provideAgent } from '@threadplane/langgraph';
import { ChatDebugComponent } from '@threadplane/chat/debug';
 
@Component({
  selector: 'app-debug-page',
  standalone: true,
  imports: [ChatDebugComponent],
  providers: [
    provideAgent({
      apiUrl: '/api/langgraph',
      assistantId: 'chat',
      threadId: signal(localStorage.getItem('threadId')),
      onThreadId: (id) => localStorage.setItem('threadId', id),
    }),
  ],
  changeDetection: ChangeDetectionStrategy.OnPush,
  template: `
    <chat-debug
      [agent]="chat"
      dock="right"
      [defaultOpen]="true"
      (replayRequested)="replay($event)"
      (forkRequested)="fork($event)"
    />
  `,
})
export class DebugPageComponent {
  protected readonly replayCheckpointId = signal<string | null>(null);
  protected readonly forkSourceCheckpointId = signal<string | null>(null);
 
  protected readonly chat = injectAgent();
 
  replay(checkpointId: string) {
    this.replayCheckpointId.set(checkpointId);
    // Route this into your app's replay workflow.
  }
 
  fork(checkpointId: string) {
    this.forkSourceCheckpointId.set(checkpointId);
    // Route this into your app's thread fork workflow.
  }
}

Inputs

InputTypeDefaultDescription
agentAgent | AgentWithHistoryRequiredAgent state. Agents with history() also enable the Timeline tab.
dock'right' | 'bottom' | 'left''right'Initial dock position.
defaultOpenbooleanfalseInitial open state when no persisted state exists.
launcher'floating' | 'none''floating'Shows the built-in floating launcher, or hides it when another surface opens the panel.
storageKeystring'chat-debug'Local storage key prefix for persisted open/dock/tab state.

Outputs

OutputTypeDescription
replayRequestedstringEmits a checkpoint id when the built-in Timeline tab requests replay.
forkRequestedstringEmits a checkpoint id when the built-in Timeline tab requests fork.
openChangebooleanEmits when the panel opens or closes.
dockChange'right' | 'bottom' | 'left'Emits when the dock position changes.

replayRequested and forkRequested are integration hooks. The debug panel does not mutate the agent by itself; the host app decides whether a checkpoint opens a replay view, starts a forked thread, or maps to a backend-specific time travel operation.

Sidenav Integration

ChatSidenavComponent can own the launcher for apps that already use the sidenav footer. Pass the same agent and keep [debug] enabled:

<chat-sidenav
  [agent]="chat"
  [debug]="true"
  (replayRequested)="replay($event)"
  (forkRequested)="fork($event)"
/>

The footer button is labelled in expanded and drawer modes. In collapsed mode it uses the status dot only. The dot pulses while agent.status() is running.

Production Bundles

The debug implementation lives under @threadplane/chat/debug; the main @threadplane/chat entry point no longer exports it. In the canonical Angular demo, normal production builds set THREADPLANE_CHAT_DEBUG=false and externalize @threadplane/chat/debug, so the debug implementation is absent from the emitted bundle. The production-debug build opts back in with THREADPLANE_CHAT_DEBUG=true.

Keep debug controls for your app outside the debug panel. The debug panel intentionally exposes a small fixed surface so consumers do not expect demo-specific controls to appear in their own applications.

See also

  • Time travel — what the replayRequested / forkRequested checkpoint hooks plug into, and how to wire replay and fork against the agent's history.
  • <chat-sidenav> — the layout composition that can own the debug launcher (see Sidenav Integration above).