@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.
- package/README.md +3 -3
- package/dist/README.md +3 -3
- package/dist/components/chat/copilot-chat-assistant-message.component.d.ts +10 -10
- package/dist/components/chat/copilot-chat-message-view.component.d.ts +42 -42
- package/dist/components/chat/copilot-chat-view.component.d.ts +14 -14
- package/dist/esm2022/components/chat/copilot-chat-assistant-message-buttons.component.mjs +384 -0
- package/dist/esm2022/components/chat/copilot-chat-assistant-message-renderer.component.mjs +286 -0
- package/dist/esm2022/components/chat/copilot-chat-assistant-message-toolbar.component.mjs +27 -0
- package/dist/esm2022/components/chat/copilot-chat-assistant-message.component.mjs +433 -0
- package/dist/esm2022/components/chat/copilot-chat-assistant-message.types.mjs +2 -0
- package/dist/esm2022/components/chat/copilot-chat-audio-recorder.component.mjs +202 -0
- package/dist/esm2022/components/chat/copilot-chat-buttons.component.mjs +321 -0
- package/dist/esm2022/components/chat/copilot-chat-input-defaults.mjs +38 -0
- package/dist/esm2022/components/chat/copilot-chat-input.component.mjs +666 -0
- package/dist/esm2022/components/chat/copilot-chat-input.types.mjs +10 -0
- package/dist/esm2022/components/chat/copilot-chat-message-view-cursor.component.mjs +45 -0
- package/dist/esm2022/components/chat/copilot-chat-message-view.component.mjs +296 -0
- package/dist/esm2022/components/chat/copilot-chat-message-view.types.mjs +2 -0
- package/dist/esm2022/components/chat/copilot-chat-textarea.component.mjs +188 -0
- package/dist/esm2022/components/chat/copilot-chat-tool-calls-view.component.mjs +216 -0
- package/dist/esm2022/components/chat/copilot-chat-toolbar.component.mjs +25 -0
- package/dist/esm2022/components/chat/copilot-chat-tools-menu.component.mjs +199 -0
- package/dist/esm2022/components/chat/copilot-chat-user-message-branch-navigation.component.mjs +137 -0
- package/dist/esm2022/components/chat/copilot-chat-user-message-buttons.component.mjs +207 -0
- package/dist/esm2022/components/chat/copilot-chat-user-message-renderer.component.mjs +35 -0
- package/dist/esm2022/components/chat/copilot-chat-user-message-toolbar.component.mjs +34 -0
- package/dist/esm2022/components/chat/copilot-chat-user-message.component.mjs +341 -0
- package/dist/esm2022/components/chat/copilot-chat-user-message.types.mjs +2 -0
- package/dist/esm2022/components/chat/copilot-chat-view-disclaimer.component.mjs +52 -0
- package/dist/esm2022/components/chat/copilot-chat-view-feather.component.mjs +55 -0
- package/dist/esm2022/components/chat/copilot-chat-view-handlers.service.mjs +19 -0
- package/dist/esm2022/components/chat/copilot-chat-view-input-container.component.mjs +110 -0
- package/dist/esm2022/components/chat/copilot-chat-view-scroll-to-bottom-button.component.mjs +93 -0
- package/dist/esm2022/components/chat/copilot-chat-view-scroll-view.component.mjs +443 -0
- package/dist/esm2022/components/chat/copilot-chat-view.component.mjs +479 -0
- package/dist/esm2022/components/chat/copilot-chat-view.types.mjs +2 -0
- package/dist/esm2022/components/chat/copilot-chat.component.mjs +214 -0
- package/dist/esm2022/components/copilotkit-tool-render.component.mjs +153 -0
- package/dist/esm2022/copilotkitnext-angular.mjs +5 -0
- package/dist/esm2022/core/chat-configuration/chat-configuration.providers.mjs +65 -0
- package/dist/esm2022/core/chat-configuration/chat-configuration.service.mjs +145 -0
- package/dist/esm2022/core/chat-configuration/chat-configuration.types.mjs +26 -0
- package/dist/esm2022/core/copilotkit.providers.mjs +34 -0
- package/dist/esm2022/core/copilotkit.service.mjs +430 -0
- package/dist/esm2022/core/copilotkit.types.mjs +12 -0
- package/dist/esm2022/directives/copilotkit-agent-context.directive.mjs +130 -0
- package/dist/esm2022/directives/copilotkit-agent.directive.mjs +217 -0
- package/dist/esm2022/directives/copilotkit-chat-config.directive.mjs +218 -0
- package/dist/esm2022/directives/copilotkit-config.directive.mjs +94 -0
- package/dist/esm2022/directives/copilotkit-frontend-tool.directive.mjs +130 -0
- package/dist/esm2022/directives/copilotkit-human-in-the-loop.directive.mjs +266 -0
- package/dist/esm2022/directives/stick-to-bottom.directive.mjs +181 -0
- package/dist/esm2022/index.mjs +70 -0
- package/dist/esm2022/lib/directives/tooltip.directive.mjs +211 -0
- package/dist/esm2022/lib/slots/copilot-slot.component.mjs +144 -0
- package/dist/esm2022/lib/slots/slot.types.mjs +6 -0
- package/dist/esm2022/lib/slots/slot.utils.mjs +222 -0
- package/dist/esm2022/lib/utils.mjs +10 -0
- package/dist/esm2022/services/resize-observer.service.mjs +152 -0
- package/dist/esm2022/services/scroll-position.service.mjs +124 -0
- package/dist/esm2022/types/frontend-tool.mjs +2 -0
- package/dist/esm2022/types/human-in-the-loop.mjs +2 -0
- package/dist/esm2022/utils/agent-context.utils.mjs +114 -0
- package/dist/esm2022/utils/agent.utils.mjs +204 -0
- package/dist/esm2022/utils/chat-config.utils.mjs +186 -0
- package/dist/esm2022/utils/copilotkit.utils.mjs +20 -0
- package/dist/esm2022/utils/frontend-tool.utils.mjs +228 -0
- package/dist/esm2022/utils/human-in-the-loop.utils.mjs +296 -0
- package/dist/fesm2022/copilotkitnext-angular.mjs +163 -164
- package/dist/fesm2022/copilotkitnext-angular.mjs.map +1 -1
- package/package.json +21 -18
- package/vitest.config.mts +32 -21
- package/.turbo/turbo-build.log +0 -38
- package/.turbo/turbo-check-types.log +0 -0
- package/.turbo/turbo-test.log +0 -71
- package/ng-package.json +0 -19
- package/src/components/chat/__tests__/copilot-chat-assistant-message.component.spec.ts +0 -282
- package/src/components/chat/__tests__/copilot-chat-input.component.spec.ts +0 -419
- package/src/components/chat/__tests__/copilot-chat-message-view.component.spec.ts +0 -372
- package/src/components/chat/__tests__/copilot-chat-user-message.component.spec.ts +0 -249
- package/src/components/chat/copilot-chat-assistant-message-buttons.component.ts +0 -292
- package/src/components/chat/copilot-chat-assistant-message-renderer.component.ts +0 -472
- package/src/components/chat/copilot-chat-assistant-message-toolbar.component.ts +0 -29
- package/src/components/chat/copilot-chat-assistant-message.component.ts +0 -463
- package/src/components/chat/copilot-chat-assistant-message.types.ts +0 -50
- package/src/components/chat/copilot-chat-audio-recorder.component.ts +0 -241
- package/src/components/chat/copilot-chat-buttons.component.ts +0 -308
- package/src/components/chat/copilot-chat-buttons.component.ts.bak +0 -471
- package/src/components/chat/copilot-chat-input-defaults.ts +0 -47
- package/src/components/chat/copilot-chat-input.component.ts +0 -512
- package/src/components/chat/copilot-chat-input.types.ts +0 -148
- package/src/components/chat/copilot-chat-message-view-cursor.component.ts +0 -51
- package/src/components/chat/copilot-chat-message-view.component.ts +0 -233
- package/src/components/chat/copilot-chat-message-view.types.ts +0 -39
- package/src/components/chat/copilot-chat-textarea.component.ts +0 -220
- package/src/components/chat/copilot-chat-tool-calls-view.component.ts +0 -261
- package/src/components/chat/copilot-chat-toolbar.component.ts +0 -35
- package/src/components/chat/copilot-chat-tools-menu.component.ts +0 -185
- package/src/components/chat/copilot-chat-user-message-branch-navigation.component.ts +0 -121
- package/src/components/chat/copilot-chat-user-message-buttons.component.ts +0 -170
- package/src/components/chat/copilot-chat-user-message-renderer.component.ts +0 -37
- package/src/components/chat/copilot-chat-user-message-toolbar.component.ts +0 -37
- package/src/components/chat/copilot-chat-user-message.component.ts +0 -247
- package/src/components/chat/copilot-chat-user-message.types.ts +0 -42
- package/src/components/chat/copilot-chat-view-disclaimer.component.ts +0 -51
- package/src/components/chat/copilot-chat-view-feather.component.ts +0 -47
- package/src/components/chat/copilot-chat-view-handlers.service.ts +0 -14
- package/src/components/chat/copilot-chat-view-input-container.component.ts +0 -87
- package/src/components/chat/copilot-chat-view-scroll-to-bottom-button.component.ts +0 -79
- package/src/components/chat/copilot-chat-view-scroll-view.component.ts +0 -322
- package/src/components/chat/copilot-chat-view.component.ts +0 -420
- package/src/components/chat/copilot-chat-view.types.ts +0 -52
- package/src/components/chat/copilot-chat.component.ts +0 -232
- package/src/components/copilotkit-tool-render.component.ts +0 -169
- package/src/core/__tests__/copilotkit.service.spec.ts +0 -1051
- package/src/core/__tests__/copilotkit.service.wildcard.spec.ts +0 -316
- package/src/core/chat-configuration/__tests__/chat-configuration.service.spec.ts +0 -287
- package/src/core/chat-configuration/chat-configuration.providers.ts +0 -71
- package/src/core/chat-configuration/chat-configuration.service.ts +0 -162
- package/src/core/chat-configuration/chat-configuration.types.ts +0 -57
- package/src/core/copilotkit.providers.ts +0 -59
- package/src/core/copilotkit.service.ts +0 -542
- package/src/core/copilotkit.types.ts +0 -132
- package/src/directives/__tests__/copilotkit-agent-context.directive.spec.ts +0 -384
- package/src/directives/__tests__/copilotkit-agent.directive.spec.ts +0 -253
- package/src/directives/__tests__/copilotkit-chat-config.directive.spec.ts +0 -385
- package/src/directives/__tests__/copilotkit-config.directive.spec.ts +0 -69
- package/src/directives/__tests__/copilotkit-frontend-tool-simple.directive.spec.ts +0 -60
- package/src/directives/__tests__/copilotkit-frontend-tool.directive.spec.ts +0 -108
- package/src/directives/__tests__/copilotkit-human-in-the-loop.directive.spec.ts +0 -452
- package/src/directives/copilotkit-agent-context.directive.ts +0 -138
- package/src/directives/copilotkit-agent.directive.ts +0 -225
- package/src/directives/copilotkit-chat-config.directive.ts +0 -241
- package/src/directives/copilotkit-config.directive.ts +0 -81
- package/src/directives/copilotkit-frontend-tool.directive.ts +0 -145
- package/src/directives/copilotkit-human-in-the-loop.directive.ts +0 -281
- package/src/directives/stick-to-bottom.directive.ts +0 -204
- package/src/index.ts +0 -105
- package/src/lib/directives/tooltip.directive.ts +0 -292
- package/src/lib/slots/__tests__/slot.utils.spec.ts +0 -377
- package/src/lib/slots/copilot-slot.component.ts +0 -135
- package/src/lib/slots/index.ts +0 -3
- package/src/lib/slots/slot.types.ts +0 -64
- package/src/lib/slots/slot.utils.ts +0 -289
- package/src/lib/utils.ts +0 -10
- package/src/public-api.ts +0 -1
- package/src/services/resize-observer.service.ts +0 -181
- package/src/services/scroll-position.service.ts +0 -169
- package/src/styles/globals.css +0 -266
- package/src/styles/index.css +0 -3
- package/src/test-setup.ts +0 -15
- package/src/testing/index.ts +0 -3
- package/src/testing/testing.utils.ts +0 -248
- package/src/types/frontend-tool.ts +0 -44
- package/src/types/human-in-the-loop.ts +0 -52
- package/src/utils/__tests__/agent.utils.spec.ts +0 -234
- package/src/utils/__tests__/chat-config.utils.spec.ts +0 -306
- package/src/utils/__tests__/frontend-tool-inject.spec.ts +0 -350
- package/src/utils/__tests__/frontend-tool-integration.spec.ts +0 -199
- package/src/utils/__tests__/frontend-tool.utils.spec.ts +0 -272
- package/src/utils/__tests__/human-in-the-loop.utils.spec.ts +0 -365
- package/src/utils/agent-context.utils.ts +0 -133
- package/src/utils/agent.utils.ts +0 -239
- package/src/utils/chat-config.utils.ts +0 -221
- package/src/utils/copilotkit.utils.ts +0 -20
- package/src/utils/frontend-tool.utils.ts +0 -266
- package/src/utils/human-in-the-loop.utils.ts +0 -359
- 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
|
-
}
|