Skip to content

Commit 7c0094d

Browse files
fix(mcp): correct code tool API endpoint
1 parent 51bb415 commit 7c0094d

File tree

5 files changed

+629
-1
lines changed

5 files changed

+629
-1
lines changed

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/onkernel/hypeman-go v0.8.0
1616
github.com/tidwall/gjson v1.18.0
1717
github.com/tidwall/pretty v1.2.1
18+
github.com/tidwall/sjson v1.2.5
1819
github.com/urfave/cli-docs/v3 v3.0.0-alpha6
1920
github.com/urfave/cli/v3 v3.3.2
2021
golang.org/x/sys v0.38.0
@@ -60,7 +61,6 @@ require (
6061
github.com/russross/blackfriday/v2 v2.1.0 // indirect
6162
github.com/sirupsen/logrus v1.9.3 // indirect
6263
github.com/tidwall/match v1.1.1 // indirect
63-
github.com/tidwall/sjson v1.2.5 // indirect
6464
github.com/vbatts/tar-split v0.12.2 // indirect
6565
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
6666
go.opentelemetry.io/auto/sdk v1.1.0 // indirect

pkg/cmd/util.go

Lines changed: 239 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,239 @@
1+
// File generated from our OpenAPI spec by Stainless. See CONTRIBUTING.md for details.
2+
3+
package cmd
4+
5+
import (
6+
"bytes"
7+
"encoding/base64"
8+
"encoding/json"
9+
"fmt"
10+
"io"
11+
"log"
12+
"net/http"
13+
"net/http/httputil"
14+
"os"
15+
"reflect"
16+
"strings"
17+
18+
"golang.org/x/term"
19+
20+
"github.com/onkernel/hypeman-cli/pkg/jsonview"
21+
"github.com/onkernel/hypeman-go/option"
22+
23+
"github.com/itchyny/json2yaml"
24+
"github.com/tidwall/gjson"
25+
"github.com/tidwall/pretty"
26+
"github.com/tidwall/sjson"
27+
"github.com/urfave/cli/v3"
28+
)
29+
30+
func getDefaultRequestOptions(cmd *cli.Command) []option.RequestOption {
31+
opts := []option.RequestOption{
32+
option.WithHeader("User-Agent", fmt.Sprintf("Hypeman/CLI %s", Version)),
33+
option.WithHeader("X-Stainless-Lang", "cli"),
34+
option.WithHeader("X-Stainless-Package-Version", Version),
35+
option.WithHeader("X-Stainless-Runtime", "cli"),
36+
option.WithHeader("X-Stainless-CLI-Command", cmd.FullName()),
37+
}
38+
39+
// Override base URL if the --base-url flag is provided
40+
if baseURL := cmd.String("base-url"); baseURL != "" {
41+
opts = append(opts, option.WithBaseURL(baseURL))
42+
}
43+
44+
return opts
45+
}
46+
47+
type fileReader struct {
48+
Value io.Reader
49+
Base64Encoded bool
50+
}
51+
52+
func (f *fileReader) Set(filename string) error {
53+
reader, err := os.Open(filename)
54+
if err != nil {
55+
return fmt.Errorf("failed to read file %q: %w", filename, err)
56+
}
57+
f.Value = reader
58+
return nil
59+
}
60+
61+
func (f *fileReader) String() string {
62+
if f.Value == nil {
63+
return ""
64+
}
65+
buf := new(bytes.Buffer)
66+
buf.ReadFrom(f.Value)
67+
if f.Base64Encoded {
68+
return base64.StdEncoding.EncodeToString(buf.Bytes())
69+
}
70+
return buf.String()
71+
}
72+
73+
func (f *fileReader) Get() any {
74+
return f.String()
75+
}
76+
77+
func unmarshalWithReaders(data []byte, v any) error {
78+
var fields map[string]json.RawMessage
79+
if err := json.Unmarshal(data, &fields); err != nil {
80+
return err
81+
}
82+
83+
rv := reflect.ValueOf(v).Elem()
84+
rt := rv.Type()
85+
86+
for i := 0; i < rv.NumField(); i++ {
87+
fv := rv.Field(i)
88+
ft := rt.Field(i)
89+
90+
jsonKey := ft.Tag.Get("json")
91+
if jsonKey == "" {
92+
jsonKey = ft.Name
93+
} else if idx := strings.Index(jsonKey, ","); idx != -1 {
94+
jsonKey = jsonKey[:idx]
95+
}
96+
97+
rawVal, ok := fields[jsonKey]
98+
if !ok {
99+
continue
100+
}
101+
102+
if ft.Type == reflect.TypeOf((*io.Reader)(nil)).Elem() {
103+
var s string
104+
if err := json.Unmarshal(rawVal, &s); err != nil {
105+
return fmt.Errorf("field %s: %w", ft.Name, err)
106+
}
107+
fv.Set(reflect.ValueOf(strings.NewReader(s)))
108+
} else {
109+
ptr := fv.Addr().Interface()
110+
if err := json.Unmarshal(rawVal, ptr); err != nil {
111+
return fmt.Errorf("field %s: %w", ft.Name, err)
112+
}
113+
}
114+
}
115+
116+
return nil
117+
}
118+
119+
func unmarshalStdinWithFlags(cmd *cli.Command, flags map[string]string, target any) error {
120+
var data []byte
121+
if isInputPiped() {
122+
var err error
123+
if data, err = io.ReadAll(os.Stdin); err != nil {
124+
return err
125+
}
126+
}
127+
128+
// Merge CLI flags into the body
129+
for flag, path := range flags {
130+
if cmd.IsSet(flag) {
131+
var err error
132+
data, err = sjson.SetBytes(data, path, cmd.Value(flag))
133+
if err != nil {
134+
return err
135+
}
136+
}
137+
}
138+
139+
if data != nil {
140+
if err := unmarshalWithReaders(data, target); err != nil {
141+
return fmt.Errorf("failed to unmarshal JSON: %w", err)
142+
}
143+
}
144+
145+
return nil
146+
}
147+
148+
func debugMiddleware(debug bool) option.Middleware {
149+
return func(r *http.Request, mn option.MiddlewareNext) (*http.Response, error) {
150+
if debug {
151+
logger := log.Default()
152+
153+
if reqBytes, err := httputil.DumpRequest(r, true); err == nil {
154+
logger.Printf("Request Content:\n%s\n", reqBytes)
155+
}
156+
157+
resp, err := mn(r)
158+
if err != nil {
159+
return resp, err
160+
}
161+
162+
if respBytes, err := httputil.DumpResponse(resp, true); err == nil {
163+
logger.Printf("Response Content:\n%s\n", respBytes)
164+
}
165+
166+
return resp, err
167+
}
168+
169+
return mn(r)
170+
}
171+
}
172+
173+
func isInputPiped() bool {
174+
stat, _ := os.Stdin.Stat()
175+
return (stat.Mode() & os.ModeCharDevice) == 0
176+
}
177+
178+
func isTerminal(w io.Writer) bool {
179+
switch v := w.(type) {
180+
case *os.File:
181+
return term.IsTerminal(int(v.Fd()))
182+
default:
183+
return false
184+
}
185+
}
186+
187+
func shouldUseColors(w io.Writer) bool {
188+
force, ok := os.LookupEnv("FORCE_COLOR")
189+
190+
if ok {
191+
if force == "1" {
192+
return true
193+
}
194+
if force == "0" {
195+
return false
196+
}
197+
}
198+
199+
return isTerminal(w)
200+
}
201+
202+
func ShowJSON(title string, res gjson.Result, format string, transform string) error {
203+
if format != "raw" && transform != "" {
204+
transformed := res.Get(transform)
205+
if transformed.Exists() {
206+
res = transformed
207+
}
208+
}
209+
switch strings.ToLower(format) {
210+
case "auto":
211+
return ShowJSON(title, res, "json", "")
212+
case "explore":
213+
return jsonview.ExploreJSON(title, res)
214+
case "pretty":
215+
jsonview.DisplayJSON(title, res)
216+
return nil
217+
case "json":
218+
prettyJSON := pretty.Pretty([]byte(res.Raw))
219+
if shouldUseColors(os.Stdout) {
220+
fmt.Print(string(pretty.Color(prettyJSON, pretty.TerminalStyle)))
221+
} else {
222+
fmt.Print(string(prettyJSON))
223+
}
224+
return nil
225+
case "raw":
226+
fmt.Println(res.Raw)
227+
return nil
228+
case "yaml":
229+
input := strings.NewReader(res.Raw)
230+
var yaml strings.Builder
231+
if err := json2yaml.Convert(&yaml, input); err != nil {
232+
return err
233+
}
234+
fmt.Print(yaml.String())
235+
return nil
236+
default:
237+
return fmt.Errorf("Invalid format: %s, valid formats are: %s", format, strings.Join(OutputFormats, ", "))
238+
}
239+
}

0 commit comments

Comments
 (0)