@copilotkitnext/angular 0.0.2 → 0.0.4

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 (168) 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/esm2022/components/chat/copilot-chat-assistant-message-buttons.component.mjs +384 -0
  7. package/dist/esm2022/components/chat/copilot-chat-assistant-message-renderer.component.mjs +286 -0
  8. package/dist/esm2022/components/chat/copilot-chat-assistant-message-toolbar.component.mjs +27 -0
  9. package/dist/esm2022/components/chat/copilot-chat-assistant-message.component.mjs +433 -0
  10. package/dist/esm2022/components/chat/copilot-chat-assistant-message.types.mjs +2 -0
  11. package/dist/esm2022/components/chat/copilot-chat-audio-recorder.component.mjs +202 -0
  12. package/dist/esm2022/components/chat/copilot-chat-buttons.component.mjs +321 -0
  13. package/dist/esm2022/components/chat/copilot-chat-input-defaults.mjs +38 -0
  14. package/dist/esm2022/components/chat/copilot-chat-input.component.mjs +666 -0
  15. package/dist/esm2022/components/chat/copilot-chat-input.types.mjs +10 -0
  16. package/dist/esm2022/components/chat/copilot-chat-message-view-cursor.component.mjs +45 -0
  17. package/dist/esm2022/components/chat/copilot-chat-message-view.component.mjs +296 -0
  18. package/dist/esm2022/components/chat/copilot-chat-message-view.types.mjs +2 -0
  19. package/dist/esm2022/components/chat/copilot-chat-textarea.component.mjs +188 -0
  20. package/dist/esm2022/components/chat/copilot-chat-tool-calls-view.component.mjs +216 -0
  21. package/dist/esm2022/components/chat/copilot-chat-toolbar.component.mjs +25 -0
  22. package/dist/esm2022/components/chat/copilot-chat-tools-menu.component.mjs +199 -0
  23. package/dist/esm2022/components/chat/copilot-chat-user-message-branch-navigation.component.mjs +137 -0
  24. package/dist/esm2022/components/chat/copilot-chat-user-message-buttons.component.mjs +207 -0
  25. package/dist/esm2022/components/chat/copilot-chat-user-message-renderer.component.mjs +35 -0
  26. package/dist/esm2022/components/chat/copilot-chat-user-message-toolbar.component.mjs +34 -0
  27. package/dist/esm2022/components/chat/copilot-chat-user-message.component.mjs +341 -0
  28. package/dist/esm2022/components/chat/copilot-chat-user-message.types.mjs +2 -0
  29. package/dist/esm2022/components/chat/copilot-chat-view-disclaimer.component.mjs +52 -0
  30. package/dist/esm2022/components/chat/copilot-chat-view-feather.component.mjs +55 -0
  31. package/dist/esm2022/components/chat/copilot-chat-view-handlers.service.mjs +19 -0
  32. package/dist/esm2022/components/chat/copilot-chat-view-input-container.component.mjs +110 -0
  33. package/dist/esm2022/components/chat/copilot-chat-view-scroll-to-bottom-button.component.mjs +93 -0
  34. package/dist/esm2022/components/chat/copilot-chat-view-scroll-view.component.mjs +443 -0
  35. package/dist/esm2022/components/chat/copilot-chat-view.component.mjs +479 -0
  36. package/dist/esm2022/components/chat/copilot-chat-view.types.mjs +2 -0
  37. package/dist/esm2022/components/chat/copilot-chat.component.mjs +214 -0
  38. package/dist/esm2022/components/copilotkit-tool-render.component.mjs +153 -0
  39. package/dist/esm2022/copilotkitnext-angular.mjs +5 -0
  40. package/dist/esm2022/core/chat-configuration/chat-configuration.providers.mjs +65 -0
  41. package/dist/esm2022/core/chat-configuration/chat-configuration.service.mjs +145 -0
  42. package/dist/esm2022/core/chat-configuration/chat-configuration.types.mjs +26 -0
  43. package/dist/esm2022/core/copilotkit.providers.mjs +34 -0
  44. package/dist/esm2022/core/copilotkit.service.mjs +430 -0
  45. package/dist/esm2022/core/copilotkit.types.mjs +12 -0
  46. package/dist/esm2022/directives/copilotkit-agent-context.directive.mjs +130 -0
  47. package/dist/esm2022/directives/copilotkit-agent.directive.mjs +217 -0
  48. package/dist/esm2022/directives/copilotkit-chat-config.directive.mjs +218 -0
  49. package/dist/esm2022/directives/copilotkit-config.directive.mjs +94 -0
  50. package/dist/esm2022/directives/copilotkit-frontend-tool.directive.mjs +130 -0
  51. package/dist/esm2022/directives/copilotkit-human-in-the-loop.directive.mjs +266 -0
  52. package/dist/esm2022/directives/stick-to-bottom.directive.mjs +181 -0
  53. package/dist/esm2022/index.mjs +70 -0
  54. package/dist/esm2022/lib/directives/tooltip.directive.mjs +211 -0
  55. package/dist/esm2022/lib/slots/copilot-slot.component.mjs +144 -0
  56. package/dist/esm2022/lib/slots/slot.types.mjs +6 -0
  57. package/dist/esm2022/lib/slots/slot.utils.mjs +222 -0
  58. package/dist/esm2022/lib/utils.mjs +10 -0
  59. package/dist/esm2022/services/resize-observer.service.mjs +152 -0
  60. package/dist/esm2022/services/scroll-position.service.mjs +124 -0
  61. package/dist/esm2022/types/frontend-tool.mjs +2 -0
  62. package/dist/esm2022/types/human-in-the-loop.mjs +2 -0
  63. package/dist/esm2022/utils/agent-context.utils.mjs +114 -0
  64. package/dist/esm2022/utils/agent.utils.mjs +204 -0
  65. package/dist/esm2022/utils/chat-config.utils.mjs +186 -0
  66. package/dist/esm2022/utils/copilotkit.utils.mjs +20 -0
  67. package/dist/esm2022/utils/frontend-tool.utils.mjs +228 -0
  68. package/dist/esm2022/utils/human-in-the-loop.utils.mjs +296 -0
  69. package/dist/fesm2022/copilotkitnext-angular.mjs +163 -164
  70. package/dist/fesm2022/copilotkitnext-angular.mjs.map +1 -1
  71. package/package.json +21 -18
  72. package/vitest.config.mts +32 -21
  73. package/.turbo/turbo-build.log +0 -38
  74. package/.turbo/turbo-check-types.log +0 -0
  75. package/.turbo/turbo-test.log +0 -71
  76. package/ng-package.json +0 -19
  77. package/src/components/chat/__tests__/copilot-chat-assistant-message.component.spec.ts +0 -282
  78. package/src/components/chat/__tests__/copilot-chat-input.component.spec.ts +0 -419
  79. package/src/components/chat/__tests__/copilot-chat-message-view.component.spec.ts +0 -372
  80. package/src/components/chat/__tests__/copilot-chat-user-message.component.spec.ts +0 -249
  81. package/src/components/chat/copilot-chat-assistant-message-buttons.component.ts +0 -292
  82. package/src/components/chat/copilot-chat-assistant-message-renderer.component.ts +0 -472
  83. package/src/components/chat/copilot-chat-assistant-message-toolbar.component.ts +0 -29
  84. package/src/components/chat/copilot-chat-assistant-message.component.ts +0 -463
  85. package/src/components/chat/copilot-chat-assistant-message.types.ts +0 -50
  86. package/src/components/chat/copilot-chat-audio-recorder.component.ts +0 -241
  87. package/src/components/chat/copilot-chat-buttons.component.ts +0 -308
  88. package/src/components/chat/copilot-chat-buttons.component.ts.bak +0 -471
  89. package/src/components/chat/copilot-chat-input-defaults.ts +0 -47
  90. package/src/components/chat/copilot-chat-input.component.ts +0 -512
  91. package/src/components/chat/copilot-chat-input.types.ts +0 -148
  92. package/src/components/chat/copilot-chat-message-view-cursor.component.ts +0 -51
  93. package/src/components/chat/copilot-chat-message-view.component.ts +0 -233
  94. package/src/components/chat/copilot-chat-message-view.types.ts +0 -39
  95. package/src/components/chat/copilot-chat-textarea.component.ts +0 -220
  96. package/src/components/chat/copilot-chat-tool-calls-view.component.ts +0 -261
  97. package/src/components/chat/copilot-chat-toolbar.component.ts +0 -35
  98. package/src/components/chat/copilot-chat-tools-menu.component.ts +0 -185
  99. package/src/components/chat/copilot-chat-user-message-branch-navigation.component.ts +0 -121
  100. package/src/components/chat/copilot-chat-user-message-buttons.component.ts +0 -170
  101. package/src/components/chat/copilot-chat-user-message-renderer.component.ts +0 -37
  102. package/src/components/chat/copilot-chat-user-message-toolbar.component.ts +0 -37
  103. package/src/components/chat/copilot-chat-user-message.component.ts +0 -247
  104. package/src/components/chat/copilot-chat-user-message.types.ts +0 -42
  105. package/src/components/chat/copilot-chat-view-disclaimer.component.ts +0 -51
  106. package/src/components/chat/copilot-chat-view-feather.component.ts +0 -47
  107. package/src/components/chat/copilot-chat-view-handlers.service.ts +0 -14
  108. package/src/components/chat/copilot-chat-view-input-container.component.ts +0 -87
  109. package/src/components/chat/copilot-chat-view-scroll-to-bottom-button.component.ts +0 -79
  110. package/src/components/chat/copilot-chat-view-scroll-view.component.ts +0 -322
  111. package/src/components/chat/copilot-chat-view.component.ts +0 -420
  112. package/src/components/chat/copilot-chat-view.types.ts +0 -52
  113. package/src/components/chat/copilot-chat.component.ts +0 -232
  114. package/src/components/copilotkit-tool-render.component.ts +0 -169
  115. package/src/core/__tests__/copilotkit.service.spec.ts +0 -1051
  116. package/src/core/__tests__/copilotkit.service.wildcard.spec.ts +0 -316
  117. package/src/core/chat-configuration/__tests__/chat-configuration.service.spec.ts +0 -287
  118. package/src/core/chat-configuration/chat-configuration.providers.ts +0 -71
  119. package/src/core/chat-configuration/chat-configuration.service.ts +0 -162
  120. package/src/core/chat-configuration/chat-configuration.types.ts +0 -57
  121. package/src/core/copilotkit.providers.ts +0 -59
  122. package/src/core/copilotkit.service.ts +0 -542
  123. package/src/core/copilotkit.types.ts +0 -132
  124. package/src/directives/__tests__/copilotkit-agent-context.directive.spec.ts +0 -384
  125. package/src/directives/__tests__/copilotkit-agent.directive.spec.ts +0 -253
  126. package/src/directives/__tests__/copilotkit-chat-config.directive.spec.ts +0 -385
  127. package/src/directives/__tests__/copilotkit-config.directive.spec.ts +0 -69
  128. package/src/directives/__tests__/copilotkit-frontend-tool-simple.directive.spec.ts +0 -60
  129. package/src/directives/__tests__/copilotkit-frontend-tool.directive.spec.ts +0 -108
  130. package/src/directives/__tests__/copilotkit-human-in-the-loop.directive.spec.ts +0 -452
  131. package/src/directives/copilotkit-agent-context.directive.ts +0 -138
  132. package/src/directives/copilotkit-agent.directive.ts +0 -225
  133. package/src/directives/copilotkit-chat-config.directive.ts +0 -241
  134. package/src/directives/copilotkit-config.directive.ts +0 -81
  135. package/src/directives/copilotkit-frontend-tool.directive.ts +0 -145
  136. package/src/directives/copilotkit-human-in-the-loop.directive.ts +0 -281
  137. package/src/directives/stick-to-bottom.directive.ts +0 -204
  138. package/src/index.ts +0 -105
  139. package/src/lib/directives/tooltip.directive.ts +0 -292
  140. package/src/lib/slots/__tests__/slot.utils.spec.ts +0 -377
  141. package/src/lib/slots/copilot-slot.component.ts +0 -135
  142. package/src/lib/slots/index.ts +0 -3
  143. package/src/lib/slots/slot.types.ts +0 -64
  144. package/src/lib/slots/slot.utils.ts +0 -289
  145. package/src/lib/utils.ts +0 -10
  146. package/src/public-api.ts +0 -1
  147. package/src/services/resize-observer.service.ts +0 -181
  148. package/src/services/scroll-position.service.ts +0 -169
  149. package/src/styles/globals.css +0 -266
  150. package/src/styles/index.css +0 -3
  151. package/src/test-setup.ts +0 -15
  152. package/src/testing/index.ts +0 -3
  153. package/src/testing/testing.utils.ts +0 -248
  154. package/src/types/frontend-tool.ts +0 -44
  155. package/src/types/human-in-the-loop.ts +0 -52
  156. package/src/utils/__tests__/agent.utils.spec.ts +0 -234
  157. package/src/utils/__tests__/chat-config.utils.spec.ts +0 -306
  158. package/src/utils/__tests__/frontend-tool-inject.spec.ts +0 -350
  159. package/src/utils/__tests__/frontend-tool-integration.spec.ts +0 -199
  160. package/src/utils/__tests__/frontend-tool.utils.spec.ts +0 -272
  161. package/src/utils/__tests__/human-in-the-loop.utils.spec.ts +0 -365
  162. package/src/utils/agent-context.utils.ts +0 -133
  163. package/src/utils/agent.utils.ts +0 -239
  164. package/src/utils/chat-config.utils.ts +0 -221
  165. package/src/utils/copilotkit.utils.ts +0 -20
  166. package/src/utils/frontend-tool.utils.ts +0 -266
  167. package/src/utils/human-in-the-loop.utils.ts +0 -359
  168. 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
- }