-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
179 lines (161 loc) · 6.45 KB
/
Copy pathmain.go
File metadata and controls
179 lines (161 loc) · 6.45 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
// Package main provides the command-line interface for Devgraph CLI.
// Devgraph CLI is a command-line tool for interacting with Devgraph.ai,
// providing AI-powered chat, authentication, and resource management capabilities.
package main
import (
"errors"
"fmt"
"os"
"reflect"
"strings"
"github.com/alecthomas/kong"
"github.com/arctir/devgraph-cli/pkg/commands"
"github.com/arctir/devgraph-cli/pkg/config"
"github.com/arctir/devgraph-cli/pkg/util"
)
// Version information (set at build time via ldflags)
var (
Version = "dev"
Commit = "none"
Date = "unknown"
)
// VersionCommand displays version information
type VersionCommand struct{}
// Run executes the version command
func (v *VersionCommand) Run() error {
fmt.Printf("devgraph version %s\n", Version)
if Commit != "none" {
fmt.Printf(" commit: %s\n", Commit)
}
if Date != "unknown" {
fmt.Printf(" built: %s\n", Date)
}
return nil
}
// CLI represents the main command-line interface structure for Devgraph CLI.
// It defines all available commands and their subcommands using Kong command-line parser.
type CLI struct {
// Auth handles authentication with Devgraph accounts
Auth commands.AuthCommand `kong:"cmd,help='Manage authentication with your Devgraph account'"`
// Chat provides interactive AI chat functionality
Chat commands.Chat `kong:"cmd,help='Start an interactive chat with AI'"`
// Complete is a hidden command for dynamic shell completions
Complete commands.CompleteCommand `kong:"cmd,hidden,help='Generate dynamic completions for resources'"`
// Completion generates shell completion scripts
Completion commands.CompletionCommand `kong:"cmd,help='Generate shell completion scripts'"`
// Config manages CLI configuration settings
Config commands.ConfigCommand `kong:"cmd,help='Manage configuration settings'"`
// Entity manages entities within Devgraph
Entity commands.EntityCommand `kong:"cmd,help='Manage entities for Devgraph'"`
// EntityDefinition manages entity definitions
EntityDefinition commands.EntityDefinitionCommand `kong:"cmd,help='Manage entity definitions for Devgraph'"`
// Environment manages Devgraph environments
Environment commands.EnvironmentCommand `kong:"cmd,name='env',help='Manage environments for Devgraph'"`
// MCP manages Model Context Protocol resources
MCP commands.MCPCommand `kong:"cmd,help='Manage MCP resources for Devgraph'"`
// Model manages AI models and configurations
Model commands.ModelCommand `kong:"cmd,help='Manage Model resources for Devgraph'"`
// ModelProvider manages AI model providers
ModelProvider commands.ModelProviderCommand `kong:"cmd,name='modelprovider',help='Manage Model Provider resources for Devgraph'"`
// OAuthService manages OAuth service configurations
OAuthService commands.OAuthServiceCommand `kong:"cmd,name='oauthservice',help='Manage OAuth services for Devgraph'"`
// Provider manages discovery providers
Provider commands.ProviderCommand `kong:"cmd,help='Manage discovery providers'"`
// Relation manages entity relations
Relation commands.RelationCommand `kong:"cmd,help='Manage entity relations'"`
// Subscription manages subscription information
Subscription commands.SubscriptionCommand `kong:"cmd,help='Manage subscriptions'"`
// Suggestion manages chat suggestions
Suggestion commands.SuggestionCommand `kong:"cmd,help='Manage chat suggestions'"`
// Token manages API tokens for Devgraph
Token commands.TokenCommand `kong:"cmd,help='Manage opaque tokens for Devgraph'"`
// User manages users in the current environment
User commands.UserCommand `kong:"cmd,help='Manage users in the current environment'"`
// Version displays version information
Version VersionCommand `kong:"cmd,help='Show version information'"`
}
// main is the entry point for the Devgraph CLI application.
// It initializes the Kong command parser, handles first-time setup,
// and executes the requested command.
func main() {
cli := CLI{}
// Parse command-line arguments using Kong
ctx := kong.Parse(&cli,
kong.Name("dg"),
kong.Description("Turn chaos into clarity"),
kong.UsageOnError(),
kong.ConfigureHelp(kong.HelpOptions{
Compact: false,
NoExpandSubcommands: true,
}),
)
// Apply defaults to embedded Config structs after parsing
if cmd := ctx.Selected(); cmd != nil {
applyConfigDefaults(cmd.Target)
}
// Show first-time setup guidance for commands that need authentication
// Skip for help, auth, completion, complete, and version commands since they don't require full config
if ctx.Command() != "help" && ctx.Command() != "completion" && ctx.Command() != "version" && !strings.HasPrefix(ctx.Command(), "auth") && !strings.HasPrefix(ctx.Command(), "complete") {
if shouldShowFirstTimeSetup() {
showFirstTimeSetupMessage()
return // Don't proceed with the command
}
}
// Execute the requested command
err := ctx.Run()
if err != nil {
// Check if this is a warning-type error
var noEnvErr *util.NoEnvironmentError
if errors.As(err, &noEnvErr) {
fmt.Fprintf(os.Stderr, "⚠️ %v\n", err)
} else {
fmt.Fprintf(os.Stderr, "❌ %v\n", err)
}
os.Exit(1)
}
}
// shouldShowFirstTimeSetup determines if the user needs to complete initial setup
func shouldShowFirstTimeSetup() bool {
// Check if user has valid credentials
if !util.IsAuthenticated() {
return true // Need to authenticate first
}
// Check if this is truly first time (no config exists)
return config.IsFirstTimeSetup()
}
// showFirstTimeSetupMessage displays helpful guidance for new users
func showFirstTimeSetupMessage() {
fmt.Println("🆕 Welcome to Devgraph!")
fmt.Println()
fmt.Println("To get started, please authenticate:")
fmt.Println(" dg auth login")
fmt.Println()
fmt.Println("For help:")
fmt.Println(" dg --help")
}
// applyConfigDefaults walks the struct and applies defaults to any embedded config.Config
func applyConfigDefaults(target interface{}) {
v := reflect.ValueOf(target)
if v.Kind() == reflect.Ptr {
v = v.Elem()
}
if v.Kind() != reflect.Struct {
return
}
t := v.Type()
for i := 0; i < v.NumField(); i++ {
field := v.Field(i)
fieldType := t.Field(i)
// Check if this field is config.Config or embeds it
if fieldType.Type == reflect.TypeOf(config.Config{}) && field.CanAddr() {
if cfg, ok := field.Addr().Interface().(*config.Config); ok {
cfg.ApplyDefaults()
}
} else if fieldType.Anonymous && fieldType.Type == reflect.TypeOf(config.Config{}) {
// Handle anonymous/embedded Config
if cfg, ok := field.Addr().Interface().(*config.Config); ok {
cfg.ApplyDefaults()
}
}
}
}