1// TODO: FIX THIS
  2package main
  3
  4import (
  5	"encoding/json"
  6	"fmt"
  7	"os"
  8
  9	"github.com/charmbracelet/crush/internal/config"
 10)
 11
 12// JSONSchemaType represents a JSON Schema type
 13type JSONSchemaType struct {
 14	Type                 string           `json:"type,omitempty"`
 15	Description          string           `json:"description,omitempty"`
 16	Properties           map[string]any   `json:"properties,omitempty"`
 17	Required             []string         `json:"required,omitempty"`
 18	AdditionalProperties any              `json:"additionalProperties,omitempty"`
 19	Enum                 []any            `json:"enum,omitempty"`
 20	Items                map[string]any   `json:"items,omitempty"`
 21	OneOf                []map[string]any `json:"oneOf,omitempty"`
 22	AnyOf                []map[string]any `json:"anyOf,omitempty"`
 23	Default              any              `json:"default,omitempty"`
 24}
 25
 26func main() {
 27	schema := generateSchema()
 28
 29	// Pretty print the schema
 30	encoder := json.NewEncoder(os.Stdout)
 31	encoder.SetIndent("", "  ")
 32	if err := encoder.Encode(schema); err != nil {
 33		fmt.Fprintf(os.Stderr, "Error encoding schema: %v\n", err)
 34		os.Exit(1)
 35	}
 36}
 37
 38func generateSchema() map[string]any {
 39	schema := map[string]any{
 40		"$schema":     "http://json-schema.org/draft-07/schema#",
 41		"title":       "Crush Configuration",
 42		"description": "Configuration schema for the Crush application",
 43		"type":        "object",
 44		"properties":  map[string]any{},
 45	}
 46
 47	// Add Data configuration
 48	schema["properties"].(map[string]any)["data"] = map[string]any{
 49		"type":        "object",
 50		"description": "Storage configuration",
 51		"properties": map[string]any{
 52			"directory": map[string]any{
 53				"type":        "string",
 54				"description": "Directory where application data is stored",
 55				"default":     ".crush",
 56			},
 57		},
 58		"required": []string{"directory"},
 59	}
 60
 61	// Add working directory
 62	schema["properties"].(map[string]any)["wd"] = map[string]any{
 63		"type":        "string",
 64		"description": "Working directory for the application",
 65	}
 66
 67	// Add debug flags
 68	schema["properties"].(map[string]any)["debug"] = map[string]any{
 69		"type":        "boolean",
 70		"description": "Enable debug mode",
 71		"default":     false,
 72	}
 73
 74	schema["properties"].(map[string]any)["debugLSP"] = map[string]any{
 75		"type":        "boolean",
 76		"description": "Enable LSP debug mode",
 77		"default":     false,
 78	}
 79
 80	schema["properties"].(map[string]any)["contextPaths"] = map[string]any{
 81		"type":        "array",
 82		"description": "Context paths for the application",
 83		"items": map[string]any{
 84			"type": "string",
 85		},
 86		"default": []string{
 87			".github/copilot-instructions.md",
 88			".cursorrules",
 89			".cursor/rules/",
 90			"CLAUDE.md",
 91			"CLAUDE.local.md",
 92			"GEMINI.md",
 93			"gemini.md",
 94			"crush.md",
 95			"crush.local.md",
 96			"Crush.md",
 97			"Crush.local.md",
 98			"CRUSH.md",
 99			"CRUSH.local.md",
100		},
101	}
102
103	schema["properties"].(map[string]any)["tui"] = map[string]any{
104		"type":        "object",
105		"description": "Terminal User Interface configuration",
106		"properties": map[string]any{
107			"theme": map[string]any{
108				"type":        "string",
109				"description": "TUI theme name",
110				"default":     "crush",
111				"enum": []string{
112					"crush",
113					"catppuccin",
114					"dracula",
115					"flexoki",
116					"gruvbox",
117					"monokai",
118					"onedark",
119					"tokyonight",
120					"tron",
121				},
122			},
123		},
124	}
125
126	// Add MCP servers
127	schema["properties"].(map[string]any)["mcpServers"] = map[string]any{
128		"type":        "object",
129		"description": "Model Control Protocol server configurations",
130		"additionalProperties": map[string]any{
131			"type":        "object",
132			"description": "MCP server configuration",
133			"properties": map[string]any{
134				"command": map[string]any{
135					"type":        "string",
136					"description": "Command to execute for the MCP server",
137				},
138				"env": map[string]any{
139					"type":        "array",
140					"description": "Environment variables for the MCP server",
141					"items": map[string]any{
142						"type": "string",
143					},
144				},
145				"args": map[string]any{
146					"type":        "array",
147					"description": "Command arguments for the MCP server",
148					"items": map[string]any{
149						"type": "string",
150					},
151				},
152				"type": map[string]any{
153					"type":        "string",
154					"description": "Type of MCP server",
155					"enum":        []string{"stdio", "sse"},
156					"default":     "stdio",
157				},
158				"url": map[string]any{
159					"type":        "string",
160					"description": "URL for SSE type MCP servers",
161				},
162				"headers": map[string]any{
163					"type":        "object",
164					"description": "HTTP headers for SSE type MCP servers",
165					"additionalProperties": map[string]any{
166						"type": "string",
167					},
168				},
169			},
170			"required": []string{"command"},
171		},
172	}
173
174	// Add providers
175	providerSchema := map[string]any{
176		"type":        "object",
177		"description": "LLM provider configurations",
178		"additionalProperties": map[string]any{
179			"type":        "object",
180			"description": "Provider configuration",
181			"properties": map[string]any{
182				"apiKey": map[string]any{
183					"type":        "string",
184					"description": "API key for the provider",
185				},
186				"disabled": map[string]any{
187					"type":        "boolean",
188					"description": "Whether the provider is disabled",
189					"default":     false,
190				},
191			},
192		},
193	}
194
195	providerSchema["additionalProperties"].(map[string]any)["properties"].(map[string]any)["provider"] = map[string]any{
196		"type":        "string",
197		"description": "Provider type",
198		"enum":        []string{},
199	}
200
201	schema["properties"].(map[string]any)["providers"] = providerSchema
202
203	// Add agents
204	agentSchema := map[string]any{
205		"type":        "object",
206		"description": "Agent configurations",
207		"additionalProperties": map[string]any{
208			"type":        "object",
209			"description": "Agent configuration",
210			"properties": map[string]any{
211				"model": map[string]any{
212					"type":        "string",
213					"description": "Model ID for the agent",
214				},
215				"maxTokens": map[string]any{
216					"type":        "integer",
217					"description": "Maximum tokens for the agent",
218					"minimum":     1,
219				},
220				"reasoningEffort": map[string]any{
221					"type":        "string",
222					"description": "Reasoning effort for models that support it (OpenAI, Anthropic)",
223					"enum":        []string{"low", "medium", "high"},
224				},
225			},
226			"required": []string{"model"},
227		},
228	}
229
230	// Add model enum
231	modelEnum := []string{}
232
233	agentSchema["additionalProperties"].(map[string]any)["properties"].(map[string]any)["model"].(map[string]any)["enum"] = modelEnum
234
235	// Add specific agent properties
236	agentProperties := map[string]any{}
237	knownAgents := []string{
238		string(config.AgentCoder),
239		string(config.AgentTask),
240	}
241
242	for _, agentName := range knownAgents {
243		agentProperties[agentName] = map[string]any{
244			"$ref": "#/definitions/agent",
245		}
246	}
247
248	// Create a combined schema that allows both specific agents and additional ones
249	combinedAgentSchema := map[string]any{
250		"type":                 "object",
251		"description":          "Agent configurations",
252		"properties":           agentProperties,
253		"additionalProperties": agentSchema["additionalProperties"],
254	}
255
256	schema["properties"].(map[string]any)["agents"] = combinedAgentSchema
257	schema["definitions"] = map[string]any{
258		"agent": agentSchema["additionalProperties"],
259	}
260
261	// Add LSP configuration
262	schema["properties"].(map[string]any)["lsp"] = map[string]any{
263		"type":        "object",
264		"description": "Language Server Protocol configurations",
265		"additionalProperties": map[string]any{
266			"type":        "object",
267			"description": "LSP configuration for a language",
268			"properties": map[string]any{
269				"disabled": map[string]any{
270					"type":        "boolean",
271					"description": "Whether the LSP is disabled",
272					"default":     false,
273				},
274				"command": map[string]any{
275					"type":        "string",
276					"description": "Command to execute for the LSP server",
277				},
278				"args": map[string]any{
279					"type":        "array",
280					"description": "Command arguments for the LSP server",
281					"items": map[string]any{
282						"type": "string",
283					},
284				},
285				"options": map[string]any{
286					"type":        "object",
287					"description": "Additional options for the LSP server",
288				},
289			},
290			"required": []string{"command"},
291		},
292	}
293
294	return schema
295}