Skip to content

Commit a2b1ed3

Browse files
committed
refine the tool calls
1 parent 7c5a63b commit a2b1ed3

File tree

6 files changed

+201
-39
lines changed

6 files changed

+201
-39
lines changed

frontend/src/app/workspace/component/copilot-chat/copilot-chat.component.html

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -67,19 +67,32 @@
6767
</div>
6868

6969
<!-- Deep Chat Component (use display to hide/show instead of *ngIf to preserve messages) -->
70-
<deep-chat
71-
#deepChat
72-
class="deep-chat-container"
73-
[class.collapsed]="!isExpanded"
74-
[style.borderRadius]="'0 0 8px 8px'"
75-
[style.width]="'100%'"
76-
[style.height]="'calc(100% - 60px)'"
77-
[style.border]="'none'"
78-
[connect]="deepChatConfig.connect"
79-
[demo]="deepChatConfig.demo"
80-
[introMessage]="deepChatConfig.introMessage"
81-
[textInput]="deepChatConfig.textInput">
82-
</deep-chat>
70+
<div class="chat-content-wrapper">
71+
<deep-chat
72+
#deepChat
73+
class="deep-chat-container"
74+
[class.collapsed]="!isExpanded"
75+
[style.borderRadius]="'0 0 8px 8px'"
76+
[style.width]="'100%'"
77+
[style.height]="'100%'"
78+
[style.border]="'none'"
79+
[connect]="deepChatConfig.connect"
80+
[demo]="deepChatConfig.demo"
81+
[introMessage]="deepChatConfig.introMessage"
82+
[textInput]="deepChatConfig.textInput"
83+
[requestBodyLimits]="deepChatConfig.requestBodyLimits">
84+
</deep-chat>
85+
86+
<!-- Loading overlay to keep visible during processing -->
87+
<div
88+
*ngIf="isProcessing && isExpanded"
89+
class="processing-indicator">
90+
<nz-spin
91+
nzSimple
92+
nzSize="small"></nz-spin>
93+
<span>Processing...</span>
94+
</div>
95+
</div>
8396

8497
<!-- Connection Status -->
8598
<div

frontend/src/app/workspace/component/copilot-chat/copilot-chat.component.scss

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,14 @@
114114
}
115115
}
116116

117+
.chat-content-wrapper {
118+
flex: 1;
119+
overflow: hidden;
120+
position: relative;
121+
display: flex;
122+
flex-direction: column;
123+
}
124+
117125
.deep-chat-container {
118126
flex: 1;
119127
overflow: hidden;
@@ -123,6 +131,40 @@
123131
}
124132
}
125133

