mirror of
https://github.com/sipeed/picoclaw.git
synced 2026-06-12 18:08:54 +00:00
feat(config): wire serial tool into runtime and dashboard
This commit is contained in:
@@ -171,6 +171,12 @@ var toolCatalog = []toolCatalogEntry{
|
||||
Category: "hardware",
|
||||
ConfigKey: "spi",
|
||||
},
|
||||
{
|
||||
Name: "serial",
|
||||
Description: "Interact with serial ports exposed on the host.",
|
||||
Category: "hardware",
|
||||
ConfigKey: "serial",
|
||||
},
|
||||
{
|
||||
Name: "tool_search_tool_regex",
|
||||
Description: "Discover hidden MCP tools by regex search when tool discovery is enabled.",
|
||||
@@ -265,6 +271,8 @@ func buildToolSupport(cfg *config.Config) []toolSupportItem {
|
||||
status, reasonCode = resolveWebSearchToolSupport(cfg)
|
||||
case "i2c", "spi":
|
||||
status, reasonCode = resolveHardwareToolSupport(cfg.Tools.IsToolEnabled(entry.ConfigKey))
|
||||
case "serial":
|
||||
status, reasonCode = resolveSerialToolSupport(cfg.Tools.IsToolEnabled(entry.ConfigKey))
|
||||
default:
|
||||
if cfg.Tools.IsToolEnabled(entry.ConfigKey) {
|
||||
status = "enabled"
|
||||
@@ -293,6 +301,18 @@ func resolveHardwareToolSupport(enabled bool) (string, string) {
|
||||
return "enabled", ""
|
||||
}
|
||||
|
||||
func resolveSerialToolSupport(enabled bool) (string, string) {
|
||||
if !enabled {
|
||||
return "disabled", ""
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
case "linux", "darwin", "windows":
|
||||
return "enabled", ""
|
||||
default:
|
||||
return "blocked", "requires_serial_platform"
|
||||
}
|
||||
}
|
||||
|
||||
func resolveDiscoveryToolSupport(cfg *config.Config, methodEnabled bool) (string, string) {
|
||||
if !cfg.Tools.IsToolEnabled("mcp") {
|
||||
return "disabled", ""
|
||||
@@ -362,6 +382,8 @@ func applyToolState(cfg *config.Config, toolName string, enabled bool) error {
|
||||
cfg.Tools.I2C.Enabled = enabled
|
||||
case "spi":
|
||||
cfg.Tools.SPI.Enabled = enabled
|
||||
case "serial":
|
||||
cfg.Tools.Serial.Enabled = enabled
|
||||
case "tool_search_tool_regex":
|
||||
cfg.Tools.MCP.Discovery.UseRegex = enabled
|
||||
if enabled {
|
||||
|
||||
@@ -92,9 +92,36 @@ func TestHandleListTools(t *testing.T) {
|
||||
if gotTools["i2c"].Status != "disabled" {
|
||||
t.Fatalf("i2c status = %q, want disabled on linux when config is off", gotTools["i2c"].Status)
|
||||
}
|
||||
if gotTools["serial"].Status != "disabled" {
|
||||
t.Fatalf("serial status = %q, want disabled when config is off", gotTools["serial"].Status)
|
||||
}
|
||||
|
||||
cfg.Tools.Serial.Enabled = true
|
||||
if err := config.SaveConfig(configPath, cfg); err != nil {
|
||||
t.Fatalf("SaveConfig() error = %v", err)
|
||||
}
|
||||
|
||||
rec = httptest.NewRecorder()
|
||||
req = httptest.NewRequest(http.MethodGet, "/api/tools", nil)
|
||||
mux.ServeHTTP(rec, req)
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("status = %d, want %d, body=%s", rec.Code, http.StatusOK, rec.Body.String())
|
||||
}
|
||||
|
||||
if err := json.Unmarshal(rec.Body.Bytes(), &resp); err != nil {
|
||||
t.Fatalf("Unmarshal() error = %v", err)
|
||||
}
|
||||
gotTools = make(map[string]toolSupportItem, len(resp.Tools))
|
||||
for _, tool := range resp.Tools {
|
||||
gotTools[tool.Name] = tool
|
||||
}
|
||||
if gotTools["serial"].Status != "enabled" {
|
||||
t.Fatalf("serial = %#v, want enabled on linux when config is on", gotTools["serial"])
|
||||
}
|
||||
} else {
|
||||
cfg.Tools.I2C.Enabled = true
|
||||
cfg.Tools.SPI.Enabled = true
|
||||
cfg.Tools.Serial.Enabled = true
|
||||
if err := config.SaveConfig(configPath, cfg); err != nil {
|
||||
t.Fatalf("SaveConfig() error = %v", err)
|
||||
}
|
||||
@@ -120,6 +147,16 @@ func TestHandleListTools(t *testing.T) {
|
||||
if gotTools["spi"].Status != "blocked" || gotTools["spi"].ReasonCode != "requires_linux" {
|
||||
t.Fatalf("spi = %#v, want blocked/requires_linux", gotTools["spi"])
|
||||
}
|
||||
switch runtime.GOOS {
|
||||
case "darwin", "windows":
|
||||
if gotTools["serial"].Status != "enabled" {
|
||||
t.Fatalf("serial = %#v, want enabled on supported host", gotTools["serial"])
|
||||
}
|
||||
default:
|
||||
if gotTools["serial"].Status != "blocked" || gotTools["serial"].ReasonCode != "requires_serial_platform" {
|
||||
t.Fatalf("serial = %#v, want blocked/requires_serial_platform", gotTools["serial"])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,6 +232,26 @@ func TestHandleUpdateToolState(t *testing.T) {
|
||||
if !updated.Tools.Cron.Enabled {
|
||||
t.Fatalf("cron should be enabled: %#v", updated.Tools.Cron)
|
||||
}
|
||||
|
||||
rec4 := httptest.NewRecorder()
|
||||
req4 := httptest.NewRequest(
|
||||
http.MethodPut,
|
||||
"/api/tools/serial/state",
|
||||
bytes.NewBufferString(`{"enabled":true}`),
|
||||
)
|
||||
req4.Header.Set("Content-Type", "application/json")
|
||||
mux.ServeHTTP(rec4, req4)
|
||||
if rec4.Code != http.StatusOK {
|
||||
t.Fatalf("serial status = %d, want %d, body=%s", rec4.Code, http.StatusOK, rec4.Body.String())
|
||||
}
|
||||
|
||||
updated, err = config.LoadConfig(configPath)
|
||||
if err != nil {
|
||||
t.Fatalf("LoadConfig(updated serial) error = %v", err)
|
||||
}
|
||||
if !updated.Tools.Serial.Enabled {
|
||||
t.Fatalf("serial should be enabled: %#v", updated.Tools.Serial)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHandleListTools_ReportsWebSearchEnabledWhenToolIsOn(t *testing.T) {
|
||||
|
||||
Reference in New Issue
Block a user