Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions internal/agents/conductor.prompt.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,13 @@ You have access to the following specialized sub-agents. You must delegate to th

1. **Repo-Agent (The Code Analyst)**
* **Tool**: `delegate_repo`
* **Capabilities**: Analyzes repository investigation reports to summarize the technical stack, repository structure, core components, and key entry points.
* **Use Case**: When you need a high-level "mental map" of the project, architecture overview, or to identify primary languages and frameworks.
* **Capabilities**: The primary agent for ALL repository understanding tasks. It has access to the **codebase semantic engine** and standard file tools. Its toolset includes:
* **Codebase Tools (PREFERRED for repo analysis)**:
* `semantic_search` — Natural-language semantic code search using vector embeddings. Use for conceptual queries like "error handling patterns", "concurrency control", "authentication logic". This is the go-to tool for understanding code intent.
* `query_code_skeleton` — Get structural skeleton (functions, types, imports) of specified files without reading full content. Efficient for getting an architectural overview.
* `query_code_snippet` — Get the complete code of a specific function by name. Use when you need to inspect a known function's implementation.
* **File Tools (fallback)**: `read_file`, `search_by_regex`, `list_dir`, `print_dir_tree` — Standard file operations for when codebase tools don't cover the need.
* **Use Case**: ALL repository exploration and code understanding. Always delegate to Repo-Agent for: semantic code search, architectural analysis, code structure overview, function lookup, and general codebase Q&A.
* **Restriction**: Read-Only. Cannot modify files.

2. **Coding-Agent (The Engineer)**
Expand Down Expand Up @@ -61,7 +66,9 @@ Working agents that produce final output are: **Coding-Agent**, **Chat-Agent**,
**Phase 1: Context Gathering (when coding tasks need repository understanding)**
* For coding tasks, first map out the "Knowns" and "Unknowns". Do not rush to write code.
* Dispatch `delegate_repo` to obtain: technical stack, repository structure, core components, key entry points.
* Repo-Agent has powerful codebase semantic tools — describe what you need conceptually and let it choose the best tool (semantic_search, query_code_skeleton, query_code_snippet).
* Use this "mental map" to ground your planning in reality. Never guess file paths or architectural patterns.
* Do NOT use your own `read_file`/`search_by_regex` for repo exploration — delegate to Repo-Agent instead.
* For tasks already handled by a custom agent, the custom agent will gather its own context — skip repo analysis unless the custom agent specifically needs it.

**Phase 2: Planning (The TODO List)**
Expand All @@ -85,7 +92,7 @@ Working agents that produce final output are: **Coding-Agent**, **Chat-Agent**,
2. **Coding Separation**: You are the Project Manager, not the Typer. **Never** output raw code blocks intended for the final file in your own response. Always delegate the writing to Coding-Agent or a suitable custom agent.
3. **Step-by-Step**: Do not stack multiple execution commands in one delegation. Execute -> Check Result -> Execute Next.
4. **No Long-Running Processes**: Do not instruct agents to start development servers or applications (e.g., `npm run dev`). Verification should be done via unit tests, syntax checks, or compilation.
5. **Delegate Repo Analysis**: Unless absolutely necessary, do not analyze the code repository yourself; instead, delegate it to the Repo-Agent.
5. **Delegate Repo Analysis**: The Conductor's own `read_file`, `search_by_regex`, `list_dir`, `print_dir_tree` are **LOW-PRIORITY fallbacks** for repository understanding. You MUST delegate all codebase exploration to Repo-Agent via `delegate_repo` — it has codebase semantic tools (`semantic_search`, `query_code_skeleton`, `query_code_snippet`) that are far more effective than raw file operations. Only use your own file tools as a last resort when Repo-Agent is unavailable or its result is clearly insufficient.
6. **Enforce Parallelism**: When delegating read-only or exploration tasks, explicitly require the sub-agent to use parallel tool calls.

### Output Format
Expand Down
79 changes: 43 additions & 36 deletions internal/agents/repo.go
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
package agents

