Skip to content

Commit aaa37ff

Browse files
committed
fix(skillmgr): use built sin-websearch binary from SIN_SKILLS_DIR
The registry used the bare command name 'sin-websearch', which only works if the user manually puts the binary on PATH. Now the registry checks SIN_SKILLS_DIR/web_search_bundle/sin-websearch first and falls back to PATH. The skill manager also builds the binary explicitly into the repo root with -o sin-websearch so the registry can find it. Adds tests for both the local-binary and PATH-fallback cases.
1 parent de69038 commit aaa37ff

3 files changed

Lines changed: 72 additions & 3 deletions

File tree

‎cmd/sin-code/internal/mcpclient/registry.go‎

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,28 @@ func DefaultServers() []ServerConfig {
2626
}
2727
return cfg
2828
}
29+
// goNative returns a ServerConfig for a Go-native skill. It prefers the
30+
// binary built inside SIN_SKILLS_DIR/<repo>/sin-websearch so that skillmgr
31+
// can install and run the skill without requiring the user to put the binary
32+
// on PATH. Falls back to the binary name on PATH if no local checkout exists.
33+
goNative := func(repo, binary string, args ...string) ServerConfig {
34+
name := shortName(repo)
35+
cfg := ServerConfig{Name: name, Transport: "stdio", Args: args}
36+
if skillsDir != "" {
37+
localBin := filepath.Join(skillsDir, repo, binary)
38+
if _, err := os.Stat(localBin); err == nil {
39+
cfg.Command = localBin
40+
} else {
41+
cfg.Command = binary
42+
}
43+
} else {
44+
cfg.Command = binary
45+
}
46+
return cfg
47+
}
2948
return []ServerConfig{
3049
// web_search_bundle is the Go-native successor to SIN-Code-Websearch-Skill.
31-
{Name: "websearch", Transport: "stdio", Command: "sin-websearch", Args: []string{"serve"}},
50+
goNative("web_search_bundle", "sin-websearch", "serve"),
3251
py("SIN-Code-Scheduler-Skill"),
3352
py("SIN-Code-Goal-Mode-Skill"),
3453
py("SIN-Code-Grill-Me-Skill"),
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// SPDX-License-Identifier: MIT
2+
// Purpose: tests for the built-in ecosystem registry in mcpclient.
3+
package mcpclient
4+
5+
import (
6+
"os"
7+
"path/filepath"
8+
"testing"
9+
)
10+
11+
func TestDefaultServersWebsearchUsesLocalBinaryWhenPresent(t *testing.T) {
12+
dir := t.TempDir()
13+
bin := filepath.Join(dir, "web_search_bundle", "sin-websearch")
14+
if err := os.MkdirAll(filepath.Dir(bin), 0o755); err != nil {
15+
t.Fatal(err)
16+
}
17+
if err := os.WriteFile(bin, []byte("#!/bin/sh\necho fake"), 0o755); err != nil {
18+
t.Fatal(err)
19+
}
20+
21+
t.Setenv("SIN_SKILLS_DIR", dir)
22+
for _, s := range DefaultServers() {
23+
if s.Name != "websearch" {
24+
continue
25+
}
26+
if s.Command != bin {
27+
t.Fatalf("websearch command should use local binary %q, got %q", bin, s.Command)
28+
}
29+
if len(s.Args) != 1 || s.Args[0] != "serve" {
30+
t.Fatalf("websearch args should be [serve], got %v", s.Args)
31+
}
32+
return
33+
}
34+
t.Fatal("websearch server not found in DefaultServers")
35+
}
36+
37+
func TestDefaultServersWebsearchFallsBackToPathBinary(t *testing.T) {
38+
t.Setenv("SIN_SKILLS_DIR", "")
39+
for _, s := range DefaultServers() {
40+
if s.Name != "websearch" {
41+
continue
42+
}
43+
if s.Command != "sin-websearch" {
44+
t.Fatalf("websearch command should fall back to %q, got %q", "sin-websearch", s.Command)
45+
}
46+
return
47+
}
48+
t.Fatal("websearch server not found in DefaultServers")
49+
}

‎cmd/sin-code/internal/skillmgr/manager.go‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,9 @@ func verifyEntrypoint(ctx context.Context, dir string) (bool, string) {
125125
return true, "node entrypoint (package.json)"
126126
}
127127
if _, err := os.Stat(filepath.Join(dir, "go.mod")); err == nil {
128-
// Go-native skill: verify it compiles.
129-
cmd := exec.CommandContext(ctx, "go", "build", "./cmd/sin-websearch")
128+
// Go-native skill: build the binary into the repo root so the MCP
129+
// registry can use the full path (SIN_SKILLS_DIR/<repo>/<binary>).
130+
cmd := exec.CommandContext(ctx, "go", "build", "-o", "sin-websearch", "./cmd/sin-websearch")
130131
cmd.Dir = dir
131132
if _, err := cmd.CombinedOutput(); err != nil {
132133
return false, fmt.Sprintf("go entrypoint exists but build failed: %v", err)

0 commit comments

Comments
 (0)