134+
.processing-indicator {
135+
position: absolute;
136+
bottom: 80px;
137+
right: 20px;
138+
display: flex;
139+
align-items: center;
140+
gap: 8px;
141+
padding: 8px 16px;
142+
background: rgba(24, 144, 255, 0.95);
143+
color: white;
144+
border-radius: 20px;
145+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
146+
font-size: 13px;
147+
z-index: 10;
148+
animation: fadeIn 0.3s ease;
149+
150+
nz-spin {
151+
::ng-deep .ant-spin-dot-item {
152+
background-color: white;
153+
}
154+
}
155+
}
156+
157+
@keyframes fadeIn {
158+
from {
159+
opacity: 0;
160+
transform: translateY(10px);
161+
}
162+
to {
163+
opacity: 1;
164+
transform: translateY(0);
165+
}
166+
}
167+
126168
.connection-warning {
127169
display: flex;
128170
align-items: center;

frontend/src/app/workspace/component/copilot-chat/copilot-chat.component.ts

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// copilot-chat.component.ts
2-
import { Component, OnInit, OnDestroy, ViewChild, ElementRef } from "@angular/core";
2+
import { Component, OnDestroy, ViewChild, ElementRef } from "@angular/core";
33
import { UntilDestroy, untilDestroyed } from "@ngneat/until-destroy";
44
import { TexeraCopilot, AgentResponse } from "../../service/copilot/texera-copilot";
55
import { CopilotCoeditorService } from "../../service/copilot/copilot-coeditor.service";
@@ -10,14 +10,14 @@ import { CopilotCoeditorService } from "../../service/copilot/copilot-coeditor.s
1010
templateUrl: "copilot-chat.component.html",
1111
styleUrls: ["copilot-chat.component.scss"],
1212
})
13-
export class CopilotChatComponent implements OnInit, OnDestroy {
13+
export class CopilotChatComponent implements OnDestroy {
1414
@ViewChild("deepChat", { static: false }) deepChatElement?: ElementRef;
1515

1616
public isChatVisible = false; // Whether chat panel is shown at all
1717
public isExpanded = true; // Whether chat content is expanded or minimized
1818
public showToolResults = false; // Whether to show tool call results
1919
public isConnected = false;
20-
public isProcessing = false;
20+
public isProcessing = false; // Whether agent is currently processing a request
2121
private isInitialized = false;
2222

2323
// Deep-chat configuration
@@ -27,31 +27,36 @@ export class CopilotChatComponent implements OnInit, OnDestroy {
2727
const last = body?.messages?.[body.messages.length - 1];
2828
const userText: string = typeof last?.text === "string" ? last.text : "";
2929

30+
// Set processing state to show loading indicator
31+
this.isProcessing = true;
32+
3033
// Send message to copilot and process AgentResponse
3134
this.copilotService
3235
.sendMessage(userText)
3336
.pipe(untilDestroyed(this))
3437
.subscribe({
3538
next: (response: AgentResponse) => {
36-
// Format the response based on type
37-
let displayText = "";
38-
3939
if (response.type === "trace") {
4040
// Format tool traces
41-
displayText = this.formatToolTrace(response);
41+
const displayText = this.formatToolTrace(response);
42+
4243
// Add trace message via addMessage API
4344
if (displayText && this.deepChatElement?.nativeElement?.addMessage) {
4445
this.deepChatElement.nativeElement.addMessage({ role: "ai", text: displayText });
4546
}
47+
48+
// Keep processing state true - loading indicator stays visible
4649
} else if (response.type === "response") {
4750
// For final response, signal completion with the content
48-
// This will let deep-chat handle adding the message
51+
// This will let deep-chat handle adding the message and clearing loading
4952
if (response.isDone) {
53+
this.isProcessing = false; // Clear processing state
5054
signals.onResponse({ text: response.content });
5155
}
5256
}
5357
},
5458
error: (e: unknown) => {
59+
this.isProcessing = false; // Clear processing state on error
5560
signals.onResponse({ error: e ?? "Unknown error" });
5661
},
5762
});
@@ -60,6 +65,7 @@ export class CopilotChatComponent implements OnInit, OnDestroy {
6065
demo: false,
6166
introMessage: { text: "Hi! I'm Texera Copilot. I can help you build and modify workflows." },
6267
textInput: { placeholder: { text: "Ask me anything about workflows..." } },
68+
requestBodyLimits: { maxMessages: -1 }, // Allow unlimited message history
6369
};
6470

6571
/**
@@ -140,10 +146,6 @@ export class CopilotChatComponent implements OnInit, OnDestroy {
140146
private copilotCoeditorService: CopilotCoeditorService
141147
) {}
142148

143-
ngOnInit(): void {
144-
// Component initialization - copilot connection is triggered by menu button
145-
}
146-
147149
ngOnDestroy(): void {
148150
// Cleanup when component is destroyed
149151
this.disconnect();

frontend/src/app/workspace/service/copilot/copilot-coeditor.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export class CopilotCoeditorService {
3333
// Virtual copilot coeditor
3434
private readonly COPILOT_COEDITOR: Coeditor = {
3535
uid: -1,
36-
name: "AI Agent",
36+
name: "AI",
3737
3838
role: "ADMIN" as any,
3939
color: "#9333ea", // Purple color for copilot

frontend/src/app/workspace/service/copilot/texera-copilot.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,9 @@ import {
3232
createDeleteOperatorTool,
3333
createDeleteLinkTool,
3434
createSetOperatorPropertyTool,
35-
createGetDynamicSchemaTool,
35+
createGetOperatorSchemaTool,
36+
createGetOperatorInputSchemaTool,
37+
createGetWorkflowCompilationStateTool,
3638
createExecuteWorkflowTool,
3739
createGetExecutionStateTool,
3840
createHasOperatorResultTool,
@@ -48,6 +50,7 @@ import { DynamicSchemaService } from "../dynamic-schema/dynamic-schema.service";
4850
import { ExecuteWorkflowService } from "../execute-workflow/execute-workflow.service";
4951
import { WorkflowResultService } from "../workflow-result/workflow-result.service";
5052
import { CopilotCoeditorService } from "./copilot-coeditor.service";
53+
import { WorkflowCompilingService } from "../compile-workflow/workflow-compiling.service";
5154

5255
// API endpoints as constants
5356
export const COPILOT_MCP_URL = "mcp";
@@ -93,7 +96,8 @@ export class TexeraCopilot {
9396
private dynamicSchemaService: DynamicSchemaService,
9497
private executeWorkflowService: ExecuteWorkflowService,
9598
private workflowResultService: WorkflowResultService,
96-
private copilotCoeditorService: CopilotCoeditorService
99+
private copilotCoeditorService: CopilotCoeditorService,
100+
private workflowCompilingService: WorkflowCompilingService
97101
) {
98102
// Don't auto-initialize, wait for user to enable
99103
}
@@ -197,7 +201,12 @@ export class TexeraCopilot {
197201
model: this.model,
198202
messages: this.messages, // full history
199203
tools,
200-
system: "You are Texera Copilot, an AI assistant for building and modifying data workflows.",
204+
system:
205+
"You are Texera Copilot, an AI assistant for building and modifying data workflows. " +
206+
"Your task is helping user explore the data using operators. " +
207+
"Common operators would be Limit to limit the size of data; " +
208+
"Aggregate to do some aggregation; and some visualization operator. " +
209+
"A good generation style is adding an operator, configuring its property and then executing it to make sure each editing is valid. Generate 3-5 operators is enough for every round of generation",
201210
stopWhen: stepCountIs(50),
202211

203212
// optional: observe every completed step (tool calls + results available)
@@ -271,11 +280,16 @@ export class TexeraCopilot {
271280
this.workflowActionService,
272281
this.copilotCoeditorService
273282
);
274-
const getDynamicSchemaTool = createGetDynamicSchemaTool(
275-
this.dynamicSchemaService,
283+
const getOperatorSchemaTool = createGetOperatorSchemaTool(
276284
this.workflowActionService,
285+
this.operatorMetadataService,
286+
this.copilotCoeditorService
287+
);
288+
const getOperatorInputSchemaTool = createGetOperatorInputSchemaTool(
289+
this.workflowCompilingService,
277290
this.copilotCoeditorService
278291
);
292+
const getWorkflowCompilationStateTool = createGetWorkflowCompilationStateTool(this.workflowCompilingService);
279293
const executeWorkflowTool = createExecuteWorkflowTool(this.executeWorkflowService);
280294
const getExecutionStateTool = createGetExecutionStateTool(this.executeWorkflowService);
281295
const hasOperatorResultTool = createHasOperatorResultTool(
@@ -308,7 +322,9 @@ export class TexeraCopilot {
308322
deleteOperator: deleteOperatorTool,
309323
deleteLink: deleteLinkTool,
310324
setOperatorProperty: setOperatorPropertyTool,
311-
getDynamicSchema: getDynamicSchemaTool,
325+
getOperatorSchema: getOperatorSchemaTool,
326+
getOperatorInputSchema: getOperatorInputSchemaTool,
327+
getWorkflowCompilationState: getWorkflowCompilationStateTool,
312328
executeWorkflow: executeWorkflowTool,
313329
getExecutionState: getExecutionStateTool,
314330
hasOperatorResult: hasOperatorResultTool,

0 commit comments

Comments
 (0)