From fbf047029f11c57542963ed3446ab191ae738643 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Thu, 23 Oct 2025 20:50:15 +0000 Subject: [PATCH 01/13] feat(api): add `description` field to chats, make `title` optional `title` now fallbacks to `null`, instead of an empty string --- .stats.yml | 4 ++-- chat.go | 13 ++++++++----- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.stats.yml b/.stats.yml index 325712c..adde7c3 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/beeper%2Fbeeper-desktop-api-0763b61997721da6f4514241bf0f7bb5f7a88c7298baf0f1b2d58036aaf7e2f1.yml -openapi_spec_hash: 5158475919c04bb52fb03c6a4582188d +openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/beeper%2Fbeeper-desktop-api-bea2e5f3b01053a66261a824c75c2640856d0ba00ad795ab71734c4ab9ae33b0.yml +openapi_spec_hash: d766f6e344c12ca6d23e6ef6713b38c4 config_hash: 5fa7ded4bfdffe4cc1944a819da87f9f diff --git a/chat.go b/chat.go index 83f17bb..8482238 100644 --- a/chat.go +++ b/chat.go @@ -141,19 +141,19 @@ type Chat struct { Network string `json:"network,required"` // Chat participants information. Participants ChatParticipants `json:"participants,required"` - // Display title of the chat as computed by the client/server. - Title string `json:"title,required"` // Chat type: 'single' for direct messages, 'group' for group chats. // // Any of "single", "group". Type ChatType `json:"type,required"` // Number of unread messages. UnreadCount int64 `json:"unreadCount,required"` + // Description of the chat. + Description string `json:"description,nullable"` // True if chat is archived. IsArchived bool `json:"isArchived"` - // True if chat notifications are muted. + // True if the chat is muted. IsMuted bool `json:"isMuted"` - // True if chat is pinned. + // True if the chat is pinned. IsPinned bool `json:"isPinned"` // Timestamp of last activity. LastActivity time.Time `json:"lastActivity" format:"date-time"` @@ -161,21 +161,24 @@ type Chat struct { LastReadMessageSortKey string `json:"lastReadMessageSortKey"` // Local chat ID specific to this Beeper Desktop installation. LocalChatID string `json:"localChatID,nullable"` + // Display title of the chat. + Title string `json:"title,nullable"` // JSON contains metadata for fields, check presence with [respjson.Field.Valid]. JSON struct { ID respjson.Field AccountID respjson.Field Network respjson.Field Participants respjson.Field - Title respjson.Field Type respjson.Field UnreadCount respjson.Field + Description respjson.Field IsArchived respjson.Field IsMuted respjson.Field IsPinned respjson.Field LastActivity respjson.Field LastReadMessageSortKey respjson.Field LocalChatID respjson.Field + Title respjson.Field ExtraFields map[string]respjson.Field raw string } `json:"-"` From 60171f3c6eed029a5689bc8ac58656baf63d88f3 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 4 Nov 2025 03:45:01 +0000 Subject: [PATCH 02/13] chore(internal): grammar fix (it's -> its) --- README.md | 2 +- packages/respjson/respjson.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 7f9cc24..bf7ef26 100644 --- a/README.md +++ b/README.md @@ -127,7 +127,7 @@ custom := param.Override[beeperdesktopapi.FooParams](12) ### Request unions -Unions are represented as a struct with fields prefixed by "Of" for each of it's variants, +Unions are represented as a struct with fields prefixed by "Of" for each of its variants, only one field can be non-zero. The non-zero field will be serialized. Sub-properties of the union can be accessed via methods on the union struct. diff --git a/packages/respjson/respjson.go b/packages/respjson/respjson.go index cc0088c..9e61c5c 100644 --- a/packages/respjson/respjson.go +++ b/packages/respjson/respjson.go @@ -5,7 +5,7 @@ package respjson // Use [Field.Valid] to check if an optional value was null or omitted. // // A Field will always occur in the following structure, where it -// mirrors the original field in it's parent struct: +// mirrors the original field in its parent struct: // // type ExampleObject struct { // Foo bool `json:"foo"` From 1194594b4e0744f59f66e0cda1929e75eb8973a2 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 12 Nov 2025 03:33:22 +0000 Subject: [PATCH 03/13] chore: bump gjson version --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bcc31c4..24af450 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/beeper/desktop-api-go go 1.22 require ( - github.com/tidwall/gjson v1.14.4 + github.com/tidwall/gjson v1.18.0 github.com/tidwall/sjson v1.2.5 ) diff --git a/go.sum b/go.sum index a70a5e0..32ba293 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,6 @@ github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= -github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY= +github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= From 2bcd6c1aaaf2b7e6e554d8a87743d2593856f678 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Wed, 19 Nov 2025 03:31:24 +0000 Subject: [PATCH 04/13] fix(client): correctly specify Accept header with */* instead of empty --- chat.go | 2 +- chatreminder.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/chat.go b/chat.go index 8482238..606eead 100644 --- a/chat.go +++ b/chat.go @@ -95,7 +95,7 @@ func (r *ChatService) ListAutoPaging(ctx context.Context, query ChatListParams, // archived=false to move back to inbox func (r *ChatService) Archive(ctx context.Context, chatID string, body ChatArchiveParams, opts ...option.RequestOption) (err error) { opts = slices.Concat(r.Options, opts) - opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...) + opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...) if chatID == "" { err = errors.New("missing required chatID parameter") return diff --git a/chatreminder.go b/chatreminder.go index 89e14cd..ed615aa 100644 --- a/chatreminder.go +++ b/chatreminder.go @@ -39,7 +39,7 @@ func NewChatReminderService(opts ...option.RequestOption) (r ChatReminderService // Set a reminder for a chat at a specific time func (r *ChatReminderService) New(ctx context.Context, chatID string, body ChatReminderNewParams, opts ...option.RequestOption) (err error) { opts = slices.Concat(r.Options, opts) - opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...) + opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...) if chatID == "" { err = errors.New("missing required chatID parameter") return @@ -52,7 +52,7 @@ func (r *ChatReminderService) New(ctx context.Context, chatID string, body ChatR // Clear an existing reminder from a chat func (r *ChatReminderService) Delete(ctx context.Context, chatID string, opts ...option.RequestOption) (err error) { opts = slices.Concat(r.Options, opts) - opts = append([]option.RequestOption{option.WithHeader("Accept", "")}, opts...) + opts = append([]option.RequestOption{option.WithHeader("Accept", "*/*")}, opts...) if chatID == "" { err = errors.New("missing required chatID parameter") return From 77a6d605f55019d31fba8ed59ddc5232f527f9ff Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 03:38:54 +0000 Subject: [PATCH 05/13] 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..0cfc1a1 --- /dev/null +++ b/internal/paramutil/sentinel.go @@ -0,0 +1,31 @@ +package paramutil + +import ( + "github.com/beeper/desktop-api-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 fa3d4564c46606bcb63fd98906eb0687758ac059 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 03:39:28 +0000 Subject: [PATCH 06/13] 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 0cfc1a1..0000000 --- a/internal/paramutil/sentinel.go +++ /dev/null @@ -1,31 +0,0 @@ -package paramutil - -import ( - "github.com/beeper/desktop-api-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 568939eff6ad5bcdcd42d7bae3439af3389e4b8a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 03:40:12 +0000 Subject: [PATCH 07/13] 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..0cfc1a1 --- /dev/null +++ b/internal/paramutil/sentinel.go @@ -0,0 +1,31 @@ +package paramutil + +import ( + "github.com/beeper/desktop-api-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 d304cbe9e74f9486567156cb28a60cf7cee5b053 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Sat, 6 Dec 2025 03:41:16 +0000 Subject: [PATCH 08/13] 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 0cfc1a1..0000000 --- a/internal/paramutil/sentinel.go +++ /dev/null @@ -1,31 +0,0 @@ -package paramutil - -import ( - "github.com/beeper/desktop-api-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 a33874294b78dc962f1acf74668ab59697d61711 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 12 Dec 2025 03:36:04 +0000 Subject: [PATCH 09/13] 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 14f2448..3a61344 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 979be5a..48a0959 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 4658d5c7d11ff703a1b7e5ccfb594b22f2ee5144 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Fri, 19 Dec 2025 03:53:57 +0000 Subject: [PATCH 10/13] 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 f2d3a30447ffaae00b456f610aba7afee08d32f0 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 6 Jan 2026 03:44:46 +0000 Subject: [PATCH 11/13] chore(internal): codegen related update --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 59424c8..76a908d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2025 beeperdesktop +Copyright 2026 beeperdesktop Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: From fcad6f33198927cfd1e144648a38fb43b1d43f06 Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 6 Jan 2026 03:54:31 +0000 Subject: [PATCH 12/13] docs: prominently feature MCP server setup in root SDK readmes --- README.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/README.md b/README.md index bf7ef26..ce5437d 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,15 @@ The Beeper Desktop Go library provides convenient access to the [Beeper Desktop REST API](https://developers.beeper.com/desktop-api/) from applications written in Go. +## MCP Server + +Use the Beeper Desktop MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application. + +[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40beeper%2Fdesktop-mcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkBiZWVwZXIvZGVza3RvcC1tY3AiXX0) +[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40beeper%2Fdesktop-mcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40beeper%2Fdesktop-mcp%22%5D%7D) + +> Note: You may need to set environment variables in your MCP client. + ## Installation From 904061fe3f3e64cb441a6a07c49e613a8795b57a Mon Sep 17 00:00:00 2001 From: "stainless-app[bot]" <142633134+stainless-app[bot]@users.noreply.github.com> Date: Tue, 6 Jan 2026 03:54:47 +0000 Subject: [PATCH 13/13] release: 0.2.0 --- .release-please-manifest.json | 2 +- CHANGELOG.md | 31 +++++++++++++++++++++++++++++++ README.md | 2 +- internal/version.go | 2 +- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 3d2ac0b..10f3091 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,3 +1,3 @@ { - ".": "0.1.0" + ".": "0.2.0" } \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 941429c..e9f5a79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,36 @@ # Changelog +## 0.2.0 (2026-01-06) + +Full Changelog: [v0.1.0...v0.2.0](https://github.com/beeper/desktop-api-go/compare/v0.1.0...v0.2.0) + +### Features + +* **api:** add `description` field to chats, make `title` optional ([fbf0470](https://github.com/beeper/desktop-api-go/commit/fbf047029f11c57542963ed3446ab191ae738643)) +* **encoder:** support bracket encoding form-data object members ([a338742](https://github.com/beeper/desktop-api-go/commit/a33874294b78dc962f1acf74668ab59697d61711)) + + +### Bug Fixes + +* **client:** correctly specify Accept header with */* instead of empty ([2bcd6c1](https://github.com/beeper/desktop-api-go/commit/2bcd6c1aaaf2b7e6e554d8a87743d2593856f678)) +* **mcp:** correct code tool API endpoint ([568939e](https://github.com/beeper/desktop-api-go/commit/568939eff6ad5bcdcd42d7bae3439af3389e4b8a)) +* rename param to avoid collision ([d304cbe](https://github.com/beeper/desktop-api-go/commit/d304cbe9e74f9486567156cb28a60cf7cee5b053)) + + +### Chores + +* add float64 to valid types for RegisterFieldValidator ([4658d5c](https://github.com/beeper/desktop-api-go/commit/4658d5c7d11ff703a1b7e5ccfb594b22f2ee5144)) +* bump gjson version ([1194594](https://github.com/beeper/desktop-api-go/commit/1194594b4e0744f59f66e0cda1929e75eb8973a2)) +* elide duplicate aliases ([fa3d456](https://github.com/beeper/desktop-api-go/commit/fa3d4564c46606bcb63fd98906eb0687758ac059)) +* **internal:** codegen related update ([f2d3a30](https://github.com/beeper/desktop-api-go/commit/f2d3a30447ffaae00b456f610aba7afee08d32f0)) +* **internal:** codegen related update ([77a6d60](https://github.com/beeper/desktop-api-go/commit/77a6d605f55019d31fba8ed59ddc5232f527f9ff)) +* **internal:** grammar fix (it's -> its) ([60171f3](https://github.com/beeper/desktop-api-go/commit/60171f3c6eed029a5689bc8ac58656baf63d88f3)) + + +### Documentation + +* prominently feature MCP server setup in root SDK readmes ([fcad6f3](https://github.com/beeper/desktop-api-go/commit/fcad6f33198927cfd1e144648a38fb43b1d43f06)) + ## 0.1.0 (2025-10-16) Full Changelog: [v0.0.1...v0.1.0](https://github.com/beeper/desktop-api-go/compare/v0.0.1...v0.1.0) diff --git a/README.md b/README.md index ce5437d..ef018c9 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Or to pin the version: ```sh -go get -u 'github.com/beeper/desktop-api-go@v0.1.0' +go get -u 'github.com/beeper/desktop-api-go@v0.2.0' ``` diff --git a/internal/version.go b/internal/version.go index 02eac73..774c6c4 100644 --- a/internal/version.go +++ b/internal/version.go @@ -2,4 +2,4 @@ package internal -const PackageVersion = "0.1.0" // x-release-please-version +const PackageVersion = "0.2.0" // x-release-please-version