@copilotkitnext/angular 0.0.1 → 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 +248 -0
- package/dist/README.md +248 -0
- 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/dist/styles.css +0 -27
- package/package.json +23 -20
- package/vitest.config.mts +32 -21
- package/.turbo/turbo-build.log +0 -39
- package/.turbo/turbo-check-types.log +0 -0
- package/.turbo/turbo-test.log +0 -71
- package/README-agent-context.md +0 -310
- package/ng-package.json +0 -19
- package/slots.md +0 -331
- 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,261 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Component,
|
|
3
|
-
Input,
|
|
4
|
-
ViewContainerRef,
|
|
5
|
-
ComponentRef,
|
|
6
|
-
inject,
|
|
7
|
-
ViewChild,
|
|
8
|
-
AfterViewInit,
|
|
9
|
-
OnChanges,
|
|
10
|
-
SimpleChanges,
|
|
11
|
-
TemplateRef,
|
|
12
|
-
Type,
|
|
13
|
-
ChangeDetectionStrategy,
|
|
14
|
-
signal,
|
|
15
|
-
computed,
|
|
16
|
-
OnDestroy,
|
|
17
|
-
} from "@angular/core";
|
|
18
|
-
import { CommonModule } from "@angular/common";
|
|
19
|
-
import type {
|
|
20
|
-
AssistantMessage,
|
|
21
|
-
Message,
|
|
22
|
-
ToolCall,
|
|
23
|
-
ToolMessage,
|
|
24
|
-
} from "@ag-ui/core";
|
|
25
|
-
import { ToolCallStatus } from "@copilotkitnext/core";
|
|
26
|
-
import { CopilotKitService } from "../../core/copilotkit.service";
|
|
27
|
-
import { partialJSONParse } from "@copilotkitnext/shared";
|
|
28
|
-
import type {
|
|
29
|
-
ToolCallProps,
|
|
30
|
-
ToolCallRender,
|
|
31
|
-
} from "../../core/copilotkit.types";
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Component for rendering all tool calls for an assistant message.
|
|
35
|
-
* This component iterates through the message's tool calls and renders each one
|
|
36
|
-
* using the registered render functions in CopilotKitService.
|
|
37
|
-
*/
|
|
38
|
-
@Component({
|
|
39
|
-
selector: "copilot-chat-tool-calls-view",
|
|
40
|
-
standalone: true,
|
|
41
|
-
imports: [CommonModule],
|
|
42
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
43
|
-
template: `
|
|
44
|
-
@for (toolCall of message?.toolCalls ?? []; track toolCall.id) {
|
|
45
|
-
<ng-container>
|
|
46
|
-
<ng-container #dynamicContainer></ng-container>
|
|
47
|
-
<ng-container *ngIf="getTemplateForToolCall(toolCall) as templateData">
|
|
48
|
-
<ng-container
|
|
49
|
-
*ngTemplateOutlet="
|
|
50
|
-
templateData.template;
|
|
51
|
-
context: templateData.context
|
|
52
|
-
"
|
|
53
|
-
></ng-container>
|
|
54
|
-
</ng-container>
|
|
55
|
-
</ng-container>
|
|
56
|
-
}
|
|
57
|
-
`,
|
|
58
|
-
})
|
|
59
|
-
export class CopilotChatToolCallsViewComponent
|
|
60
|
-
implements AfterViewInit, OnChanges, OnDestroy
|
|
61
|
-
{
|
|
62
|
-
@Input({ required: true }) message!: AssistantMessage;
|
|
63
|
-
@Input() messages: Message[] = [];
|
|
64
|
-
@Input() isLoading = false;
|
|
65
|
-
|
|
66
|
-
@ViewChild("dynamicContainer", { read: ViewContainerRef })
|
|
67
|
-
private container?: ViewContainerRef;
|
|
68
|
-
|
|
69
|
-
private copilotkit: CopilotKitService | null = inject(CopilotKitService, {
|
|
70
|
-
optional: true,
|
|
71
|
-
});
|
|
72
|
-
private componentRefs: Map<string, ComponentRef<any>> = new Map();
|
|
73
|
-
private templateCache: Map<
|
|
74
|
-
string,
|
|
75
|
-
{ template: TemplateRef<any>; context: any }
|
|
76
|
-
> = new Map();
|
|
77
|
-
|
|
78
|
-
// Signals for reactive state
|
|
79
|
-
private messageSignal = signal<AssistantMessage | null>(null);
|
|
80
|
-
private messagesSignal = signal<Message[]>([]);
|
|
81
|
-
private isLoadingSignal = signal(false);
|
|
82
|
-
|
|
83
|
-
ngAfterViewInit(): void {
|
|
84
|
-
this.renderAllToolCalls();
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
ngOnChanges(changes: SimpleChanges): void {
|
|
88
|
-
if (changes["message"]) {
|
|
89
|
-
this.messageSignal.set(this.message);
|
|
90
|
-
}
|
|
91
|
-
if (changes["messages"]) {
|
|
92
|
-
this.messagesSignal.set(this.messages);
|
|
93
|
-
}
|
|
94
|
-
if (changes["isLoading"]) {
|
|
95
|
-
this.isLoadingSignal.set(this.isLoading);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
this.renderAllToolCalls();
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
ngOnDestroy(): void {
|
|
102
|
-
// Clean up all component refs
|
|
103
|
-
this.componentRefs.forEach((ref) => ref.destroy());
|
|
104
|
-
this.componentRefs.clear();
|
|
105
|
-
this.templateCache.clear();
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
getTemplateForToolCall(
|
|
109
|
-
toolCall: ToolCall
|
|
110
|
-
): { template: TemplateRef<any>; context: any } | null {
|
|
111
|
-
return this.templateCache.get(toolCall.id) || null;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
private renderAllToolCalls(): void {
|
|
115
|
-
const message = this.messageSignal();
|
|
116
|
-
if (!message || !message.toolCalls || message.toolCalls.length === 0) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// Clear existing renders
|
|
121
|
-
this.componentRefs.forEach((ref) => ref.destroy());
|
|
122
|
-
this.componentRefs.clear();
|
|
123
|
-
this.templateCache.clear();
|
|
124
|
-
|
|
125
|
-
if (!this.copilotkit || !this.container) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
const messages = this.messagesSignal();
|
|
130
|
-
const isLoading = this.isLoadingSignal();
|
|
131
|
-
|
|
132
|
-
// Render each tool call
|
|
133
|
-
message.toolCalls.forEach((toolCall) => {
|
|
134
|
-
const toolMessage = messages.find(
|
|
135
|
-
(m) =>
|
|
136
|
-
m.role === "tool" && (m as ToolMessage).toolCallId === toolCall.id
|
|
137
|
-
) as ToolMessage | undefined;
|
|
138
|
-
|
|
139
|
-
this.renderSingleToolCall(toolCall, toolMessage, isLoading);
|
|
140
|
-
});
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
private renderSingleToolCall(
|
|
144
|
-
toolCall: ToolCall,
|
|
145
|
-
toolMessage: ToolMessage | undefined,
|
|
146
|
-
isLoading: boolean
|
|
147
|
-
): void {
|
|
148
|
-
if (!this.copilotkit) {
|
|
149
|
-
return;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Get current render tool calls
|
|
153
|
-
const currentRenderToolCalls = this.copilotkit.currentRenderToolCalls();
|
|
154
|
-
|
|
155
|
-
// Find the render config for this tool call by name
|
|
156
|
-
// Also check for wildcard (*) renders if no exact match
|
|
157
|
-
const renderConfig =
|
|
158
|
-
currentRenderToolCalls.find(
|
|
159
|
-
(rc: ToolCallRender) => rc.name === toolCall.function.name
|
|
160
|
-
) || currentRenderToolCalls.find((rc: ToolCallRender) => rc.name === "*");
|
|
161
|
-
|
|
162
|
-
if (!renderConfig) {
|
|
163
|
-
return;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Parse the arguments if they're a string
|
|
167
|
-
const args = partialJSONParse(toolCall.function.arguments);
|
|
168
|
-
|
|
169
|
-
// Determine status
|
|
170
|
-
let status: ToolCallStatus;
|
|
171
|
-
if (toolMessage) {
|
|
172
|
-
status = ToolCallStatus.Complete;
|
|
173
|
-
} else if (isLoading) {
|
|
174
|
-
status = ToolCallStatus.InProgress;
|
|
175
|
-
} else {
|
|
176
|
-
status = ToolCallStatus.Complete;
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Create props based on status - use discriminated union properly
|
|
180
|
-
let props: ToolCallProps;
|
|
181
|
-
if (status === ToolCallStatus.InProgress) {
|
|
182
|
-
props = {
|
|
183
|
-
name: toolCall.function.name,
|
|
184
|
-
description: "",
|
|
185
|
-
args: args, // Partial args for InProgress
|
|
186
|
-
status: ToolCallStatus.InProgress,
|
|
187
|
-
result: undefined,
|
|
188
|
-
};
|
|
189
|
-
} else {
|
|
190
|
-
// Complete status
|
|
191
|
-
props = {
|
|
192
|
-
name: toolCall.function.name,
|
|
193
|
-
description: "",
|
|
194
|
-
args: args, // Full args for Complete
|
|
195
|
-
status: ToolCallStatus.Complete,
|
|
196
|
-
result: toolMessage?.content || "",
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Check if render is a Component class or TemplateRef
|
|
201
|
-
if (this.isComponentClass(renderConfig.render)) {
|
|
202
|
-
// Create component dynamically
|
|
203
|
-
this.renderComponent(toolCall.id, renderConfig.render, props);
|
|
204
|
-
} else if (this.isTemplateRef(renderConfig.render)) {
|
|
205
|
-
// Use template
|
|
206
|
-
this.renderTemplate(toolCall.id, renderConfig.render, props);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
private renderComponent(
|
|
211
|
-
toolCallId: string,
|
|
212
|
-
componentClass: Type<any>,
|
|
213
|
-
props: ToolCallProps
|
|
214
|
-
): void {
|
|
215
|
-
if (!this.container) {
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
// Create the component
|
|
220
|
-
const componentRef = this.container.createComponent(componentClass);
|
|
221
|
-
this.componentRefs.set(toolCallId, componentRef);
|
|
222
|
-
|
|
223
|
-
// Set inputs on the component
|
|
224
|
-
for (const [key, value] of Object.entries(props)) {
|
|
225
|
-
try {
|
|
226
|
-
componentRef.setInput(key, value);
|
|
227
|
-
} catch (e) {
|
|
228
|
-
// Input might not exist on the component, which is fine
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
// Trigger change detection
|
|
233
|
-
componentRef.changeDetectorRef.detectChanges();
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
private renderTemplate(
|
|
237
|
-
toolCallId: string,
|
|
238
|
-
template: TemplateRef<any>,
|
|
239
|
-
props: ToolCallProps
|
|
240
|
-
): void {
|
|
241
|
-
this.templateCache.set(toolCallId, {
|
|
242
|
-
template,
|
|
243
|
-
context: {
|
|
244
|
-
$implicit: props,
|
|
245
|
-
name: props.name,
|
|
246
|
-
description: props.description,
|
|
247
|
-
args: props.args,
|
|
248
|
-
status: props.status,
|
|
249
|
-
result: props.result,
|
|
250
|
-
},
|
|
251
|
-
});
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
private isComponentClass(value: any): value is Type<any> {
|
|
255
|
-
return typeof value === "function" && value.prototype;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
private isTemplateRef(value: any): value is TemplateRef<any> {
|
|
259
|
-
return value instanceof TemplateRef;
|
|
260
|
-
}
|
|
261
|
-
}
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Component,
|
|
3
|
-
Input,
|
|
4
|
-
signal,
|
|
5
|
-
computed,
|
|
6
|
-
ChangeDetectionStrategy,
|
|
7
|
-
ViewEncapsulation
|
|
8
|
-
} from '@angular/core';
|
|
9
|
-
import { CommonModule } from '@angular/common';
|
|
10
|
-
import { cn } from '../../lib/utils';
|
|
11
|
-
|
|
12
|
-
@Component({
|
|
13
|
-
selector: 'div[copilotChatToolbar]',
|
|
14
|
-
standalone: true,
|
|
15
|
-
imports: [CommonModule],
|
|
16
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
17
|
-
encapsulation: ViewEncapsulation.None,
|
|
18
|
-
host: {
|
|
19
|
-
'[class]': 'computedClass()'
|
|
20
|
-
},
|
|
21
|
-
template: `<ng-content></ng-content>`,
|
|
22
|
-
styles: []
|
|
23
|
-
})
|
|
24
|
-
export class CopilotChatToolbarComponent {
|
|
25
|
-
@Input() set inputClass(val: string | undefined) {
|
|
26
|
-
this.customClass.set(val);
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
customClass = signal<string | undefined>(undefined);
|
|
30
|
-
|
|
31
|
-
computedClass = computed(() => {
|
|
32
|
-
const baseClasses = 'w-full h-[60px] bg-transparent flex items-center justify-between';
|
|
33
|
-
return cn(baseClasses, this.customClass());
|
|
34
|
-
});
|
|
35
|
-
}
|
|
@@ -1,185 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Component,
|
|
3
|
-
Input,
|
|
4
|
-
signal,
|
|
5
|
-
computed,
|
|
6
|
-
inject,
|
|
7
|
-
ChangeDetectionStrategy,
|
|
8
|
-
ViewEncapsulation
|
|
9
|
-
} from '@angular/core';
|
|
10
|
-
import { CommonModule } from '@angular/common';
|
|
11
|
-
import { CdkMenuModule } from '@angular/cdk/menu';
|
|
12
|
-
import { OverlayModule } from '@angular/cdk/overlay';
|
|
13
|
-
import { LucideAngularModule, Settings2, ChevronRight } from 'lucide-angular';
|
|
14
|
-
import { CopilotChatConfigurationService } from '../../core/chat-configuration/chat-configuration.service';
|
|
15
|
-
import type { ToolsMenuItem } from './copilot-chat-input.types';
|
|
16
|
-
import { cn } from '../../lib/utils';
|
|
17
|
-
|
|
18
|
-
@Component({
|
|
19
|
-
selector: 'copilot-chat-tools-menu',
|
|
20
|
-
standalone: true,
|
|
21
|
-
imports: [
|
|
22
|
-
CommonModule,
|
|
23
|
-
CdkMenuModule,
|
|
24
|
-
OverlayModule,
|
|
25
|
-
LucideAngularModule
|
|
26
|
-
],
|
|
27
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
28
|
-
encapsulation: ViewEncapsulation.None,
|
|
29
|
-
template: `
|
|
30
|
-
@if (hasItems()) {
|
|
31
|
-
<button
|
|
32
|
-
type="button"
|
|
33
|
-
[disabled]="disabled()"
|
|
34
|
-
[class]="buttonClass()"
|
|
35
|
-
[cdkMenuTriggerFor]="menu"
|
|
36
|
-
>
|
|
37
|
-
<lucide-angular [img]="Settings2Icon" [size]="18"></lucide-angular>
|
|
38
|
-
<span class="text-sm font-normal">{{ label() }}</span>
|
|
39
|
-
</button>
|
|
40
|
-
|
|
41
|
-
<ng-template #menu>
|
|
42
|
-
<div class="min-w-[200px] bg-white dark:bg-[#1F1F1F] border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-1"
|
|
43
|
-
cdkMenu>
|
|
44
|
-
@for (item of toolsMenu(); track $index) {
|
|
45
|
-
@if (item === '-') {
|
|
46
|
-
<div class="h-px bg-gray-200 dark:bg-gray-700 my-1"></div>
|
|
47
|
-
} @else if (isMenuItem(item)) {
|
|
48
|
-
@if (item.items && item.items.length > 0) {
|
|
49
|
-
<!-- Submenu trigger -->
|
|
50
|
-
<button
|
|
51
|
-
type="button"
|
|
52
|
-
class="w-full px-3 py-2 text-left bg-transparent border-none rounded hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer text-sm flex items-center justify-between"
|
|
53
|
-
[cdkMenuTriggerFor]="submenu"
|
|
54
|
-
cdkMenuItem
|
|
55
|
-
>
|
|
56
|
-
{{ item.label }}
|
|
57
|
-
<lucide-angular [img]="ChevronRightIcon" [size]="12" class="ml-auto"></lucide-angular>
|
|
58
|
-
</button>
|
|
59
|
-
|
|
60
|
-
<!-- Submenu template -->
|
|
61
|
-
<ng-template #submenu>
|
|
62
|
-
<div class="min-w-[200px] bg-white dark:bg-[#1F1F1F] border border-gray-200 dark:border-gray-700 rounded-lg shadow-lg p-1"
|
|
63
|
-
cdkMenu>
|
|
64
|
-
@for (subItem of item.items; track $index) {
|
|
65
|
-
@if (subItem === '-') {
|
|
66
|
-
<div class="h-px bg-gray-200 dark:bg-gray-700 my-1"></div>
|
|
67
|
-
} @else if (isMenuItem(subItem)) {
|
|
68
|
-
<button
|
|
69
|
-
type="button"
|
|
70
|
-
class="w-full px-3 py-2 text-left bg-transparent border-none rounded hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer text-sm"
|
|
71
|
-
(click)="handleItemClick(subItem)"
|
|
72
|
-
cdkMenuItem
|
|
73
|
-
>
|
|
74
|
-
{{ subItem.label }}
|
|
75
|
-
</button>
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
</div>
|
|
79
|
-
</ng-template>
|
|
80
|
-
} @else {
|
|
81
|
-
<!-- Regular menu item -->
|
|
82
|
-
<button
|
|
83
|
-
type="button"
|
|
84
|
-
class="w-full px-3 py-2 text-left bg-transparent border-none rounded hover:bg-gray-100 dark:hover:bg-gray-800 cursor-pointer text-sm"
|
|
85
|
-
(click)="handleItemClick(item)"
|
|
86
|
-
cdkMenuItem
|
|
87
|
-
>
|
|
88
|
-
{{ item.label }}
|
|
89
|
-
</button>
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
</div>
|
|
94
|
-
</ng-template>
|
|
95
|
-
}
|
|
96
|
-
`,
|
|
97
|
-
styles: [`
|
|
98
|
-
/* CDK Overlay styles for positioning */
|
|
99
|
-
.cdk-overlay-pane {
|
|
100
|
-
position: absolute;
|
|
101
|
-
pointer-events: auto;
|
|
102
|
-
z-index: 1000;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/* Ensure menu appears above other content */
|
|
106
|
-
.cdk-overlay-container {
|
|
107
|
-
position: fixed;
|
|
108
|
-
z-index: 1000;
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/* Menu animation */
|
|
112
|
-
[cdkMenu] {
|
|
113
|
-
animation: menuFadeIn 0.15s ease-out;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
@keyframes menuFadeIn {
|
|
117
|
-
from {
|
|
118
|
-
opacity: 0;
|
|
119
|
-
transform: translateY(4px);
|
|
120
|
-
}
|
|
121
|
-
to {
|
|
122
|
-
opacity: 1;
|
|
123
|
-
transform: translateY(0);
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
`]
|
|
127
|
-
})
|
|
128
|
-
export class CopilotChatToolsMenuComponent {
|
|
129
|
-
readonly Settings2Icon = Settings2;
|
|
130
|
-
readonly ChevronRightIcon = ChevronRight;
|
|
131
|
-
|
|
132
|
-
@Input() set inputToolsMenu(val: (ToolsMenuItem | '-')[] | undefined) {
|
|
133
|
-
this.toolsMenu.set(val || []);
|
|
134
|
-
}
|
|
135
|
-
@Input() set inputDisabled(val: boolean | undefined) {
|
|
136
|
-
this.disabled.set(val || false);
|
|
137
|
-
}
|
|
138
|
-
@Input() set inputClass(val: string | undefined) {
|
|
139
|
-
this.customClass.set(val);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
private chatConfig = inject(CopilotChatConfigurationService);
|
|
143
|
-
|
|
144
|
-
toolsMenu = signal<(ToolsMenuItem | '-')[]>([]);
|
|
145
|
-
disabled = signal<boolean>(false);
|
|
146
|
-
customClass = signal<string | undefined>(undefined);
|
|
147
|
-
|
|
148
|
-
hasItems = computed(() => this.toolsMenu().length > 0);
|
|
149
|
-
|
|
150
|
-
label = computed(() => this.chatConfig.labels().chatInputToolbarToolsButtonLabel);
|
|
151
|
-
|
|
152
|
-
buttonClass = computed(() => {
|
|
153
|
-
const baseClasses = cn(
|
|
154
|
-
// Base button styles
|
|
155
|
-
'inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-full text-sm font-medium',
|
|
156
|
-
'transition-all disabled:pointer-events-none disabled:opacity-50',
|
|
157
|
-
'shrink-0 outline-none',
|
|
158
|
-
'focus-visible:ring-[3px]',
|
|
159
|
-
// chatInputToolbarSecondary variant
|
|
160
|
-
'cursor-pointer',
|
|
161
|
-
'bg-transparent text-[#444444]',
|
|
162
|
-
'dark:text-white dark:border-[#404040]',
|
|
163
|
-
'transition-colors',
|
|
164
|
-
'focus:outline-none',
|
|
165
|
-
'hover:bg-[#f8f8f8] hover:text-[#333333]',
|
|
166
|
-
'dark:hover:bg-[#404040] dark:hover:text-[#FFFFFF]',
|
|
167
|
-
'disabled:cursor-not-allowed disabled:opacity-50',
|
|
168
|
-
'disabled:hover:bg-transparent disabled:hover:text-[#444444]',
|
|
169
|
-
'dark:disabled:hover:bg-transparent dark:disabled:hover:text-[#CCCCCC]',
|
|
170
|
-
// Size
|
|
171
|
-
'h-9 px-3 gap-2 font-normal'
|
|
172
|
-
);
|
|
173
|
-
return cn(baseClasses, this.customClass());
|
|
174
|
-
});
|
|
175
|
-
|
|
176
|
-
isMenuItem(item: any): item is ToolsMenuItem {
|
|
177
|
-
return item && typeof item === 'object' && 'label' in item;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
handleItemClick(item: ToolsMenuItem): void {
|
|
181
|
-
if (item.action) {
|
|
182
|
-
item.action();
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
}
|
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
Component,
|
|
3
|
-
Input,
|
|
4
|
-
Output,
|
|
5
|
-
EventEmitter,
|
|
6
|
-
ChangeDetectionStrategy,
|
|
7
|
-
ViewEncapsulation,
|
|
8
|
-
computed,
|
|
9
|
-
signal
|
|
10
|
-
} from '@angular/core';
|
|
11
|
-
import { CommonModule } from '@angular/common';
|
|
12
|
-
import { LucideAngularModule, ChevronLeft, ChevronRight } from 'lucide-angular';
|
|
13
|
-
import {
|
|
14
|
-
type UserMessage,
|
|
15
|
-
type CopilotChatUserMessageOnSwitchToBranchProps
|
|
16
|
-
} from './copilot-chat-user-message.types';
|
|
17
|
-
import { cn } from '../../lib/utils';
|
|
18
|
-
|
|
19
|
-
@Component({
|
|
20
|
-
selector: 'copilot-chat-user-message-branch-navigation',
|
|
21
|
-
standalone: true,
|
|
22
|
-
imports: [CommonModule, LucideAngularModule],
|
|
23
|
-
changeDetection: ChangeDetectionStrategy.OnPush,
|
|
24
|
-
encapsulation: ViewEncapsulation.None,
|
|
25
|
-
template: `
|
|
26
|
-
@if (showNavigation()) {
|
|
27
|
-
<div [class]="computedClass()">
|
|
28
|
-
<button
|
|
29
|
-
type="button"
|
|
30
|
-
[class]="buttonClass"
|
|
31
|
-
[disabled]="!canGoPrev()"
|
|
32
|
-
(click)="handlePrevious()">
|
|
33
|
-
<lucide-angular [img]="ChevronLeftIcon" [size]="20"></lucide-angular>
|
|
34
|
-
</button>
|
|
35
|
-
<span class="text-sm text-muted-foreground px-0 font-medium">
|
|
36
|
-
{{ currentBranchSignal() + 1 }}/{{ numberOfBranchesSignal() }}
|
|
37
|
-
</span>
|
|
38
|
-
<button
|
|
39
|
-
type="button"
|
|
40
|
-
[class]="buttonClass"
|
|
41
|
-
[disabled]="!canGoNext()"
|
|
42
|
-
(click)="handleNext()">
|
|
43
|
-
<lucide-angular [img]="ChevronRightIcon" [size]="20"></lucide-angular>
|
|
44
|
-
</button>
|
|
45
|
-
</div>
|
|
46
|
-
}
|
|
47
|
-
`
|
|
48
|
-
})
|
|
49
|
-
export class CopilotChatUserMessageBranchNavigationComponent {
|
|
50
|
-
@Input() set currentBranch(val: number) {
|
|
51
|
-
this.currentBranchSignal.set(val);
|
|
52
|
-
}
|
|
53
|
-
@Input() set numberOfBranches(val: number) {
|
|
54
|
-
this.numberOfBranchesSignal.set(val);
|
|
55
|
-
}
|
|
56
|
-
@Input() message!: UserMessage;
|
|
57
|
-
@Input() inputClass?: string;
|
|
58
|
-
@Output() switchToBranch = new EventEmitter<CopilotChatUserMessageOnSwitchToBranchProps>();
|
|
59
|
-
|
|
60
|
-
readonly ChevronLeftIcon = ChevronLeft;
|
|
61
|
-
readonly ChevronRightIcon = ChevronRight;
|
|
62
|
-
|
|
63
|
-
currentBranchSignal = signal(0);
|
|
64
|
-
numberOfBranchesSignal = signal(1);
|
|
65
|
-
|
|
66
|
-
readonly buttonClass = cn(
|
|
67
|
-
// Flex centering
|
|
68
|
-
'inline-flex items-center justify-center',
|
|
69
|
-
// Cursor
|
|
70
|
-
'cursor-pointer',
|
|
71
|
-
// Background and text
|
|
72
|
-
'p-0 text-[rgb(93,93,93)] hover:bg-[#E8E8E8]',
|
|
73
|
-
// Dark mode
|
|
74
|
-
'dark:text-[rgb(243,243,243)] dark:hover:bg-[#303030]',
|
|
75
|
-
// Shape and sizing
|
|
76
|
-
'h-6 w-6 rounded-md',
|
|
77
|
-
// Interactions
|
|
78
|
-
'transition-colors',
|
|
79
|
-
// Disabled state
|
|
80
|
-
'disabled:opacity-50 disabled:cursor-not-allowed'
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
showNavigation = computed(() => {
|
|
84
|
-
const branches = this.numberOfBranchesSignal();
|
|
85
|
-
return branches > 1;
|
|
86
|
-
});
|
|
87
|
-
|
|
88
|
-
canGoPrev = computed(() => {
|
|
89
|
-
return this.currentBranchSignal() > 0;
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
canGoNext = computed(() => {
|
|
93
|
-
return this.currentBranchSignal() < this.numberOfBranchesSignal() - 1;
|
|
94
|
-
});
|
|
95
|
-
|
|
96
|
-
computedClass = computed(() => {
|
|
97
|
-
return cn('flex items-center gap-1', this.inputClass);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
handlePrevious(): void {
|
|
101
|
-
if (this.canGoPrev()) {
|
|
102
|
-
const newIndex = this.currentBranchSignal() - 1;
|
|
103
|
-
this.switchToBranch.emit({
|
|
104
|
-
branchIndex: newIndex,
|
|
105
|
-
numberOfBranches: this.numberOfBranchesSignal(),
|
|
106
|
-
message: this.message
|
|
107
|
-
});
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
handleNext(): void {
|
|
112
|
-
if (this.canGoNext()) {
|
|
113
|
-
const newIndex = this.currentBranchSignal() + 1;
|
|
114
|
-
this.switchToBranch.emit({
|
|
115
|
-
branchIndex: newIndex,
|
|
116
|
-
numberOfBranches: this.numberOfBranchesSignal(),
|
|
117
|
-
message: this.message
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|