feat: upgrade to core v0.8.0-alpha.1, replace banned stdlib imports
Some checks failed
Security Scan / security (push) Successful in 11s
Test / test (push) Failing after 1m56s

Replace fmt, log, path/filepath, encoding/json, core/log with Core
primitives across 3 files. Structured logging via core.Info/Warn/Error.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Claude 2026-03-26 14:21:16 +00:00
parent 0669feb69b
commit d5ea045431
No known key found for this signature in database
GPG key ID: AF404715446AEB41
6 changed files with 55 additions and 48 deletions

BIN
deps Executable file

Binary file not shown.

3
go.mod
View file

@ -3,6 +3,7 @@ module dappco.re/go/core/ide
go 1.26.0
require (
dappco.re/go/core v0.8.0-alpha.1
dappco.re/go/core/scm v0.4.0
forge.lthn.ai/core/api v0.1.5
forge.lthn.ai/core/config v0.1.8
@ -30,7 +31,7 @@ require (
require (
dappco.re/go/core/io v0.2.0 // indirect
dappco.re/go/core/log v0.1.0
dappco.re/go/core/log v0.1.0 // indirect
dario.cat/mergo v1.0.2 // indirect
forge.lthn.ai/core/go-ai v0.1.11 // indirect
forge.lthn.ai/core/go-io v0.1.7 // indirect

2
go.sum
View file

@ -1,3 +1,5 @@
dappco.re/go/core v0.8.0-alpha.1 h1:gj7+Scv+L63Z7wMxbJYHhaRFkHJo2u4MMPuUSv/Dhtk=
dappco.re/go/core v0.8.0-alpha.1/go.mod h1:f2/tBZ3+3IqDrg2F5F598llv0nmb/4gJVCFzM5geE4A=
dappco.re/go/core/io v0.2.0 h1:zuudgIiTsQQ5ipVt97saWdGLROovbEB/zdVyy9/l+I4=
dappco.re/go/core/io v0.2.0/go.mod h1:1QnQV6X9LNgFKfm8SkOtR9LLaj3bDcsOIeJOOyjbL5E=
dappco.re/go/core/log v0.1.0 h1:pa71Vq2TD2aoEUQWFKwNcaJ3GBY8HbaNGqtE688Unyc=

47
main.go
View file

@ -4,13 +4,13 @@ import (
"context"
"embed"
"io/fs"
"log"
"net/http"
"os"
"os/signal"
"runtime"
"syscall"
corelib "dappco.re/go/core"
"dappco.re/go/core/ide/icons"
"forge.lthn.ai/core/api"
"forge.lthn.ai/core/api/pkg/provider"
@ -45,7 +45,8 @@ func main() {
cwd, err := os.Getwd()
if err != nil {
log.Fatalf("failed to get working directory: %v", err)
corelib.Error("failed to get working directory", "err", err)
os.Exit(1)
}
// ── Shared resources (built before Core) ───────────────────
@ -103,13 +104,15 @@ func main() {
}),
)
if err != nil {
log.Fatalf("failed to create core: %v", err)
corelib.Error("failed to create core", "err", err)
os.Exit(1)
}
// Retrieve the MCP service for transport control
mcpSvc, err := core.ServiceFor[*mcp.Service](c, "mcp")
if err != nil {
log.Fatalf("failed to get MCP service: %v", err)
corelib.Error("failed to get MCP service", "err", err)
os.Exit(1)
}
// ── Mode selection ─────────────────────────────────────────
@ -120,25 +123,26 @@ func main() {
defer cancel()
if err := c.ServiceStartup(ctx, nil); err != nil {
log.Fatalf("core startup failed: %v", err)
corelib.Error("core startup failed", "err", err)
os.Exit(1)
}
bridge.Start(ctx)
go hub.Run(ctx)
// Start runtime providers
if err := rm.StartAll(ctx); err != nil {
log.Printf("runtime provider error: %v", err)
corelib.Warn("runtime provider error", "err", err)
}
// Start API server in background for provider endpoints
go func() {
if err := engine.Serve(ctx); err != nil {
log.Printf("API server error: %v", err)
corelib.Warn("API server error", "err", err)
}
}()
if err := mcpSvc.ServeStdio(ctx); err != nil {
log.Printf("MCP stdio error: %v", err)
corelib.Warn("MCP stdio error", "err", err)
}
rm.StopAll()
@ -154,27 +158,28 @@ func main() {
defer cancel()
if err := c.ServiceStartup(ctx, nil); err != nil {
log.Fatalf("core startup failed: %v", err)
corelib.Error("core startup failed", "err", err)
os.Exit(1)
}
bridge.Start(ctx)
go hub.Run(ctx)
// Start runtime providers
if err := rm.StartAll(ctx); err != nil {
log.Printf("runtime provider error: %v", err)
corelib.Warn("runtime provider error", "err", err)
}
// Start API server
go func() {
log.Printf("API server listening on %s", apiAddr)
corelib.Info("API server listening", "addr", apiAddr)
if err := engine.Serve(ctx); err != nil {
log.Printf("API server error: %v", err)
corelib.Warn("API server error", "err", err)
}
}()
go func() {
if err := mcpSvc.Run(ctx); err != nil {
log.Printf("MCP error: %v", err)
corelib.Warn("MCP error", "err", err)
}
}()
@ -189,7 +194,8 @@ func main() {
// ── GUI mode ───────────────────────────────────────────────
staticAssets, err := fs.Sub(assets, "frontend/dist/wails-angular-template/browser")
if err != nil {
log.Fatal(err)
corelib.Error("failed to load static assets", "err", err)
os.Exit(1)
}
app := application.New(application.Options{
@ -276,26 +282,27 @@ func main() {
// Start runtime providers
if err := rm.StartAll(ctx); err != nil {
log.Printf("runtime provider error: %v", err)
corelib.Warn("runtime provider error", "err", err)
}
// Start API server
go func() {
log.Printf("API server listening on %s", apiAddr)
corelib.Info("API server listening", "addr", apiAddr)
if err := engine.Serve(ctx); err != nil {
log.Printf("API server error: %v", err)
corelib.Warn("API server error", "err", err)
}
}()
if err := mcpSvc.Run(ctx); err != nil {
log.Printf("MCP error: %v", err)
corelib.Warn("MCP error", "err", err)
}
}()
log.Println("Starting Core IDE...")
corelib.Info("Starting Core IDE...")
if err := app.Run(); err != nil {
log.Fatal(err)
corelib.Error("application error", "err", err)
os.Exit(1)
}
}

View file

@ -1,11 +1,11 @@
package main
import (
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
corelib "dappco.re/go/core"
"dappco.re/go/core/scm/manifest"
"forge.lthn.ai/core/api/pkg/provider"
"github.com/gin-gonic/gin"
@ -41,8 +41,8 @@ func TestProvidersAPI_List_Good_Empty(t *testing.T) {
assert.Equal(t, http.StatusOK, w.Code)
var resp providersResponse
err := json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
r := corelib.JSONUnmarshal(w.Body.Bytes(), &resp)
require.True(t, r.OK)
assert.Empty(t, resp.Providers)
}
@ -77,8 +77,8 @@ func TestProvidersAPI_List_Good_WithRuntimeProviders(t *testing.T) {
assert.Equal(t, http.StatusOK, w.Code)
var resp providersResponse
err := json.Unmarshal(w.Body.Bytes(), &resp)
require.NoError(t, err)
r := corelib.JSONUnmarshal(w.Body.Bytes(), &resp)
require.True(t, r.OK)
require.Len(t, resp.Providers, 1)
assert.Equal(t, "test-provider", resp.Providers[0].Name)
assert.Equal(t, "test", resp.Providers[0].BasePath)

View file

@ -2,18 +2,15 @@ package main
import (
"context"
"fmt"
"log"
"net"
"net/http"
"os"
"os/exec"
"path/filepath"
"strconv"
"sync"
"time"
coreerr "dappco.re/go/core/log"
corelib "dappco.re/go/core"
"dappco.re/go/core/scm/manifest"
"dappco.re/go/core/scm/marketplace"
"forge.lthn.ai/core/api"
@ -51,7 +48,7 @@ func defaultProvidersDir() string {
if err != nil {
home = os.TempDir()
}
return filepath.Join(home, ".core", "providers")
return corelib.Path(home, ".core", "providers")
}
// StartAll discovers providers in ~/.core/providers/ and starts each one.
@ -64,24 +61,24 @@ func (rm *RuntimeManager) StartAll(ctx context.Context) error {
dir := defaultProvidersDir()
discovered, err := marketplace.DiscoverProviders(dir)
if err != nil {
return coreerr.E("runtime.StartAll", "discover providers", err)
return corelib.E("runtime.StartAll", "discover providers", err)
}
if len(discovered) == 0 {
log.Println("runtime: no providers found in", dir)
corelib.Info("runtime: no providers found", "dir", dir)
return nil
}
log.Printf("runtime: discovered %d provider(s) in %s", len(discovered), dir)
corelib.Info("runtime: discovered providers", "count", len(discovered), "dir", dir)
for _, dp := range discovered {
rp, err := rm.startProvider(ctx, dp)
if err != nil {
log.Printf("runtime: failed to start %s: %v", dp.Manifest.Code, err)
corelib.Warn("runtime: failed to start provider", "code", dp.Manifest.Code, "err", err)
continue
}
rm.providers = append(rm.providers, rp)
log.Printf("runtime: started %s on port %d", dp.Manifest.Code, rp.Port)
corelib.Info("runtime: started provider", "code", dp.Manifest.Code, "port", rp.Port)
}
return nil
@ -94,13 +91,13 @@ func (rm *RuntimeManager) startProvider(ctx context.Context, dp marketplace.Disc
// Assign a free port.
port, err := findFreePort()
if err != nil {
return nil, coreerr.E("runtime.startProvider", "find free port", err)
return nil, corelib.E("runtime.startProvider", "find free port", err)
}
// Resolve binary path.
binaryPath := m.Binary
if !filepath.IsAbs(binaryPath) {
binaryPath = filepath.Join(dp.Dir, binaryPath)
if !corelib.PathIsAbs(binaryPath) {
binaryPath = corelib.Path(dp.Dir, binaryPath)
}
// Build command args.
@ -115,22 +112,22 @@ func (rm *RuntimeManager) startProvider(ctx context.Context, dp marketplace.Disc
cmd.Stderr = os.Stderr
if err := cmd.Start(); err != nil {
return nil, coreerr.E("runtime.startProvider", fmt.Sprintf("start binary %s", binaryPath), err)
return nil, corelib.E("runtime.startProvider", corelib.Sprintf("start binary %s", binaryPath), err)
}
// Wait for health check.
healthURL := fmt.Sprintf("http://127.0.0.1:%d/health", port)
healthURL := corelib.Sprintf("http://127.0.0.1:%d/health", port)
if err := waitForHealth(healthURL, 10*time.Second); err != nil {
// Kill the process if health check fails.
_ = cmd.Process.Kill()
return nil, coreerr.E("runtime.startProvider", fmt.Sprintf("health check failed for %s", m.Code), err)
return nil, corelib.E("runtime.startProvider", corelib.Sprintf("health check failed for %s", m.Code), err)
}
// Register proxy provider.
cfg := provider.ProxyConfig{
Name: m.Code,
BasePath: m.Namespace,
Upstream: fmt.Sprintf("http://127.0.0.1:%d", port),
Upstream: corelib.Sprintf("http://127.0.0.1:%d", port),
}
if m.Element != nil {
cfg.Element = provider.ElementSpec{
@ -139,7 +136,7 @@ func (rm *RuntimeManager) startProvider(ctx context.Context, dp marketplace.Disc
}
}
if m.Spec != "" {
cfg.SpecFile = filepath.Join(dp.Dir, m.Spec)
cfg.SpecFile = corelib.Path(dp.Dir, m.Spec)
}
proxy := provider.NewProxy(cfg)
@ -147,7 +144,7 @@ func (rm *RuntimeManager) startProvider(ctx context.Context, dp marketplace.Disc
// Serve JS assets if the provider has an element source.
if m.Element != nil && m.Element.Source != "" {
assetsDir := filepath.Join(dp.Dir, "assets")
assetsDir := corelib.Path(dp.Dir, "assets")
if _, err := os.Stat(assetsDir); err == nil {
// Assets are served at /assets/{code}/
rm.engine.Register(&staticAssetGroup{
@ -175,7 +172,7 @@ func (rm *RuntimeManager) StopAll() {
for _, rp := range rm.providers {
if rp.Cmd != nil && rp.Cmd.Process != nil {
log.Printf("runtime: stopping %s (pid %d)", rp.Manifest.Code, rp.Cmd.Process.Pid)
corelib.Info("runtime: stopping provider", "code", rp.Manifest.Code, "pid", rp.Cmd.Process.Pid)
_ = rp.Cmd.Process.Signal(os.Interrupt)
// Give the process 5 seconds to exit gracefully.
@ -232,7 +229,7 @@ func findFreePort() (int, error) {
defer l.Close()
tcpAddr, ok := l.Addr().(*net.TCPAddr)
if !ok {
return 0, coreerr.E("runtime.findFreePort", "unexpected address type", nil)
return 0, corelib.E("runtime.findFreePort", "unexpected address type", nil)
}
return tcpAddr.Port, nil
}
@ -253,7 +250,7 @@ func waitForHealth(url string, timeout time.Duration) error {
time.Sleep(100 * time.Millisecond)
}
return coreerr.E("runtime.waitForHealth", fmt.Sprintf("timed out after %s: %s", timeout, url), nil)
return corelib.E("runtime.waitForHealth", corelib.Sprintf("timed out after %s: %s", timeout, url), nil)
}
// staticAssetGroup is a simple RouteGroup that serves static files.