feat(cli): migrate imports to split repos + wire go-agentic registry
Some checks are pending
Security Scan / Go Vulnerability Check (push) Waiting to run
Security Scan / Secret Detection (push) Waiting to run
Security Scan / Dependency & Config Scan (push) Waiting to run

Virgil split go-ai into standalone modules (go-agentic, go-ml, go-mlx,
go-rag). This migrates all CLI imports to the new module paths and fixes
API mismatches from the split.

Key changes:
- go-ai/agentic → go-agentic (cmd/ai, cmd/dev)
- go-ai/ml → go-ml (31 files in cmd/ml)
- go-ai/rag → go-rag (3 files in cmd/rag)
- go-ai/mlx → go-mlx (1 file)
- Fix go.work path (../core → ../go)
- Add all split repos to go.work and go.mod
- Simplify daemon to goroutine-based MCP (remove missing supervisor)
- Wire go-agentic SQLiteRegistry into dispatch watch (--agent-id flag)
- Add `core ai agent fleet` command for local registry status
- Fix rag collections API (PointCount, Status string)
- Fix ml live/expand-status to use available go-ml API

Co-Authored-By: Charon <charon@lethean.io>
This commit is contained in:
Claude 2026-02-20 12:47:02 +00:00
parent 41f786a222
commit a43cc099cd
No known key found for this signature in database
GPG key ID: AF404715446AEB41
45 changed files with 307 additions and 120 deletions

View file

