Skip to content

Commit bf808ac

Browse files
author
razvan
committed
fix: resolve PR #36 Copilot review comments (19/24 fixed)
Documentation fixes: - README.md: Go version badge 1.25+ → 1.24.4+ to match go.mod - internal/service/tools/README.md: corrected filenames in tool table and package tree (update_tools.go → updates.go, agent_skills.go → skills.go) - internal/updater/README.md: sha256sums.txt → checksums.txt, removed non-existent info.UpdateAvailable field from example code - docs/headless-usage.md: rewritten to match current implementation — SSE/session endpoints → stateless /mcp, --port → --http-port, ragcode-sse skill → ragcode-http Code fixes: - pkg/telemetry/metrics_reader.go: increased scanner buffer to 1MB for long JSONL lines, added explicit HybridSearches counter (was incorrectly counted as VectorSearches) - smart_search_pipeline.go: normalizeInput now clamps min_score to [0.0, 1.0] range, buildFallbackNote no longer emits empty 'Progress: .' when all languages have TotalFiles==0, restored SessionMetrics population in buildResponseMeta via telemetry.ReadAggregatedMetrics Deferred (4 items for separate PRs): - existingCollections edge case in engine fan-out - lazy embed optimization for unindexed workspaces - reportLang/reportColl accuracy for polyglot workspaces - score filter unit test coverage
1 parent 190ed5c commit bf808ac

6 files changed

Lines changed: 57 additions & 51 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
<div align="center">
66

