@copilotkitnext/angular 0.0.2 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (173) hide show
  1. package/README.md +3 -3
  2. package/dist/README.md +3 -3
  3. package/dist/components/chat/copilot-chat-assistant-message.component.d.ts +10 -10
  4. package/dist/components/chat/copilot-chat-message-view.component.d.ts +42 -42
  5. package/dist/components/chat/copilot-chat-view.component.d.ts +14 -14
  6. package/dist/core/copilotkit.providers.d.ts +1 -1
  7. package/dist/core/copilotkit.service.d.ts +5 -5
  8. package/dist/core/copilotkit.types.d.ts +8 -10
  9. package/dist/directives/copilotkit-frontend-tool.directive.d.ts +1 -1
  10. package/dist/esm2022/components/chat/copilot-chat-assistant-message-buttons.component.mjs +384 -0
  11. package/dist/esm2022/components/chat/copilot-chat-assistant-message-renderer.component.mjs +286 -0
  12. package/dist/esm2022/components/chat/copilot-chat-assistant-message-toolbar.component.mjs +27 -0
  13. package/dist/esm2022/components/chat/copilot-chat-assistant-message.component.mjs +433 -0
  14. package/dist/esm2022/components/chat/copilot-chat-assistant-message.types.mjs +2 -0
  15. package/dist/esm2022/components/chat/copilot-chat-audio-recorder.component.mjs +202 -0
  16. package/dist/esm2022/components/chat/copilot-chat-buttons.component.mjs +321 -0
  17. package/dist/esm2022/components/chat/copilot-chat-input-defaults.mjs +38 -0
  18. package/dist/esm2022/components/chat/copilot-chat-input.component.mjs +666 -0
  19. package/dist/esm2022/components/chat/copilot-chat-input.types.mjs +10 -0
  20. package/dist/esm2022/components/chat/copilot-chat-message-view-cursor.component.mjs +45 -0
  21. package/dist/esm2022/components/chat/copilot-chat-message-view.component.mjs +296 -0
  22. package/dist/esm2022/components/chat/copilot-chat-message-view.types.mjs +2 -0
  23. package/dist/esm2022/components/chat/copilot-chat-textarea.component.mjs +188 -0
  24. package/dist/esm2022/components/chat/copilot-chat-tool-calls-view.component.mjs +216 -0
  25. package/dist/esm2022/components/chat/copilot-chat-toolbar.component.mjs +25 -0
  26. package/dist/esm2022/components/chat/copilot-chat-tools-menu.component.mjs +199 -0
  27. package/dist/esm2022/components/chat/copilot-chat-user-message-branch-navigation.component.mjs +137 -0
  28. package/dist/esm2022/components/chat/copilot-chat-user-message-buttons.component.mjs +207 -0
  29. package/dist/esm2022/components/chat/copilot-chat-user-message-renderer.component.mjs +35 -0
  30. package/dist/esm2022/components/chat/copilot-chat-user-message-toolbar.component.mjs +34 -0
  31. package/dist/esm2022/components/chat/copilot-chat-user-message.component.mjs +341 -0
  32. package/dist/esm2022/components/chat/copilot-chat-user-message.types.mjs +2 -0
  33. package/dist/esm2022/components/chat/copilot-chat-view-disclaimer.component.mjs +52 -0
  34. package/dist/esm2022/components/chat/copilot-chat-view-feather.component.mjs +55 -0
  35. package/dist/esm2022/components/chat/copilot-chat-view-handlers.service.mjs +19 -0
  36. package/dist/esm2022/components/chat/copilot-chat-view-input-container.component.mjs +110 -0
  37. package/dist/esm2022/components/chat/copilot-chat-view-scroll-to-bottom-button.component.mjs +93 -0
  38. package/dist/esm2022/components/chat/copilot-chat-view-scroll-view.component.mjs +443 -0
  39. package/dist/esm2022/components/chat/copilot-chat-view.component.mjs +479 -0
  40. package/dist/esm2022/components/chat/copilot-chat-view.types.mjs +2 -0
  41. package/dist/esm2022/components/chat/copilot-chat.component.mjs +214 -0
  42. package/dist/esm2022/components/copilotkit-tool-render.component.mjs +153 -0
  43. package/dist/esm2022/copilotkitnext-angular.mjs +5 -0
  44. package/dist/esm2022/core/chat-configuration/chat-configuration.providers.mjs +65 -0
  45. package/dist/esm2022/core/chat-configuration/chat-configuration.service.mjs +145 -0
  46. package/dist/esm2022/core/chat-configuration/chat-configuration.types.mjs +26 -0
  47. package/dist/esm2022/core/copilotkit.providers.mjs +34 -0
  48. package/dist/esm2022/core/copilotkit.service.mjs +426 -0
  49. package/dist/esm2022/core/copilotkit.types.mjs +13 -0
  50. package/dist/esm2022/directives/copilotkit-agent-context.directive.mjs +130 -0
  51. package/dist/esm2022/directives/copilotkit-agent.directive.mjs +217 -0
  52. package/dist/esm2022/directives/copilotkit-chat-config.directive.mjs +218 -0
  53. package/dist/esm2022/directives/copilotkit-config.directive.mjs +94 -0
  54. package/dist/esm2022/directives/copilotkit-frontend-tool.directive.mjs +128 -0
  55. package/dist/esm2022/directives/copilotkit-human-in-the-loop.directive.mjs +265 -0
  56. package/dist/esm2022/directives/stick-to-bottom.directive.mjs +181 -0
  57. package/dist/esm2022/index.mjs +70 -0
  58. package/dist/esm2022/lib/directives/tooltip.directive.mjs +211 -0
  59. package/dist/esm2022/lib/slots/copilot-slot.component.mjs +144 -0
  60. package/dist/esm2022/lib/slots/slot.types.mjs +6 -0
  61. package/dist/esm2022/lib/slots/slot.utils.mjs +222 -0
  62. package/dist/esm2022/lib/utils.mjs +10 -0
  63. package/dist/esm2022/services/resize-observer.service.mjs +152 -0
  64. package/dist/esm2022/services/scroll-position.service.mjs +124 -0
  65. package/dist/esm2022/types/frontend-tool.mjs +2 -0
  66. package/dist/esm2022/types/human-in-the-loop.mjs +2 -0
  67. package/dist/esm2022/utils/agent-context.utils.mjs +114 -0
  68. package/dist/esm2022/utils/agent.utils.mjs +204 -0
  69. package/dist/esm2022/utils/chat-config.utils.mjs +186 -0
  70. package/dist/esm2022/utils/copilotkit.utils.mjs +20 -0
  71. package/dist/esm2022/utils/frontend-tool.utils.mjs +224 -0
  72. package/dist/esm2022/utils/human-in-the-loop.utils.mjs +293 -0
  73. package/dist/fesm2022/copilotkitnext-angular.mjs +174 -187
  74. package/dist/fesm2022/copilotkitnext-angular.mjs.map +1 -1
  75. package/dist/utils/frontend-tool.utils.d.ts +1 -1
  76. package/package.json +23 -20
  77. package/vitest.config.mts +32 -21
  78. package/.turbo/turbo-build.log +0 -38
  79. package/.turbo/turbo-check-types.log +0 -0
  80. package/.turbo/turbo-test.log +0 -71
  81. package/ng-package.json +0 -19
  82. package/src/components/chat/__tests__/copilot-chat-assistant-message.component.spec.ts +0 -282
  83. package/src/components/chat/__tests__/copilot-chat-input.component.spec.ts +0 -419
  84. package/src/components/chat/__tests__/copilot-chat-message-view.component.spec.ts +0 -372
  85. package/src/components/chat/__tests__/copilot-chat-user-message.component.spec.ts +0 -249
  86. package/src/components/chat/copilot-chat-assistant-message-buttons.component.ts +0 -292
  87. package/src/components/chat/copilot-chat-assistant-message-renderer.component.ts +0 -472
  88. package/src/components/chat/copilot-chat-assistant-message-toolbar.component.ts +0 -29
  89. package/src/components/chat/copilot-chat-assistant-message.component.ts +0 -463
  90. package/src/components/chat/copilot-chat-assistant-message.types.ts +0 -50
  91. package/src/components/chat/copilot-chat-audio-recorder.component.ts +0 -241
  92. package/src/components/chat/copilot-chat-buttons.component.ts +0 -308
  93. package/src/components/chat/copilot-chat-buttons.component.ts.bak +0 -471
  94. package/src/components/chat/copilot-chat-input-defaults.ts +0 -47
  95. package/src/components/chat/copilot-chat-input.component.ts +0 -512
  96. package/src/components/chat/copilot-chat-input.types.ts +0 -148
  97. package/src/components/chat/copilot-chat-message-view-cursor.component.ts +0 -51
  98. package/src/components/chat/copilot-chat-message-view.component.ts +0 -233
  99. package/src/components/chat/copilot-chat-message-view.types.ts +0 -39
  100. package/src/components/chat/copilot-chat-textarea.component.ts +0 -220
  101. package/src/components/chat/copilot-chat-tool-calls-view.component.ts +0 -261
  102. package/src/components/chat/copilot-chat-toolbar.component.ts +0 -35
  103. package/src/components/chat/copilot-chat-tools-menu.component.ts +0 -185
  104. package/src/components/chat/copilot-chat-user-message-branch-navigation.component.ts +0 -121
  105. package/src/components/chat/copilot-chat-user-message-buttons.component.ts +0 -170
  106. package/src/components/chat/copilot-chat-user-message-renderer.component.ts +0 -37
  107. package/src/components/chat/copilot-chat-user-message-toolbar.component.ts +0 -37
  108. package/src/components/chat/copilot-chat-user-message.component.ts +0 -247
  109. package/src/components/chat/copilot-chat-user-message.types.ts +0 -42
  110. package/src/components/chat/copilot-chat-view-disclaimer.component.ts +0 -51
  111. package/src/components/chat/copilot-chat-view-feather.component.ts +0 -47
  112. package/src/components/chat/copilot-chat-view-handlers.service.ts +0 -14
  113. package/src/components/chat/copilot-chat-view-input-container.component.ts +0 -87
  114. package/src/components/chat/copilot-chat-view-scroll-to-bottom-button.component.ts +0 -79
  115. package/src/components/chat/copilot-chat-view-scroll-view.component.ts +0 -322
  116. package/src/components/chat/copilot-chat-view.component.ts +0 -420
  117. package/src/components/chat/copilot-chat-view.types.ts +0 -52
  118. package/src/components/chat/copilot-chat.component.ts +0 -232
  119. package/src/components/copilotkit-tool-render.component.ts +0 -169
  120. package/src/core/__tests__/copilotkit.service.spec.ts +0 -1051
  121. package/src/core/__tests__/copilotkit.service.wildcard.spec.ts +0 -316
  122. package/src/core/chat-configuration/__tests__/chat-configuration.service.spec.ts +0 -287
  123. package/src/core/chat-configuration/chat-configuration.providers.ts +0 -71
  124. package/src/core/chat-configuration/chat-configuration.service.ts +0 -162
  125. package/src/core/chat-configuration/chat-configuration.types.ts +0 -57
  126. package/src/core/copilotkit.providers.ts +0 -59
  127. package/src/core/copilotkit.service.ts +0 -542
  128. package/src/core/copilotkit.types.ts +0 -132
  129. package/src/directives/__tests__/copilotkit-agent-context.directive.spec.ts +0 -384
  130. package/src/directives/__tests__/copilotkit-agent.directive.spec.ts +0 -253
  131. package/src/directives/__tests__/copilotkit-chat-config.directive.spec.ts +0 -385
  132. package/src/directives/__tests__/copilotkit-config.directive.spec.ts +0 -69
  133. package/src/directives/__tests__/copilotkit-frontend-tool-simple.directive.spec.ts +0 -60
  134. package/src/directives/__tests__/copilotkit-frontend-tool.directive.spec.ts +0 -108
  135. package/src/directives/__tests__/copilotkit-human-in-the-loop.directive.spec.ts +0 -452
  136. package/src/directives/copilotkit-agent-context.directive.ts +0 -138
  137. package/src/directives/copilotkit-agent.directive.ts +0 -225
  138. package/src/directives/copilotkit-chat-config.directive.ts +0 -241
  139. package/src/directives/copilotkit-config.directive.ts +0 -81
  140. package/src/directives/copilotkit-frontend-tool.directive.ts +0 -145
  141. package/src/directives/copilotkit-human-in-the-loop.directive.ts +0 -281
  142. package/src/directives/stick-to-bottom.directive.ts +0 -204
  143. package/src/index.ts +0 -105
  144. package/src/lib/directives/tooltip.directive.ts +0 -292
  145. package/src/lib/slots/__tests__/slot.utils.spec.ts +0 -377
  146. package/src/lib/slots/copilot-slot.component.ts +0 -135
  147. package/src/lib/slots/index.ts +0 -3
  148. package/src/lib/slots/slot.types.ts +0 -64
  149. package/src/lib/slots/slot.utils.ts +0 -289
  150. package/src/lib/utils.ts +0 -10
  151. package/src/public-api.ts +0 -1
  152. package/src/services/resize-observer.service.ts +0 -181
  153. package/src/services/scroll-position.service.ts +0 -169
  154. package/src/styles/globals.css +0 -266
  155. package/src/styles/index.css +0 -3
  156. package/src/test-setup.ts +0 -15
  157. package/src/testing/index.ts +0 -3
  158. package/src/testing/testing.utils.ts +0 -248
  159. package/src/types/frontend-tool.ts +0 -44
  160. package/src/types/human-in-the-loop.ts +0 -52
  161. package/src/utils/__tests__/agent.utils.spec.ts +0 -234
  162. package/src/utils/__tests__/chat-config.utils.spec.ts +0 -306
  163. package/src/utils/__tests__/frontend-tool-inject.spec.ts +0 -350
  164. package/src/utils/__tests__/frontend-tool-integration.spec.ts +0 -199
  165. package/src/utils/__tests__/frontend-tool.utils.spec.ts +0 -272
  166. package/src/utils/__tests__/human-in-the-loop.utils.spec.ts +0 -365
  167. package/src/utils/agent-context.utils.ts +0 -133
  168. package/src/utils/agent.utils.ts +0 -239
  169. package/src/utils/chat-config.utils.ts +0 -221
  170. package/src/utils/copilotkit.utils.ts +0 -20
  171. package/src/utils/frontend-tool.utils.ts +0 -266
  172. package/src/utils/human-in-the-loop.utils.ts +0 -359
  173. package/tsconfig.spec.json +0 -12
