Skip to content

Commit f4d50fa

Browse files
committed
02-solution
1 parent c2df326 commit f4d50fa

File tree

1 file changed

+60
-21
lines changed

1 file changed

+60
-21
lines changed

app/src/app/chat/chat-panel.ts

Lines changed: 60 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,25 @@
1-
import {
2-
Component,
3-
effect,
4-
ElementRef,
5-
inject,
6-
viewChild,
7-
} from '@angular/core';
1+
import { Component, effect, ElementRef, inject, viewChild } from '@angular/core';
82
import { MatProgressBarModule } from '@angular/material/progress-bar';
9-
import { chatResource } from '@hashbrownai/angular';
3+
import { prompt, s } from '@hashbrownai/core';
4+
import { exposeComponent, RenderMessageComponent, uiChatResource } from '@hashbrownai/angular';
105
import { SmartHome } from '../smart-home';
116
import { Squircle } from '../squircle';
127
import { ChatLayout } from './chat-layout';
138
import { ChatPrompts } from './chat-prompts';
149
import { Composer } from './composer';
10+
import { Markdown } from './markdown';
1511

1612
@Component({
1713
selector: 'app-chat-panel',
1814
standalone: true,
19-
imports: [MatProgressBarModule, Composer, ChatLayout, ChatPrompts, Squircle],
15+
imports: [
16+
MatProgressBarModule,
17+
Composer,
18+
ChatLayout,
19+
ChatPrompts,
20+
Squircle,
21+
RenderMessageComponent,
22+
],
2023
template: `
2124
<div
2225
class="container"
@@ -25,18 +28,24 @@ import { Composer } from './composer';
2528
appSquircleBorderColor="#EEC7AD"
2629
>
2730
@if (chat.isLoading()) {
28-
<div class="chat-loading">
29-
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
30-
</div>
31+
<div class="chat-loading">
32+
<mat-progress-bar mode="indeterminate"></mat-progress-bar>
33+
</div>
3134
}
3235
<app-chat-layout>
3336
<div class="chat-messages" #contentDiv>
3437
@for (message of chat.value(); track $index) {
35-
<div class="chat-message">
36-
<p>{{ message.content }}</p>
37-
</div>
38-
} @if (chat.value().length === 0) {
39-
<app-chat-prompts (selectPrompt)="sendMessage($event)" />
38+
@switch (message.role) {
39+
@case ('user') {
40+
<p>{{ message.content }}</p>
41+
}
42+
@case ('assistant') {
43+
<hb-render-message [message]="message" />
44+
}
45+
}
46+
}
47+
@if (chat.value().length === 0) {
48+
<app-chat-prompts (selectPrompt)="sendMessage($event)" />
4049
}
4150
</div>
4251
<app-chat-composer
@@ -102,11 +111,41 @@ export class ChatPanelComponent {
102111
});
103112
}
104113

105-
chat = chatResource({
114+
chat = uiChatResource({
106115
model: 'gpt-4.1',
107-
debugName: 'chatResource',
108-
system:
109-
'You are a helpful assistant that can answer questions and help with tasks.',
116+
debugName: 'ui-chat',
117+
system: prompt`
118+
### ROLE & TONE
119+
You are **Smart Home Assistant**, a friendly and concise AI assistant for a
120+
smart home web application.
121+
122+
- Voice: clear, helpful, and respectful.
123+
- Audience: users controlling lights and scenes via the web interface.
124+
125+
### RULES
126+
1. **Never** expose raw data or internal code details.
127+
2. For commands you cannot perform, **admit it** and suggest an alternative.
128+
3. For actionable requests (e.g., changing light settings), **precede** any
129+
explanation with the appropriate tool call.
130+
131+
132+
### EXAMPLES
133+
134+
<user>Hello</user>
135+
<assistant>
136+
<ui>
137+
<app-markdown data="How may I assist you?" />
138+
</ui>
139+
</assistant>
140+
`,
141+
components: [
142+
exposeComponent(Markdown, {
143+
description: 'Show markdown to the user',
144+
input: {
145+
data: s.streaming.string('The markdown content'),
146+
},
147+
}),
148+
],
110149
});
111150

112151
sendMessage(message: string) {

0 commit comments

Comments
 (0)