Files
wehub-resource-sync a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

116 lines
2.9 KiB
Go

package mcp
import (
"os"
"path/filepath"
"strings"
"time"
"github.com/zzet/gortex/internal/docs"
)
// stringArgOrDefault returns args[key] coerced to a trimmed string,
// or fallback when the key is absent or empty.
func stringArgOrDefault(args map[string]any, key, fallback string) string {
if v := stringArg(args, key); v != "" {
return v
}
return fallback
}
// intArgOrDefault returns args[key] coerced to an int, or fallback
// when the key is absent/zero. Both float64 and int forms are
// accepted (JSON-unmarshal vs. Go-callsite).
func intArgOrDefault(args map[string]any, key string, fallback int) int {
switch v := args[key].(type) {
case float64:
if v > 0 {
return int(v)
}
case int:
if v > 0 {
return v
}
case int64:
if v > 0 {
return int(v)
}
}
return fallback
}
// boolArgValue returns args[key] as a bool, false when absent.
// Thin wrapper around boolArg that drops the "ok" return for callers
// that want zero-value semantics.
func boolArgValue(args map[string]any, key string) bool {
v, _ := boolArg(args, key)
return v
}
// parseDurationArg accepts a duration argument expressed as a Go
// duration string (e.g. "24h", "30m", "7d"). The "Nd" suffix is a
// gortex extension — Go's stdlib doesn't accept days natively, so we
// translate it to hours here.
func parseDurationArg(args map[string]any, key string) (time.Duration, error) {
raw := strings.TrimSpace(stringArg(args, key))
if raw == "" {
return 0, nil
}
if strings.HasSuffix(raw, "d") {
core := strings.TrimSuffix(raw, "d")
if d, err := time.ParseDuration(core + "h"); err == nil {
return d * 24, nil
}
}
d, err := time.ParseDuration(raw)
if err != nil {
return 0, err
}
return d, nil
}
// writeWikiFile is a thin wrapper around os.WriteFile that ensures
// the parent directory exists. Used by the MCP handler when the
// caller passes an output_path.
func writeWikiFile(path string, body []byte) error {
dir := filepath.Dir(path)
if dir != "" && dir != "." {
if err := os.MkdirAll(dir, 0o755); err != nil {
return err
}
}
return os.WriteFile(path, body, 0o644)
}
// docsHistoryProvider adapts the server's watcher into the
// docs-package shape. Returns nil when no watcher is attached, in
// which case the recent-changes section will be empty.
func (s *Server) docsHistoryProvider() docs.HistoryProvider {
if s.watcher == nil {
return nil
}
return &watcherHistoryAdapter{w: s.watcher}
}
type watcherHistoryAdapter struct {
w watcherHistory
}
func (a *watcherHistoryAdapter) HistorySince(since time.Time) []docs.HistoryEvent {
if a.w == nil {
return nil
}
src := a.w.HistorySince(since)
out := make([]docs.HistoryEvent, 0, len(src))
for _, ev := range src {
out = append(out, docs.HistoryEvent{
FilePath: ev.FilePath,
Kind: string(ev.Kind),
NodesAdded: ev.NodesAdded,
NodesRemoved: ev.NodesRemoved,
Timestamp: ev.Timestamp,
})
}
return out
}