-
Inputs
-
{{ formatJson(toolCall().args) }}
+
+
Inputs
+
{{ formatJson(toolCall().args) }}
@if (toolCall().result !== undefined) {
-
-
Output
-
{{ formatJson(toolCall().result) }}
+
+
Output
+
{{ formatJson(toolCall().result) }}
}
@@ -58,6 +61,11 @@ export class ChatToolCallCardComponent {
readonly expanded = signal(false);
+ readonly toolIcon = ICON_TOOL;
+ readonly checkIcon = ICON_CHECK;
+ readonly chevronUp = ICON_CHEVRON_UP;
+ readonly chevronDown = ICON_CHEVRON_DOWN;
+
formatJson(value: unknown): string {
if (typeof value === 'string') return value;
try {
diff --git a/libs/chat/src/lib/compositions/chat/chat.component.ts b/libs/chat/src/lib/compositions/chat/chat.component.ts
index ba56dbd3a..943e5e797 100644
--- a/libs/chat/src/lib/compositions/chat/chat.component.ts
+++ b/libs/chat/src/lib/compositions/chat/chat.component.ts
@@ -1,10 +1,19 @@
+// libs/chat/src/lib/compositions/chat/chat.component.ts
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
import {
Component,
input,
output,
+ signal,
+ computed,
+ effect,
+ viewChild,
+ ElementRef,
ChangeDetectionStrategy,
+ inject,
+ ViewEncapsulation,
} from '@angular/core';
+import { DomSanitizer } from '@angular/platform-browser';
import type { StreamResourceRef } from '@cacheplane/stream-resource';
import { ChatMessagesComponent } from '../../primitives/chat-messages/chat-messages.component';
import { MessageTemplateDirective } from '../../primitives/chat-messages/message-template.directive';
@@ -14,6 +23,8 @@ import { ChatErrorComponent } from '../../primitives/chat-error/chat-error.compo
import { ChatInterruptComponent } from '../../primitives/chat-interrupt/chat-interrupt.component';
import { ChatThreadListComponent, Thread } from '../../primitives/chat-thread-list/chat-thread-list.component';
import { messageContent } from '../shared/message-utils';
+import { CHAT_THEME_STYLES } from '../../styles/chat-theme';
+import { CHAT_MARKDOWN_STYLES, renderMarkdown } from '../../styles/chat-markdown';
@Component({
selector: 'chat',
@@ -28,58 +39,21 @@ import { messageContent } from '../shared/message-utils';
ChatThreadListComponent,
],
changeDetection: ChangeDetectionStrategy.OnPush,
- styles: [
- // Theme CSS custom properties (sourced from libs/chat/src/lib/styles/chat-theme.css)
- `:host {
- --chat-bg: #171717; --chat-bg-alt: #222222; --chat-bg-hover: #2a2a2a;
- --chat-text: #e0e0e0; --chat-text-muted: #777777; --chat-text-placeholder: #666666;
- --chat-border: #333333; --chat-border-light: #2a2a2a;
- --chat-user-bg: #2a2a2a; --chat-user-text: #f5f5f5; --chat-user-border: #333333;
- --chat-avatar-bg: #333333; --chat-avatar-text: #aaaaaa;
- --chat-input-bg: #222222; --chat-input-border: #333333; --chat-input-focus-border: #555555;
- --chat-send-bg: #444444; --chat-send-text: #aaaaaa;
- --chat-error-bg: #2d1515; --chat-error-text: #f87171;
- --chat-warning-bg: #2d2315; --chat-warning-text: #fbbf24; --chat-success: #4ade80;
- --chat-radius-message: 20px; --chat-radius-input: 24px; --chat-radius-card: 12px;
- --chat-radius-avatar: 8px; --chat-max-width: 720px;
- --chat-font-family: -apple-system, BlinkMacSystemFont, 'SF Pro Text', system-ui, sans-serif;
- --chat-font-size: 15px; --chat-line-height: 1.6;
- font-family: var(--chat-font-family); font-size: var(--chat-font-size);
- line-height: var(--chat-line-height); color: var(--chat-text); background: var(--chat-bg);
- display: flex; flex-direction: column; height: 100%; overflow: hidden;
- }
- @media (prefers-color-scheme: light) {
- :host:not([data-chat-theme="dark"]) {
- --chat-bg: #ffffff; --chat-bg-alt: #f5f5f5; --chat-bg-hover: #ebebeb;
- --chat-text: #1a1a1a; --chat-text-muted: #999999; --chat-text-placeholder: #999999;
- --chat-border: #e5e5e5; --chat-border-light: #f0f0f0;
- --chat-user-bg: #f0f0f0; --chat-user-text: #1a1a1a; --chat-user-border: transparent;
- --chat-avatar-bg: #f0f0f0; --chat-avatar-text: #666666;
- --chat-input-bg: #f5f5f5; --chat-input-border: #e5e5e5; --chat-input-focus-border: #cccccc;
- --chat-send-bg: #e5e5e5; --chat-send-text: #999999;
- --chat-error-bg: #fef2f2; --chat-error-text: #dc2626;
- --chat-warning-bg: #fffbeb; --chat-warning-text: #d97706; --chat-success: #16a34a;
- }
- }
- :host([data-chat-theme="light"]) {
- --chat-bg: #ffffff; --chat-bg-alt: #f5f5f5; --chat-bg-hover: #ebebeb;
- --chat-text: #1a1a1a; --chat-text-muted: #999999; --chat-text-placeholder: #999999;
- --chat-border: #e5e5e5; --chat-border-light: #f0f0f0;
- --chat-user-bg: #f0f0f0; --chat-user-text: #1a1a1a; --chat-user-border: transparent;
- --chat-avatar-bg: #f0f0f0; --chat-avatar-text: #666666;
- --chat-input-bg: #f5f5f5; --chat-input-border: #e5e5e5; --chat-input-focus-border: #cccccc;
- --chat-send-bg: #e5e5e5; --chat-send-text: #999999;
- --chat-error-bg: #fef2f2; --chat-error-text: #dc2626;
- --chat-warning-bg: #fffbeb; --chat-warning-text: #d97706; --chat-success: #16a34a;
- }`,
- ],
+ encapsulation: ViewEncapsulation.None,
+ styles: [CHAT_THEME_STYLES, CHAT_MARKDOWN_STYLES],
template: `
-
-
+
+
@if (threads().length > 0) {
-
-
-
Threads
+
+
+
Threads