From 4375919ca3cf44fc6877cd807fc99c98f78584c2 Mon Sep 17 00:00:00 2001 From: Snider Date: Sat, 14 Mar 2026 09:47:59 +0000 Subject: [PATCH] feat: wire service provider framework into IDE Adds provider registry and API engine to all three modes (MCP-only, headless, GUI). Registers process and brain providers, starts the API server on :9880 (configurable via CORE_API_ADDR), and runs the WS hub for real-time event streaming. go-api and go-process promoted to direct dependencies. Co-Authored-By: Virgil --- go.mod | 9 +++++---- go.sum | 7 +++---- main.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index 6e91187..c995b8a 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,9 @@ go 1.26.0 require ( forge.lthn.ai/core/go v0.2.2 + forge.lthn.ai/core/go-api v0.1.0 forge.lthn.ai/core/go-config v0.1.2 + forge.lthn.ai/core/go-process v0.1.0 forge.lthn.ai/core/go-ws v0.1.3 forge.lthn.ai/core/gui v0.0.0 forge.lthn.ai/core/mcp v0.0.0 @@ -14,13 +16,11 @@ require ( require ( dario.cat/mergo v1.0.2 // indirect forge.lthn.ai/core/go-ai v0.1.5 // indirect - forge.lthn.ai/core/go-api v0.1.0 // indirect forge.lthn.ai/core/go-inference v0.1.0 // indirect forge.lthn.ai/core/go-io v0.0.5 // indirect forge.lthn.ai/core/go-log v0.0.1 // indirect forge.lthn.ai/core/go-ml v0.1.0 // indirect forge.lthn.ai/core/go-mlx v0.1.0 // indirect - forge.lthn.ai/core/go-process v0.1.0 // indirect forge.lthn.ai/core/go-rag v0.1.0 // indirect forge.lthn.ai/core/go-webview v0.1.2 // indirect github.com/99designs/gqlgen v0.17.87 // indirect @@ -64,7 +64,7 @@ require ( github.com/gin-contrib/sse v1.1.0 // indirect github.com/gin-contrib/static v1.1.5 // indirect github.com/gin-contrib/timeout v1.1.0 // indirect - github.com/gin-gonic/gin v1.11.0 // indirect + github.com/gin-gonic/gin v1.12.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect github.com/go-git/go-billy/v5 v5.7.0 // indirect github.com/go-git/go-git/v5 v5.16.4 // indirect @@ -152,6 +152,7 @@ require ( github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect github.com/zeebo/xxh3 v1.1.0 // indirect + go.mongodb.org/mongo-driver/v2 v2.5.0 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.65.0 // indirect go.opentelemetry.io/otel v1.40.0 // indirect @@ -164,7 +165,7 @@ require ( golang.org/x/crypto v0.48.0 // indirect golang.org/x/exp v0.0.0-20260218203240-3dfff04db8fa // indirect golang.org/x/mod v0.33.0 // indirect - golang.org/x/net v0.50.0 // indirect + golang.org/x/net v0.51.0 // indirect golang.org/x/oauth2 v0.35.0 // indirect golang.org/x/sync v0.19.0 // indirect golang.org/x/sys v0.41.0 // indirect diff --git a/go.sum b/go.sum index 1565400..a833cfb 100644 --- a/go.sum +++ b/go.sum @@ -145,8 +145,7 @@ github.com/gin-contrib/static v1.1.5 h1:bAPqT4KTZN+4uDY1b90eSrD1t8iNzod7Jj8njwmn github.com/gin-contrib/static v1.1.5/go.mod h1:8JSEXwZHcQ0uCrLPcsvnAJ4g+ODxeupP8Zetl9fd8wM= github.com/gin-contrib/timeout v1.1.0 h1:WAmWseo5gfBUbMrMJu5hJxDclehfSJUmK2wGwCC/EFw= github.com/gin-contrib/timeout v1.1.0/go.mod h1:NpRo4gd1Ad8ZQ4T6bQLVFDqiplCmPRs2nvfckxS2Fw4= -github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= -github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= +github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8= github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= @@ -398,6 +397,7 @@ github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs= github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s= +go.mongodb.org/mongo-driver/v2 v2.5.0 h1:yXUhImUjjAInNcpTcAlPHiT7bIXhshCTL3jVBkF3xaE= go.opentelemetry.io/auto/sdk v1.2.1 h1:jXsnJ4Lmnqd11kwkBV2LgLoFMZKizbCi5fNZ/ipaZ64= go.opentelemetry.io/auto/sdk v1.2.1/go.mod h1:KRTj+aOaElaLi+wW1kO/DZRXwkF4C5xPbEe3ZiIhN7Y= go.opentelemetry.io/contrib/instrumentation/github.com/gin-gonic/gin/otelgin v0.65.0 h1:LSJsvNqhj2sBNFb5NWHbyDK4QJ/skQ2ydjeOZ9OYNZ4= @@ -442,8 +442,7 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.50.0 h1:ucWh9eiCGyDR3vtzso0WMQinm2Dnt8cFMuQa9K33J60= -golang.org/x/net v0.50.0/go.mod h1:UgoSli3F/pBgdJBHCTc+tp3gmrU4XswgGRgtnwWTfyM= +golang.org/x/net v0.51.0 h1:94R/GTO7mt3/4wIKpcR5gkGmRLOuE/2hNGeWq/GBIFo= golang.org/x/oauth2 v0.35.0 h1:Mv2mzuHuZuY2+bkyWXIHMfhNdJAdwW3FuWeCPYN5GVQ= golang.org/x/oauth2 v0.35.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/main.go b/main.go index 81804bd..d7ccc43 100644 --- a/main.go +++ b/main.go @@ -5,12 +5,17 @@ import ( "embed" "io/fs" "log" + "net/http" "os" "os/signal" "runtime" "syscall" + "forge.lthn.ai/core/go-api" + "forge.lthn.ai/core/go-api/pkg/provider" "forge.lthn.ai/core/go-config" + process "forge.lthn.ai/core/go-process" + processapi "forge.lthn.ai/core/go-process/pkg/api" "forge.lthn.ai/core/go-ws" "forge.lthn.ai/core/go/pkg/core" guiMCP "forge.lthn.ai/core/gui/pkg/mcp" @@ -55,6 +60,24 @@ func main() { } bridge := ide.NewBridge(hub, bridgeCfg) + // ── Service Provider Registry ────────────────────────────── + reg := provider.NewRegistry() + reg.Add(processapi.NewProvider(process.DefaultRegistry(), hub)) + reg.Add(brain.NewProvider(bridge, hub)) + + // ── API Engine ───────────────────────────────────────────── + apiAddr := ":9880" + if addr := os.Getenv("CORE_API_ADDR"); addr != "" { + apiAddr = addr + } + engine, _ := api.New( + api.WithAddr(apiAddr), + api.WithCORS("*"), + api.WithWSHandler(http.Handler(hub.Handler())), + api.WithSwagger("Core IDE", "Service Provider API", "0.1.0"), + ) + reg.MountAll(engine) + // ── Core framework ───────────────────────────────────────── c, err := core.New( core.WithName("ws", func(c *core.Core) (any, error) { @@ -87,11 +110,18 @@ func main() { syscall.SIGINT, syscall.SIGTERM) defer cancel() - // Start Core lifecycle manually if err := c.ServiceStartup(ctx, nil); err != nil { log.Fatalf("core startup failed: %v", err) } bridge.Start(ctx) + go hub.Run(ctx) + + // Start API server in background for provider endpoints + go func() { + if err := engine.Serve(ctx); err != nil { + log.Printf("API server error: %v", err) + } + }() if err := mcpSvc.ServeStdio(ctx); err != nil { log.Printf("MCP stdio error: %v", err) @@ -112,6 +142,15 @@ func main() { log.Fatalf("core startup failed: %v", err) } bridge.Start(ctx) + go hub.Run(ctx) + + // Start API server + go func() { + log.Printf("API server listening on %s", apiAddr) + if err := engine.Serve(ctx); err != nil { + log.Printf("API server error: %v", err) + } + }() go func() { if err := mcpSvc.Run(ctx); err != nil { @@ -182,10 +221,20 @@ func main() { }) systray.SetMenu(trayMenu) - // Start MCP transport alongside Wails + // Start MCP transport and API server alongside Wails go func() { ctx := context.Background() bridge.Start(ctx) + go hub.Run(ctx) + + // Start API server + go func() { + log.Printf("API server listening on %s", apiAddr) + if err := engine.Serve(ctx); err != nil { + log.Printf("API server error: %v", err) + } + }() + if err := mcpSvc.Run(ctx); err != nil { log.Printf("MCP error: %v", err) }