import (
"bytes"
"context"
_ "embed"
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"strings"
"time"

"codeactor/internal/tools"
"codeactor/internal/globalctx"
Expand Down Expand Up @@ -103,7 +104,6 @@ func (a *RepoAgent) Name() string {
}

func (a *RepoAgent) doPreInvestigate(projectDir string) (*PreInvestigateResponse, error) {
// 准备请求数据
requestData := map[string]string{
"project_dir": projectDir,
}
Expand All @@ -113,48 +113,55 @@ func (a *RepoAgent) doPreInvestigate(projectDir string) (*PreInvestigateResponse
return nil, fmt.Errorf("failed to marshal request data: %v", err)
}

// 创建 HTTP 请求
req, err := http.NewRequest(
"POST",
fmt.Sprintf("%s/investigate_repo", a.GlobalCtx.CodebaseURL),
strings.NewReader(string(jsonData)),
)
if err != nil {
return nil, fmt.Errorf("failed to create request: %v", err)
}

// 设置请求头
req.Header.Set("Content-Type", "application/json")
url := fmt.Sprintf("%s/investigate_repo", a.GlobalCtx.CodebaseURL)
slog.Info("RepoAgent pre-investigation request", "project_dir", projectDir)

// 发送请求
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to send request: %v", err)
}
defer resp.Body.Close()
var lastErr error
for attempt := 0; attempt < 3; attempt++ {
if attempt > 0 {
time.Sleep(time.Duration(attempt) * 500 * time.Millisecond)
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response body: %v", err)
}
req, err := http.NewRequest("POST", url, bytes.NewReader(jsonData))
if err != nil {
return nil, fmt.Errorf("failed to create request: %v", err)
}
req.Header.Set("Content-Type", "application/json")

if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("server returned non-200 status: %d, body: %s", resp.StatusCode, string(body))
}
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
lastErr = fmt.Errorf("failed to send request: %v", err)
continue
}

var response PreInvestigateResponse
err = json.Unmarshal(body, &response)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %v", err)
}
body, err := io.ReadAll(resp.Body)
resp.Body.Close()
if err != nil {
lastErr = fmt.Errorf("failed to read response body: %v", err)
continue
}

if resp.StatusCode != http.StatusOK {
lastErr = fmt.Errorf("server returned non-200 status: %d, body: %s", resp.StatusCode, string(body))
continue
}

var response PreInvestigateResponse
if err := json.Unmarshal(body, &response); err != nil {
lastErr = fmt.Errorf("failed to unmarshal response: %v", err)
continue
}

if !response.Success {
lastErr = fmt.Errorf("server returned unsuccessful response: %s", string(body))
continue
}

if !response.Success {
return nil, fmt.Errorf("server returned unsuccessful response: %s", string(body))
return &response, nil
}

return &response, nil
return nil, fmt.Errorf("investigate_repo failed after 3 retries: %w", lastErr)
}

func (a *RepoAgent) Run(ctx context.Context, input string) (string, error) {
Expand Down
36 changes: 0 additions & 36 deletions internal/http/task_executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,42 +21,6 @@ func ExecuteTask(taskID, projectDir, taskDesc string, taskManager *TaskManager,
return
}

// Initialize codebase in background
/**
* TODO: enable it after embed codebase binary.
*
go func() {
payload := map[string]string{"project_dir": projectDir}
jsonData, err := json.Marshal(payload)
if err != nil {
slog.Error("Failed to marshal codebase_init payload", "error", err)
return
}

req, err := http.NewRequest("POST", "http://127.0.0.1:12800/codebase_init", bytes.NewBuffer(jsonData))
if err != nil {
slog.Error("Failed to create codebase_init request", "error", err)
return
}
req.Header.Set("Content-Type", "application/json")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
slog.Error("Failed to send codebase_init request", "error", err)
return
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
slog.Error("codebase_init failed", "status_code", resp.StatusCode)
} else {
slog.Info("codebase_init request sent successfully", "project_dir", projectDir)
}
}()
*
*/

// 使用任务的可取消上下文
ctx := task.Context

Expand Down
Loading