@dcode-dev/dcode-cli 1.0.0
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/NPM_README.md +78 -0
- package/README.md +341 -0
- package/bin/dcode-bin +0 -0
- package/bin/dcode.js +44 -0
- package/cmd/agent_v2.go +448 -0
- package/cmd/analyze.go +97 -0
- package/cmd/auth.go +338 -0
- package/cmd/compose.go +284 -0
- package/cmd/context.go +111 -0
- package/cmd/edit.go +116 -0
- package/cmd/env.go +10 -0
- package/cmd/fix.go +145 -0
- package/cmd/gemini.go +20 -0
- package/cmd/generate.go +47 -0
- package/cmd/interactive.go +33 -0
- package/cmd/mcp.go +196 -0
- package/cmd/patch.go +19 -0
- package/cmd/providers.go +67 -0
- package/cmd/root.go +41 -0
- package/cmd/search.go +61 -0
- package/cmd/server.go +36 -0
- package/cmd/switch.go +122 -0
- package/cmd/terminal.go +277 -0
- package/go.mod +42 -0
- package/go.sum +86 -0
- package/internal/agent/agent.go +332 -0
- package/internal/agent/parse.go +25 -0
- package/internal/agents/base.go +154 -0
- package/internal/agents/documenter.go +77 -0
- package/internal/agents/generalist.go +266 -0
- package/internal/agents/investigator.go +60 -0
- package/internal/agents/registry.go +34 -0
- package/internal/agents/reviewer.go +67 -0
- package/internal/agents/tester.go +73 -0
- package/internal/ai/client.go +634 -0
- package/internal/ai/tools.go +332 -0
- package/internal/auth/adc.go +108 -0
- package/internal/auth/apikey.go +67 -0
- package/internal/auth/factory.go +145 -0
- package/internal/auth/oauth2.go +227 -0
- package/internal/auth/store.go +216 -0
- package/internal/auth/types.go +79 -0
- package/internal/auth/vertex.go +138 -0
- package/internal/config/config.go +428 -0
- package/internal/config/policy.go +251 -0
- package/internal/context/builder.go +312 -0
- package/internal/detector/detector.go +204 -0
- package/internal/diffutil/diffutil.go +30 -0
- package/internal/fsutil/fsutil.go +35 -0
- package/internal/mcp/client.go +314 -0
- package/internal/mcp/manager.go +221 -0
- package/internal/policy/policy.go +89 -0
- package/internal/prompt/interactive.go +338 -0
- package/internal/registry/agent.go +201 -0
- package/internal/registry/tool.go +181 -0
- package/internal/scheduler/scheduler.go +250 -0
- package/internal/server/server.go +167 -0
- package/internal/tools/file.go +183 -0
- package/internal/tools/filesystem.go +286 -0
- package/internal/tools/git.go +355 -0
- package/internal/tools/memory.go +269 -0
- package/internal/tools/registry.go +49 -0
- package/internal/tools/search.go +230 -0
- package/internal/tools/shell.go +84 -0
- package/internal/websearch/search.go +40 -0
- package/internal/websearch/tavily.go +79 -0
- package/main.go +19 -0
- package/package.json +57 -0
- package/scripts/install.js +59 -0
- package/scripts/uninstall.js +28 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
package agents
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"context"
|
|
5
|
+
"fmt"
|
|
6
|
+
|
|
7
|
+
"github.com/ddhanush1/dcode/internal/ai"
|
|
8
|
+
"github.com/ddhanush1/dcode/internal/config"
|
|
9
|
+
"github.com/ddhanush1/dcode/internal/registry"
|
|
10
|
+
)
|
|
11
|
+
|
|
12
|
+
// GeneralistAgent is the main conversational agent
|
|
13
|
+
type GeneralistAgent struct {
|
|
14
|
+
aiClient *ai.Client
|
|
15
|
+
config *config.Config
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// NewGeneralistAgent creates a new generalist agent
|
|
19
|
+
func NewGeneralistAgent(cfg *config.Config, aiClient *ai.Client) *registry.AgentDefinition {
|
|
20
|
+
agent := &GeneralistAgent{
|
|
21
|
+
aiClient: aiClient,
|
|
22
|
+
config: cfg,
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
return ®istry.AgentDefinition{
|
|
26
|
+
ID: "generalist",
|
|
27
|
+
Name: "Generalist Agent",
|
|
28
|
+
Description: "A general-purpose conversational agent that can help with various tasks",
|
|
29
|
+
Version: "1.0.0",
|
|
30
|
+
Tools: []string{
|
|
31
|
+
"read_file",
|
|
32
|
+
"write_file",
|
|
33
|
+
"ls",
|
|
34
|
+
"shell",
|
|
35
|
+
"grep",
|
|
36
|
+
"glob",
|
|
37
|
+
"git_status",
|
|
38
|
+
"git_diff",
|
|
39
|
+
"git_log",
|
|
40
|
+
"save_memory",
|
|
41
|
+
"recall_memory",
|
|
42
|
+
},
|
|
43
|
+
SystemPrompt: `You are a helpful AI assistant with access to tools for working with code and files.
|
|
44
|
+
|
|
45
|
+
CORE MANDATES:
|
|
46
|
+
• Security: Never expose credentials or API keys in responses
|
|
47
|
+
• Standards: Follow existing code conventions and project patterns
|
|
48
|
+
• Expertise: Use tools proactively to get information before responding
|
|
49
|
+
|
|
50
|
+
AVAILABLE TOOLS:
|
|
51
|
+
• read_file: Read file contents
|
|
52
|
+
• write_file: Write to files
|
|
53
|
+
• ls: List directory contents
|
|
54
|
+
• shell: Execute shell commands
|
|
55
|
+
• grep: Search for patterns in files
|
|
56
|
+
• glob: Find files by pattern
|
|
57
|
+
• git_status, git_diff, git_log: Git operations
|
|
58
|
+
• save_memory, recall_memory: Persistent memory
|
|
59
|
+
|
|
60
|
+
WORKFLOW:
|
|
61
|
+
1. For file/code questions: Use read_file or grep to examine code first
|
|
62
|
+
2. For system questions: Use shell to gather information
|
|
63
|
+
3. For modifications: Confirm changes before using write_file
|
|
64
|
+
4. For analysis: Start broad (ls, git_log), then deep dive (read_file, grep)
|
|
65
|
+
|
|
66
|
+
Always explain what you're doing and why. Be concise but thorough.`,
|
|
67
|
+
AllowSubAgents: true,
|
|
68
|
+
MaxTurns: 50,
|
|
69
|
+
Config: make(map[string]interface{}),
|
|
70
|
+
Executor: agent.Execute,
|
|
71
|
+
Instance: agent, // Store the actual agent instance
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Execute executes the generalist agent with tool support
|
|
76
|
+
func (a *GeneralistAgent) Execute(input *registry.AgentInput) (*registry.AgentOutput, error) {
|
|
77
|
+
return a.execute(input, nil)
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ExecuteStream executes with streaming callback
|
|
81
|
+
func (a *GeneralistAgent) ExecuteStream(input *registry.AgentInput, onChunk func(string)) (*registry.AgentOutput, error) {
|
|
82
|
+
return a.execute(input, onChunk)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// execute is the internal implementation
|
|
86
|
+
func (a *GeneralistAgent) execute(input *registry.AgentInput, onChunk func(string)) (*registry.AgentOutput, error) {
|
|
87
|
+
// Build messages from history
|
|
88
|
+
messages := []ai.Message{}
|
|
89
|
+
|
|
90
|
+
// Add system prompt as first message
|
|
91
|
+
if input.SystemPrompt != "" {
|
|
92
|
+
messages = append(messages, ai.Message{
|
|
93
|
+
Role: "system",
|
|
94
|
+
Content: input.SystemPrompt,
|
|
95
|
+
})
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Add history
|
|
99
|
+
for _, msg := range input.History {
|
|
100
|
+
messages = append(messages, ai.Message{
|
|
101
|
+
Role: msg.Role,
|
|
102
|
+
Content: msg.Content,
|
|
103
|
+
})
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Add current query (only if not empty)
|
|
107
|
+
if input.Query != "" {
|
|
108
|
+
messages = append(messages, ai.Message{
|
|
109
|
+
Role: "user",
|
|
110
|
+
Content: input.Query,
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Convert tools to Gemini function declarations
|
|
115
|
+
tools := convertToolsToGeminiFormat(input.ToolRegistry)
|
|
116
|
+
|
|
117
|
+
// Call AI with tools (streaming if callback provided)
|
|
118
|
+
ctx := context.Background()
|
|
119
|
+
var response *ai.ToolResponse
|
|
120
|
+
var err error
|
|
121
|
+
|
|
122
|
+
if onChunk != nil {
|
|
123
|
+
response, err = a.aiClient.ChatWithToolsStream(ctx, messages, tools, onChunk)
|
|
124
|
+
} else {
|
|
125
|
+
response, err = a.aiClient.ChatWithTools(ctx, messages, tools)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if err != nil {
|
|
129
|
+
return nil, fmt.Errorf("AI call failed: %w", err)
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// Convert function calls to tool calls
|
|
133
|
+
toolCalls := []registry.ToolCall{}
|
|
134
|
+
for _, fc := range response.FunctionCalls {
|
|
135
|
+
toolCalls = append(toolCalls, registry.ToolCall{
|
|
136
|
+
ID: fc.Name, // Use function name as ID
|
|
137
|
+
ToolName: fc.Name,
|
|
138
|
+
Parameters: fc.Args,
|
|
139
|
+
Status: "pending",
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return ®istry.AgentOutput{
|
|
144
|
+
Message: response.Text,
|
|
145
|
+
ToolCalls: toolCalls,
|
|
146
|
+
Data: make(map[string]interface{}),
|
|
147
|
+
TerminationReason: response.FinishReason,
|
|
148
|
+
Metadata: map[string]interface{}{
|
|
149
|
+
"model": a.aiClient.Model,
|
|
150
|
+
"provider": a.aiClient.Provider,
|
|
151
|
+
"tool_count": len(toolCalls),
|
|
152
|
+
},
|
|
153
|
+
}, nil
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
// convertToolsToGeminiFormat converts registry tools to Gemini function declarations
|
|
157
|
+
func convertToolsToGeminiFormat(toolRegistry *registry.ToolRegistry) []ai.Tool {
|
|
158
|
+
if toolRegistry == nil {
|
|
159
|
+
return nil
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
tools := []ai.Tool{}
|
|
163
|
+
declarations := []ai.FunctionDeclaration{}
|
|
164
|
+
|
|
165
|
+
for _, tool := range toolRegistry.List() {
|
|
166
|
+
// Use the tool's actual InputSchema if available
|
|
167
|
+
params := tool.InputSchema
|
|
168
|
+
if params == nil {
|
|
169
|
+
// Fallback to generic input
|
|
170
|
+
params = map[string]interface{}{
|
|
171
|
+
"type": "object",
|
|
172
|
+
"properties": map[string]interface{}{
|
|
173
|
+
"input": map[string]interface{}{
|
|
174
|
+
"type": "string",
|
|
175
|
+
"description": "Input to the tool",
|
|
176
|
+
},
|
|
177
|
+
},
|
|
178
|
+
"required": []string{},
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
declarations = append(declarations, ai.FunctionDeclaration{
|
|
183
|
+
Name: tool.ID,
|
|
184
|
+
Description: fmt.Sprintf("%s - %s (Risk: %s)", tool.Name, tool.Description, tool.RiskLevel),
|
|
185
|
+
Parameters: params,
|
|
186
|
+
})
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
if len(declarations) > 0 {
|
|
190
|
+
tools = append(tools, ai.Tool{
|
|
191
|
+
FunctionDeclarations: declarations,
|
|
192
|
+
})
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return tools
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// CreateGeneralistExecutor creates an executor for generalist-style agents
|
|
199
|
+
func CreateGeneralistExecutor(aiClient *ai.Client) func(*registry.AgentInput) (*registry.AgentOutput, error) {
|
|
200
|
+
return func(input *registry.AgentInput) (*registry.AgentOutput, error) {
|
|
201
|
+
// Build messages from history
|
|
202
|
+
messages := []ai.Message{}
|
|
203
|
+
|
|
204
|
+
// Add system prompt
|
|
205
|
+
if input.SystemPrompt != "" {
|
|
206
|
+
messages = append(messages, ai.Message{
|
|
207
|
+
Role: "system",
|
|
208
|
+
Content: input.SystemPrompt,
|
|
209
|
+
})
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Add history
|
|
213
|
+
for _, msg := range input.History {
|
|
214
|
+
messages = append(messages, ai.Message{
|
|
215
|
+
Role: msg.Role,
|
|
216
|
+
Content: msg.Content,
|
|
217
|
+
})
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Add current query
|
|
221
|
+
messages = append(messages, ai.Message{
|
|
222
|
+
Role: "user",
|
|
223
|
+
Content: input.Query,
|
|
224
|
+
})
|
|
225
|
+
|
|
226
|
+
// Convert tools to Gemini format
|
|
227
|
+
tools := convertToolsToGeminiFormat(input.ToolRegistry)
|
|
228
|
+
|
|
229
|
+
// Call AI with tools
|
|
230
|
+
ctx := context.Background()
|
|
231
|
+
response, err := aiClient.ChatWithTools(ctx, messages, tools)
|
|
232
|
+
if err != nil {
|
|
233
|
+
return nil, fmt.Errorf("AI call failed: %w", err)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Convert function calls to tool calls
|
|
237
|
+
toolCalls := []registry.ToolCall{}
|
|
238
|
+
for _, fc := range response.FunctionCalls {
|
|
239
|
+
toolCalls = append(toolCalls, registry.ToolCall{
|
|
240
|
+
ID: fc.Name,
|
|
241
|
+
ToolName: fc.Name,
|
|
242
|
+
Parameters: fc.Args,
|
|
243
|
+
Status: "pending",
|
|
244
|
+
})
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return ®istry.AgentOutput{
|
|
248
|
+
Message: response.Text,
|
|
249
|
+
ToolCalls: toolCalls,
|
|
250
|
+
Data: make(map[string]interface{}),
|
|
251
|
+
TerminationReason: response.FinishReason,
|
|
252
|
+
Metadata: map[string]interface{}{
|
|
253
|
+
"model": aiClient.Model,
|
|
254
|
+
"provider": aiClient.Provider,
|
|
255
|
+
"tool_count": len(toolCalls),
|
|
256
|
+
},
|
|
257
|
+
}, nil
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
// RegisterGeneralistAgent registers the generalist agent
|
|
262
|
+
func RegisterGeneralistAgent(agentRegistry *registry.AgentRegistry, cfg *config.Config, aiClient *ai.Client) error {
|
|
263
|
+
agent := NewGeneralistAgent(cfg, aiClient)
|
|
264
|
+
return agentRegistry.Register(agent)
|
|
265
|
+
}
|
|
266
|
+
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
package agents
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"github.com/ddhanush1/dcode/internal/ai"
|
|
5
|
+
"github.com/ddhanush1/dcode/internal/registry"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
const investigatorSystemPrompt = `You are a Codebase Investigator, an AI agent specialized in analyzing and understanding code repositories.
|
|
9
|
+
|
|
10
|
+
Your capabilities:
|
|
11
|
+
- Analyze project architecture and structure
|
|
12
|
+
- Map dependencies and relationships between components
|
|
13
|
+
- Identify design patterns and architectural decisions
|
|
14
|
+
- Understand code organization and conventions
|
|
15
|
+
- Provide insights on codebase health and maintainability
|
|
16
|
+
- Answer questions about how the codebase works
|
|
17
|
+
|
|
18
|
+
When analyzing code:
|
|
19
|
+
1. Start with high-level structure (directories, modules)
|
|
20
|
+
2. Identify entry points and main components
|
|
21
|
+
3. Map data flow and dependencies
|
|
22
|
+
4. Document key architectural decisions
|
|
23
|
+
5. Provide clear, actionable insights
|
|
24
|
+
|
|
25
|
+
Use available tools to:
|
|
26
|
+
- grep: Search for patterns, imports, function definitions
|
|
27
|
+
- glob: Find files by pattern
|
|
28
|
+
- read_file: Read source files and configs
|
|
29
|
+
- git_log: Understand project history
|
|
30
|
+
- save_memory: Store important findings
|
|
31
|
+
- recall_memory: Retrieve previous analysis
|
|
32
|
+
|
|
33
|
+
Be thorough but concise. Focus on understanding "how" and "why" the code works.`
|
|
34
|
+
|
|
35
|
+
// GetInvestigatorTools returns tools best suited for investigation
|
|
36
|
+
func GetInvestigatorTools() []string {
|
|
37
|
+
return []string{
|
|
38
|
+
"grep",
|
|
39
|
+
"glob",
|
|
40
|
+
"read_file",
|
|
41
|
+
"ls",
|
|
42
|
+
"git_log",
|
|
43
|
+
"git_status",
|
|
44
|
+
"save_memory",
|
|
45
|
+
"recall_memory",
|
|
46
|
+
"list_memories",
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// RegisterInvestigatorAgent registers the investigator agent
|
|
51
|
+
func RegisterInvestigatorAgent(agentRegistry *registry.AgentRegistry, aiClient *ai.Client) error {
|
|
52
|
+
return agentRegistry.Register(®istry.AgentDefinition{
|
|
53
|
+
ID: "investigator",
|
|
54
|
+
Name: "Codebase Investigator",
|
|
55
|
+
Description: "Specialized in analyzing and understanding code repositories",
|
|
56
|
+
SystemPrompt: investigatorSystemPrompt,
|
|
57
|
+
Tools: GetInvestigatorTools(),
|
|
58
|
+
Executor: CreateGeneralistExecutor(aiClient),
|
|
59
|
+
})
|
|
60
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
package agents
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"github.com/ddhanush1/dcode/internal/ai"
|
|
5
|
+
"github.com/ddhanush1/dcode/internal/config"
|
|
6
|
+
"github.com/ddhanush1/dcode/internal/registry"
|
|
7
|
+
)
|
|
8
|
+
|
|
9
|
+
// RegisterAllAgents registers all built-in agents
|
|
10
|
+
func RegisterAllAgents(agentRegistry *registry.AgentRegistry, cfg *config.Config, aiClient *ai.Client) error {
|
|
11
|
+
// Register all agents
|
|
12
|
+
agents := []func(*registry.AgentRegistry, *ai.Client) error{
|
|
13
|
+
RegisterGeneralistAgent2,
|
|
14
|
+
RegisterInvestigatorAgent,
|
|
15
|
+
RegisterReviewerAgent,
|
|
16
|
+
RegisterTesterAgent,
|
|
17
|
+
RegisterDocumenterAgent,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
for _, registerFn := range agents {
|
|
21
|
+
if err := registerFn(agentRegistry, aiClient); err != nil {
|
|
22
|
+
return err
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
return nil
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// RegisterGeneralistAgent2 is a wrapper for the new signature
|
|
30
|
+
func RegisterGeneralistAgent2(agentRegistry *registry.AgentRegistry, aiClient *ai.Client) error {
|
|
31
|
+
// Get config from a default location or pass nil
|
|
32
|
+
return RegisterGeneralistAgent(agentRegistry, nil, aiClient)
|
|
33
|
+
}
|
|
34
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
package agents
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"github.com/ddhanush1/dcode/internal/ai"
|
|
5
|
+
"github.com/ddhanush1/dcode/internal/registry"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
const reviewerSystemPrompt = `You are a Code Reviewer, an AI agent specialized in reviewing code quality and providing actionable feedback.
|
|
9
|
+
|
|
10
|
+
Your focus areas:
|
|
11
|
+
- Code quality and best practices
|
|
12
|
+
- Potential bugs and edge cases
|
|
13
|
+
- Security vulnerabilities
|
|
14
|
+
- Performance issues
|
|
15
|
+
- Code maintainability and readability
|
|
16
|
+
- Test coverage gaps
|
|
17
|
+
- Documentation quality
|
|
18
|
+
|
|
19
|
+
When reviewing code:
|
|
20
|
+
1. Start by understanding the context and purpose
|
|
21
|
+
2. Check for common issues (null checks, error handling, edge cases)
|
|
22
|
+
3. Look for security vulnerabilities (SQL injection, XSS, etc.)
|
|
23
|
+
4. Evaluate code structure and organization
|
|
24
|
+
5. Suggest concrete improvements
|
|
25
|
+
6. Prioritize issues by severity (critical, major, minor)
|
|
26
|
+
|
|
27
|
+
Review principles:
|
|
28
|
+
- Be constructive and specific
|
|
29
|
+
- Explain WHY something is an issue
|
|
30
|
+
- Provide code examples for fixes
|
|
31
|
+
- Consider the broader context
|
|
32
|
+
- Balance perfectionism with pragmatism
|
|
33
|
+
|
|
34
|
+
Use available tools to:
|
|
35
|
+
- git_diff: Review changes
|
|
36
|
+
- read_file: Read full context
|
|
37
|
+
- grep: Search for patterns or anti-patterns
|
|
38
|
+
- confirm: Ask before making suggestions
|
|
39
|
+
- write_file: Apply fixes (with permission)
|
|
40
|
+
|
|
41
|
+
Focus on substance over style. Prioritize correctness, security, and maintainability.`
|
|
42
|
+
|
|
43
|
+
// GetReviewerTools returns tools best suited for code review
|
|
44
|
+
func GetReviewerTools() []string {
|
|
45
|
+
return []string{
|
|
46
|
+
"git_diff",
|
|
47
|
+
"git_status",
|
|
48
|
+
"read_file",
|
|
49
|
+
"write_file",
|
|
50
|
+
"grep",
|
|
51
|
+
"glob",
|
|
52
|
+
"confirm",
|
|
53
|
+
"ask_user",
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// RegisterReviewerAgent registers the reviewer agent
|
|
58
|
+
func RegisterReviewerAgent(agentRegistry *registry.AgentRegistry, aiClient *ai.Client) error {
|
|
59
|
+
return agentRegistry.Register(®istry.AgentDefinition{
|
|
60
|
+
ID: "reviewer",
|
|
61
|
+
Name: "Code Reviewer",
|
|
62
|
+
Description: "Specialized in reviewing code quality and providing feedback",
|
|
63
|
+
SystemPrompt: reviewerSystemPrompt,
|
|
64
|
+
Tools: GetReviewerTools(),
|
|
65
|
+
Executor: CreateGeneralistExecutor(aiClient),
|
|
66
|
+
})
|
|
67
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
package agents
|
|
2
|
+
|
|
3
|
+
import (
|
|
4
|
+
"github.com/ddhanush1/dcode/internal/ai"
|
|
5
|
+
"github.com/ddhanush1/dcode/internal/registry"
|
|
6
|
+
)
|
|
7
|
+
|
|
8
|
+
const testerSystemPrompt = `You are a Test Generator, an AI agent specialized in creating comprehensive test suites.
|
|
9
|
+
|
|
10
|
+
Your expertise:
|
|
11
|
+
- Unit test generation with high coverage
|
|
12
|
+
- Integration test design
|
|
13
|
+
- Edge case identification
|
|
14
|
+
- Test data generation
|
|
15
|
+
- Mocking and stubbing strategies
|
|
16
|
+
- Test organization and structure
|
|
17
|
+
- Test-driven development (TDD) practices
|
|
18
|
+
|
|
19
|
+
When generating tests:
|
|
20
|
+
1. Understand the code under test thoroughly
|
|
21
|
+
2. Identify all code paths and branches
|
|
22
|
+
3. Generate tests for:
|
|
23
|
+
- Happy path scenarios
|
|
24
|
+
- Edge cases and boundary conditions
|
|
25
|
+
- Error handling and exceptions
|
|
26
|
+
- Invalid inputs and states
|
|
27
|
+
4. Use appropriate testing patterns
|
|
28
|
+
5. Include descriptive test names and comments
|
|
29
|
+
6. Follow language-specific conventions
|
|
30
|
+
|
|
31
|
+
Test quality guidelines:
|
|
32
|
+
- Tests should be independent and isolated
|
|
33
|
+
- Use meaningful assertions
|
|
34
|
+
- Keep tests simple and focused
|
|
35
|
+
- Test behavior, not implementation
|
|
36
|
+
- Ensure tests are maintainable
|
|
37
|
+
- Aim for high coverage but prioritize meaningful tests
|
|
38
|
+
|
|
39
|
+
Use available tools to:
|
|
40
|
+
- read_file: Read code to test
|
|
41
|
+
- write_file: Create test files
|
|
42
|
+
- shell: Run tests
|
|
43
|
+
- grep: Find existing tests
|
|
44
|
+
- glob: Locate test files
|
|
45
|
+
- git_status: Check test changes
|
|
46
|
+
|
|
47
|
+
Generate practical, maintainable tests that provide real value.`
|
|
48
|
+
|
|
49
|
+
// GetTesterTools returns tools best suited for test generation
|
|
50
|
+
func GetTesterTools() []string {
|
|
51
|
+
return []string{
|
|
52
|
+
"read_file",
|
|
53
|
+
"write_file",
|
|
54
|
+
"shell",
|
|
55
|
+
"grep",
|
|
56
|
+
"glob",
|
|
57
|
+
"git_status",
|
|
58
|
+
"ls",
|
|
59
|
+
"confirm",
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// RegisterTesterAgent registers the tester agent
|
|
64
|
+
func RegisterTesterAgent(agentRegistry *registry.AgentRegistry, aiClient *ai.Client) error {
|
|
65
|
+
return agentRegistry.Register(®istry.AgentDefinition{
|
|
66
|
+
ID: "tester",
|
|
67
|
+
Name: "Test Generator",
|
|
68
|
+
Description: "Specialized in generating comprehensive test suites",
|
|
69
|
+
SystemPrompt: testerSystemPrompt,
|
|
70
|
+
Tools: GetTesterTools(),
|
|
71
|
+
Executor: CreateGeneralistExecutor(aiClient),
|
|
72
|
+
})
|
|
73
|
+
}
|