@@ -1,472 +0,0 @@
1
- import {
2
- Component,
3
- Input,
4
- ChangeDetectionStrategy,
5
- ViewEncapsulation,
6
- OnChanges,
7
- SimpleChanges,
8
- signal,
9
- computed,
10
- inject,
11
- ElementRef,
12
- AfterViewInit,
13
- ViewChild,
14
- } from "@angular/core";
15
- import { CommonModule } from "@angular/common";
16
- import { Marked } from "marked";
17
- import hljs from "highlight.js";
18
- import * as katex from "katex";
19
- import { completePartialMarkdown } from "@copilotkitnext/core";
20
- import { LucideAngularModule, Copy, Check } from "lucide-angular";
21
- import { CopilotChatConfigurationService } from "../../core/chat-configuration/chat-configuration.service";
22
-
23
- @Component({
24
- selector: "copilot-chat-assistant-message-renderer",
25
- standalone: true,
26
- imports: [CommonModule, LucideAngularModule],
27
- changeDetection: ChangeDetectionStrategy.OnPush,
28
- encapsulation: ViewEncapsulation.None,
29
- template: `
30
- <div
31
- #markdownContainer
32
- [class]="inputClass"
33
- (click)="handleClick($event)"
34
- ></div>
35
- `,
36
- styles: [
37
- `
38
- copilot-chat-assistant-message-renderer {
39
- display: block;
40
- width: 100%;
41
- }
42
-
43
- /* Inline code styling */
44
- copilot-chat-assistant-message-renderer code:not(pre code) {
45
- padding: 2.5px 4.8px;
46
- background-color: rgb(236, 236, 236);
47
- border-radius: 0.25rem;
48
- font-size: 0.875rem;
49
- font-family:
50
- ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono",
51
- Menlo, monospace;
52
- font-weight: 500;
53
- color: #000000;
54
- }
55
-
56
- .dark copilot-chat-assistant-message-renderer code:not(pre code) {
57
- background-color: #171717; /* same as code blocks */
58
- color: rgb(248, 250, 252); /* text-foreground in dark mode */
59
- }
60
-
61
- /* Code block container */
62
- copilot-chat-assistant-message-renderer .code-block-container {
63
- position: relative;
64
- margin: 0.25rem 0;
65
- background-color: rgb(249, 249, 249);
66
- border-radius: 1rem;
67
- }
68
-
69
- .dark copilot-chat-assistant-message-renderer .code-block-container {
70
- background-color: #171717;
71
- }
72
-
73
- copilot-chat-assistant-message-renderer .code-block-header {
74
- display: flex;
75
- align-items: center;
76
- justify-content: space-between;
77
- padding: 0.75rem 1rem 0.75rem 1rem;
78
- font-size: 0.75rem;
79
- background-color: transparent;
80
- }
81
-
82
- copilot-chat-assistant-message-renderer .code-block-language {
83
- font-weight: 400;
84
- color: rgba(115, 115, 115, 1);
85
- }
86
-
87
- .dark copilot-chat-assistant-message-renderer .code-block-language {
88
- color: white;
89
- }
90
-
91
- copilot-chat-assistant-message-renderer .code-block-copy-button {
92
- display: flex;
93
- align-items: center;
94
- gap: 0.125rem;
95
- padding: 0 0.5rem;
96
- font-size: 0.75rem;
97
- color: rgba(115, 115, 115, 1);
98
- cursor: pointer;
99
- background: none;
100
- border: none;
101
- transition: opacity 0.2s;
102
- }
103
-
104
- .dark copilot-chat-assistant-message-renderer .code-block-copy-button {
105
- color: white;
106
- }
107
-
108
- copilot-chat-assistant-message-renderer .code-block-copy-button:hover {
109
- opacity: 0.8;
110
- }
111
-
112
- copilot-chat-assistant-message-renderer .code-block-copy-button svg {
113
- width: 10px;
114
- height: 10px;
115
- }
116
-
117
- copilot-chat-assistant-message-renderer .code-block-copy-button span {
118
- font-size: 11px;
119
- }
120
-
121
- copilot-chat-assistant-message-renderer pre {
122
- margin: 0;
123
- padding: 0 1rem 1rem 1rem;
124
- overflow-x: auto;
125
- background-color: transparent;
126
- border-radius: 1rem;
127
- }
128
-
129
- .dark copilot-chat-assistant-message-renderer pre {
130
- background-color: transparent;
131
- }
132
-
133
- copilot-chat-assistant-message-renderer pre code {
134
- background-color: transparent;
135
- padding: 0;
136
- font-size: 0.875rem;
137
- font-family:
138
- ui-monospace, SFMono-Regular, "SF Mono", Consolas, "Liberation Mono",
139
- Menlo, monospace;
140
- }
141
-
142
- /* Highlight.js theme adjustments */
143
- copilot-chat-assistant-message-renderer .hljs {
144
- background: transparent;
145
- color: rgb(56, 58, 66);
146
- }
147
-
148
- .dark copilot-chat-assistant-message-renderer .hljs {
149
- background: transparent;
150
- color: #abb2bf;
151
- }
152
-
153
- /* Math equations */
154
- copilot-chat-assistant-message-renderer .katex-display {
155
- overflow-x: auto;
156
- overflow-y: hidden;
157
- padding: 1rem 0;
158
- }
159
- `,
160
- ],
161
- })
162
- export class CopilotChatAssistantMessageRendererComponent
163
- implements OnChanges, AfterViewInit
164
- {
165
- private _content = "";
166
- @Input()
167
- set content(value: string) {
168
- this._content = value;
169
- this.contentSignal.set(value);
170
- }
171
- get content(): string {
172
- return this._content;
173
- }
174
-
175
- @Input() inputClass?: string;
176
-
177
- private contentSignal = signal<string>("");
178
-
179
- @ViewChild("markdownContainer", { static: false })
180
- markdownContainer?: ElementRef<HTMLDivElement>;
181
-
182
- private chatConfig = inject(CopilotChatConfigurationService);
183
- private elementRef = inject(ElementRef);
184
-
185
- // Track copy states for code blocks
186
- private copyStates = new Map<string, boolean>();
187
- private copyStateSignal = signal(new Map<string, boolean>());
188
-
189
- renderedHtml = computed(() => {
190
- const currentContent = this.contentSignal();
191
- const completedMarkdown = completePartialMarkdown(currentContent);
192
- return this.renderMarkdown(completedMarkdown);
193
- });
194
-
195
- get labels() {
196
- return this.chatConfig.labels();
197
- }
198
-
199
- ngOnChanges(changes: SimpleChanges): void {
200
- if (changes["content"]) {
201
- // Reset copy states when content changes
202
- this.copyStates.clear();
203
- this.copyStateSignal.set(new Map());
204
- // Update content if container exists
205
- if (this.markdownContainer) {
206
- this.updateContent();
207
- this.renderMathEquations();
208
- }
209
- }
210
- }
211
-
212
- ngAfterViewInit(): void {
213
- this.updateContent();
214
- this.renderMathEquations();
215
- }
216
-
217
- private updateContent(): void {
218
- if (!this.markdownContainer) return;
219
- const container = this.markdownContainer.nativeElement;
220
- const html = this.renderedHtml();
221
- container.innerHTML = html;
222
- }
223
-
224
- private codeBlocksMap = new Map<string, string>();
225
- private markedInstance: Marked | null = null;
226
-
227
- private initializeMarked(): void {
228
- if (this.markedInstance) return;
229
-
230
- // Store highlighted code blocks temporarily
231
- const highlightedBlocks = new Map<string, string>();
232
-
233
- // Create a new Marked instance
234
- this.markedInstance = new Marked();
235
-
236
- // Configure marked options
237
- this.markedInstance.setOptions({
238
- gfm: true,
239
- breaks: true,
240
- });
241
-
242
- // Add a walkTokens function to process code tokens before rendering
243
- this.markedInstance.use({
244
- walkTokens: (token: any) => {
245
- if (token.type === "code") {
246
- const rawCode = token.text;
247
- const lang = token.lang || "";
248
-
249
- const blockId = this.generateBlockId(rawCode);
250
- // Store the raw code in our map for copying
251
- this.codeBlocksMap.set(blockId, rawCode);
252
-
253
- const copied = this.copyStateSignal().get(blockId) || false;
254
- const copyLabel = copied
255
- ? this.labels.assistantMessageToolbarCopyCodeCopiedLabel
256
- : this.labels.assistantMessageToolbarCopyCodeLabel;
257
-
258
- // Manually highlight the code
259
- const language = hljs.getLanguage(lang) ? lang : "plaintext";
260
- const highlighted = hljs.highlight(rawCode, { language }).value;
261
- const codeClass = lang ? `hljs language-${lang}` : "hljs";
262
-
263
- // Create the full HTML with header and highlighted code
264
- const fullHtml = `
265
- <div class="code-block-container">
266
- <div class="code-block-header">
267
- ${lang ? `<span class="code-block-language">${lang}</span>` : "<span></span>"}
268
- <button
269
- class="code-block-copy-button"
270
- data-code-block-id="${blockId}"
271
- aria-label="${copyLabel} code">
272
- ${
273
- copied
274
- ? '<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>'
275
- : '<svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.11 0-2-.9-2-2V4c0-1.11.89-2 2-2h10c1.11 0 2 .89 2 2"/></svg>'
276
- }
277
- <span>${copyLabel}</span>
278
- </button>
279
- </div>
280
- <pre><code class="${codeClass}">${highlighted}</code></pre>
281
- </div>
282
- `;
283
-
284
- // Store the highlighted HTML
285
- highlightedBlocks.set(blockId, fullHtml);
286
-
287
- // Change the token to an html token to bypass marked's escaping
288
- token.type = "html";
289
- token.text = fullHtml;
290
- }
291
- },
292
- });
293
- }
294
-
295
- private renderMarkdown(content: string): string {
296
- // Initialize marked if not already done
297
- this.initializeMarked();
298
-
299
- // Clear the code blocks map for new render
300
- this.codeBlocksMap.clear();
301
-
302
- // Parse markdown
303
- let html = this.markedInstance!.parse(content) as string;
304
-
305
- // Process math equations
306
- html = this.processMathEquations(html);
307
-
308
- return html;
309
- }
310
-
311
- private processMathEquations(html: string): string {
312
- // First, temporarily replace code blocks with placeholders to protect them from math processing
313
- const codeBlocks: string[] = [];
314
- const placeholder = "___CODE_BLOCK_PLACEHOLDER_";
315
-
316
- // Store code blocks and replace with placeholders
317
- html = html.replace(/<pre><code[\s\S]*?<\/code><\/pre>/g, (match) => {
318
- const index = codeBlocks.length;
319
- codeBlocks.push(match);
320
- return `${placeholder}${index}___`;
321
- });
322
-
323
- // Also protect inline code
324
- const inlineCode: string[] = [];
325
- const inlinePlaceholder = "___INLINE_CODE_PLACEHOLDER_";
326
- html = html.replace(/<code>[\s\S]*?<\/code>/g, (match) => {
327
- const index = inlineCode.length;
328
- inlineCode.push(match);
329
- return `${inlinePlaceholder}${index}___`;
330
- });
331
-
332
- // Process display math $$ ... $$
333
- html = html.replace(/\$\$([\s\S]*?)\$\$/g, (match, equation) => {
334
- try {
335
- return katex.renderToString(equation, {
336
- displayMode: true,
337
- throwOnError: false,
338
- });
339
- } catch {
340
- return match;
341
- }
342
- });
343
-
344
- // Process inline math $ ... $
345
- html = html.replace(/\$([^\$]+)\$/g, (match, equation) => {
346
- try {
347
- return katex.renderToString(equation, {
348
- displayMode: false,
349
- throwOnError: false,
350
- });
351
- } catch {
352
- return match;
353
- }
354
- });
355
-
356
- // Restore code blocks
357
- codeBlocks.forEach((block, index) => {
358
- html = html.replace(`${placeholder}${index}___`, block);
359
- });
360
-
361
- // Restore inline code
362
- inlineCode.forEach((code, index) => {
363
- html = html.replace(`${inlinePlaceholder}${index}___`, code);
364
- });
365
-
366
- return html;
367
- }
368
-
369
- private renderMathEquations(): void {
370
- if (!this.markdownContainer) return;
371
-
372
- const container = this.markdownContainer.nativeElement;
373
-
374
- // Find all math placeholders and render them
375
- const mathElements = container.querySelectorAll(".math-placeholder");
376
- mathElements.forEach((element) => {
377
- const equation = element.getAttribute("data-equation");
378
- const displayMode = element.getAttribute("data-display") === "true";
379
-
380
- if (equation) {
381
- try {
382
- katex.render(equation, element as HTMLElement, {
383
- displayMode,
384
- throwOnError: false,
385
- });
386
- } catch (error) {
387
- console.error("Failed to render math equation:", error);
388
- }
389
- }
390
- });
391
- }
392
-
393
- handleClick(event: MouseEvent): void {
394
- const target = event.target as HTMLElement;
395
-
396
- // Check if clicked on copy button or its children
397
- const copyButton = target.closest(
398
- ".code-block-copy-button"
399
- ) as HTMLButtonElement;
400
- if (copyButton) {
401
- event.preventDefault();
402
- const blockId = copyButton.getAttribute("data-code-block-id");
403
-
404
- if (blockId) {
405
- // Get the raw code from our map instead of from DOM
406
- const code = this.codeBlocksMap.get(blockId);
407
- if (code) {
408
- this.copyCodeBlock(blockId, code);
409
- }
410
- }
411
- }
412
- }
413
-
414
- private copyCodeBlock(blockId: string, code: string): void {
415
- navigator.clipboard.writeText(code).then(
416
- () => {
417
- // Update copy state
418
- const newStates = new Map(this.copyStateSignal());
419
- newStates.set(blockId, true);
420
- this.copyStateSignal.set(newStates);
421
-
422
- // Update the button in the DOM
423
- const button = this.elementRef.nativeElement.querySelector(
424
- `[data-code-block-id="${blockId}"]`
425
- );
426
- if (button) {
427
- const originalHTML = button.innerHTML;
428
- button.innerHTML = `
429
- <svg xmlns="http://www.w3.org/2000/svg" width="10" height="10" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg>
430
- <span>${this.labels.assistantMessageToolbarCopyCodeCopiedLabel}</span>
431
- `;
432
- button.setAttribute(
433
- "aria-label",
434
- `${this.labels.assistantMessageToolbarCopyCodeCopiedLabel} code`
435
- );
436
-
437
- // Reset after 2 seconds
438
- setTimeout(() => {
439
- const states = new Map(this.copyStateSignal());
440
- states.set(blockId, false);
441
- this.copyStateSignal.set(states);
442
- button.innerHTML = originalHTML;
443
- button.setAttribute(
444
- "aria-label",
445
- `${this.labels.assistantMessageToolbarCopyCodeLabel} code`
446
- );
447
- }, 2000);
448
- }
449
- },
450
- (err) => {
451
- console.error("Failed to copy code:", err);
452
- }
453
- );
454
- }
455
-
456
- private generateBlockId(code: string): string {
457
- // Simple hash function for generating unique IDs
458
- let hash = 0;
459
- for (let i = 0; i < code.length; i++) {
460
- const char = code.charCodeAt(i);
461
- hash = (hash << 5) - hash + char;
462
- hash = hash & hash; // Convert to 32-bit integer
463
- }
464
- return `code-block-${hash}`;
465
- }
466
-
467
- private escapeHtml(text: string): string {
468
- const div = document.createElement("div");
469
- div.textContent = text;
470
- return div.innerHTML;
471
- }
472
- }
@@ -1,29 +0,0 @@
1
- import {
2
- Directive,
3
- Input,
4
- signal,
5
- computed
6
- } from '@angular/core';
7
- import { cn } from '../../lib/utils';
8
-
9
- @Directive({
10
- selector: '[copilotChatAssistantMessageToolbar]',
11
- standalone: true,
12
- host: {
13
- '[class]': 'computedClass()'
14
- }
15
- })
16
- export class CopilotChatAssistantMessageToolbarComponent {
17
- @Input() set inputClass(value: string | undefined) {
18
- this.customClass.set(value);
19
- }
20
-
21
- private customClass = signal<string | undefined>(undefined);
22
-
23
- computedClass = computed(() => {
24
- return cn(
25
- 'w-full bg-transparent flex items-center -ml-[5px] -mt-[0px]',
26
- this.customClass()
27
- );
28
- });
29
- }