77
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](./LICENSE)
8-
[![Go Version](https://img.shields.io/badge/Go-1.25%2B-blue)](https://go.dev/)
8+
[![Go Version](https://img.shields.io/badge/Go-1.24.4%2B-blue)](https://go.dev/)
99
[![MCP](https://img.shields.io/badge/MCP-Compatible-green)](https://modelcontextprotocol.io)
1010
![AI Ready](https://img.shields.io/badge/Codebase-AI%20Ready-blueviolet)
1111

docs/headless-usage.md

Lines changed: 13 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,29 @@
1-
# Headless Usage (HTTP & SSE)
1+
# Headless Usage (Streamable HTTP)
22

33
RagCode MCP is primarily an MCP Server designed to be invoked via `stdio` by conforming clients (like Cursor, Windsurf, Claude Desktop). However, the architecture is **Protocol Agnostic**, allowing it to be used "headlessly" without IDE integration.
44

55
This is especially useful for purely autonomous AI agents (like Antigravity scripts, custom Python bots, or CI/CD integrations) that need to issue JSON-RPC queries to the engine over TCP instead of standard I/O pipes.
66

7-
## SSE (Server-Sent Events) Mode
7+
## Streamable HTTP Mode
88

9-
RagCode features a subpackage `internal/daemon/` which can spawn an SSE HTTP server that perfectly conforms to the MCP standard over HTTP GET/POST.
9+
RagCode features a subpackage `internal/daemon/` which spawns a stateless Streamable HTTP handler that conforms to the MCP standard.
1010

1111
To start the daemon:
1212

1313
```bash
14-
rag-code-mcp --port 8080
14+
rag-code-mcp --http-port 8080
1515
```
1616

1717
When the server starts successfully, it will print:
18-
`[INFO] SSE MCP server listening on :8080`
18+
`[INFO] HTTP MCP server listening on :8080`
1919

2020
### Example Integration (Using cURL or HTTP Agents)
2121

22-
Once the daemon is active, your AI Script can connect to it using standard MCP-over-SSE endpoints:
22+
Once the daemon is active, your AI Script can send standard MCP JSON-RPC requests directly to the `/mcp` endpoint:
2323

24-
**1. Establish an SSE Session (GET)**
24+
**Send an MCP Command (POST)**
2525
```bash
26-
curl -N http://localhost:8080/sse
27-
```
28-
*This endpoint yields events and is intended to be kept alive. It will return a URI specifying the exact Session ID endpoint where you must send queries.*
29-
30-
**2. Send an MCP Command (POST)**
31-
Suppose the SSE terminal returned `Endpoint: /message?sessionId=123`.
32-
33-
```bash
34-
curl -X POST http://localhost:8080/message?sessionId=123 \
26+
curl -X POST http://localhost:8080/mcp \
3527
-H "Content-Type: application/json" \
3628
-d '{
3729
"jsonrpc": "2.0",
@@ -47,16 +39,16 @@ curl -X POST http://localhost:8080/message?sessionId=123 \
4739
}'
4840
```
4941

50-
The response will be sent via JSON-RPC 2.0 back on the open `/sse` channel you hold.
42+
The response will be returned as a standard JSON-RPC 2.0 response in the HTTP body.
5143

52-
## "The `ragcode-sse` Skill" Integration
44+
## "The `ragcode-http` Skill" Integration
5345

54-
For agents that do not inherently support SSE/MCP natively in their prompt cycle, developers can push the officially provided `ragcode-sse` agent skill.
46+
For agents that do not inherently support MCP natively in their prompt cycle, developers can push the officially provided `ragcode-http` agent skill.
5547

56-
This skill injects bash commands that wrap `curl` payloads, allowing the agent to perform raw POST/GET queries seamlessly, extracting context from large workspaces directly into standard markdown without installing a Desktop IDE.
48+
This skill injects bash commands that wrap `curl` payloads, allowing the agent to perform raw POST queries seamlessly, extracting context from large workspaces directly into standard markdown without installing a Desktop IDE.
5749

5850
1. Agent discovers skill via `rag_list_skills`.
59-
2. Agent runs `rag_install_skill {"skill_id": "ragcode-sse", "target": "agent"}`.
51+
2. Agent runs `rag_install_skill {"skill_id": "ragcode-http", "target": "agent"}`.
6052
3. The agent reads `SKILL.md` to learn how to frame HTTP POST queries toward port `8080`.
6153

6254
**Note on Workspace Context:** Always ensure the script explicitly sends `"file_path": "/absolute/path/to/project/file.ext"` inside the arguments payload. Without an IDE, RagCode completely relies on `file_path` to map the workspace identity correctly.

internal/service/tools/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@ Implementation of the MCP tools exposed by the RagCode AI assistants server.
1717
| `rag_read_file_context` | `read_file_context.go` | [doc_read_file_context.md](/docs/tools/doc_read_file_context.md) |
1818
| `rag_index_workspace` | `index_workspace.go` | [doc_index_workspace.md](/docs/tools/doc_index_workspace.md) |
1919
| `rag_evaluate` | `evaluate_ragcode.go` | [doc_evaluate_ragcode.md](/docs/tools/doc_evaluate_ragcode.md) |
20-
| `rag_check_update` | `update_tools.go` | [doc_updates.md](/docs/tools/doc_updates.md) |
21-
| `rag_apply_update` | `update_tools.go` | [doc_updates.md](/docs/tools/doc_updates.md) |
22-
| `rag_list_skills` | `agent_skills.go` | (none) |
23-
| `rag_install_skill` | `agent_skills.go` | (none) |
20+
| `rag_check_update` | `updates.go` | [doc_updates.md](/docs/tools/doc_updates.md) |
21+
| `rag_apply_update` | `updates.go` | [doc_updates.md](/docs/tools/doc_updates.md) |
22+
| `rag_list_skills` | `skills.go` | (none) |
23+
| `rag_install_skill` | `skills.go` | (none) |
2424

2525
---
2626

@@ -39,8 +39,8 @@ internal/service/tools/
3939
├── read_file_context.go
4040
├── index_workspace.go
4141
├── evaluate_ragcode.go
42-
├── update_tools.go # Check and apply updates tools
43-
├── agent_skills.go # List and install skills tools
42+
├── updates.go # Check and apply updates tools
43+
├── skills.go # List and install skills tools
4444
├── healthcheck.go
4545
├── response.go # ToolResponse, ContextMetadata, JSON helpers
4646
└── README.md

internal/service/tools/smart_search_pipeline.go

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,12 @@ func normalizeInput(input SmartSearchInput, defaultLimit int) (string, int, Smar
2929
if input.Mode == "strict_docs" {
3030
input.IncludeDocs = true
3131
}
32+
// Clamp min_score to valid range [0.0, 1.0]
33+
if input.MinScore < 0 {
34+
input.MinScore = 0
35+
} else if input.MinScore > 1.0 {
36+
input.MinScore = 1.0
37+
}
3238
return query, limit, input, nil
3339
}
3440

@@ -212,6 +218,7 @@ func (t *SmartSearchTool) buildResponseMeta(meta searchMetadata) ToolResponse {
212218
Language: meta.language,
213219
Collection: meta.collection,
214220
IndexingProgress: idxProgress,
221+
SessionMetrics: telemetry.ReadAggregatedMetrics(meta.workspaceRoot),
215222
},
216223
}
217224

@@ -257,23 +264,23 @@ func buildFallbackNote(progress *IndexingProgressSummary) string {
257264
// Report per-language progress and collect fully-indexed langs
258265
var readyLangs []string
259266
if progress != nil && len(progress.Languages) > 0 {
260-
sb.WriteString("Progress: ")
261-
first := true
267+
var langParts []string
262268
for lang, lp := range progress.Languages {
263269
if lp.TotalFiles == 0 {
264270
continue
265271
}
266-
if !first {
267-
sb.WriteString(" · ")
268-
}
269-
sb.WriteString(fmt.Sprintf("%s %d%%", lang, lp.Percent))
272+
entry := fmt.Sprintf("%s %d%%", lang, lp.Percent)
270273
if lp.Percent == 100 {
271-
sb.WriteString(" ✓")
274+
entry += " ✓"
272275
readyLangs = append(readyLangs, lang)
273276
}
274-
first = false
277+
langParts = append(langParts, entry)
278+
}
279+
if len(langParts) > 0 {
280+
sb.WriteString("Progress: ")
281+
sb.WriteString(strings.Join(langParts, " · "))
282+
sb.WriteString(". ")
275283
}
276-
sb.WriteString(". ")
277284
}
278285

279286
// Actionable hint: tell agent which langs can use vector search now

internal/updater/README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ if err != nil {
2222
// Handle error
2323
}
2424

25-
if info != nil && info.UpdateAvailable {
26-
// Perform update and verification
25+
if info != nil {
26+
// Non-nil info means an update is available
2727
err := updater.DownloadVerifyAndApply(ctx, info)
2828
if err != nil {
2929
// Handle error
@@ -33,5 +33,5 @@ if info != nil && info.UpdateAvailable {
3333

3434
## Safety Considerations
3535

36-
- **Verification**: Updates are cryptographically verified using `sha256sums.txt` included in releases.
36+
- **Verification**: Updates are cryptographically verified using `checksums.txt` included in releases.
3737
- **Rollback**: Updates happen via binary replacement; if the process fails mid-way, the original executable is restored from a temporary backup.

pkg/telemetry/metrics_reader.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@ import (
99

1010
// AggregatedMetrics holds cumulative statistics from search_metrics.jsonl.
1111
type AggregatedMetrics struct {
12-
TotalSearches int `json:"total_searches"`
13-
SearchesWithResults int `json:"searches_with_results"`
14-
FallbackSearches int `json:"fallback_searches"`
15-
VectorSearches int `json:"vector_searches"`
16-
AvgTopScore float32 `json:"avg_top_score"`
17-
TotalBytesSaved int64 `json:"total_bytes_saved"`
18-
TotalTokensSaved int64 `json:"total_tokens_saved"`
19-
AvgResponseMs int64 `json:"avg_response_ms"`
12+
TotalSearches int `json:"total_searches"`
13+
SearchesWithResults int `json:"searches_with_results"`
14+
FallbackSearches int `json:"fallback_searches"`
15+
VectorSearches int `json:"vector_searches"`
16+
HybridSearches int `json:"hybrid_searches"`
17+
AvgTopScore float32 `json:"avg_top_score"`
18+
TotalBytesSaved int64 `json:"total_bytes_saved"`
19+
TotalTokensSaved int64 `json:"total_tokens_saved"`
20+
AvgResponseMs int64 `json:"avg_response_ms"`
2021
}
2122

2223
// ReadAggregatedMetrics reads and aggregates all metrics from the JSONL file.
23-
// Returns nil if no metrics file exists.
24+
// Returns nil if no metrics file exists or on read errors.
2425
func ReadAggregatedMetrics(workspaceRoot string) *AggregatedMetrics {
2526
if workspaceRoot == "" {
2627
return nil
@@ -37,6 +38,9 @@ func ReadAggregatedMetrics(workspaceRoot string) *AggregatedMetrics {
3738
var msSum int64
3839

3940
scanner := bufio.NewScanner(f)
41+
// Increase buffer to 1MB to handle long JSONL lines (large query strings, etc.)
42+
scanner.Buffer(make([]byte, 0, 64*1024), 1024*1024)
43+
4044
for scanner.Scan() {
4145
var m SearchMetric
4246
if json.Unmarshal(scanner.Bytes(), &m) != nil {
@@ -46,9 +50,12 @@ func ReadAggregatedMetrics(workspaceRoot string) *AggregatedMetrics {
4650
if m.ResultCount > 0 {
4751
agg.SearchesWithResults++
4852
}
49-
if m.Source == "fallback" {
53+
switch m.Source {
54+
case "fallback":
5055
agg.FallbackSearches++
51-
} else {
56+
case "hybrid":
57+
agg.HybridSearches++
58+
default:
5259
agg.VectorSearches++
5360
}
5461
scoreSum += m.TopScore

0 commit comments

Comments
 (0)