@ -6,7 +6,9 @@ import (
"os/exec"
"path/filepath"
"strings"
"time"
agentic "forge.lthn.ai/core/go-agentic"
"forge.lthn.ai/core/go-scm/agentci"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go/pkg/config"
@ -25,6 +27,7 @@ func AddAgentCommands(parent *cli.Command) {
agentCmd.AddCommand(agentLogsCmd())
agentCmd.AddCommand(agentSetupCmd())
agentCmd.AddCommand(agentRemoveCmd())
agentCmd.AddCommand(agentFleetCmd())
parent.AddCommand(agentCmd)
}
@ -321,6 +324,76 @@ func agentRemoveCmd() *cli.Command {
}
}
func agentFleetCmd() *cli.Command {
cmd := &cli.Command{
Use: "fleet",
Short: "Show fleet status from the go-agentic registry",
RunE: func(cmd *cli.Command, args []string) error {
workDir, _ := cmd.Flags().GetString("work-dir")
if workDir == "" {
home, _ := os.UserHomeDir()
workDir = filepath.Join(home, defaultWorkDir)
}
dbPath := filepath.Join(workDir, "registry.db")
if _, err := os.Stat(dbPath); os.IsNotExist(err) {
fmt.Println(dimStyle.Render("No registry found. Start a dispatch watcher first: core ai dispatch watch"))
return nil
}
registry, err := agentic.NewSQLiteRegistry(dbPath)
if err != nil {
return fmt.Errorf("failed to open registry: %w", err)
}
defer registry.Close()
// Reap stale agents (no heartbeat for 10 minutes).
reaped := registry.Reap(10 * time.Minute)
if len(reaped) > 0 {
for _, id := range reaped {
fmt.Printf(" Reaped stale agent: %s\n", dimStyle.Render(id))
}
fmt.Println()
}
agents := registry.List()
if len(agents) == 0 {
fmt.Println(dimStyle.Render("No agents registered."))
return nil
}
table := cli.NewTable("ID", "STATUS", "LOAD", "LAST HEARTBEAT", "CAPABILITIES")
for _, a := range agents {
status := dimStyle.Render(string(a.Status))
switch a.Status {
case agentic.AgentAvailable:
status = successStyle.Render("available")
case agentic.AgentBusy:
status = taskPriorityMediumStyle.Render("busy")
case agentic.AgentOffline:
status = errorStyle.Render("offline")
}
load := fmt.Sprintf("%d/%d", a.CurrentLoad, a.MaxLoad)
hb := a.LastHeartbeat.Format("15:04:05")
ago := time.Since(a.LastHeartbeat).Truncate(time.Second)
hbStr := fmt.Sprintf("%s (%s ago)", hb, ago)
caps := "-"
if len(a.Capabilities) > 0 {
caps = strings.Join(a.Capabilities, ", ")
}
table.AddRow(a.ID, status, load, hbStr, caps)
}
table.Render()
return nil
},
}
cmd.Flags().String("work-dir", "", "Working directory (default: ~/ai-work)")
return cmd
}
// findSetupScript looks for agent-setup.sh in common locations.
func findSetupScript() string {
exe, _ := os.Executable()

View file

@ -18,6 +18,8 @@ import (
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go/pkg/log"
agentic "forge.lthn.ai/core/go-agentic"
)
// AddDispatchCommands registers the 'dispatch' subcommand group under 'ai'.
@ -125,30 +127,45 @@ func dispatchWatchCmd() *cli.Command {
RunE: func(cmd *cli.Command, args []string) error {
workDir, _ := cmd.Flags().GetString("work-dir")
interval, _ := cmd.Flags().GetDuration("interval")
agentID, _ := cmd.Flags().GetString("agent-id")
paths := getPaths(workDir)
if err := ensureDispatchDirs(paths); err != nil {
return err
}
log.Info("Starting dispatch watcher", "dir", paths.root, "interval", interval)
// Register this agent in the go-agentic registry.
registry, events, cleanup := registerAgent(agentID, paths)
if cleanup != nil {
defer cleanup()
}
log.Info("Starting dispatch watcher", "dir", paths.root, "interval", interval, "agent", agentID)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
// Heartbeat loop — keeps agent status fresh.
if registry != nil {
go heartbeatLoop(ctx, registry, agentID, interval/2)
}
ticker := time.NewTicker(interval)
defer ticker.Stop()
runCycle(paths)
runCycleWithEvents(paths, registry, events, agentID)
for {
select {
case <-ticker.C:
runCycle(paths)
runCycleWithEvents(paths, registry, events, agentID)
case <-sigChan:
log.Info("Shutting down watcher...")
if registry != nil {
_ = registry.Deregister(agentID)
}
return nil
case <-ctx.Done():
return nil
@ -158,9 +175,95 @@ func dispatchWatchCmd() *cli.Command {
}
cmd.Flags().String("work-dir", "", "Working directory (default: ~/ai-work)")
cmd.Flags().Duration("interval", 5*time.Minute, "Polling interval")
cmd.Flags().String("agent-id", defaultAgentID(), "Agent identifier for registry")
return cmd
}
// defaultAgentID returns a sensible agent ID from hostname.
func defaultAgentID() string {
host, _ := os.Hostname()
if host == "" {
return "unknown"
}
return host
}
// registerAgent creates a SQLite registry and registers this agent.
// Returns the registry, event emitter, and a cleanup function.
func registerAgent(agentID string, paths runnerPaths) (agentic.AgentRegistry, agentic.EventEmitter, func()) {
dbPath := filepath.Join(paths.root, "registry.db")
registry, err := agentic.NewSQLiteRegistry(dbPath)
if err != nil {
log.Warn("Failed to create agent registry", "error", err, "path", dbPath)
return nil, nil, nil
}
info := agentic.AgentInfo{
ID: agentID,
Name: agentID,
Status: agentic.AgentAvailable,
LastHeartbeat: time.Now().UTC(),
MaxLoad: 1,
}
if err := registry.Register(info); err != nil {
log.Warn("Failed to register agent", "error", err)
} else {
log.Info("Agent registered", "id", agentID)
}
events := agentic.NewChannelEmitter(64)
// Drain events to log.
go func() {
for ev := range events.Events() {
log.Debug("Event", "type", string(ev.Type), "task", ev.TaskID, "agent", ev.AgentID)
}
}()
return registry, events, func() {
events.Close()
}
}
// heartbeatLoop sends periodic heartbeats to keep the agent status fresh.
func heartbeatLoop(ctx context.Context, registry agentic.AgentRegistry, agentID string, interval time.Duration) {
if interval < 30*time.Second {
interval = 30 * time.Second
}
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-ctx.Done():
return
case <-ticker.C:
_ = registry.Heartbeat(agentID)
}
}
}
// runCycleWithEvents wraps runCycle with registry status updates and event emission.
func runCycleWithEvents(paths runnerPaths, registry agentic.AgentRegistry, events agentic.EventEmitter, agentID string) {
if registry != nil {
// Set busy while processing.
if agent, err := registry.Get(agentID); err == nil {
agent.Status = agentic.AgentBusy
_ = registry.Register(agent)
}
}
runCycle(paths)
if registry != nil {
// Back to available.
if agent, err := registry.Get(agentID); err == nil {
agent.Status = agentic.AgentAvailable
agent.LastHeartbeat = time.Now().UTC()
_ = registry.Register(agent)
}
}
}
func dispatchStatusCmd() *cli.Command {
cmd := &cli.Command{
Use: "status",

View file

@ -10,7 +10,7 @@ import (
"strings"
"time"
"forge.lthn.ai/core/go-ai/agentic"
"forge.lthn.ai/core/go-agentic"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go/pkg/i18n"
)

View file

@ -9,7 +9,7 @@ import (
"strings"
"time"
"forge.lthn.ai/core/go-ai/agentic"
"forge.lthn.ai/core/go-agentic"
"forge.lthn.ai/core/go-ai/ai"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go/pkg/i18n"

View file

@ -6,7 +6,7 @@ import (
"context"
"time"
"forge.lthn.ai/core/go-ai/agentic"
"forge.lthn.ai/core/go-agentic"
"forge.lthn.ai/core/go-ai/ai"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go/pkg/i18n"

View file

@ -3,7 +3,6 @@ package daemon
import (
"context"
"encoding/json"
"fmt"
"net/http"
"os"
@ -16,7 +15,6 @@ import (
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go/pkg/log"
"forge.lthn.ai/core/go/pkg/process"
"forge.lthn.ai/core/go-ai/mcp"
)
@ -301,61 +299,33 @@ func runForeground(cfg Config) error {
return fmt.Errorf("failed to start daemon: %w", err)
}
// Create supervisor for managed services
sup := process.NewSupervisor(nil) // nil service — we only supervise Go functions
// Register MCP server as a supervised service
sup.RegisterFunc(process.GoSpec{
Name: "mcp",
Func: func(ctx context.Context) error {
return startMCP(ctx, mcpSvc, cfg)
},
Restart: process.RestartPolicy{
Delay: 3 * time.Second,
MaxRestarts: -1, // Unlimited restarts
},
})
// Start supervised services
sup.Start()
// Mark as ready
daemon.SetReady(true)
// Add supervisor status to health checks
daemon.AddHealthCheck(func() error {
statuses := sup.Statuses()
for name, status := range statuses {
if !status.Running {
return fmt.Errorf("service %s is not running (restarts: %d)", name, status.RestartCount)
}
}
return nil
})
// Start MCP server in a goroutine
ctx := cli.Context()
mcpErr := make(chan error, 1)
go func() {
mcpErr <- startMCP(ctx, mcpSvc, cfg)
}()
log.Info("Daemon ready",
"pid", os.Getpid(),
"health", daemon.HealthAddr(),
"services", strings.Join(sup.UnitNames(), ", "),
"services", "mcp",
)
// Print supervised service status as JSON for machine consumption
statuses := sup.Statuses()
if data, err := json.Marshal(statuses); err == nil {
log.Debug("Supervised services", "statuses", string(data))
// Wait for shutdown signal or MCP error
select {
case <-ctx.Done():
log.Info("Shutting down daemon")
case err := <-mcpErr:
if err != nil {
log.Error("MCP server exited", "error", err)
}
}
// Get context that cancels on SIGINT/SIGTERM
ctx := cli.Context()
// Wait for shutdown signal
<-ctx.Done()
log.Info("Shutting down daemon")
// Stop supervised services first
sup.Stop()
// Then stop the daemon (releases PID, stops health server)
// Stop the daemon (releases PID, stops health server)
return daemon.Stop()
}

View file

@ -3,7 +3,7 @@ package dev
import (
"context"
"forge.lthn.ai/core/go-ai/agentic"
"forge.lthn.ai/core/go-agentic"
"forge.lthn.ai/core/go/pkg/framework"
"forge.lthn.ai/core/go-scm/git"
)

View file

@ -7,7 +7,7 @@ import (
"sort"
"strings"
"forge.lthn.ai/core/go-ai/agentic"
"forge.lthn.ai/core/go-agentic"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-scm/git"
"forge.lthn.ai/core/go/pkg/i18n"

View file

@ -5,7 +5,7 @@ import (
"sort"
"strings"
"forge.lthn.ai/core/go-ai/agentic"
"forge.lthn.ai/core/go-agentic"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go/pkg/framework"
"forge.lthn.ai/core/go-scm/git"

View file

@ -2,7 +2,7 @@ package ml
import (
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -6,7 +6,7 @@ import (
"path/filepath"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -12,7 +12,7 @@ import (
"sort"
"time"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
"forge.lthn.ai/core/go/pkg/cli"
)

View file

@ -12,7 +12,7 @@ import (
"strings"
"time"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
"forge.lthn.ai/core/go/pkg/cli"
)

View file

@ -2,7 +2,7 @@ package ml
import (
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -4,7 +4,7 @@ import (
"fmt"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -5,7 +5,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var coverageCmd = &cli.Command{

View file

@ -6,7 +6,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -5,7 +5,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var expandStatusCmd = &cli.Command{
@ -34,40 +34,32 @@ func runExpandStatus(cmd *cli.Command, args []string) error {
fmt.Fprintln(os.Stdout, "==================================================")
// Expansion prompts
total, pending, err := db.ExpansionPromptCounts()
total, pending, err := db.CountExpansionPrompts()
if err != nil {
fmt.Fprintln(os.Stdout, " Expansion prompts: not created (run: normalize)")
return nil
}
fmt.Fprintf(os.Stdout, " Expansion prompts: %d total, %d pending\n", total, pending)
// Generated responses
generated, models, err := db.ExpansionRawCounts()
if err != nil {
generated = 0
// Generated responses — query raw counts via SQL
generated := 0
rows, err := db.QueryRows("SELECT count(*) AS n FROM expansion_raw")
if err != nil || len(rows) == 0 {
fmt.Fprintln(os.Stdout, " Generated: 0 (run: core ml expand)")
} else if len(models) > 0 {
modelStr := ""
for i, m := range models {
if i > 0 {
modelStr += ", "
}
modelStr += fmt.Sprintf("%s: %d", m.Name, m.Count)
}
fmt.Fprintf(os.Stdout, " Generated: %d (%s)\n", generated, modelStr)
} else {
if n, ok := rows[0]["n"]; ok {
generated = toInt(n)
}
fmt.Fprintf(os.Stdout, " Generated: %d\n", generated)
}
// Scored
scored, hPassed, jScored, jPassed, err := db.ExpansionScoreCounts()
if err != nil {
// Scored — query scoring counts via SQL
sRows, err := db.QueryRows("SELECT count(*) AS n FROM scoring_results WHERE suite = 'heuristic'")
if err != nil || len(sRows) == 0 {
fmt.Fprintln(os.Stdout, " Scored: 0 (run: score --tier 1)")
} else {
fmt.Fprintf(os.Stdout, " Heuristic scored: %d (%d passed)\n", scored, hPassed)
if jScored > 0 {
fmt.Fprintf(os.Stdout, " Judge scored: %d (%d passed)\n", jScored, jPassed)
}
scored := toInt(sRows[0]["n"])
fmt.Fprintf(os.Stdout, " Heuristic scored: %d\n", scored)
}
// Pipeline progress
@ -77,7 +69,7 @@ func runExpandStatus(cmd *cli.Command, args []string) error {
}
// Golden set context
golden, err := db.GoldenSetCount()
golden, err := db.CountGoldenSet()
if err == nil && golden > 0 {
fmt.Fprintf(os.Stdout, "\n Golden set: %d / %d\n", golden, targetTotal)
if generated > 0 {
@ -87,3 +79,17 @@ func runExpandStatus(cmd *cli.Command, args []string) error {
return nil
}
// toInt converts an interface{} (typically from QueryRows) to int.
func toInt(v interface{}) int {
switch n := v.(type) {
case int:
return n
case int64:
return int(n)
case float64:
return int(n)
default:
return 0
}
}

View file

@ -5,7 +5,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -4,7 +4,7 @@ import (
"fmt"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -6,7 +6,7 @@ import (
"path/filepath"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var importCmd = &cli.Command{

View file

@ -5,7 +5,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var ingestCmd = &cli.Command{

View file

@ -5,7 +5,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var inventoryCmd = &cli.Command{

View file

@ -13,7 +13,7 @@ import (
"strings"
"time"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
"forge.lthn.ai/core/go/pkg/cli"
"gopkg.in/yaml.v3"
)

View file

@ -5,7 +5,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
const targetTotal = 15000
@ -21,24 +21,27 @@ func runLive(cmd *cli.Command, args []string) error {
influx := ml.NewInfluxClient(influxURL, influxDB)
// Total completed generations
total, err := influx.QueryScalar("SELECT count(DISTINCT i) AS n FROM gold_gen")
totalRows, err := influx.QuerySQL("SELECT count(DISTINCT i) AS n FROM gold_gen")
if err != nil {
return fmt.Errorf("live: query total: %w", err)
}
total := sqlScalar(totalRows)
// Distinct domains and voices
domains, err := influx.QueryScalar("SELECT count(DISTINCT d) AS n FROM gold_gen")
domainRows, err := influx.QuerySQL("SELECT count(DISTINCT d) AS n FROM gold_gen")
if err != nil {
return fmt.Errorf("live: query domains: %w", err)
}
domains := sqlScalar(domainRows)
voices, err := influx.QueryScalar("SELECT count(DISTINCT v) AS n FROM gold_gen")
voiceRows, err := influx.QuerySQL("SELECT count(DISTINCT v) AS n FROM gold_gen")
if err != nil {
return fmt.Errorf("live: query voices: %w", err)
}
voices := sqlScalar(voiceRows)
// Per-worker breakdown
workers, err := influx.QueryRows("SELECT w, count(DISTINCT i) AS n FROM gold_gen GROUP BY w ORDER BY n DESC")
workers, err := influx.QuerySQL("SELECT w, count(DISTINCT i) AS n FROM gold_gen GROUP BY w ORDER BY n DESC")
if err != nil {
return fmt.Errorf("live: query workers: %w", err)
}
@ -66,3 +69,14 @@ func runLive(cmd *cli.Command, args []string) error {
return nil
}
// sqlScalar extracts the first numeric value from a QuerySQL result.
func sqlScalar(rows []map[string]interface{}) int {
if len(rows) == 0 {
return 0
}
for _, v := range rows[0] {
return toInt(v)
}
return 0
}

View file

@ -5,7 +5,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var metricsCmd = &cli.Command{

View file

@ -5,7 +5,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var normalizeMinLen int

View file

@ -7,7 +7,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -2,7 +2,7 @@ package ml
import (
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -7,7 +7,7 @@ import (
"strings"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var queryCmd = &cli.Command{

View file

@ -11,7 +11,7 @@ import (
"runtime"
"time"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
"forge.lthn.ai/core/go/pkg/cli"
)

View file

@ -6,7 +6,7 @@ import (
"time"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -5,7 +5,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var seedInfluxCmd = &cli.Command{

View file

@ -11,7 +11,7 @@ import (
"strings"
"time"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
"forge.lthn.ai/core/go/pkg/cli"
"gopkg.in/yaml.v3"
)

View file

@ -15,7 +15,7 @@ import (
"time"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var serveCmd = &cli.Command{

View file

@ -5,7 +5,7 @@ import (
"os"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var statusCmd = &cli.Command{

View file

@ -12,8 +12,8 @@ import (
"strings"
"time"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ai/mlx"
"forge.lthn.ai/core/go-ml"
"forge.lthn.ai/core/go-mlx"
"forge.lthn.ai/core/go-ai/mlx/model"
"forge.lthn.ai/core/go-ai/mlx/tokenizer"
"forge.lthn.ai/core/go/pkg/cli"

View file

@ -4,7 +4,7 @@ import (
"time"
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
var (

View file

@ -2,7 +2,7 @@
package ml
import "forge.lthn.ai/core/go-ai/ml"
import "forge.lthn.ai/core/go-ml"
func createServeBackend() (ml.Backend, error) {
return ml.NewHTTPBackend(apiURL, modelName), nil

View file

@ -6,7 +6,7 @@ import (
"fmt"
"log/slog"
"forge.lthn.ai/core/go-ai/ml"
"forge.lthn.ai/core/go-ml"
)
func createServeBackend() (ml.Backend, error) {

View file

@ -6,7 +6,7 @@ import (
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go/pkg/i18n"
"forge.lthn.ai/core/go-ai/rag"
"forge.lthn.ai/core/go-rag"
"github.com/spf13/cobra"
)
@ -74,8 +74,8 @@ func runCollections(cmd *cobra.Command, args []string) error {
continue
}
fmt.Printf(" %s\n", cli.ValueStyle.Render(name))
fmt.Printf(" Points: %d\n", info.PointsCount)
fmt.Printf(" Status: %s\n", info.Status.String())
fmt.Printf(" Points: %d\n", info.PointCount)
fmt.Printf(" Status: %s\n", info.Status)
fmt.Println()
} else {
fmt.Printf(" %s\n", name)

View file

@ -6,7 +6,7 @@ import (
"forge.lthn.ai/core/go/pkg/cli"
"forge.lthn.ai/core/go/pkg/i18n"
"forge.lthn.ai/core/go-ai/rag"
"forge.lthn.ai/core/go-rag"
"github.com/spf13/cobra"
)

View file

@ -5,7 +5,7 @@ import (
"fmt"
"forge.lthn.ai/core/go/pkg/i18n"
"forge.lthn.ai/core/go-ai/rag"
"forge.lthn.ai/core/go-rag"
"github.com/spf13/cobra"
)

16
go.mod
View file

@ -4,11 +4,18 @@ go 1.25.5
require (
forge.lthn.ai/core/go v0.0.0
forge.lthn.ai/core/go-agentic v0.0.0
forge.lthn.ai/core/go-ai v0.0.0
forge.lthn.ai/core/go-crypt v0.0.0
forge.lthn.ai/core/go-devops v0.0.0
forge.lthn.ai/core/go-inference v0.0.0
forge.lthn.ai/core/go-ml v0.0.0
forge.lthn.ai/core/go-mlx v0.0.0
forge.lthn.ai/core/go-netops v0.0.0
forge.lthn.ai/core/go-rag v0.0.0
forge.lthn.ai/core/go-scm v0.0.0
forge.lthn.ai/core/go-store v0.0.0
forge.lthn.ai/core/go-webview v0.0.0
)
require (
@ -125,10 +132,17 @@ require (
)
replace (
forge.lthn.ai/core/go => ../core
forge.lthn.ai/core/go => ../go
forge.lthn.ai/core/go-agentic => ../go-agentic
forge.lthn.ai/core/go-ai => ../go-ai
forge.lthn.ai/core/go-crypt => ../go-crypt
forge.lthn.ai/core/go-devops => ../go-devops
forge.lthn.ai/core/go-inference => ../go-inference
forge.lthn.ai/core/go-ml => ../go-ml
forge.lthn.ai/core/go-mlx => ../go-mlx
forge.lthn.ai/core/go-netops => ../go-netops
forge.lthn.ai/core/go-rag => ../go-rag
forge.lthn.ai/core/go-scm => ../go-scm
forge.lthn.ai/core/go-store => ../go-store
forge.lthn.ai/core/go-webview => ../go-webview
)

View file

@ -2,10 +2,17 @@ go 1.25.5
use (
.
../core
../go
../go-agentic
../go-ai
../go-crypt
../go-devops
../go-inference
../go-ml
../go-mlx
../go-netops
../go-rag
../go-scm
../go-store
../go-webview
)