Skip to content

Commit 007cb1e

Browse files
feat: Implement agent task completion and clarification tools
- Added task workflow for signaling task completion using agentTaskComplete and agentRequestClarification tools. - Enhanced agents API to include new tools for task management. - Refactored AgentChat component to utilize useAgentExecution hook for managing agent interactions. - Updated Kanban store to handle agent execution, including starting, stopping, and updating task statuses. - Introduced markdown rendering for agent comments to improve message display. - Implemented context menu actions for task management, including accept, reject, and delete functionalities. - Added utility functions for agent execution management in the Kanban store.
1 parent af197cf commit 007cb1e

10 files changed

Lines changed: 701 additions & 142 deletions

File tree

src/api/ai/agent-system-prompt.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,20 @@ Otherwise, follow debugging best practices:
5959
2. Add descriptive logging statements and error messages to track variable and code state.
6060
3. Add test functions and statements to isolate the problem.
6161
</debugging>
62+
63+
<task_workflow>
64+
You are working on tasks in a kanban board system. When you complete your work, you must use one of these tools to signal completion:
65+
66+
1. **agentTaskComplete**: Use this when you have successfully completed the task. You must specify:
67+
- status: "review" if your work is complete and ready for human review
68+
- status: "need_clarification" if you need more information to proceed
69+
- message: Explain what you completed or what clarification you need
70+
- summary: (optional) Brief summary of work done for review status
71+
72+
2. **agentRequestClarification**: Use this if you encounter issues that require user input:
73+
- questions: Array of specific questions you need answered
74+
- context: Why you need clarification
75+
76+
**Important**: You MUST call one of these tools when you finish working on a task. Never leave a task without properly signaling its completion status. The system uses these calls to move the task to the appropriate column (review or need clarification).
77+
</task_workflow>
6278
`;

src/api/ai/agents.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@ import { CoreMessage, streamText, createDataStreamResponse } from 'ai';
33
import { toolRegistry } from '../../pages/workspace/components/chat/tools';
44
import { settingsManager } from '../../helpers/ipc/settings/settings-listeners';
55
import { agentSystemPrompt } from './agent-system-prompt';
6+
import { agentTaskCompleteTool, agentRequestClarificationTool } from '../../pages/workspace/components/agents-view/agent-tools';
67

78
export async function agentsApi({ messages }: { messages: CoreMessage[] }) {
9+
console.log("Agents API called with messages:", messages);
810
try {
911
// Get XAI API key from secure settings
1012
const xaiApiKey = await settingsManager.getSecure('apiKeys.xai');
@@ -21,7 +23,11 @@ export async function agentsApi({ messages }: { messages: CoreMessage[] }) {
2123
model: model("grok-4-0709"),
2224
system: agentSystemPrompt,
2325
messages: messages,
24-
tools: toolRegistry.getTools(),
26+
tools: {
27+
...toolRegistry.getTools(),
28+
agentTaskComplete: agentTaskCompleteTool,
29+
agentRequestClarification: agentRequestClarificationTool,
30+
},
2531
maxSteps: 100,
2632
// maxTokens: 10000,
2733
});
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
import React, { useCallback, useRef, useEffect, useState, useImperativeHandle, forwardRef } from 'react';
2+
import { Button } from '@/components/ui/button';
3+
import { MoreHorizontal, Send } from 'lucide-react';
4+
import { MessageComponent } from '../chat/chat-message';
5+
import { useKanbanStore } from '@/stores/kanban';
6+
import { useProjectStore } from '@/stores/project';
7+
import { Input } from '@/components/ui/input';
8+
import DotMatrix from '@/components/ui/animated-dot-matrix';
9+
import { useAgentExecution } from './use-agent-execution';
10+
11+
interface AgentChatProps {
12+
taskId: string;
13+
className?: string;
14+
}
15+
16+
export interface AgentChatRef {
17+
executeAgent: () => Promise<void>;
18+
stopAgent: () => void;
19+
}
20+
21+
export const AgentChat = forwardRef<AgentChatRef, AgentChatProps>(({ taskId, className = '' }, ref) => {
22+
const { currentProject } = useProjectStore();
23+
const { addMessage } = useKanbanStore();
24+
const [inputValue, setInputValue] = useState('');
25+
26+
// Use the new agent execution hook
27+
const {
28+
messages,
29+
executeAgent,
30+
stopAgent,
31+
isExecuting,
32+
error,
33+
append,
34+
} = useAgentExecution({ taskId });
35+
36+
const messagesEndRef = useRef<HTMLDivElement>(null);
37+
38+
// Expose methods to parent via ref
39+
useImperativeHandle(ref, () => ({
40+
executeAgent,
41+
stopAgent,
42+
}), [executeAgent, stopAgent]);
43+
44+
const scrollToBottom = useCallback(() => {
45+
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' });
46+
}, []);
47+
48+
useEffect(() => {
49+
scrollToBottom();
50+
}, [messages, scrollToBottom]);
51+
52+
// Add message to chat (no auto-execution)
53+
const handleSend = useCallback(async () => {
54+
if (!inputValue.trim()) return;
55+
56+
const userMessage = inputValue.trim();
57+
setInputValue('');
58+
59+
// Save user message to kanban store
60+
if (currentProject) {
61+
addMessage(currentProject, taskId, {
62+
role: 'user',
63+
content: userMessage
64+
});
65+
}
66+
67+
// Add to chat via useChat
68+
await append({
69+
role: 'user',
70+
content: userMessage,
71+
});
72+
}, [inputValue, currentProject, taskId, addMessage, append]);
73+
74+
const handleKeyPress = useCallback((e: React.KeyboardEvent) => {
75+
if (e.key === 'Enter' && !e.shiftKey) {
76+
e.preventDefault();
77+
handleSend();
78+
}
79+
}, [handleSend]);
80+
81+
const handleCopyMessage = useCallback((content: string) => {
82+
navigator.clipboard.writeText(content);
83+
}, []);
84+
85+
const handleDeleteMessage = useCallback((id: string) => {
86+
// Note: Deleting from useChat messages would require custom implementation
87+
// For now, we'll just copy to clipboard
88+
console.log('Delete message:', id);
89+
}, []);
90+
91+
return (
92+
<div className={`flex flex-col h-full ${className}`}>
93+
{/* Header */}
94+
<div className="border-b p-3 flex-shrink-0">
95+
<div className="flex items-center justify-between">
96+
<h3 className="text-sm font-medium">Agent Chat</h3>
97+
<Button variant="ghost" size="sm" className="h-6 w-6 p-0">
98+
<MoreHorizontal className="h-3 w-3" />
99+
</Button>
100+
</div>
101+
</div>
102+
103+
{/* Messages */}
104+
<div className="flex-1 overflow-hidden">
105+
<div className="h-full overflow-y-auto">
106+
<div className="p-3 space-y-4">
107+
{messages.map((message) => (
108+
<MessageComponent
109+
key={message.id}
110+
message={message}
111+
onCopy={handleCopyMessage}
112+
onDelete={handleDeleteMessage}
113+
// Note: Tool handling for agents would be different from regular chat
114+
onToolApprove={() => {}}
115+
onToolCancel={() => {}}
116+
/>
117+
))}
118+
119+
{isExecuting && (
120+
<div className="flex justify-start">
121+
<DotMatrix
122+
baseColor='#444'
123+
fillColor="#4caf50"
124+
dotSize={3}
125+
rows={3}
126+
fillSpeed={3000}
127+
autoFill={true}
128+
/>
129+
</div>
130+
)}
131+
132+
{error && (
133+
<div className="text-red-500 text-sm p-2 bg-red-50 rounded">
134+
Error: {error.message}
135+
</div>
136+
)}
137+
138+
<div ref={messagesEndRef} />
139+
</div>
140+
</div>
141+
</div>
142+
143+
{/* Input Area */}
144+
<div className="border-t p-3 flex-shrink-0">
145+
<div className="flex gap-2">
146+
<Input
147+
value={inputValue}
148+
onChange={(e) => setInputValue(e.target.value)}
149+
onKeyPress={handleKeyPress}
150+
placeholder="Add message for the agent..."
151+
disabled={isExecuting}
152+
className="flex-1"
153+
/>
154+
<Button
155+
onClick={handleSend}
156+
disabled={!inputValue.trim() || isExecuting}
157+
size="sm"
158+
className="px-3"
159+
>
160+
<Send className="h-4 w-4" />
161+
</Button>
162+
</div>
163+
</div>
164+
</div>
165+
);
166+
});
167+
168+
AgentChat.displayName = 'AgentChat';

0 commit comments

Comments
 (0)