style: gofmt all packages
This commit is contained in:
@@ -5,9 +5,9 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/david/knox/internal/db"
|
"github.com/david/knox/internal/db"
|
||||||
"github.com/david/knox/internal/ingest"
|
"github.com/david/knox/internal/ingest"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewBrowserCmd(kdb *db.KnoxDB) *cobra.Command {
|
func NewBrowserCmd(kdb *db.KnoxDB) *cobra.Command {
|
||||||
@@ -65,10 +65,10 @@ Run periodically to capture browsing exhaust.`,
|
|||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
domains[extractDomain(r.Summary)]++
|
domains[extractDomain(r.Summary)]++
|
||||||
}
|
}
|
||||||
fmt.Println("\nTop domains:")
|
fmt.Println("\nTop domains:")
|
||||||
for _, d := range topDomains(domains, 10) {
|
for _, d := range topDomains(domains, 10) {
|
||||||
fmt.Printf(" %-40s %d\n", d.Name, d.Count)
|
fmt.Printf(" %-40s %d\n", d.Name, d.Count)
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/david/knox/internal/db"
|
"github.com/david/knox/internal/db"
|
||||||
"github.com/david/knox/internal/ingest"
|
"github.com/david/knox/internal/ingest"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewGiteaCmd(kdb *db.KnoxDB) *cobra.Command {
|
func NewGiteaCmd(kdb *db.KnoxDB) *cobra.Command {
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/david/knox/internal/db"
|
"github.com/david/knox/internal/db"
|
||||||
"github.com/david/knox/internal/watch"
|
"github.com/david/knox/internal/watch"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewGossipCmd exposes peer status/diff for the gossip protocol.
|
// NewGossipCmd exposes peer status/diff for the gossip protocol.
|
||||||
@@ -154,4 +154,4 @@ func min(a, b int) int {
|
|||||||
return a
|
return a
|
||||||
}
|
}
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|||||||
+73
-73
@@ -5,10 +5,10 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/david/knox/internal/db"
|
"github.com/david/knox/internal/db"
|
||||||
"github.com/david/knox/internal/ingest"
|
"github.com/david/knox/internal/ingest"
|
||||||
"github.com/david/knox/internal/watch"
|
"github.com/david/knox/internal/watch"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewIngestCmd(kdb *db.KnoxDB) *cobra.Command {
|
func NewIngestCmd(kdb *db.KnoxDB) *cobra.Command {
|
||||||
@@ -27,92 +27,92 @@ func NewIngestCmd(kdb *db.KnoxDB) *cobra.Command {
|
|||||||
ingest.NewSkillsIngester(),
|
ingest.NewSkillsIngester(),
|
||||||
}
|
}
|
||||||
|
|
||||||
var totalNew, totalUpdated int
|
var totalNew, totalUpdated int
|
||||||
|
|
||||||
record := func(result *ingest.IngestResult) {
|
record := func(result *ingest.IngestResult) {
|
||||||
_, isNew, err := kdb.RecordObservation(db.ObservationRecord{
|
_, isNew, err := kdb.RecordObservation(db.ObservationRecord{
|
||||||
Fingerprint: result.Fingerprint,
|
Fingerprint: result.Fingerprint,
|
||||||
SourceID: result.SourceID,
|
SourceID: result.SourceID,
|
||||||
SourcePath: result.SourcePath,
|
SourcePath: result.SourcePath,
|
||||||
Project: result.Project,
|
Project: result.Project,
|
||||||
ContentType: result.ContentType,
|
ContentType: result.ContentType,
|
||||||
Title: result.Title,
|
Title: result.Title,
|
||||||
Summary: result.Summary,
|
Summary: result.Summary,
|
||||||
CreatedAt: result.CreatedAt,
|
CreatedAt: result.CreatedAt,
|
||||||
LineStart: result.LineStart,
|
LineStart: result.LineStart,
|
||||||
LineEnd: result.LineEnd,
|
LineEnd: result.LineEnd,
|
||||||
Confidence: result.Confidence,
|
Confidence: result.Confidence,
|
||||||
IngesterVersion: result.IngesterVersion,
|
IngesterVersion: result.IngesterVersion,
|
||||||
Trigger: "ingest",
|
Trigger: "ingest",
|
||||||
Provenance: ingest.ProvenanceJSON(result.Provenance),
|
Provenance: ingest.ProvenanceJSON(result.Provenance),
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Printf("[knox] db error: %v", err)
|
log.Printf("[knox] db error: %v", err)
|
||||||
return
|
return
|
||||||
}
|
|
||||||
if isNew {
|
|
||||||
totalNew++
|
|
||||||
} else {
|
|
||||||
totalUpdated++
|
|
||||||
}
|
|
||||||
|
|
||||||
if result.SourceID == "opencode-session" {
|
|
||||||
sessionID, _ := result.Provenance["session_id"].(string)
|
|
||||||
if sessionID != "" {
|
|
||||||
kdb.UpsertSession(sessionID, result.Project, result.Title, "active")
|
|
||||||
}
|
}
|
||||||
}
|
if isNew {
|
||||||
}
|
totalNew++
|
||||||
|
} else {
|
||||||
for _, ing := range ingesters {
|
totalUpdated++
|
||||||
sid := ing.SourceID()
|
|
||||||
log.Printf("[knox] ingesting %s...", sid)
|
|
||||||
|
|
||||||
for _, dir := range dirs {
|
|
||||||
patterns := []string{
|
|
||||||
dir + "/*",
|
|
||||||
dir + "/*/SKILL.md",
|
|
||||||
}
|
}
|
||||||
for _, pattern := range patterns {
|
|
||||||
entries, _ := filepath.Glob(pattern)
|
|
||||||
for _, path := range entries {
|
|
||||||
if !watch.MatchesIngester(path, sid) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
result, err := ing.Ingest(path)
|
if result.SourceID == "opencode-session" {
|
||||||
if err != nil || result == nil {
|
sessionID, _ := result.Provenance["session_id"].(string)
|
||||||
continue
|
if sessionID != "" {
|
||||||
}
|
kdb.UpsertSession(sessionID, result.Project, result.Title, "active")
|
||||||
record(result)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Non-file sources: obsidian vault, browser history, gitea
|
for _, ing := range ingesters {
|
||||||
if vault, err := ingest.DetectObsidianVault(); err == nil {
|
sid := ing.SourceID()
|
||||||
log.Printf("[knox] ingesting obsidian...")
|
log.Printf("[knox] ingesting %s...", sid)
|
||||||
if results, err := ingest.NewObsidianIngester(vault).IngestAll(); err == nil {
|
|
||||||
|
for _, dir := range dirs {
|
||||||
|
patterns := []string{
|
||||||
|
dir + "/*",
|
||||||
|
dir + "/*/SKILL.md",
|
||||||
|
}
|
||||||
|
for _, pattern := range patterns {
|
||||||
|
entries, _ := filepath.Glob(pattern)
|
||||||
|
for _, path := range entries {
|
||||||
|
if !watch.MatchesIngester(path, sid) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
result, err := ing.Ingest(path)
|
||||||
|
if err != nil || result == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
record(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Non-file sources: obsidian vault, browser history, gitea
|
||||||
|
if vault, err := ingest.DetectObsidianVault(); err == nil {
|
||||||
|
log.Printf("[knox] ingesting obsidian...")
|
||||||
|
if results, err := ingest.NewObsidianIngester(vault).IngestAll(); err == nil {
|
||||||
|
for _, r := range results {
|
||||||
|
record(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Printf("[knox] ingesting browser-history...")
|
||||||
|
if results, err := ingest.NewBrowserHistoryIngester().IngestAll(); err == nil {
|
||||||
for _, r := range results {
|
for _, r := range results {
|
||||||
record(r)
|
record(r)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
log.Printf("[knox] ingesting gitea...")
|
||||||
log.Printf("[knox] ingesting browser-history...")
|
if results, err := ingest.NewGiteaIngester().IngestAll(); err == nil {
|
||||||
if results, err := ingest.NewBrowserHistoryIngester().IngestAll(); err == nil {
|
for _, r := range results {
|
||||||
for _, r := range results {
|
record(r)
|
||||||
record(r)
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
log.Printf("[knox] ingesting gitea...")
|
|
||||||
if results, err := ingest.NewGiteaIngester().IngestAll(); err == nil {
|
|
||||||
for _, r := range results {
|
|
||||||
record(r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("\nIngest complete: %d new entries, %d updated\n", totalNew, totalUpdated)
|
fmt.Printf("\nIngest complete: %d new entries, %d updated\n", totalNew, totalUpdated)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.Flags().StringSliceVarP(&dirs, "dir", "d", nil, "Directories to scan (default: opencode storage/log + skills)")
|
cmd.Flags().StringSliceVarP(&dirs, "dir", "d", nil, "Directories to scan (default: opencode storage/log + skills)")
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/david/knox/internal/db"
|
"github.com/david/knox/internal/db"
|
||||||
"github.com/david/knox/internal/ingest"
|
"github.com/david/knox/internal/ingest"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewObsidianCmd(kdb *db.KnoxDB) *cobra.Command {
|
func NewObsidianCmd(kdb *db.KnoxDB) *cobra.Command {
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package cmd
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/david/knox/internal/db"
|
"github.com/david/knox/internal/db"
|
||||||
"github.com/david/knox/internal/watch"
|
"github.com/david/knox/internal/watch"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewReconcileCmd rebuilds all derived state (entries cache, threads) from the
|
// NewReconcileCmd rebuilds all derived state (entries cache, threads) from the
|
||||||
@@ -51,4 +51,4 @@ func dryRunReconcile(kdb *db.KnoxDB) error {
|
|||||||
fmt.Printf("drift: %d entries current, %d from log (%+d), %d threads would be created, %d obs would be linked\n",
|
fmt.Printf("drift: %d entries current, %d from log (%+d), %d threads would be created, %d obs would be linked\n",
|
||||||
current, logCount, logCount-current, created, linked)
|
current, logCount, logCount-current, created, linked)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/david/knox/internal/db"
|
"github.com/david/knox/internal/db"
|
||||||
"github.com/david/knox/internal/index"
|
"github.com/david/knox/internal/index"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func paginate(entries []db.Entry, page, limit int) []db.Entry {
|
func paginate(entries []db.Entry, page, limit int) []db.Entry {
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ import (
|
|||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/david/knox/internal/db"
|
"github.com/david/knox/internal/db"
|
||||||
"github.com/david/knox/internal/index"
|
"github.com/david/knox/internal/index"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewTopicsCmd(kdb *db.KnoxDB) *cobra.Command {
|
func NewTopicsCmd(kdb *db.KnoxDB) *cobra.Command {
|
||||||
|
|||||||
@@ -4,9 +4,9 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
"github.com/david/knox/internal/db"
|
"github.com/david/knox/internal/db"
|
||||||
"github.com/david/knox/internal/watch"
|
"github.com/david/knox/internal/watch"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewWatchCmd(kdb *db.KnoxDB) *cobra.Command {
|
func NewWatchCmd(kdb *db.KnoxDB) *cobra.Command {
|
||||||
|
|||||||
@@ -286,4 +286,4 @@ func (k *KnoxDB) ThreadStatusByCluster() (map[string]string, error) {
|
|||||||
out[key] = status
|
out[key] = status
|
||||||
}
|
}
|
||||||
return out, rows.Err()
|
return out, rows.Err()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ type MetricsSnapshot struct {
|
|||||||
PendingReflections int
|
PendingReflections int
|
||||||
ThreadsByStatus map[string]int
|
ThreadsByStatus map[string]int
|
||||||
Peers int
|
Peers int
|
||||||
ByOriginNode map[string]int // node_id → observation count
|
ByOriginNode map[string]int // node_id → observation count
|
||||||
KnowledgeVector map[string]int64 // node_id → max hcl
|
KnowledgeVector map[string]int64 // node_id → max hcl
|
||||||
EarliestObservation string
|
EarliestObservation string
|
||||||
}
|
}
|
||||||
@@ -105,4 +105,4 @@ func (k *KnoxDB) MetricsSnapshot() (*MetricsSnapshot, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return s, nil
|
return s, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -57,4 +57,4 @@ func (c *Clock) Now() (int64, time.Time) {
|
|||||||
// WallTime extracts the wall-clock component embedded in a packed HLC value.
|
// WallTime extracts the wall-clock component embedded in a packed HLC value.
|
||||||
func WallTime(v int64) time.Time {
|
func WallTime(v int64) time.Time {
|
||||||
return time.UnixMilli(v >> wallShift).UTC()
|
return time.UnixMilli(v >> wallShift).UTC()
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-16
@@ -19,23 +19,23 @@ import (
|
|||||||
// scrape-time gauges derived from the database (refreshed on each scrape).
|
// scrape-time gauges derived from the database (refreshed on each scrape).
|
||||||
type Metrics struct {
|
type Metrics struct {
|
||||||
// Gossip counters (live).
|
// Gossip counters (live).
|
||||||
pullsTotal prometheus.Counter
|
pullsTotal prometheus.Counter
|
||||||
pushesTotal prometheus.Counter
|
pushesTotal prometheus.Counter
|
||||||
obsPulledTotal prometheus.Counter
|
obsPulledTotal prometheus.Counter
|
||||||
obsPushedTotal prometheus.Counter
|
obsPushedTotal prometheus.Counter
|
||||||
errorsTotal prometheus.Counter
|
errorsTotal prometheus.Counter
|
||||||
|
|
||||||
// Snapshot gauges (updated per scrape).
|
// Snapshot gauges (updated per scrape).
|
||||||
observationsGauge *prometheus.GaugeVec
|
observationsGauge *prometheus.GaugeVec
|
||||||
entriesGauge prometheus.Gauge
|
entriesGauge prometheus.Gauge
|
||||||
projectsGauge prometheus.Gauge
|
projectsGauge prometheus.Gauge
|
||||||
sessionsGauge prometheus.Gauge
|
sessionsGauge prometheus.Gauge
|
||||||
pendingReflections prometheus.Gauge
|
pendingReflections prometheus.Gauge
|
||||||
peersGauge prometheus.Gauge
|
peersGauge prometheus.Gauge
|
||||||
threadsByStatus *prometheus.GaugeVec
|
threadsByStatus *prometheus.GaugeVec
|
||||||
byOriginNode *prometheus.GaugeVec
|
byOriginNode *prometheus.GaugeVec
|
||||||
knowledgeVector *prometheus.GaugeVec
|
knowledgeVector *prometheus.GaugeVec
|
||||||
observationsLast24h prometheus.Gauge
|
observationsLast24h prometheus.Gauge
|
||||||
|
|
||||||
registry *prometheus.Registry
|
registry *prometheus.Registry
|
||||||
kdb *db.KnoxDB
|
kdb *db.KnoxDB
|
||||||
@@ -161,4 +161,4 @@ func (m *Metrics) Handler() http.Handler {
|
|||||||
}
|
}
|
||||||
h.ServeHTTP(w, r)
|
h.ServeHTTP(w, r)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,4 +111,4 @@ func TestMetricsCounters(t *testing.T) {
|
|||||||
if got := testutil.ToFloat64(m.errorsTotal); got != 1 {
|
if got := testutil.ToFloat64(m.errorsTotal); got != 1 {
|
||||||
t.Errorf("errorsTotal = %v, want 1", got)
|
t.Errorf("errorsTotal = %v, want 1", got)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-14
@@ -33,11 +33,11 @@ type Node struct {
|
|||||||
|
|
||||||
// pingResponse is the anti-entropy summary returned by /v1/ping.
|
// pingResponse is the anti-entropy summary returned by /v1/ping.
|
||||||
type pingResponse struct {
|
type pingResponse struct {
|
||||||
NodeID string `json:"node_id"`
|
NodeID string `json:"node_id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Vector map[string]int64 `json:"vector"` // node_id → max hcl
|
Vector map[string]int64 `json:"vector"` // node_id → max hcl
|
||||||
Peers []db.PeerInfo `json:"peers"` // swarm membership this node knows
|
Peers []db.PeerInfo `json:"peers"` // swarm membership this node knows
|
||||||
MaxHCL *int64 `json:"max_hcl,omitempty"`
|
MaxHCL *int64 `json:"max_hcl,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) Handler() http.Handler {
|
func (n *Node) Handler() http.Handler {
|
||||||
@@ -123,11 +123,11 @@ func (n *Node) handleBatch(w http.ResponseWriter, r *http.Request) {
|
|||||||
// DiffSummary is the divergence snapshot served at /v1/diff: everything this
|
// DiffSummary is the divergence snapshot served at /v1/diff: everything this
|
||||||
// node observes, plus the status of auto-threaded threads (for tombstones).
|
// node observes, plus the status of auto-threaded threads (for tombstones).
|
||||||
type DiffSummary struct {
|
type DiffSummary struct {
|
||||||
NodeID string `json:"node_id"`
|
NodeID string `json:"node_id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Fingerprints []string `json:"fingerprints"`
|
Fingerprints []string `json:"fingerprints"`
|
||||||
ThreadStatus map[string]string `json:"thread_status"`
|
ThreadStatus map[string]string `json:"thread_status"`
|
||||||
ObsCount int `json:"obs_count"`
|
ObsCount int `json:"obs_count"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *Node) handleDiff(w http.ResponseWriter, r *http.Request) {
|
func (n *Node) handleDiff(w http.ResponseWriter, r *http.Request) {
|
||||||
@@ -163,9 +163,9 @@ func writeJSON(w http.ResponseWriter, v any) {
|
|||||||
|
|
||||||
// Client is the pull/push half used by the exchange loop.
|
// Client is the pull/push half used by the exchange loop.
|
||||||
type Client struct {
|
type Client struct {
|
||||||
NodeID string
|
NodeID string
|
||||||
Addr string
|
Addr string
|
||||||
Timeout time.Duration
|
Timeout time.Duration
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) Ping() (*pingResponse, error) {
|
func (c *Client) Ping() (*pingResponse, error) {
|
||||||
@@ -410,4 +410,4 @@ func PeerAddrs() []string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -240,4 +240,4 @@ func TestGossipIdempotent(t *testing.T) {
|
|||||||
if before != after {
|
if before != after {
|
||||||
t.Errorf("second sweep changed entry count: %d -> %d", before, after)
|
t.Errorf("second sweep changed entry count: %d -> %d", before, after)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,4 +20,4 @@ func Reconcile(kdb *db.KnoxDB) (int, int, error) {
|
|||||||
return 0, 0, fmt.Errorf("auto-thread: %w", err)
|
return 0, 0, fmt.Errorf("auto-thread: %w", err)
|
||||||
}
|
}
|
||||||
return created, linked, nil
|
return created, linked, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
mcpServer "github.com/mark3labs/mcp-go/server"
|
|
||||||
"github.com/spf13/cobra"
|
|
||||||
knoxcmd "github.com/david/knox/internal/cmd"
|
knoxcmd "github.com/david/knox/internal/cmd"
|
||||||
"github.com/david/knox/internal/db"
|
"github.com/david/knox/internal/db"
|
||||||
knoxserver "github.com/david/knox/internal/server"
|
knoxserver "github.com/david/knox/internal/server"
|
||||||
|
mcpServer "github.com/mark3labs/mcp-go/server"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func newServeCmd(kdb *db.KnoxDB) *cobra.Command {
|
func newServeCmd(kdb *db.KnoxDB) *cobra.Command {
|
||||||
|
|||||||
Reference in New Issue
Block a user