11package cmd
22
33import (
4- "bufio"
54 "fmt"
5+ "io"
66 "os"
7- "strings"
87
98 "github.com/MakeNowJust/heredoc"
109 "github.com/scalvert/glean-cli/pkg/llm"
10+ "github.com/scalvert/glean-cli/pkg/output"
1111 "github.com/spf13/cobra"
1212)
1313
@@ -16,89 +16,89 @@ var (
1616 outputFile string
1717 prompt string
1818 model string
19+ noColor bool
1920)
2021
21- var openapiSpecCmd = & cobra.Command {
22- Use : "openapi-spec" ,
23- Short : "Generate an OpenAPI spec from an API definition or curl command" ,
24- Long : heredoc .Doc (`
25- This command reads an input (either stdin or a file) describing an API endpoint or
26- a curl command and generates an OpenAPI spec, simplifying the creation of Glean Actions.
27-
28- Usage:
29- # Generate from a file
30- glean generate openapi-spec -f input.txt -o spec.yaml
31-
32- # Generate from stdin
33- echo "curl example.com/api" | glean generate openapi-spec
34-
35- # Add custom instructions
36- glean generate openapi-spec -f input.txt --prompt "Include rate limiting details"
37-
38- Input Format:
39- - A curl command
40- - An API description in a simple format
41-
42- Output:
43- OpenAPI specification in YAML format
44- ` ),
45- SilenceUsage : true ,
46- SilenceErrors : true ,
47- RunE : func (cmd * cobra.Command , args []string ) error {
48- var input string
49-
50- if inputFile != "" {
51- data , err := os .ReadFile (inputFile )
52-
53- if err != nil {
54- return fmt .Errorf ("could not read file: %w" , err )
22+ func newOpenapiSpecCmd () * cobra.Command {
23+ cmd := & cobra.Command {
24+ Use : "openapi-spec" ,
25+ Short : "Generate an OpenAPI spec from an API definition or curl command" ,
26+ Long : heredoc .Doc (`
27+ Generate an OpenAPI specification from an API definition or curl command.
28+
29+ The input can be provided via a file or through stdin:
30+ glean generate openapi-spec -f api.txt
31+ echo "curl example.com/api" | glean generate openapi-spec
32+
33+ The generated spec will be in YAML format and can be saved to a file:
34+ glean generate openapi-spec -f api.txt -o spec.yaml
35+
36+ Add custom instructions to guide the generation:
37+ glean generate openapi-spec -f api.txt --prompt "Include rate limiting details"
38+
39+ Use --no-color to disable colorized output.
40+ ` ),
41+ Example : heredoc .Doc (`
42+ # Generate from a curl command
43+ $ echo 'curl -X POST https://api.example.com/users \
44+ -H "Content-Type: application/json" \
45+ -d '"'"'{"name": "John", "email": "john@example.com"}'"'"'' | \
46+ glean generate openapi-spec
47+
48+ # Generate from a file with custom instructions
49+ $ glean generate openapi-spec -f api.txt --prompt "Include authentication details"
50+
51+ # Save to a file
52+ $ glean generate openapi-spec -f api.txt -o spec.yaml
53+ ` ),
54+ RunE : func (cmd * cobra.Command , args []string ) error {
55+ var input []byte
56+ var err error
57+
58+ if inputFile == "-" || inputFile == "" {
59+ input , err = io .ReadAll (os .Stdin )
60+ if err != nil {
61+ return fmt .Errorf ("failed to read from stdin: %w" , err )
62+ }
63+ if len (input ) == 0 {
64+ return fmt .Errorf ("no input provided" )
65+ }
66+ } else {
67+ input , err = os .ReadFile (inputFile )
68+ if err != nil {
69+ return fmt .Errorf ("failed to read input file: %w" , err )
70+ }
5571 }
56- input = string (data )
57- } else {
58- stat , _ := os .Stdin .Stat ()
5972
60- if (stat .Mode () & os .ModeCharDevice ) != 0 {
61- return fmt .Errorf ("no input found; please provide a file or pipe input to stdin" )
62- }
63-
64- scanner := bufio .NewScanner (os .Stdin )
65-
66- var lines []string
67-
68- for scanner .Scan () {
69- lines = append (lines , scanner .Text ())
73+ spec , err := llm .GenerateOpenAPISpec (string (input ), prompt , model )
74+ if err != nil {
75+ return fmt .Errorf ("failed to generate OpenAPI spec: %w" , err )
7076 }
7177
72- if err := scanner .Err (); err != nil {
73- return fmt .Errorf ("error reading input: %w" , err )
78+ if outputFile != "" {
79+ if err := os .WriteFile (outputFile , []byte (spec ), 0644 ); err != nil {
80+ return fmt .Errorf ("failed to write output file: %w" , err )
81+ }
82+ fmt .Fprintf (cmd .OutOrStdout (), "OpenAPI spec written to %s\n " , outputFile )
83+ return nil
7484 }
7585
76- input = strings .Join (lines , "\n " )
77- }
78-
79- spec , err := llm .GenerateOpenAPISpec (input , prompt , model )
80- if err != nil {
81- return err
82- }
86+ return output .WriteString (cmd .OutOrStdout (), spec , output.Options {
87+ NoColor : noColor ,
88+ Format : "yaml" ,
89+ })
90+ },
91+ }
8392
84- if outputFile != "" {
85- if err := os .WriteFile (outputFile , []byte (spec ), 0600 ); err != nil {
86- return fmt .Errorf ("failed to write output file: %w" , err )
87- }
88- fmt .Printf ("OpenAPI spec written to %s\n " , outputFile )
89- } else {
90- fmt .Println (spec )
91- }
93+ cmd .Flags ().StringVarP (& inputFile , "file" , "f" , "" , "Input file containing the API/curl command (use \" -\" for stdin)" )
94+ cmd .Flags ().StringVarP (& outputFile , "output" , "o" , "" , "Output file for the OpenAPI spec" )
95+ cmd .Flags ().StringVarP (& prompt , "prompt" , "p" , "" , "Additional instructions for the LLM" )
96+ cmd .Flags ().StringVar (& model , "model" , "gpt-4" , "LLM model to use" )
97+ cmd .Flags ().BoolVar (& noColor , "no-color" , false , "Disable colorized output" )
9298
93- return nil
94- },
99+ return cmd
95100}
96101
97102func init () {
98- generateCmd .AddCommand (openapiSpecCmd )
99-
100- openapiSpecCmd .Flags ().StringVarP (& inputFile , "file" , "f" , "" , "Input file containing the API/curl command" )
101- openapiSpecCmd .Flags ().StringVarP (& outputFile , "output" , "o" , "" , "Output file for the OpenAPI spec (defaults to stdout)" )
102- openapiSpecCmd .Flags ().StringVarP (& prompt , "prompt" , "p" , "" , "Additional instructions for the LLM" )
103- openapiSpecCmd .Flags ().StringVar (& model , "model" , "gpt-4" , "LLM model to use" )
103+ generateCmd .AddCommand (newOpenapiSpecCmd ())
104104}
0 commit comments