From dd70400abff7e7332cf7a7f3dee59e9e2e4b61b5 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 02:03:10 +0000 Subject: [PATCH 01/16] feat(api): api update --- .stats.yml | 4 ++-- node.go | 17 ++++++++++++++--- node_test.go | 3 ++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/.stats.yml b/.stats.yml index 649bd1e..a4da285 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-c9d6d56eabd56a40a29dc2639a77d22dd5394ecd3ec9aeaebb3a3977811571da.yml -openapi_spec_hash: beda3f45c48679e14d6fe8bbe7003d51 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-7284b205c8d1bc77799405fdd08ca68120426b87031cbc22718da68e22ed5a4c.yml +openapi_spec_hash: b0248957ae5bcf9896f6d74d5c05351b config_hash: a187153315a646ecf95709ee4a223df5 diff --git a/node.go b/node.go index b15c3ad..e37d18a 100644 --- a/node.go +++ b/node.go @@ -125,16 +125,16 @@ const ( AcceleratorTypeH200 AcceleratorType = "H200" ) -// The properties DesiredCount, MaxPricePerNodeHour, Zone are required. +// The properties DesiredCount, MaxPricePerNodeHour are required. type CreateNodesRequestParam struct { DesiredCount int64 `json:"desired_count,required"` // Max price per hour for a node in cents MaxPricePerNodeHour int64 `json:"max_price_per_node_hour,required"` - // Zone to create the nodes in - Zone string `json:"zone,required"` // End time as Unix timestamp in seconds If provided, end time must be aligned to // the hour If not provided, the node will be created as an autoreserved node EndAt param.Opt[int64] `json:"end_at,omitzero"` + // Allow auto reserved nodes to be created in any zone that meets the requirements + AnyZone param.Opt[bool] `json:"any_zone,omitzero"` // User script to be executed during the VM's boot process Data should be base64 // encoded CloudInitUserData param.Opt[string] `json:"cloud_init_user_data,omitzero" format:"byte"` @@ -143,6 +143,9 @@ type CreateNodesRequestParam struct { // Start time as Unix timestamp in seconds Optional for reserved nodes. If not // provided, defaults to now StartAt param.Opt[int64] `json:"start_at,omitzero"` + // Zone to create the nodes in. Required for auto reserved nodes if any_zone is + // false. + Zone param.Opt[string] `json:"zone,omitzero"` // Custom node names Names cannot begin with 'vm*' or 'n*' as this is reserved for // system-generated IDs Names cannot be numeric strings Names cannot exceed 128 // characters @@ -265,6 +268,7 @@ type ListResponseNodeDataCurrentVM struct { // Any of "Pending", "Running", "Destroyed", "NodeFailure", "Unspecified". Status string `json:"status,required"` UpdatedAt int64 `json:"updated_at,required"` + Zone string `json:"zone,required"` ImageID string `json:"image_id,nullable"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { @@ -275,6 +279,7 @@ type ListResponseNodeDataCurrentVM struct { StartAt respjson.Field Status respjson.Field UpdatedAt respjson.Field + Zone respjson.Field ImageID respjson.Field ExtraFields map[string]respjson.Field raw string @@ -314,6 +319,7 @@ type ListResponseNodeDataVMsData struct { // Any of "Pending", "Running", "Destroyed", "NodeFailure", "Unspecified". Status string `json:"status,required"` UpdatedAt int64 `json:"updated_at,required"` + Zone string `json:"zone,required"` ImageID string `json:"image_id,nullable"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { @@ -324,6 +330,7 @@ type ListResponseNodeDataVMsData struct { StartAt respjson.Field Status respjson.Field UpdatedAt respjson.Field + Zone respjson.Field ImageID respjson.Field ExtraFields map[string]respjson.Field raw string @@ -405,6 +412,7 @@ type NodeCurrentVM struct { // Any of "Pending", "Running", "Destroyed", "NodeFailure", "Unspecified". Status string `json:"status,required"` UpdatedAt int64 `json:"updated_at,required"` + Zone string `json:"zone,required"` ImageID string `json:"image_id,nullable"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { @@ -415,6 +423,7 @@ type NodeCurrentVM struct { StartAt respjson.Field Status respjson.Field UpdatedAt respjson.Field + Zone respjson.Field ImageID respjson.Field ExtraFields map[string]respjson.Field raw string @@ -454,6 +463,7 @@ type NodeVMsData struct { // Any of "Pending", "Running", "Destroyed", "NodeFailure", "Unspecified". Status string `json:"status,required"` UpdatedAt int64 `json:"updated_at,required"` + Zone string `json:"zone,required"` ImageID string `json:"image_id,nullable"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { @@ -464,6 +474,7 @@ type NodeVMsData struct { StartAt respjson.Field Status respjson.Field UpdatedAt respjson.Field + Zone respjson.Field ImageID respjson.Field ExtraFields map[string]respjson.Field raw string diff --git a/node_test.go b/node_test.go index 88ca793..026a72a 100644 --- a/node_test.go +++ b/node_test.go @@ -30,13 +30,14 @@ func TestNodeNewWithOptionalParams(t *testing.T) { CreateNodesRequest: sfcnodes.CreateNodesRequestParam{ DesiredCount: 1, MaxPricePerNodeHour: 1000, - Zone: "hayesvalley", + AnyZone: sfcnodes.Bool(false), CloudInitUserData: sfcnodes.String("aGVsbG8gd29ybGQ="), EndAt: sfcnodes.Int(0), ImageID: sfcnodes.String("vmi_1234567890abcdef"), Names: []string{"cuda-crunch"}, NodeType: sfcnodes.NodeTypeAutoreserved, StartAt: sfcnodes.Int(1640995200), + Zone: sfcnodes.String("hayesvalley"), }, }) if err != nil { From e40a3debee22efa7015e5230d14374245af79b1f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 04:29:23 +0000 Subject: [PATCH 02/16] chore(internal): codegen related update --- internal/paramutil/sentinel.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 internal/paramutil/sentinel.go diff --git a/internal/paramutil/sentinel.go b/internal/paramutil/sentinel.go new file mode 100644 index 0000000..ba8eaee --- /dev/null +++ b/internal/paramutil/sentinel.go @@ -0,0 +1,31 @@ +package paramutil + +import ( + "github.com/sfcompute/nodes-go/internal/encoding/json/sentinel" +) + +// NullPtr returns a pointer to the zero value of the type T. +// When used with [MarshalObject] or [MarshalUnion], it will be marshaled as null. +// +// It is unspecified behavior to mutate the value pointed to by the returned pointer. +func NullPtr[T any]() *T { + return sentinel.NullPtr[T]() +} + +// IsNullPtr returns true if the pointer was created by [NullPtr]. +func IsNullPtr[T any](ptr *T) bool { + return sentinel.IsNullPtr(ptr) +} + +// NullSlice returns a non-nil slice with a length of 0. +// When used with [MarshalObject] or [MarshalUnion], it will be marshaled as null. +// +// It is undefined behavior to mutate the slice returned by [NullSlice]. +func NullSlice[T any]() []T { + return sentinel.NullSlice[T]() +} + +// IsNullSlice returns true if the slice was created by [NullSlice]. +func IsNullSlice[T any](slice []T) bool { + return sentinel.IsNullSlice(slice) +} From 9e83189fd37d851e8441c313c738656a72760483 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 04:30:09 +0000 Subject: [PATCH 03/16] chore: elide duplicate aliases --- internal/paramutil/sentinel.go | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 internal/paramutil/sentinel.go diff --git a/internal/paramutil/sentinel.go b/internal/paramutil/sentinel.go deleted file mode 100644 index ba8eaee..0000000 --- a/internal/paramutil/sentinel.go +++ /dev/null @@ -1,31 +0,0 @@ -package paramutil - -import ( - "github.com/sfcompute/nodes-go/internal/encoding/json/sentinel" -) - -// NullPtr returns a pointer to the zero value of the type T. -// When used with [MarshalObject] or [MarshalUnion], it will be marshaled as null. -// -// It is unspecified behavior to mutate the value pointed to by the returned pointer. -func NullPtr[T any]() *T { - return sentinel.NullPtr[T]() -} - -// IsNullPtr returns true if the pointer was created by [NullPtr]. -func IsNullPtr[T any](ptr *T) bool { - return sentinel.IsNullPtr(ptr) -} - -// NullSlice returns a non-nil slice with a length of 0. -// When used with [MarshalObject] or [MarshalUnion], it will be marshaled as null. -// -// It is undefined behavior to mutate the slice returned by [NullSlice]. -func NullSlice[T any]() []T { - return sentinel.NullSlice[T]() -} - -// IsNullSlice returns true if the slice was created by [NullSlice]. -func IsNullSlice[T any](slice []T) bool { - return sentinel.IsNullSlice(slice) -} From 2eeb64be8909979b8cb3524a077cb764c85a1f21 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 04:30:46 +0000 Subject: [PATCH 04/16] fix(mcp): correct code tool API endpoint --- internal/paramutil/sentinel.go | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 internal/paramutil/sentinel.go diff --git a/internal/paramutil/sentinel.go b/internal/paramutil/sentinel.go new file mode 100644 index 0000000..ba8eaee --- /dev/null +++ b/internal/paramutil/sentinel.go @@ -0,0 +1,31 @@ +package paramutil + +import ( + "github.com/sfcompute/nodes-go/internal/encoding/json/sentinel" +) + +// NullPtr returns a pointer to the zero value of the type T. +// When used with [MarshalObject] or [MarshalUnion], it will be marshaled as null. +// +// It is unspecified behavior to mutate the value pointed to by the returned pointer. +func NullPtr[T any]() *T { + return sentinel.NullPtr[T]() +} + +// IsNullPtr returns true if the pointer was created by [NullPtr]. +func IsNullPtr[T any](ptr *T) bool { + return sentinel.IsNullPtr(ptr) +} + +// NullSlice returns a non-nil slice with a length of 0. +// When used with [MarshalObject] or [MarshalUnion], it will be marshaled as null. +// +// It is undefined behavior to mutate the slice returned by [NullSlice]. +func NullSlice[T any]() []T { + return sentinel.NullSlice[T]() +} + +// IsNullSlice returns true if the slice was created by [NullSlice]. +func IsNullSlice[T any](slice []T) bool { + return sentinel.IsNullSlice(slice) +} From f221c7569b746c43bd46c4ab3c1615b30fc0c05c Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 04:31:27 +0000 Subject: [PATCH 05/16] fix: rename param to avoid collision --- internal/paramutil/sentinel.go | 31 ------------------------------- 1 file changed, 31 deletions(-) delete mode 100644 internal/paramutil/sentinel.go diff --git a/internal/paramutil/sentinel.go b/internal/paramutil/sentinel.go deleted file mode 100644 index ba8eaee..0000000 --- a/internal/paramutil/sentinel.go +++ /dev/null @@ -1,31 +0,0 @@ -package paramutil - -import ( - "github.com/sfcompute/nodes-go/internal/encoding/json/sentinel" -) - -// NullPtr returns a pointer to the zero value of the type T. -// When used with [MarshalObject] or [MarshalUnion], it will be marshaled as null. -// -// It is unspecified behavior to mutate the value pointed to by the returned pointer. -func NullPtr[T any]() *T { - return sentinel.NullPtr[T]() -} - -// IsNullPtr returns true if the pointer was created by [NullPtr]. -func IsNullPtr[T any](ptr *T) bool { - return sentinel.IsNullPtr(ptr) -} - -// NullSlice returns a non-nil slice with a length of 0. -// When used with [MarshalObject] or [MarshalUnion], it will be marshaled as null. -// -// It is undefined behavior to mutate the slice returned by [NullSlice]. -func NullSlice[T any]() []T { - return sentinel.NullSlice[T]() -} - -// IsNullSlice returns true if the slice was created by [NullSlice]. -func IsNullSlice[T any](slice []T) bool { - return sentinel.IsNullSlice(slice) -} From 0af4350619954ebd42478fe2d59dc4f17dcd8642 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Mon, 8 Dec 2025 07:21:45 +0000 Subject: [PATCH 06/16] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index a4da285..c0212fd 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-7284b205c8d1bc77799405fdd08ca68120426b87031cbc22718da68e22ed5a4c.yml -openapi_spec_hash: b0248957ae5bcf9896f6d74d5c05351b +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-d630bbe1a2a6a2f640d4391fcde47e5d1e260ce7773132fbacaa2a1dad692f93.yml +openapi_spec_hash: 0e328dfa7e269debc666a0d4f7fb349e config_hash: a187153315a646ecf95709ee4a223df5 From 59ae9e5d89b240e99acc2ac64cc889be1a4d7665 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 9 Dec 2025 02:22:06 +0000 Subject: [PATCH 07/16] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index c0212fd..4184093 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-d630bbe1a2a6a2f640d4391fcde47e5d1e260ce7773132fbacaa2a1dad692f93.yml -openapi_spec_hash: 0e328dfa7e269debc666a0d4f7fb349e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-00ce4132845e0412fe1cc0c1f490124468a13306eee4fa6110265cb74b0e44a9.yml +openapi_spec_hash: e04281f57e0fe175d6614d0440a1e81f config_hash: a187153315a646ecf95709ee4a223df5 From bf75f99a26c353742229dabb561684545d0835c7 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 04:39:29 +0000 Subject: [PATCH 08/16] feat(encoder): support bracket encoding form-data object members --- internal/apiform/encoder.go | 80 +++++++++++++++++++---------------- internal/apiform/form_test.go | 51 +++++++++++++++++++++- 2 files changed, 94 insertions(+), 37 deletions(-) diff --git a/internal/apiform/encoder.go b/internal/apiform/encoder.go index 8fd59d9..cd7b726 100644 --- a/internal/apiform/encoder.go +++ b/internal/apiform/encoder.go @@ -60,6 +60,7 @@ type encoderField struct { type encoderEntry struct { reflect.Type dateFormat string + arrayFmt string root bool } @@ -77,6 +78,7 @@ func (e *encoder) typeEncoder(t reflect.Type) encoderFunc { entry := encoderEntry{ Type: t, dateFormat: e.dateFormat, + arrayFmt: e.arrayFmt, root: e.root, } @@ -178,34 +180,9 @@ func (e *encoder) newPrimitiveTypeEncoder(t reflect.Type) encoderFunc { } } -func arrayKeyEncoder(arrayFmt string) func(string, int) string { - var keyFn func(string, int) string - switch arrayFmt { - case "comma", "repeat": - keyFn = func(k string, _ int) string { return k } - case "brackets": - keyFn = func(key string, _ int) string { return key + "[]" } - case "indices:dots": - keyFn = func(k string, i int) string { - if k == "" { - return strconv.Itoa(i) - } - return k + "." + strconv.Itoa(i) - } - case "indices:brackets": - keyFn = func(k string, i int) string { - if k == "" { - return strconv.Itoa(i) - } - return k + "[" + strconv.Itoa(i) + "]" - } - } - return keyFn -} - func (e *encoder) newArrayTypeEncoder(t reflect.Type) encoderFunc { itemEncoder := e.typeEncoder(t.Elem()) - keyFn := arrayKeyEncoder(e.arrayFmt) + keyFn := e.arrayKeyEncoder() return func(key string, v reflect.Value, writer *multipart.Writer) error { if keyFn == nil { return fmt.Errorf("apiform: unsupported array format") @@ -303,13 +280,10 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc { }) return func(key string, value reflect.Value, writer *multipart.Writer) error { - if key != "" { - key = key + "." - } - + keyFn := e.objKeyEncoder(key) for _, ef := range encoderFields { field := value.FieldByIndex(ef.idx) - err := ef.fn(key+ef.tag.name, field, writer) + err := ef.fn(keyFn(ef.tag.name), field, writer) if err != nil { return err } @@ -405,6 +379,43 @@ func (e *encoder) newReaderTypeEncoder() encoderFunc { } } +func (e encoder) arrayKeyEncoder() func(string, int) string { + var keyFn func(string, int) string + switch e.arrayFmt { + case "comma", "repeat": + keyFn = func(k string, _ int) string { return k } + case "brackets": + keyFn = func(key string, _ int) string { return key + "[]" } + case "indices:dots": + keyFn = func(k string, i int) string { + if k == "" { + return strconv.Itoa(i) + } + return k + "." + strconv.Itoa(i) + } + case "indices:brackets": + keyFn = func(k string, i int) string { + if k == "" { + return strconv.Itoa(i) + } + return k + "[" + strconv.Itoa(i) + "]" + } + } + return keyFn +} + +func (e encoder) objKeyEncoder(parent string) func(string) string { + if parent == "" { + return func(child string) string { return child } + } + switch e.arrayFmt { + case "brackets": + return func(child string) string { return parent + "[" + child + "]" } + default: + return func(child string) string { return parent + "." + child } + } +} + // Given a []byte of json (may either be an empty object or an object that already contains entries) // encode all of the entries in the map to the json byte array. func (e *encoder) encodeMapEntries(key string, v reflect.Value, writer *multipart.Writer) error { @@ -413,10 +424,6 @@ func (e *encoder) encodeMapEntries(key string, v reflect.Value, writer *multipar value reflect.Value } - if key != "" { - key = key + "." - } - pairs := []mapPair{} iter := v.MapRange() @@ -434,8 +441,9 @@ func (e *encoder) encodeMapEntries(key string, v reflect.Value, writer *multipar }) elementEncoder := e.typeEncoder(v.Type().Elem()) + keyFn := e.objKeyEncoder(key) for _, p := range pairs { - err := elementEncoder(key+string(p.key), p.value, writer) + err := elementEncoder(keyFn(p.key), p.value, writer) if err != nil { return err } diff --git a/internal/apiform/form_test.go b/internal/apiform/form_test.go index 0d05c4a..1874257 100644 --- a/internal/apiform/form_test.go +++ b/internal/apiform/form_test.go @@ -123,6 +123,18 @@ type StructUnion struct { param.APIUnion } +type MultipartMarshalerParent struct { + Middle MultipartMarshalerMiddleNext `form:"middle"` +} + +type MultipartMarshalerMiddleNext struct { + MiddleNext MultipartMarshalerMiddle `form:"middleNext"` +} + +type MultipartMarshalerMiddle struct { + Child int `form:"child"` +} + var tests = map[string]struct { buf string val any @@ -366,6 +378,19 @@ true }, }, }, + "recursive_struct,brackets": { + `--xxx +Content-Disposition: form-data; name="child[name]" + +Alex +--xxx +Content-Disposition: form-data; name="name" + +Robert +--xxx-- +`, + Recursive{Name: "Robert", Child: &Recursive{Name: "Alex"}}, + }, "recursive_struct": { `--xxx @@ -529,6 +554,30 @@ Content-Disposition: form-data; name="union" Union: UnionTime(time.Date(2010, 05, 23, 0, 0, 0, 0, time.UTC)), }, }, + "deeply-nested-struct,brackets": { + `--xxx +Content-Disposition: form-data; name="middle[middleNext][child]" + +10 +--xxx-- +`, + MultipartMarshalerParent{ + Middle: MultipartMarshalerMiddleNext{ + MiddleNext: MultipartMarshalerMiddle{ + Child: 10, + }, + }, + }, + }, + "deeply-nested-map,brackets": { + `--xxx +Content-Disposition: form-data; name="middle[middleNext][child]" + +10 +--xxx-- +`, + map[string]any{"middle": map[string]any{"middleNext": map[string]any{"child": 10}}}, + }, } func TestEncode(t *testing.T) { @@ -553,7 +602,7 @@ func TestEncode(t *testing.T) { } raw := buf.Bytes() if string(raw) != strings.ReplaceAll(test.buf, "\n", "\r\n") { - t.Errorf("expected %+#v to serialize to '%s' but got '%s'", test.val, test.buf, string(raw)) + t.Errorf("expected %+#v to serialize to '%s' but got '%s' (with format %s)", test.val, test.buf, string(raw), arrayFmt) } }) } From aa2636805de581a3595d96e7b20de580696393ce Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 03:21:43 +0000 Subject: [PATCH 09/16] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 4184093..47588b8 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-00ce4132845e0412fe1cc0c1f490124468a13306eee4fa6110265cb74b0e44a9.yml -openapi_spec_hash: e04281f57e0fe175d6614d0440a1e81f +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-ad234e475934741940c514edea2d2cfb9e0576b6f58087bb26a5ca440d818eae.yml +openapi_spec_hash: 5676172e7f99c37ad7425a4891525c9e config_hash: a187153315a646ecf95709ee4a223df5 From e16239107a6784fcfbd90cd29e7c24343d83a11f Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 16 Dec 2025 06:21:58 +0000 Subject: [PATCH 10/16] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 47588b8..996b4fa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-ad234e475934741940c514edea2d2cfb9e0576b6f58087bb26a5ca440d818eae.yml -openapi_spec_hash: 5676172e7f99c37ad7425a4891525c9e +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-331baedc042497d9185a8161e2697f02086ca49f8bb15e6e8d162c881d493059.yml +openapi_spec_hash: a37a2df2a9638363141188cdac38ea73 config_hash: a187153315a646ecf95709ee4a223df5 From 61d03bd3c1f7772a74bef48676020df27c371ab1 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 06:35:13 +0000 Subject: [PATCH 11/16] fix: skip usage tests that don't work with Prism --- usage_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/usage_test.go b/usage_test.go index 1117ee4..dc7e012 100644 --- a/usage_test.go +++ b/usage_test.go @@ -24,6 +24,7 @@ func TestUsage(t *testing.T) { option.WithBaseURL(baseURL), option.WithBearerToken("My Bearer Token"), ) + t.Skip("Prism tests are disabled") listResponseNode, err := client.Nodes.List(context.TODO(), sfcnodes.NodeListParams{}) if err != nil { t.Fatalf("err should be nil: %s", err.Error()) From e87a5d36d82b6df6fe59de944d341e4aaf8fccfb Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 22:21:39 +0000 Subject: [PATCH 12/16] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 996b4fa..883b0fa 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-331baedc042497d9185a8161e2697f02086ca49f8bb15e6e8d162c881d493059.yml -openapi_spec_hash: a37a2df2a9638363141188cdac38ea73 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-54af1b82f474ebc6f28e82b3ad603a8fd9c5f9c0ebcc6e72c6d53876126bc432.yml +openapi_spec_hash: 105d4fa4782b22a506739072d6905df7 config_hash: a187153315a646ecf95709ee4a223df5 From 499e663b659fa00c013ebe3db1e0622b5e2a6a51 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 05:41:34 +0000 Subject: [PATCH 13/16] chore: add float64 to valid types for RegisterFieldValidator --- internal/apijson/enum.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/apijson/enum.go b/internal/apijson/enum.go index 18b218a..5bef11c 100644 --- a/internal/apijson/enum.go +++ b/internal/apijson/enum.go @@ -29,7 +29,7 @@ type validatorFunc func(reflect.Value) exactness var validators sync.Map var validationRegistry = map[reflect.Type][]validationEntry{} -func RegisterFieldValidator[T any, V string | bool | int](fieldName string, values ...V) { +func RegisterFieldValidator[T any, V string | bool | int | float64](fieldName string, values ...V) { var t T parentType := reflect.TypeOf(t) From e871fac7f47970664bf5b4b608ffd83f02342d12 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 09:21:47 +0000 Subject: [PATCH 14/16] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 883b0fa..1899ae9 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-54af1b82f474ebc6f28e82b3ad603a8fd9c5f9c0ebcc6e72c6d53876126bc432.yml -openapi_spec_hash: 105d4fa4782b22a506739072d6905df7 +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-03edf542ab3939ae0c77273542f4f33e07924cc44316260f855e884f42ae9929.yml +openapi_spec_hash: 52771530706e879f6c58d8f7ede21d1c config_hash: a187153315a646ecf95709ee4a223df5 From 356e8a03ed9ed0763fb8f2bf8c7fd34616ee2c5a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 23:21:58 +0000 Subject: [PATCH 15/16] codegen metadata --- .stats.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.stats.yml b/.stats.yml index 1899ae9..a890fcc 100644 --- a/.stats.yml +++ b/.stats.yml @@ -1,4 +1,4 @@ configured_endpoints: 15 -openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-03edf542ab3939ae0c77273542f4f33e07924cc44316260f855e884f42ae9929.yml -openapi_spec_hash: 52771530706e879f6c58d8f7ede21d1c +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/the-san-francisco-compute-company%2Fsfc-nodes-7686e4482b4198d5272206797ea47239ffa1beba6e49f3db5a257e4c7d3f832d.yml +openapi_spec_hash: 19955ca78c8b6ebca90ab66394aca311 config_hash: a187153315a646ecf95709ee4a223df5 From 2541af27a97f4f25601b3ecfeac3d038113e441a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 23:22:15 +0000 Subject: [PATCH 16/16] release: 0.1.0-alpha.5 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 23 +++++++++++++++++++++++ README.md | 2 +- internal/version.go | 2 +- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index b56c3d0..e8285b7 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0-alpha.4" + ".": "0.1.0-alpha.5" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 074875f..a338186 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,28 @@ # Changelog +## 0.1.0-alpha.5 (2025-12-19) + +Full Changelog: [v0.1.0-alpha.4...v0.1.0-alpha.5](https://github.com/sfcompute/nodes-go/compare/v0.1.0-alpha.4...v0.1.0-alpha.5) + +### Features + +* **api:** api update ([dd70400](https://github.com/sfcompute/nodes-go/commit/dd70400abff7e7332cf7a7f3dee59e9e2e4b61b5)) +* **encoder:** support bracket encoding form-data object members ([bf75f99](https://github.com/sfcompute/nodes-go/commit/bf75f99a26c353742229dabb561684545d0835c7)) + + +### Bug Fixes + +* **mcp:** correct code tool API endpoint ([2eeb64b](https://github.com/sfcompute/nodes-go/commit/2eeb64be8909979b8cb3524a077cb764c85a1f21)) +* rename param to avoid collision ([f221c75](https://github.com/sfcompute/nodes-go/commit/f221c7569b746c43bd46c4ab3c1615b30fc0c05c)) +* skip usage tests that don't work with Prism ([61d03bd](https://github.com/sfcompute/nodes-go/commit/61d03bd3c1f7772a74bef48676020df27c371ab1)) + + +### Chores + +* add float64 to valid types for RegisterFieldValidator ([499e663](https://github.com/sfcompute/nodes-go/commit/499e663b659fa00c013ebe3db1e0622b5e2a6a51)) +* elide duplicate aliases ([9e83189](https://github.com/sfcompute/nodes-go/commit/9e83189fd37d851e8441c313c738656a72760483)) +* **internal:** codegen related update ([e40a3de](https://github.com/sfcompute/nodes-go/commit/e40a3debee22efa7015e5230d14374245af79b1f)) + ## 0.1.0-alpha.4 (2025-12-01) Full Changelog: [v0.1.0-alpha.3...v0.1.0-alpha.4](https://github.com/sfcompute/nodes-go/compare/v0.1.0-alpha.3...v0.1.0-alpha.4) diff --git a/README.md b/README.md index 43ac98e..0d65833 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ Or to pin the version: ```sh -go get -u 'github.com/sfcompute/nodes-go@v0.1.0-alpha.4' +go get -u 'github.com/sfcompute/nodes-go@v0.1.0-alpha.5' ``` diff --git a/internal/version.go b/internal/version.go index 5469df6..2aad167 100644 --- a/internal/version.go +++ b/internal/version.go @@ -2,4 +2,4 @@ package internal -const PackageVersion = "0.1.0-alpha.4" // x-release-please-version +const PackageVersion = "0.1.0-alpha.5" // x-release-please-version