Skip to content

Instantly share code, notes, and snippets.

@trjordan
Created April 22, 2025 18:56
Show Gist options
  • Select an option

  • Save trjordan/a10772a79a202f5de58bbf1056b223d4 to your computer and use it in GitHub Desktop.

Select an option

Save trjordan/a10772a79a202f5de58bbf1056b223d4 to your computer and use it in GitHub Desktop.
Anthropic alpha 13 to beta 3 diff
This file has been truncated, but you can view the full file.
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 9ff53ed..8077d60 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -42,4 +42,3 @@ jobs:
- name: Run tests
run: ./scripts/test
-
diff --git a/.release-please-manifest.json b/.release-please-manifest.json
index ecfd70b..bee6b5e 100644
--- a/.release-please-manifest.json
+++ b/.release-please-manifest.json
@@ -1,3 +1,3 @@
{
- ".": "0.2.0-alpha.13"
-}
\ No newline at end of file
+ ".": "0.2.0-beta.3"
+}
diff --git a/.stats.yml b/.stats.yml
index 756a363..2c1bac2 100644
--- a/.stats.yml
+++ b/.stats.yml
@@ -1,2 +1,4 @@
configured_endpoints: 21
openapi_spec_url: https://storage.googleapis.com/stainless-sdk-openapi-specs/anthropic-fd7537a41646cd9253c04f350436c5471e4762750fce8ca8f1909a3052d98608.yml
+openapi_spec_hash: d2d7ec2a7a35a1ed2443c3b690c802c4
+config_hash: 92dd03fd872d52f9707c9e7a7953c3d1
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dc6bdaa..18d08a3 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,319 +1,53 @@
# Changelog
-## 0.2.0-alpha.13 (2025-02-28)
-
-Full Changelog: [v0.2.0-alpha.12...v0.2.0-alpha.13](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.12...v0.2.0-alpha.13)
-
-### Features
-
-* **api:** add support for disabling tool calls ([#133](https://github.com/anthropics/anthropic-sdk-go/issues/133)) ([90f7490](https://github.com/anthropics/anthropic-sdk-go/commit/90f7490774321fdbcadea60c4390244afd5b4c3d))
-
-
-### Documentation
-
-* update URLs from stainlessapi.com to stainless.com ([#131](https://github.com/anthropics/anthropic-sdk-go/issues/131)) ([334be2b](https://github.com/anthropics/anthropic-sdk-go/commit/334be2b932571846203e0019ee3fe5b551d42c96))
-
-## 0.2.0-alpha.12 (2025-02-27)
-
-Full Changelog: [v0.2.0-alpha.11...v0.2.0-alpha.12](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.11...v0.2.0-alpha.12)
-
-### Features
-
-* **api:** add URL source blocks for images and PDFs ([#129](https://github.com/anthropics/anthropic-sdk-go/issues/129)) ([589f5dc](https://github.com/anthropics/anthropic-sdk-go/commit/589f5dc44bdcfbec7269dcd0ad94baf72c3876b3))
-
-
-### Bug Fixes
-
-* Preserve Thinking and Signature fields in Message.ToParam() method ([#128](https://github.com/anthropics/anthropic-sdk-go/issues/128)) ([b67c786](https://github.com/anthropics/anthropic-sdk-go/commit/b67c786b64d3a3903a0dcdc50ceac07fc4a6396a))
-
-
-### Chores
-
-* **internal:** update spec ([#124](https://github.com/anthropics/anthropic-sdk-go/issues/124)) ([3b3bdad](https://github.com/anthropics/anthropic-sdk-go/commit/3b3bdad4b5038278d26ed1c82e0a37259326c049))
-
-## 0.2.0-alpha.11 (2025-02-24)
-
-Full Changelog: [v0.2.0-alpha.10...v0.2.0-alpha.11](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.10...v0.2.0-alpha.11)
-
-### Features
-
-* **api:** add claude-3.7 + support for thinking ([cc7ddcc](https://github.com/anthropics/anthropic-sdk-go/commit/cc7ddcc83a2aeabc17037035b42e94d59679d9e3))
-* **client:** send `X-Stainless-Timeout` header ([#114](https://github.com/anthropics/anthropic-sdk-go/issues/114)) ([66f2aec](https://github.com/anthropics/anthropic-sdk-go/commit/66f2aec50b2abf200eaca7fd6636c64059bc884b))
-* **pagination:** avoid fetching when has_more: false ([#118](https://github.com/anthropics/anthropic-sdk-go/issues/118)) ([6d90a30](https://github.com/anthropics/anthropic-sdk-go/commit/6d90a300dd0553b92b2f555cc11bc4a134593b90))
-
-
-### Bug Fixes
-
-* **client:** don't truncate manually specified filenames ([#121](https://github.com/anthropics/anthropic-sdk-go/issues/121)) ([ce64cf5](https://github.com/anthropics/anthropic-sdk-go/commit/ce64cf54d299d5d3d7b707024ea5ca65c4bd5b56))
-* do not call path.Base on ContentType ([#120](https://github.com/anthropics/anthropic-sdk-go/issues/120)) ([5f20f48](https://github.com/anthropics/anthropic-sdk-go/commit/5f20f48a882546e5e25492a543a7cc56be3eb7dc))
-* fix early cancel when RequestTimeout is provided for streaming requests ([#119](https://github.com/anthropics/anthropic-sdk-go/issues/119)) ([20af10e](https://github.com/anthropics/anthropic-sdk-go/commit/20af10e556caa9dd1691fee0c68aab528d61bc87))
-* fix unicode encoding for json ([#111](https://github.com/anthropics/anthropic-sdk-go/issues/111)) ([699e5cd](https://github.com/anthropics/anthropic-sdk-go/commit/699e5cd7a37a20b48824d0b1b978b28df1d8afbf))
-* **stream:** ensure .Close() doesn't panic ([#113](https://github.com/anthropics/anthropic-sdk-go/issues/113)) ([2125563](https://github.com/anthropics/anthropic-sdk-go/commit/2125563ac0bf773e0795ce51933e535854a30a0e))
-* update stream error handling ([#117](https://github.com/anthropics/anthropic-sdk-go/issues/117)) ([40d1ea2](https://github.com/anthropics/anthropic-sdk-go/commit/40d1ea2589b3df6111c8cf000f49ec46ede7a7a4))
-
-
-### Chores
-
-* add UnionUnmarshaler for responses that are interfaces ([#116](https://github.com/anthropics/anthropic-sdk-go/issues/116)) ([93f533c](https://github.com/anthropics/anthropic-sdk-go/commit/93f533c1c940b1dd6264886344902239a268634a))
-* **api:** update openapi spec url ([#108](https://github.com/anthropics/anthropic-sdk-go/issues/108)) ([8f291ed](https://github.com/anthropics/anthropic-sdk-go/commit/8f291ed434cd1cd0eb7f82a2e8b39b9e97744f6e))
-* **docs:** add docstring explaining streaming pattern ([#115](https://github.com/anthropics/anthropic-sdk-go/issues/115)) ([862c3d4](https://github.com/anthropics/anthropic-sdk-go/commit/862c3d41e8d19ad4b0e9d2d228719c930e6f7d18))
-* **internal:** fix devcontainers setup ([#123](https://github.com/anthropics/anthropic-sdk-go/issues/123)) ([6f9dcc1](https://github.com/anthropics/anthropic-sdk-go/commit/6f9dcc103ee4dfeeda6a5c78e3d461d0c3ddab0b))
-
-
-### Documentation
-
-* document raw responses ([#112](https://github.com/anthropics/anthropic-sdk-go/issues/112)) ([1cf3aee](https://github.com/anthropics/anthropic-sdk-go/commit/1cf3aee0a28edc06e0e19723f94290b80074d6ce))
-
-## 0.2.0-alpha.10 (2025-01-28)
-
-Full Changelog: [v0.2.0-alpha.9...v0.2.0-alpha.10](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.9...v0.2.0-alpha.10)
-
-### Bug Fixes
-
-* fix interface implementation stub names for unions ([#106](https://github.com/anthropics/anthropic-sdk-go/issues/106)) ([0ac5655](https://github.com/anthropics/anthropic-sdk-go/commit/0ac5655d4033ec3d6448ecf89216b048bccbbd85))
-
-
-### Chores
-
-* **api:** deprecate some models ([#105](https://github.com/anthropics/anthropic-sdk-go/issues/105)) ([f1e30cc](https://github.com/anthropics/anthropic-sdk-go/commit/f1e30ccd3ace4165bf0653cf5251b1fc06a1e78a))
-* **docs:** updates ([#103](https://github.com/anthropics/anthropic-sdk-go/issues/103)) ([c264f59](https://github.com/anthropics/anthropic-sdk-go/commit/c264f59fc3f58a0233f8c801436cccc0f4eeef6c))
-* refactor client tests ([#107](https://github.com/anthropics/anthropic-sdk-go/issues/107)) ([f02b038](https://github.com/anthropics/anthropic-sdk-go/commit/f02b038063ab0095cc3497cbe1c3f585cb471817))
-
-## 0.2.0-alpha.9 (2025-01-23)
-
-Full Changelog: [v0.2.0-alpha.8...v0.2.0-alpha.9](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.8...v0.2.0-alpha.9)
-
-### Features
-
-* **api:** add citations ([#101](https://github.com/anthropics/anthropic-sdk-go/issues/101)) ([59fd065](https://github.com/anthropics/anthropic-sdk-go/commit/59fd065fe106db20527f37e4ecdc6cc771c10418))
-* **api:** add message batch delete endpoint ([#81](https://github.com/anthropics/anthropic-sdk-go/issues/81)) ([b3a63e7](https://github.com/anthropics/anthropic-sdk-go/commit/b3a63e7cbf73d06141750cf126af25412b12061d))
-* **client:** support results endpoint ([#98](https://github.com/anthropics/anthropic-sdk-go/issues/98)) ([380054f](https://github.com/anthropics/anthropic-sdk-go/commit/380054fc5608380cdc054a181d83558ee7c5b946))
-
-
-### Bug Fixes
-
-* fix apijson.Port for embedded structs ([#95](https://github.com/anthropics/anthropic-sdk-go/issues/95)) ([5c3a7f7](https://github.com/anthropics/anthropic-sdk-go/commit/5c3a7f7f4d2694b8b52a0c4a36701a489a58dcf0))
-* fix apijson.Port for embedded structs ([#97](https://github.com/anthropics/anthropic-sdk-go/issues/97)) ([55a3365](https://github.com/anthropics/anthropic-sdk-go/commit/55a3365c873b6b385d27f2315e370fa40736778e))
-* fix header parameter value ([#90](https://github.com/anthropics/anthropic-sdk-go/issues/90)) ([d52699a](https://github.com/anthropics/anthropic-sdk-go/commit/d52699aa2036162f6842a3115eb754b6870260e1))
-* prevent niche naming conflicts for string enums with different casing ([#100](https://github.com/anthropics/anthropic-sdk-go/issues/100)) ([3af5fe8](https://github.com/anthropics/anthropic-sdk-go/commit/3af5fe8993928a6985022cdbea6bfe220a6d6be5))
-* support array query parameters ([#89](https://github.com/anthropics/anthropic-sdk-go/issues/89)) ([d728bcc](https://github.com/anthropics/anthropic-sdk-go/commit/d728bcc9d69414bb3ba577e504e1285f0eb22bc5))
+## 0.2.0-beta.3 (2025-03-27)
+Full Changelog: [v0.2.0-beta.2...v0.2.0-beta.3](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-beta.2...v0.2.0-beta.3)
### Chores
-* bump license year ([#88](https://github.com/anthropics/anthropic-sdk-go/issues/88)) ([c8ddc6b](https://github.com/anthropics/anthropic-sdk-go/commit/c8ddc6b1364485e299e050423e459023e2d65b46))
-* **internal:** remove unused field ([#94](https://github.com/anthropics/anthropic-sdk-go/issues/94)) ([b98d12a](https://github.com/anthropics/anthropic-sdk-go/commit/b98d12a3991ae2f1d714833a71ec90dedc552661))
-* **internal:** rename `streaming.go` ([#96](https://github.com/anthropics/anthropic-sdk-go/issues/96)) ([ce8ac0f](https://github.com/anthropics/anthropic-sdk-go/commit/ce8ac0fe762132d230241f021eeb0cd4215f271b))
-* **internal:** update examples ([#91](https://github.com/anthropics/anthropic-sdk-go/issues/91)) ([9717662](https://github.com/anthropics/anthropic-sdk-go/commit/97176628489158be07baf1747ba39f15429d3a39))
-
+* add hash of OpenAPI spec/config inputs to .stats.yml ([#154](https://github.com/anthropics/anthropic-sdk-go/issues/154)) ([76b91b5](https://github.com/anthropics/anthropic-sdk-go/commit/76b91b56fbf42fe8982e7b861885db179b1bdcc5))
+* fix typos ([#152](https://github.com/anthropics/anthropic-sdk-go/issues/152)) ([1cf6a6a](https://github.com/anthropics/anthropic-sdk-go/commit/1cf6a6ae25231b88d2eedbe0758f1281cbe439d8))
-### Documentation
+## 0.2.0-beta.2 (2025-03-25)
-* **readme:** fix misplaced period ([#93](https://github.com/anthropics/anthropic-sdk-go/issues/93)) ([953d510](https://github.com/anthropics/anthropic-sdk-go/commit/953d5104b1460b749b776a6ba4df90d2604c06cd))
-
-## 0.2.0-alpha.8 (2024-12-19)
-
-Full Changelog: [v0.2.0-alpha.7...v0.2.0-alpha.8](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.7...v0.2.0-alpha.8)
+Full Changelog: [v0.2.0-beta.1...v0.2.0-beta.2](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-beta.1...v0.2.0-beta.2)
### Bug Fixes
-* **bedrock:** handle exceptions messages in bedrock stream ([7786f8f](https://github.com/anthropics/anthropic-sdk-go/commit/7786f8f7f97d073b79f5e1faaec1a6de285001c2))
+* **client:** use raw json for tool input ([1013c2b](https://github.com/anthropics/anthropic-sdk-go/commit/1013c2bdb87a27d2420dbe0dcadc57d1fe3589f2))
### Chores
-* bump testing data uri ([#79](https://github.com/anthropics/anthropic-sdk-go/issues/79)) ([0dc9c88](https://github.com/anthropics/anthropic-sdk-go/commit/0dc9c8811f211cdd25eb5451aa88f258591fb9bd))
-
-## 0.2.0-alpha.7 (2024-12-17)
+* add request options to client tests ([#150](https://github.com/anthropics/anthropic-sdk-go/issues/150)) ([7c70ae1](https://github.com/anthropics/anthropic-sdk-go/commit/7c70ae134a345aff775694abcad255c76e7dfcba))
-Full Changelog: [v0.2.0-alpha.6...v0.2.0-alpha.7](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.6...v0.2.0-alpha.7)
-
-### Bug Fixes
+## 0.2.0-beta.1 (2025-03-25)
-* **vertex:** remove `anthropic_version` deletion for token counting ([15987ac](https://github.com/anthropics/anthropic-sdk-go/commit/15987ac82378e0e0d28878f91e2ddca8f6fb5ab9))
+Full Changelog: [v0.2.0-alpha.13...v0.2.0-beta.1](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.13...v0.2.0-beta.1)
-## 0.2.0-alpha.6 (2024-12-17)
+### ⚠ BREAKING CHANGES
-Full Changelog: [v0.2.0-alpha.5...v0.2.0-alpha.6](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.5...v0.2.0-alpha.6)
+* **api:** migrate to v2
### Features
-* **api:** general availability updates ([#74](https://github.com/anthropics/anthropic-sdk-go/issues/74)) ([0c19b86](https://github.com/anthropics/anthropic-sdk-go/commit/0c19b86f4d0f8496d551f3b707bfb8834b98b315))
-* **vertex:** add support for token counting ([86e085b](https://github.com/anthropics/anthropic-sdk-go/commit/86e085b0452926491ec11b2c77abec4c0a733d3b))
-
-
-### Bug Fixes
-
-* **messages:** correct batch params type ([2a39e4b](https://github.com/anthropics/anthropic-sdk-go/commit/2a39e4b9af65f0318374f88c2aef150b69df7107))
-* replace `MessageParamContentUnion` with `ContentBlockParamUnion` to fix go script ([#70](https://github.com/anthropics/anthropic-sdk-go/issues/70)) ([5d32a5f](https://github.com/anthropics/anthropic-sdk-go/commit/5d32a5f2be05c31932451d8033e954cd71c9fbc8))
-* **tests:** correct input schema type ([6514952](https://github.com/anthropics/anthropic-sdk-go/commit/6514952ac492f3f7ceed1c5726dfbc7b5b3f72db))
-
-
-### Chores
-
-* **api:** update spec version ([#72](https://github.com/anthropics/anthropic-sdk-go/issues/72)) ([854416b](https://github.com/anthropics/anthropic-sdk-go/commit/854416b61b37fff95bca34d7c91035fb11aef921))
-* **internal:** update spec ([#73](https://github.com/anthropics/anthropic-sdk-go/issues/73)) ([6da0443](https://github.com/anthropics/anthropic-sdk-go/commit/6da04433a0cdf00600080f45d41cfd92064e7471))
-
-
-### Documentation
-
-* **examples:** use claude 3 sonnet more ([c02fdac](https://github.com/anthropics/anthropic-sdk-go/commit/c02fdac54687c966a8641be10035c0f389bddfe0))
-
-## 0.2.0-alpha.5 (2024-12-01)
-
-Full Changelog: [v0.2.0-alpha.4...v0.2.0-alpha.5](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.4...v0.2.0-alpha.5)
-
-### Bug Fixes
-
-* **api:** escape key values when encoding maps ([#56](https://github.com/anthropics/anthropic-sdk-go/issues/56)) ([fa49eb8](https://github.com/anthropics/anthropic-sdk-go/commit/fa49eb8c4f8d6fa7e45ec4e7eb457a87218349c4))
-* **client:** no panic on missing BaseURL ([#61](https://github.com/anthropics/anthropic-sdk-go/issues/61)) ([7438b15](https://github.com/anthropics/anthropic-sdk-go/commit/7438b15855bd6b5902d62fdbf02f143544eee986))
-* correct required fields for flattened unions ([#59](https://github.com/anthropics/anthropic-sdk-go/issues/59)) ([735c07c](https://github.com/anthropics/anthropic-sdk-go/commit/735c07c66a3bbf54bff97db7fe5290d7635c0774))
-* forward error and close for bedrock decoder ([#66](https://github.com/anthropics/anthropic-sdk-go/issues/66)) ([5f6f6fd](https://github.com/anthropics/anthropic-sdk-go/commit/5f6f6fd822b029dffd90aa49b06add0661251de0))
-* **types:** remove anthropic-instant-1.2 model ([#57](https://github.com/anthropics/anthropic-sdk-go/issues/57)) ([23fbc37](https://github.com/anthropics/anthropic-sdk-go/commit/23fbc3752122462a1e29e15327b1736072032ba3))
+* add SKIP_BREW env var to ./scripts/bootstrap ([#137](https://github.com/anthropics/anthropic-sdk-go/issues/137)) ([4057111](https://github.com/anthropics/anthropic-sdk-go/commit/40571110129d5c66f171ead36f5d725663262bc4))
+* **api:** migrate to v2 ([fcd95eb](https://github.com/anthropics/anthropic-sdk-go/commit/fcd95eb8f45d0ffedcd1e47cd0879d7e66783540))
+* **client:** accept RFC6838 JSON content types ([#139](https://github.com/anthropics/anthropic-sdk-go/issues/139)) ([78d17cd](https://github.com/anthropics/anthropic-sdk-go/commit/78d17cd4122893ba62b1e14714a1da004c128344))
+* **client:** allow custom baseurls without trailing slash ([#135](https://github.com/anthropics/anthropic-sdk-go/issues/135)) ([9b30fce](https://github.com/anthropics/anthropic-sdk-go/commit/9b30fce0a71a35910315e02cd3a2f2afc1fd7962))
+* **client:** improve default client options support ([07f82a6](https://github.com/anthropics/anthropic-sdk-go/commit/07f82a6f9e07bf9aadf4ca150287887cb9e75bc4))
+* **client:** improve default client options support ([#142](https://github.com/anthropics/anthropic-sdk-go/issues/142)) ([f261355](https://github.com/anthropics/anthropic-sdk-go/commit/f261355e497748bcb112eecb67a95d7c7c5075c0))
+* **client:** support v2 ([#147](https://github.com/anthropics/anthropic-sdk-go/issues/147)) ([6b3af98](https://github.com/anthropics/anthropic-sdk-go/commit/6b3af98e02a9b6126bd715d43f83b8adf8b861e8))
### Chores
-* **api:** update spec version ([#62](https://github.com/anthropics/anthropic-sdk-go/issues/62)) ([1526051](https://github.com/anthropics/anthropic-sdk-go/commit/1526051561d4e1fe7792d90f0c2299036fedbc21))
-* **ci:** remove unneeded workflow ([#55](https://github.com/anthropics/anthropic-sdk-go/issues/55)) ([0181fc2](https://github.com/anthropics/anthropic-sdk-go/commit/0181fc2796bc5fea1a21e2744257900caef8ee72))
-* fix references to content block param types ([dea6478](https://github.com/anthropics/anthropic-sdk-go/commit/dea647890542036c1ed4cc55409002fd2e00adb6))
-* **tests:** limit array example length ([#64](https://github.com/anthropics/anthropic-sdk-go/issues/64)) ([9fb231b](https://github.com/anthropics/anthropic-sdk-go/commit/9fb231b806af753b6c9aae82c023e087c2ecaefb))
-
-
-### Documentation
-
-* add missing docs for some enums ([#54](https://github.com/anthropics/anthropic-sdk-go/issues/54)) ([56db6b8](https://github.com/anthropics/anthropic-sdk-go/commit/56db6b832d0e0454895b6d4ab43d32bd6b7418b4))
+* **docs:** clarify breaking changes ([#146](https://github.com/anthropics/anthropic-sdk-go/issues/146)) ([a2586b4](https://github.com/anthropics/anthropic-sdk-go/commit/a2586b4beb2b9a0ad252e90223fbb471e6c25bc1))
+* **internal:** codegen metadata ([ce0eca2](https://github.com/anthropics/anthropic-sdk-go/commit/ce0eca25c6a83fca9ececccb41faf04e74566e2d))
+* **internal:** remove extra empty newlines ([#143](https://github.com/anthropics/anthropic-sdk-go/issues/143)) ([2ed1584](https://github.com/anthropics/anthropic-sdk-go/commit/2ed1584c7d80fddf2ef5143eabbd33b8f1a4603d))
### Refactors
-* sort fields for squashed union structs ([#51](https://github.com/anthropics/anthropic-sdk-go/issues/51)) ([a9874d1](https://github.com/anthropics/anthropic-sdk-go/commit/a9874d193998572a28475781dd8de296d4021bf2))
-
-## 0.2.0-alpha.4 (2024-11-04)
-
-Full Changelog: [v0.2.0-alpha.3...v0.2.0-alpha.4](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.3...v0.2.0-alpha.4)
-
-### Features
-
-* **api:** add message token counting & PDFs support ([#45](https://github.com/anthropics/anthropic-sdk-go/issues/45)) ([775de6d](https://github.com/anthropics/anthropic-sdk-go/commit/775de6d75c61cd3a6b3d63fdf129b1564b1f147c))
-* **api:** add new haiku model ([#48](https://github.com/anthropics/anthropic-sdk-go/issues/48)) ([8cb9d59](https://github.com/anthropics/anthropic-sdk-go/commit/8cb9d59b13d12a70866a579dca8cc965e33eeba5))
-
-
-### Bug Fixes
-
-* **types:** add missing token-counting-2024-11-01 ([#47](https://github.com/anthropics/anthropic-sdk-go/issues/47)) ([bc46a6e](https://github.com/anthropics/anthropic-sdk-go/commit/bc46a6e648f9ad804b119eff977e050843efb7f6))
-* **types:** correct claude-3-5-haiku-20241022 name ([#50](https://github.com/anthropics/anthropic-sdk-go/issues/50)) ([f0016bb](https://github.com/anthropics/anthropic-sdk-go/commit/f0016bbb272fd65fcc42f0b664e3ab45a665e673))
-
-
-### Chores
-
-* **internal:** update spec version ([#40](https://github.com/anthropics/anthropic-sdk-go/issues/40)) ([b41d55f](https://github.com/anthropics/anthropic-sdk-go/commit/b41d55f13b57553bd6e639ae359c5c6f0a9031bb))
-
-## 0.2.0-alpha.3 (2024-10-22)
-
-Full Changelog: [v0.2.0-alpha.2...v0.2.0-alpha.3](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.2...v0.2.0-alpha.3)
-
-### Features
-
-* **api:** add new model and `computer-use-2024-10-22` beta ([#37](https://github.com/anthropics/anthropic-sdk-go/issues/37)) ([a520abe](https://github.com/anthropics/anthropic-sdk-go/commit/a520abeedd326cea2161166cd2259345c15a82e4))
-
-
-### Chores
-
-* **api:** add title ([#34](https://github.com/anthropics/anthropic-sdk-go/issues/34)) ([2b96326](https://github.com/anthropics/anthropic-sdk-go/commit/2b96326e58bb7179d21476f9ce1a550664f13a38))
-* **internal:** update spec ([#36](https://github.com/anthropics/anthropic-sdk-go/issues/36)) ([a735bf7](https://github.com/anthropics/anthropic-sdk-go/commit/a735bf7e7872c8cc3ee08e57167860270e6cdba6))
-
-## 0.2.0-alpha.2 (2024-10-17)
-
-Full Changelog: [v0.2.0-alpha.1...v0.2.0-alpha.2](https://github.com/anthropics/anthropic-sdk-go/compare/v0.2.0-alpha.1...v0.2.0-alpha.2)
-
-### Features
-
-* move pagination package from internal to packages ([#33](https://github.com/anthropics/anthropic-sdk-go/issues/33)) ([ee3edb1](https://github.com/anthropics/anthropic-sdk-go/commit/ee3edb16dcd406435ade212cb7553f75b161e297))
-
-
-### Bug Fixes
-
-* **beta:** merge betas param with the default value ([#32](https://github.com/anthropics/anthropic-sdk-go/issues/32)) ([9191ae0](https://github.com/anthropics/anthropic-sdk-go/commit/9191ae0b8a47c3c6ea9dfbb5073f1e66f5b4e1d8))
-
-
-### Chores
-
-* fix GetNextPage docstring ([#29](https://github.com/anthropics/anthropic-sdk-go/issues/29)) ([acf8009](https://github.com/anthropics/anthropic-sdk-go/commit/acf8009c886ec27cc07665b0377a2a3b3493c336))
-* **internal:** update spec URL ([#31](https://github.com/anthropics/anthropic-sdk-go/issues/31)) ([240f1c3](https://github.com/anthropics/anthropic-sdk-go/commit/240f1c3d7e4dc145988d2f8d11e45ccfd255861e))
-
-## 0.2.0-alpha.1 (2024-10-08)
-
-Full Changelog: [v0.1.0-alpha.2...v0.2.0-alpha.1](https://github.com/anthropics/anthropic-sdk-go/compare/v0.1.0-alpha.2...v0.2.0-alpha.1)
-
-### Features
-
-* **api:** add message batches api ([#28](https://github.com/anthropics/anthropic-sdk-go/issues/28)) ([169eb3c](https://github.com/anthropics/anthropic-sdk-go/commit/169eb3c83d39126b4f9ec3a8d7f70c06466d9ef6))
-
-
-### Bug Fixes
-
-* **beta:** pass beta header by default ([#27](https://github.com/anthropics/anthropic-sdk-go/issues/27)) ([c79ba68](https://github.com/anthropics/anthropic-sdk-go/commit/c79ba6826c452ca1eeefd34db1638722fa942082))
-
-
-### Refactors
-
-* **types:** improve metadata type names ([#26](https://github.com/anthropics/anthropic-sdk-go/issues/26)) ([95f0266](https://github.com/anthropics/anthropic-sdk-go/commit/95f0266f62ba90590db68f1f98e41d80ea8f5388))
-* **types:** improve tool type names ([#23](https://github.com/anthropics/anthropic-sdk-go/issues/23)) ([79e4d75](https://github.com/anthropics/anthropic-sdk-go/commit/79e4d75d26bbf2339841d27696477817c01a55fc))
-
-## 0.1.0-alpha.2 (2024-10-04)
-
-Full Changelog: [v0.1.0-alpha.1...v0.1.0-alpha.2](https://github.com/anthropics/anthropic-sdk-go/compare/v0.1.0-alpha.1...v0.1.0-alpha.2)
-
-### Features
-
-* **api:** support disabling parallel tool use ([#22](https://github.com/anthropics/anthropic-sdk-go/issues/22)) ([1d8c00b](https://github.com/anthropics/anthropic-sdk-go/commit/1d8c00b317536d77a26f74d0008e1a4760b17d2e))
-* **client:** send retry count header ([#19](https://github.com/anthropics/anthropic-sdk-go/issues/19)) ([d1c8ea1](https://github.com/anthropics/anthropic-sdk-go/commit/d1c8ea1f84d05002705ac7aa4d47a5ba13c388e9))
-* improve error message ([#15](https://github.com/anthropics/anthropic-sdk-go/issues/15)) ([98d1ffd](https://github.com/anthropics/anthropic-sdk-go/commit/98d1ffd29f97e85ea543f36ce104c341e729a7d2))
-
-
-### Bug Fixes
-
-* **requestconfig:** copy over more fields when cloning ([#17](https://github.com/anthropics/anthropic-sdk-go/issues/17)) ([d5e7415](https://github.com/anthropics/anthropic-sdk-go/commit/d5e741578ac0ff88db3b04564810321b18f4dd40))
-
-
-### Chores
-
-* **ci:** add CODEOWNERS file ([#12](https://github.com/anthropics/anthropic-sdk-go/issues/12)) ([71c33b8](https://github.com/anthropics/anthropic-sdk-go/commit/71c33b841dece97e77f04ea4feae3d586b59b0d6))
-
-
-### Documentation
-
-* improve and reference contributing documentation ([#21](https://github.com/anthropics/anthropic-sdk-go/issues/21)) ([7288df1](https://github.com/anthropics/anthropic-sdk-go/commit/7288df1e1e62401487bee0685f77119bae5287ee))
-* update CONTRIBUTING.md ([#18](https://github.com/anthropics/anthropic-sdk-go/issues/18)) ([dcfcbf8](https://github.com/anthropics/anthropic-sdk-go/commit/dcfcbf8d07e3d7a7d6b6398d60724f38eca050a4))
-
-## 0.1.0-alpha.1 (2024-08-14)
-
-Full Changelog: [v0.0.1-alpha.0...v0.1.0-alpha.1](https://github.com/anthropics/anthropic-sdk-go/compare/v0.0.1-alpha.0...v0.1.0-alpha.1)
-
-### Features
-
-* **api:** add prompt caching beta ([#11](https://github.com/anthropics/anthropic-sdk-go/issues/11)) ([78f8c72](https://github.com/anthropics/anthropic-sdk-go/commit/78f8c7266dd98ef5f76d258f485ee284b7a0e590))
-* publish ([5ff0ff8](https://github.com/anthropics/anthropic-sdk-go/commit/5ff0ff8cc5706c39a6dde75ae69d11c892ef8bb3))
-* simplify system prompt ([#3](https://github.com/anthropics/anthropic-sdk-go/issues/3)) ([cd3fcef](https://github.com/anthropics/anthropic-sdk-go/commit/cd3fcefad20baef3c28375adf16ab266f97e7d94))
-* simplify system prompt ([#4](https://github.com/anthropics/anthropic-sdk-go/issues/4)) ([85e1b34](https://github.com/anthropics/anthropic-sdk-go/commit/85e1b349619e7dd26c06ed0d9f566ddbbe80db2a))
-
-
-### Bug Fixes
-
-* deserialization of struct unions that implement json.Unmarshaler ([#6](https://github.com/anthropics/anthropic-sdk-go/issues/6)) ([a883a3a](https://github.com/anthropics/anthropic-sdk-go/commit/a883a3a8232dfca1ce8a139047a0356a3fd6015f))
-* handle nil pagination responses when HTTP status is 200 ([#2](https://github.com/anthropics/anthropic-sdk-go/issues/2)) ([2bb2325](https://github.com/anthropics/anthropic-sdk-go/commit/2bb232557a9f75d58b7e7145c69771c927574dd3))
-* message accumulation with union content block ([09457cb](https://github.com/anthropics/anthropic-sdk-go/commit/09457cb2ef8019cc23bcdefa0d3102e642d64b3d))
-
-
-### Chores
-
-* add back custom code ([106c404](https://github.com/anthropics/anthropic-sdk-go/commit/106c40466382daaa403e7f472647248e14d939d7))
-* bump Go to v1.21 ([#7](https://github.com/anthropics/anthropic-sdk-go/issues/7)) ([928ed50](https://github.com/anthropics/anthropic-sdk-go/commit/928ed50c83154eb4f56575cf9f405a132000888e))
-* **ci:** bump prism mock server version ([#5](https://github.com/anthropics/anthropic-sdk-go/issues/5)) ([0b326c6](https://github.com/anthropics/anthropic-sdk-go/commit/0b326c6b18effa222b8b03a17c1e562d0aedce1d))
-* **examples:** minor formatting changes ([#8](https://github.com/anthropics/anthropic-sdk-go/issues/8)) ([4195c55](https://github.com/anthropics/anthropic-sdk-go/commit/4195c5541a1a517a3890bfe43eb84e3ddc496bfe))
-
-
-### Documentation
-
-* add examples to README ([df47298](https://github.com/anthropics/anthropic-sdk-go/commit/df4729897b782faeaa6a0795359ecf20b4a833ca))
+* tidy up dependencies ([#140](https://github.com/anthropics/anthropic-sdk-go/issues/140)) ([289cc1b](https://github.com/anthropics/anthropic-sdk-go/commit/289cc1b007094421305dfc4ef01ae68bb2d50ee5))
diff --git a/MIGRATION.md b/MIGRATION.md
new file mode 100644
index 0000000..1bf985c
--- /dev/null
+++ b/MIGRATION.md
@@ -0,0 +1,284 @@
+# Anthropic Go Migration Guide
+
+<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go"><img src="https://pkg.go.dev/badge/github.com/anthropics/anthropic-sdk-go.svg" alt="Go Reference"></a>
+
+This SDK includes breaking changes to improve the ergonomics of constructing parameters and accessing responses.
+
+To reduce verbosity, the `anthropic.F(...)` and `param.Field[T]` have been removed.
+All calls to `anthropic.F(...)` can be deleted.
+
+The SDK now uses the <code>\`json:"...,omitzero"\`</code> struct tag to omit fields. Nested structs, arrays and maps
+can be declared like normal.
+
+The old SDK used interfaces for unions in requests, which required
+a type assertion to access variants and fields. The new design uses
+structs with a field for each variant, wherein only one field can be set.
+These struct unions also expose 'Get' methods to access and mutate subfields
+which may be shared by multiple variants.
+
+# Request parameters
+
+## Required primitives parameters serialize their zero values (`string`, `int64`, etc.)
+
+> [!CAUTION]
+>
+> **This change can cause new behavior in existing code, without compiler warnings.**
+
+While migrating, ensure that all required fields are explicitly set. A required primitive
+field `Age` will use the <code>\`json:"age,required"\`</code> struct tag without `omitzero`.
+
+If a required primitive field is not set, the zero value will be serialized.
+This was not the case in with `param.Field[T]`.
+
+```diff
+type FooParams struct {
+- Age param.Field[int64] `json:"age,required"`
+- Name param.Field[string] `json:"name"`
++ Age int64 `json:"age,required"` // <== Notice no omitzero
++ Name param.Opt[string] `json:"name,omitzero"`
+}
+```
+
+<table>
+<tr>
+<th>Previous</th>
+<th>New</th>
+</tr>
+<tr>
+<td>
+
+```go
+_ = FooParams{
+ Name: anthropic.String("Jerry")
+}
+`{"name": "Jerry"}` // (after serialization)
+```
+
+</td>
+<td>
+
+```go
+_ = FooParams{
+ Name: anthropic.String("Jerry")
+}
+`{"name": "Jerry", "age": 0}` // <== Notice the age field
+```
+
+</td>
+</tr>
+</table>
+
+The required field `"age"` is now present as `0`. Fields without the <code>\`json:"...,omitzero"\`</code> struct tag
+are always serialized, including their zero values.
+
+## Transition from `param.Field[T]` to `omitzero`
+
+The `anthropic.F(...)` function and `param.Field[T]` type are no longer present in the new SDK.
+
+To represent omitted fields, the SDK uses <a href="https://pkg.go.dev/encoding/json#Marshal"><code>\`json:"...,omitzero"\`</code> semantics</a> from Go 1.24+ for JSON encoding[^1]. `omitzero` always omits fields
+with zero values.
+
+In all cases other than optional primitives, `anthropic.F()` can simply be removed.
+For optional primitive types, such as `param.Opt[string]`, you can use `anthropic.String(string)` to construct the value.
+Similar functions exist for other primitive types like `anthropic.Int(int)`, `anthropic.Bool(bool)`, etc.
+
+`omitzero` is used for fields whose type is either a struct, slice, map, string enum,
+or wrapped optional primitive (e.g. `param.Opt[T]`). Required primitive fields don't use `omitzero`.
+
+**Example User Code: Constructing a request**
+
+```diff
+foo = FooParams{
+- RequiredString: anthropic.String("hello"),
++ RequiredString: "hello",
+
+- OptionalString: anthropic.String("hi"),
++ OptionalString: anthropic.String("hi"),
+
+- Array: anthropic.F([]BarParam{
+- BarParam{Prop: ... }
+- }),
++ Array: []BarParam{
++ BarParam{Prop: ... }
++ },
+
+- RequiredObject: anthropic.F(BarParam{ ... }),
++ RequiredObject: BarParam{ ... },
+
+- OptionalObject: anthropic.F(BarParam{ ... }),
++ OptionalObject: BarParam{ ... },
+
+- StringEnum: anthropic.F[BazEnum]("baz-ok"),
++ StringEnum: "baz-ok",
+}
+```
+
+**Internal SDK Code: Fields of a request struct:**
+
+```diff
+type FooParams struct {
+- RequiredString param.Field[string] `json:"required_string,required"`
++ RequiredString string `json:"required_string,required"`
+
+- OptionalString param.Field[string] `json:"optional_string"`
++ OptionalString param.Opt[string] `json:"optional_string,omitzero"`
+
+- Array param.Field[[]BarParam] `json"array"`
++ Array []BarParam `json"array,omitzero"`
+
+- Map param.Field[map[string]BarParam] `json"map"`
++ Map map[string]BarParam `json"map,omitzero"`
+
+- RequiredObject param.Field[BarParam] `json:"required_object,required"`
++ RequiredObject BarParam `json:"required_object,omitzero,required"`
+
+- OptionalObject param.Field[BarParam] `json:"optional_object"`
++ OptionalObject BarParam `json:"optional_object,omitzero"`
+
+- StringEnum param.Field[BazEnum] `json:"string_enum"`
++ StringEnum BazEnum `json:"string_enum,omitzero"`
+}
+```
+
+## Request Unions: Removing interfaces and moving to structs
+
+For a type `AnimalUnionParam` which could be either a `CatParam | DogParam`.
+
+<table>
+<tr><th>Previous</th> <th>New</th></tr>
+<tr>
+<td>
+
+```go
+type AnimalParam interface {
+ ImplAnimalParam()
+}
+
+func (Dog) ImplAnimalParam() {}
+func (Cat) ImplAnimalParam() {}
+```
+
+</td>
+<td>
+
+```go
+type AnimalUnionParam struct {
+ OfCat *Cat `json:",omitzero,inline`
+ OfDog *Dog `json:",omitzero,inline`
+}
+```
+
+</td>
+</tr>
+
+<tr style="background:rgb(209, 217, 224)">
+<td>
+
+```go
+var dog AnimalParam = DogParam{
+ Name: "spot", ...
+}
+var cat AnimalParam = CatParam{
+ Name: "whiskers", ...
+}
+```
+
+</td>
+<td>
+
+```go
+dog := AnimalUnionParam{
+ OfDog: &DogParam{Name: "spot", ... },
+}
+cat := AnimalUnionParam{
+ OfCat: &CatParam{Name: "whiskers", ... },
+}
+```
+
+</td>
+</tr>
+
+<tr>
+<td>
+
+```go
+var name string
+switch v := animal.(type) {
+case Dog:
+ name = v.Name
+case Cat:
+ name = v.Name
+}
+```
+
+</td>
+<td>
+
+```go
+// Accessing fields
+var name *string = animal.GetName()
+```
+
+</td>
+</tr>
+</table>
+
+## Sending explicit `null` values
+
+The old SDK had a function `param.Null[T]()` which could set `param.Field[T]` to `null`.
+
+The new SDK uses `param.NullOpt[T]()` for to set a `param.Opt[T]` to `null`,
+and `param.NullObj[T]()` to set a param struct `T` to `null`.
+
+```diff
+- var nullObj param.Field[BarParam] = param.Null[BarParam]()
++ var nullObj BarParam = param.NullObj[BarParam]()
+
+- var nullPrimitive param.Field[int64] = param.Null[int64]()
++ var nullPrimitive param.Opt[int64] = param.NullOpt[int64]()
+```
+
+## Sending custom values
+
+The `anthropic.Raw[T](any)` function has been removed. All request structs now support a
+`.WithExtraField(map[string]any)` method to customize the fields.
+
+```diff
+foo := FooParams{
+ A: param.String("hello"),
+- B: param.Raw[string](12) // sending `12` instead of a string
+}
++ foo.WithExtraFields(map[string]any{
++ "B": 12,
++ })
+```
+
+# Response Properties
+
+## Checking for presence of optional fields
+
+The `.IsNull()` method has been changed to `.IsPresent()` to better reflect its behavior.
+
+```diff
+- if !resp.Foo.JSON.Bar.IsNull() {
++ if resp.Foo.JSON.Bar.IsPresent() {
+ println("bar is present:", resp.Foo.Bar)
+}
+```
+
+| Previous | New | Returns true for values |
+| -------------- | ------------------- | ----------------------- |
+| `.IsNull()` | `!.IsPresent()` | `null` or Omitted |
+| `.IsMissing()` | `.Raw() == ""` | Omitted |
+| | `.IsExplicitNull()` | `null` |
+
+## Checking Raw JSON of a response
+
+The `.RawJSON()` method has moved to the parent of the `.JSON` property.
+
+```diff
+- resp.Foo.JSON.RawJSON()
++ resp.Foo.RawJSON()
+```
+
+[^1]: The SDK doesn't require Go 1.24, despite supporting the `omitzero` feature
diff --git a/README.md b/README.md
index 6a5dbf4..f437e49 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,10 @@
The Anthropic Go library provides convenient access to [the Anthropic REST
API](https://docs.anthropic.com/claude/reference/) from applications written in Go. The full API of this library can be found in [api.md](api.md).
+> [!WARNING]
+> The latest version of this package uses a new design with significant breaking changes.
+> Please refer to the [migration guide](./MIGRATION.md) for more information on how to update your code.
+
## Installation
<!-- x-release-please-start-version -->
@@ -22,7 +26,7 @@ Or to pin the version:
<!-- x-release-please-start-version -->
```sh
-go get -u 'github.com/anthropics/[email protected]'
+go get -u 'github.com/anthropics/[email protected]'
```
<!-- x-release-please-end -->
@@ -51,11 +55,14 @@ func main() {
option.WithAPIKey("my-anthropic-api-key"), // defaults to os.LookupEnv("ANTHROPIC_API_KEY")
)
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{
- anthropic.NewUserMessage(anthropic.NewTextBlock("What is a quaternion?")),
- }),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?"},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
if err != nil {
panic(err.Error())
@@ -70,25 +77,32 @@ func main() {
```go
messages := []anthropic.MessageParam{
- anthropic.NewUserMessage(anthropic.NewTextBlock("What is my first name?")),
+ anthropic.NewUserMessage(anthropic.NewTextBlock("What is my first name?")),
}
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- Messages: anthropic.F(messages),
- MaxTokens: anthropic.F(int64(1024)),
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ Messages: messages,
+ MaxTokens: 1024,
})
+if err != nil {
+ panic(err)
+}
+
+fmt.Printf("%+v\n", message.Content)
messages = append(messages, message.ToParam())
messages = append(messages, anthropic.NewUserMessage(
- anthropic.NewTextBlock("My full name is John Doe"),
+ anthropic.NewTextBlock("My full name is John Doe"),
))
message, err = client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- Messages: anthropic.F(messages),
- MaxTokens: anthropic.F(int64(1024)),
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ Messages: messages,
+ MaxTokens: 1024,
})
+
+fmt.Printf("%+v\n", message.Content)
```
</details>
@@ -97,17 +111,13 @@ message, err = client.Messages.New(context.TODO(), anthropic.MessageNewParams{
<summary>System prompts</summary>
```go
-messages := []anthropic.MessageParam{
- anthropic.NewUserMessage(anthropic.NewTextBlock("What is my first name?")),
-}
-
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- MaxTokens: anthropic.Int(1024),
- System: anthropic.F([]anthropic.TextBlockParam{
- anthropic.NewTextBlock("Be very serious at all times."),
- }),
- Messages: anthropic.F(messages),
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ MaxTokens: 1024,
+ System: []anthropic.TextBlockParam{
+ {Text: "Be very serious at all times."},
+ },
+ Messages: messages,
})
```
@@ -117,29 +127,36 @@ message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
<summary>Streaming</summary>
```go
+content := "What is a quaternion?"
+
stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F([]anthropic.MessageParam{
- anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
- }),
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{
+ anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
+ },
})
message := anthropic.Message{}
for stream.Next() {
- event := stream.Current()
- message.Accumulate(event)
-
- switch delta := event.Delta.(type) {
- case anthropic.ContentBlockDeltaEventDelta:
- if delta.Text != "" {
- print(delta.Text)
- }
- }
-}
-
-if stream.Err() != nil {
- panic(stream.Err())
+ event := stream.Current()
+ err := message.Accumulate(event)
+ if err != nil {
+ panic(err)
+ }
+
+ switch eventVariant := event.AsAny().(type) {
+ case anthropic.ContentBlockDeltaEvent:
+ switch deltaVariant := eventVariant.Delta.AsAny().(type) {
+ case anthropic.TextDelta:
+ print(deltaVariant.Text)
+ }
+
+ }
+
+ if stream.Err() != nil {
+ panic(stream.Err())
+ }
}
```
@@ -156,8 +173,8 @@ import (
"encoding/json"
"fmt"
- "github.com/invopop/jsonschema"
"github.com/anthropics/anthropic-sdk-go"
+ "github.com/invopop/jsonschema"
)
func main() {
@@ -171,20 +188,24 @@ func main() {
anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
}
- tools := []anthropic.ToolParam{
+ toolParams := []anthropic.ToolParam{
{
- Name: anthropic.F("get_coordinates"),
- Description: anthropic.F("Accepts a place as an address, then returns the latitude and longitude coordinates."),
- InputSchema: anthropic.F(GetCoordinatesInputSchema),
+ Name: "get_coordinates",
+ Description: anthropic.String("Accepts a place as an address, then returns the latitude and longitude coordinates."),
+ InputSchema: GetCoordinatesInputSchema,
},
}
+ tools := make([]anthropic.ToolUnionParam, len(toolParams))
+ for i, toolParam := range toolParams {
+ tools[i] = anthropic.ToolUnionParam{OfTool: &toolParam}
+ }
for {
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F(messages),
- Tools: anthropic.F(tools),
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ MaxTokens: 1024,
+ Messages: messages,
+ Tools: tools,
})
if err != nil {
@@ -193,29 +214,37 @@ func main() {
print(color("[assistant]: "))
for _, block := range message.Content {
- switch block := block.AsUnion().(type) {
+ switch block := block.AsAny().(type) {
case anthropic.TextBlock:
println(block.Text)
+ println()
case anthropic.ToolUseBlock:
- println(block.Name + ": " + string(block.Input))
+ inputJSON, _ := json.Marshal(block.Input)
+ println(block.Name + ": " + string(inputJSON))
+ println()
}
}
messages = append(messages, message.ToParam())
- toolResults := []anthropic.MessageParamContentUnion{}
+ toolResults := []anthropic.ContentBlockParamUnion{}
for _, block := range message.Content {
- if block.Type == anthropic.ContentBlockTypeToolUse {
- print("[user (" + block.Name + ")]: ")
+ switch variant := block.AsAny().(type) {
+ case anthropic.ToolUseBlock:
+ print(color("[user (" + block.Name + ")]: "))
var response interface{}
switch block.Name {
case "get_coordinates":
- input := GetCoordinatesInput{}
- err := json.Unmarshal(block.Input, &input)
+ var input struct {
+ Location string `json:"location"`
+ }
+
+ err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
if err != nil {
panic(err)
}
+
response = GetCoordinates(input.Location)
}
@@ -224,8 +253,11 @@ func main() {
panic(err)
}
+ println(string(b))
+
toolResults = append(toolResults, anthropic.NewToolResultBlock(block.ID, string(b), false))
}
+
}
if len(toolResults) == 0 {
break
@@ -252,13 +284,22 @@ func GetCoordinates(location string) GetCoordinateResponse {
}
}
-func GenerateSchema[T any]() interface{} {
+func GenerateSchema[T any]() anthropic.ToolInputSchemaParam {
reflector := jsonschema.Reflector{
AllowAdditionalProperties: false,
DoNotReference: true,
}
var v T
- return reflector.Reflect(v)
+
+ schema := reflector.Reflect(v)
+
+ return anthropic.ToolInputSchemaParam{
+ Properties: schema.Properties,
+ }
+}
+
+func color(s string) string {
+ return fmt.Sprintf("\033[1;%sm%s\033[0m", "33", s)
}
```
@@ -266,31 +307,82 @@ func GenerateSchema[T any]() interface{} {
### Request fields
-All request parameters are wrapped in a generic `Field` type,
-which we use to distinguish zero values from null or omitted fields.
+The anthropic library uses the [`omitzero`](https://tip.golang.org/doc/go1.24#encodingjsonpkgencodingjson)
+semantics from the Go 1.24+ `encoding/json` release for request fields.
+
+Required primitive fields (`int64`, `string`, etc.) feature the tag <code>\`json:...,required\`</code>. These
+fields are always serialized, even their zero values.
+
+Optional primitive types are wrapped in a `param.Opt[T]`. Use the provided constructors set `param.Opt[T]` fields such as `anthropic.String(string)`, `anthropic.Int(int64)`, etc.
+
+Optional primitives, maps, slices and structs and string enums (represented as `string`) always feature the
+tag <code>\`json:"...,omitzero"\`</code>. Their zero values are considered omitted.
-This prevents accidentally sending a zero value if you forget a required parameter,
-and enables explicitly sending `null`, `false`, `''`, or `0` on optional parameters.
-Any field not specified is not sent.
+Any non-nil slice of length zero will serialize as an empty JSON array, `"[]"`. Similarly, any non-nil map with length zero with serialize as an empty JSON object, `"{}"`.
-To construct fields with values, use the helpers `String()`, `Int()`, `Float()`, or most commonly, the generic `F[T]()`.
-To send a null, use `Null[T]()`, and to send a nonconforming value, use `Raw[T](any)`. For example:
+To send `null` instead of an `param.Opt[T]`, use `param.NullOpt[T]()`.
+To send `null` instead of a struct, use `param.NullObj[T]()`, where `T` is a struct.
+To send a custom value instead of a struct, use `param.OverrideObj[T](value)`.
+
+To override request structs contain a `.WithExtraFields(map[string]any)` method which can be used to
+send non-conforming fields in the request body. Extra fields overwrite any struct fields with a matching
+key, so only use with trusted data.
```go
params := FooParams{
- Name: anthropic.F("hello"),
+ ID: "id_xxx", // required property
+ Name: anthropic.String("hello"), // optional property
+ Description: param.NullOpt[string](), // explicit null property
+
+ Point: anthropic.Point{
+ X: 0, // required field will serialize as 0
+ Y: anthropic.Int(1), // optional field will serialize as 1
+ // ... omitted non-required fields will not be serialized
+ }),
- // Explicitly send `"description": null`
- Description: anthropic.Null[string](),
+ Origin: anthropic.Origin{}, // the zero value of [Origin] is considered omitted
+}
- Point: anthropic.F(anthropic.Point{
- X: anthropic.Int(0),
- Y: anthropic.Int(1),
+// In cases where the API specifies a given type,
+// but you want to send something else, use [WithExtraFields]:
+params.WithExtraFields(map[string]any{
+ "x": 0.01, // send "x" as a float instead of int
+})
- // In cases where the API specifies a given type,
- // but you want to send something else, use `Raw`:
- Z: anthropic.Raw[int64](0.01), // sends a float
- }),
+// Send a number instead of an object
+custom := param.OverrideObj[anthropic.FooParams](12)
+```
+
+When available, use the `.IsPresent()` method to check if an optional parameter is not omitted or `null`.
+Otherwise, the `param.IsOmitted(any)` function can confirm the presence of any `omitzero` field.
+
+### Request unions
+
+Unions are represented as a struct with fields prefixed by "Of" for each of it's 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.
+These methods return a mutable pointer to the underlying data, if present.
+
+```go
+// Only one field can be non-zero, use param.IsOmitted() to check if a field is set
+type AnimalUnionParam struct {
+ OfCat *Cat `json:",omitzero,inline`
+ OfDog *Dog `json:",omitzero,inline`
+}
+
+animal := AnimalUnionParam{
+ OfCat: &Cat{
+ Name: "Whiskers",
+ Owner: PersonParam{
+ Address: AddressParam{Street: "3333 Coyote Hill Rd", Zip: 0},
+ },
+ },
+}
+
+// Mutating a field
+if address := animal.GetOwner().GetAddress(); address != nil {
+ address.ZipCode = 94304
}
```
@@ -306,14 +398,14 @@ information about each property, which you can use like so:
```go
if res.Name == "" {
- // true if `"name"` is either not present or explicitly null
- res.JSON.Name.IsNull()
+ // true if `"name"` was unmarshalled successfully
+ res.JSON.Name.IsPresent()
- // true if the `"name"` key was not present in the response JSON at all
- res.JSON.Name.IsMissing()
+ res.JSON.Name.IsExplicitNull() // true if `"name"` is explicitly null
+ res.JSON.Name.Raw() == "" // true if `"name"` field does not exist
// When the API returns data that cannot be coerced to the expected type:
- if res.JSON.Name.IsInvalid() {
+ if !res.JSON.Name.IsPresent() && res.JSON.Name.Raw() != "" {
raw := res.JSON.Name.Raw()
legacyName := struct{
@@ -326,7 +418,7 @@ if res.Name == "" {
}
```
-These `.JSON` structs also include an `Extras` map containing
+These `.JSON` structs also include an `ExtraFields` map containing
any properties in the json response that were not specified
in the struct. This can be useful for API features not yet
present in the SDK.
@@ -335,6 +427,49 @@ present in the SDK.
body := res.JSON.ExtraFields["my_unexpected_field"].Raw()
```
+### Response Unions
+
+In responses, unions are represented by a flattened struct containing all possible fields from each of the
+object variants.
+To convert it to a variant use the `.AsFooVariant()` method or the `.AsAny()` method if present.
+
+If a response value union contains primitive values, primitive fields will be alongside
+the properties but prefixed with `Of` and feature the tag `json:"...,inline"`.
+
+```go
+type AnimalUnion struct {
+ OfString string `json:",inline"`
+ Name string `json:"name"`
+ Owner Person `json:"owner"`
+ // ...
+ JSON struct {
+ OfString resp.Field
+ Name resp.Field
+ Owner resp.Field
+ // ...
+ }
+}
+
+// If animal variant
+if animal.Owner.Address.JSON.ZipCode == "" {
+ panic("missing zip code")
+}
+
+// If string variant
+if !animal.OfString == "" {
+ panic("expected a name")
+}
+
+// Switch on the variant
+switch variant := animalOrName.AsAny().(type) {
+case string:
+case Dog:
+case Cat:
+default:
+ panic("unexpected type")
+}
+```
+
### RequestOptions
This library uses the functional options pattern. Functions defined in the
@@ -366,7 +501,7 @@ You can use `.ListAutoPaging()` methods to iterate through items across all page
```go
iter := client.Beta.Messages.Batches.ListAutoPaging(context.TODO(), anthropic.BetaMessageBatchListParams{
- Limit: anthropic.F(int64(20)),
+ Limit: anthropic.Int(20),
})
// Automatically fetches more pages as needed.
for iter.Next() {
@@ -383,7 +518,7 @@ with additional helper methods like `.GetNextPage()`, e.g.:
```go
page, err := client.Beta.Messages.Batches.List(context.TODO(), anthropic.BetaMessageBatchListParams{
- Limit: anthropic.F(int64(20)),
+ Limit: anthropic.Int(20),
})
for page != nil {
for _, batch := range page.Data {
@@ -407,8 +542,16 @@ To handle errors, we recommend that you use the `errors.As` pattern:
```go
_, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
if err != nil {
var apierr *anthropic.Error
@@ -437,11 +580,14 @@ defer cancel()
client.Messages.New(
ctx,
anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{
- anthropic.NewUserMessage(anthropic.NewTextBlock("What is a quaternion?")),
- }),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?"},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
},
// This sets the per-retry timeout
option.WithRequestTimeout(20*time.Second),
@@ -462,7 +608,7 @@ Calling `.Messages.NewStreaming()` or [setting a custom timeout](#timeouts) disa
### File uploads
Request parameters that correspond to file uploads in multipart requests are typed as
-`param.Field[io.Reader]`. The contents of the `io.Reader` will by default be sent as a multipart form
+`io.Reader`. The contents of the `io.Reader` will by default be sent as a multipart form
part with the file name of "anonymous_file" and content-type of "application/octet-stream".
The file name and content-type can be customized by implementing `Name() string` or `ContentType()
@@ -490,11 +636,14 @@ client := anthropic.NewClient(
client.Messages.New(
context.TODO(),
anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{
- anthropic.NewUserMessage(anthropic.NewTextBlock("What is a quaternion?")),
- }),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?"},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
},
option.WithMaxRetries(5),
)
@@ -511,12 +660,16 @@ var response *http.Response
message, err := client.Messages.New(
context.TODO(),
anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
},
option.WithResponseInto(&response),
)
@@ -541,17 +694,17 @@ To make requests to undocumented endpoints, you can use `client.Get`, `client.Po
```go
var (
- // params can be an io.Reader, a []byte, an encoding/json serializable object,
- // or a "…Params" struct defined in this library.
- params map[string]interface{}
+ // params can be an io.Reader, a []byte, an encoding/json serializable object,
+ // or a "…Params" struct defined in this library.
+ params map[string]interface{}
- // result can be an []byte, *http.Response, a encoding/json deserializable object,
- // or a model defined in this library.
- result *http.Response
+ // result can be an []byte, *http.Response, a encoding/json deserializable object,
+ // or a model defined in this library.
+ result *http.Response
)
err := client.Post(context.Background(), "/unspecified", params, &result)
if err != nil {
- …
+ …
}
```
@@ -562,10 +715,10 @@ or the `option.WithJSONSet()` methods.
```go
params := FooNewParams{
- ID: anthropic.F("id_xxxx"),
- Data: anthropic.F(FooNewParamsData{
- FirstName: anthropic.F("John"),
- }),
+ ID: "id_xxxx",
+ Data: FooNewParamsData{
+ FirstName: anthropic.String("John"),
+ },
}
client.Foo.New(context.Background(), params, option.WithJSONSet("data.last_name", "Doe"))
```
@@ -596,7 +749,7 @@ func Logger(req *http.Request, next option.MiddlewareNext) (res *http.Response,
end := time.Now()
LogRes(res, err, start - end)
- return res, err
+ return res, err
}
client := anthropic.NewClient(
@@ -661,7 +814,7 @@ import (
func main() {
client := anthropic.NewClient(
- vertex.WithGoogleAuth(context.Background(), "us-central1", "stainless-399616"),
+ vertex.WithGoogleAuth(context.Background(), "us-central1", "id-xxx"),
)
}
```
diff --git a/aliases.go b/aliases.go
index 0205358..da74b40 100644
--- a/aliases.go
+++ b/aliases.go
@@ -4,130 +4,37 @@ package anthropic
import (
"github.com/anthropics/anthropic-sdk-go/internal/apierror"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
"github.com/anthropics/anthropic-sdk-go/shared"
)
-type Error = apierror.Error
-
-// This is an alias to an internal type.
-type APIErrorObject = shared.APIErrorObject
-
-// This is an alias to an internal type.
-type APIErrorObjectType = shared.APIErrorObjectType
-
-// This is an alias to an internal value.
-const APIErrorObjectTypeAPIError = shared.APIErrorObjectTypeAPIError
-
-// This is an alias to an internal type.
-type AuthenticationError = shared.AuthenticationError
-
-// This is an alias to an internal type.
-type AuthenticationErrorType = shared.AuthenticationErrorType
-
-// This is an alias to an internal value.
-const AuthenticationErrorTypeAuthenticationError = shared.AuthenticationErrorTypeAuthenticationError
-
-// This is an alias to an internal type.
-type BillingError = shared.BillingError
+// aliased to make [param.APIUnion] private when embedding
+type paramUnion = param.APIUnion
-// This is an alias to an internal type.
-type BillingErrorType = shared.BillingErrorType
+// aliased to make [param.APIObject] private when embedding
+type paramObj = param.APIObject
-// This is an alias to an internal value.
-const BillingErrorTypeBillingError = shared.BillingErrorTypeBillingError
+type Error = apierror.Error
// This is an alias to an internal type.
-type ErrorObject = shared.ErrorObject
+type APIErrorObject = shared.APIErrorObject
// This is an alias to an internal type.
-type ErrorObjectType = shared.ErrorObjectType
-
-// This is an alias to an internal value.
-const ErrorObjectTypeInvalidRequestError = shared.ErrorObjectTypeInvalidRequestError
-
-// This is an alias to an internal value.
-const ErrorObjectTypeAuthenticationError = shared.ErrorObjectTypeAuthenticationError
-
-// This is an alias to an internal value.
-const ErrorObjectTypeBillingError = shared.ErrorObjectTypeBillingError
-
-// This is an alias to an internal value.
-const ErrorObjectTypePermissionError = shared.ErrorObjectTypePermissionError
-
-// This is an alias to an internal value.
-const ErrorObjectTypeNotFoundError = shared.ErrorObjectTypeNotFoundError
-
-// This is an alias to an internal value.
-const ErrorObjectTypeRateLimitError = shared.ErrorObjectTypeRateLimitError
-
-// This is an alias to an internal value.
-const ErrorObjectTypeTimeoutError = shared.ErrorObjectTypeTimeoutError
-
-// This is an alias to an internal value.
-const ErrorObjectTypeAPIError = shared.ErrorObjectTypeAPIError
-
-// This is an alias to an internal value.
-const ErrorObjectTypeOverloadedError = shared.ErrorObjectTypeOverloadedError
+type ErrorObjectUnion = shared.ErrorObjectUnion
// This is an alias to an internal type.
type ErrorResponse = shared.ErrorResponse
-// This is an alias to an internal type.
-type ErrorResponseType = shared.ErrorResponseType
-
-// This is an alias to an internal value.
-const ErrorResponseTypeError = shared.ErrorResponseTypeError
-
// This is an alias to an internal type.
type GatewayTimeoutError = shared.GatewayTimeoutError
-// This is an alias to an internal type.
-type GatewayTimeoutErrorType = shared.GatewayTimeoutErrorType
-
-// This is an alias to an internal value.
-const GatewayTimeoutErrorTypeTimeoutError = shared.GatewayTimeoutErrorTypeTimeoutError
-
-// This is an alias to an internal type.
-type InvalidRequestError = shared.InvalidRequestError
-
-// This is an alias to an internal type.
-type InvalidRequestErrorType = shared.InvalidRequestErrorType
-
-// This is an alias to an internal value.
-const InvalidRequestErrorTypeInvalidRequestError = shared.InvalidRequestErrorTypeInvalidRequestError
-
-// This is an alias to an internal type.
-type NotFoundError = shared.NotFoundError
-
-// This is an alias to an internal type.
-type NotFoundErrorType = shared.NotFoundErrorType
-
-// This is an alias to an internal value.
-const NotFoundErrorTypeNotFoundError = shared.NotFoundErrorTypeNotFoundError
-
-// This is an alias to an internal type.
-type OverloadedError = shared.OverloadedError
-
-// This is an alias to an internal type.
-type OverloadedErrorType = shared.OverloadedErrorType
-
-// This is an alias to an internal value.
-const OverloadedErrorTypeOverloadedError = shared.OverloadedErrorTypeOverloadedError
-
-// This is an alias to an internal type.
-type PermissionError = shared.PermissionError
-
-// This is an alias to an internal type.
-type PermissionErrorType = shared.PermissionErrorType
-
-// This is an alias to an internal value.
-const PermissionErrorTypePermissionError = shared.PermissionErrorTypePermissionError
-
-// This is an alias to an internal type.
-type RateLimitError = shared.RateLimitError
-
-// This is an alias to an internal type.
-type RateLimitErrorType = shared.RateLimitErrorType
-
-// This is an alias to an internal value.
-const RateLimitErrorTypeRateLimitError = shared.RateLimitErrorTypeRateLimitError
+func toParam[T comparable](value T, meta resp.Field) param.Opt[T] {
+ if meta.IsPresent() {
+ return param.NewOpt(value)
+ }
+ if meta.IsExplicitNull() {
+ return param.NullOpt[T]()
+ }
+ return param.Opt[T]{}
+}
diff --git a/api.md b/api.md
index 4f9239a..674ae97 100644
--- a/api.md
+++ b/api.md
@@ -3,7 +3,7 @@
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared#APIErrorObject">APIErrorObject</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared#AuthenticationError">AuthenticationError</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared#BillingError">BillingError</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared#ErrorObject">ErrorObject</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared#ErrorObjectUnion">ErrorObjectUnion</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared#ErrorResponse">ErrorResponse</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared#GatewayTimeoutError">GatewayTimeoutError</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared">shared</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go/shared#InvalidRequestError">InvalidRequestError</a>
@@ -49,7 +49,7 @@ Params Types:
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#ToolChoiceToolParam">ToolChoiceToolParam</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#ToolResultBlockParam">ToolResultBlockParam</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#ToolTextEditor20250124Param">ToolTextEditor20250124Param</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#ToolUnionUnionParam">ToolUnionUnionParam</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#ToolUnionParam">ToolUnionParam</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#ToolUseBlockParam">ToolUseBlockParam</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#URLImageSourceParam">URLImageSourceParam</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#URLPDFSourceParam">URLPDFSourceParam</a>
@@ -60,7 +60,7 @@ Response Types:
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#CitationContentBlockLocation">CitationContentBlockLocation</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#CitationPageLocation">CitationPageLocation</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#CitationsDelta">CitationsDelta</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#ContentBlock">ContentBlock</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#ContentBlockUnion">ContentBlockUnion</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#InputJSONDelta">InputJSONDelta</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#Message">Message</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageDeltaUsage">MessageDeltaUsage</a>
@@ -72,11 +72,11 @@ Response Types:
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageDeltaEvent">MessageDeltaEvent</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageStartEvent">MessageStartEvent</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageStopEvent">MessageStopEvent</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageStreamEvent">MessageStreamEvent</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageStreamEventUnion">MessageStreamEventUnion</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#RedactedThinkingBlock">RedactedThinkingBlock</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#SignatureDelta">SignatureDelta</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#TextBlock">TextBlock</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#TextCitation">TextCitation</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#TextCitationUnion">TextCitationUnion</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#TextDelta">TextDelta</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#ThinkingBlock">ThinkingBlock</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#ThinkingDelta">ThinkingDelta</a>
@@ -99,7 +99,7 @@ Response Types:
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageBatchExpiredResult">MessageBatchExpiredResult</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageBatchIndividualResponse">MessageBatchIndividualResponse</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageBatchRequestCounts">MessageBatchRequestCounts</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageBatchResult">MessageBatchResult</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageBatchResultUnion">MessageBatchResultUnion</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#MessageBatchSucceededResult">MessageBatchSucceededResult</a>
Methods:
@@ -133,7 +133,7 @@ Response Types:
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaAPIError">BetaAPIError</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaAuthenticationError">BetaAuthenticationError</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaBillingError">BetaBillingError</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaError">BetaError</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaErrorUnion">BetaErrorUnion</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaErrorResponse">BetaErrorResponse</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaGatewayTimeoutError">BetaGatewayTimeoutError</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaInvalidRequestError">BetaInvalidRequestError</a>
@@ -192,7 +192,7 @@ Params Types:
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaToolResultBlockParam">BetaToolResultBlockParam</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaToolTextEditor20241022Param">BetaToolTextEditor20241022Param</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaToolTextEditor20250124Param">BetaToolTextEditor20250124Param</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaToolUnionUnionParam">BetaToolUnionUnionParam</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaToolUnionParam">BetaToolUnionParam</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaToolUseBlockParam">BetaToolUseBlockParam</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaURLImageSourceParam">BetaURLImageSourceParam</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaURLPDFSourceParam">BetaURLPDFSourceParam</a>
@@ -203,7 +203,7 @@ Response Types:
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaCitationContentBlockLocation">BetaCitationContentBlockLocation</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaCitationPageLocation">BetaCitationPageLocation</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaCitationsDelta">BetaCitationsDelta</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaContentBlock">BetaContentBlock</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaContentBlockUnion">BetaContentBlockUnion</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaInputJSONDelta">BetaInputJSONDelta</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaMessage">BetaMessage</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaMessageDeltaUsage">BetaMessageDeltaUsage</a>
@@ -214,11 +214,11 @@ Response Types:
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaRawMessageDeltaEvent">BetaRawMessageDeltaEvent</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaRawMessageStartEvent">BetaRawMessageStartEvent</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaRawMessageStopEvent">BetaRawMessageStopEvent</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaRawMessageStreamEvent">BetaRawMessageStreamEvent</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaRawMessageStreamEventUnion">BetaRawMessageStreamEventUnion</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaRedactedThinkingBlock">BetaRedactedThinkingBlock</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaSignatureDelta">BetaSignatureDelta</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaTextBlock">BetaTextBlock</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaTextCitation">BetaTextCitation</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaTextCitationUnion">BetaTextCitationUnion</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaTextDelta">BetaTextDelta</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaThinkingBlock">BetaThinkingBlock</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaThinkingDelta">BetaThinkingDelta</a>
@@ -241,7 +241,7 @@ Response Types:
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaMessageBatchExpiredResult">BetaMessageBatchExpiredResult</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaMessageBatchIndividualResponse">BetaMessageBatchIndividualResponse</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaMessageBatchRequestCounts">BetaMessageBatchRequestCounts</a>
-- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaMessageBatchResult">BetaMessageBatchResult</a>
+- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaMessageBatchResultUnion">BetaMessageBatchResultUnion</a>
- <a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go">anthropic</a>.<a href="https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#BetaMessageBatchSucceededResult">BetaMessageBatchSucceededResult</a>
Methods:
diff --git a/bedrock/bedrock.go b/bedrock/bedrock.go
index d535321..57b0008 100644
--- a/bedrock/bedrock.go
+++ b/bedrock/bedrock.go
@@ -180,12 +180,12 @@ func WithConfig(cfg aws.Config) option.RequestOption {
signer := v4.NewSigner()
middleware := bedrockMiddleware(signer, cfg)
- return func(rc *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(rc *requestconfig.RequestConfig) error {
return rc.Apply(
option.WithBaseURL(fmt.Sprintf("https://bedrock-runtime.%s.amazonaws.com", cfg.Region)),
option.WithMiddleware(middleware),
)
- }
+ })
}
func bedrockMiddleware(signer *v4.Signer, cfg aws.Config) option.Middleware {
diff --git a/bedrock/bedrock_test.go b/bedrock/bedrock_test.go
deleted file mode 100644
index 2f98f2b..0000000
--- a/bedrock/bedrock_test.go
+++ /dev/null
@@ -1,38 +0,0 @@
-package bedrock
-
-import (
- "context"
- "errors"
- "net/http"
- "testing"
-
- "github.com/anthropics/anthropic-sdk-go"
- "github.com/anthropics/anthropic-sdk-go/option"
-)
-
-func TestBedrockError(t *testing.T) {
- expectedErr := errors.New("simulated network error")
-
- client := anthropic.NewClient(
- option.WithMiddleware(func(r *http.Request, next option.MiddlewareNext) (*http.Response, error) {
- return nil, expectedErr
- }),
- )
-
- // Attempt to make a request
- stream := client.Messages.NewStreaming(context.Background(), anthropic.MessageNewParams{
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F([]anthropic.MessageParam{
- anthropic.NewUserMessage(anthropic.NewTextBlock("test message")),
- }),
- Model: anthropic.F("anthropic.claude-3-sonnet-20240229-v1:0"),
- })
-
- for stream.Next() {
- stream.Current()
- }
-
- if stream.Err() != expectedErr {
- t.Fatal()
- }
-}
diff --git a/beta.go b/beta.go
index 9b01387..7abc9ec 100644
--- a/beta.go
+++ b/beta.go
@@ -3,11 +3,12 @@
package anthropic
import (
- "reflect"
+ "encoding/json"
"github.com/anthropics/anthropic-sdk-go/internal/apijson"
"github.com/anthropics/anthropic-sdk-go/option"
- "github.com/tidwall/gjson"
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
+ "github.com/anthropics/anthropic-sdk-go/shared/constant"
)
// BetaService contains methods and other services that help with interacting with
@@ -18,15 +19,15 @@ import (
// the [NewBetaService] method instead.
type BetaService struct {
Options []option.RequestOption
- Models *BetaModelService
- Messages *BetaMessageService
+ Models BetaModelService
+ Messages BetaMessageService
}
// NewBetaService generates a new service that applies the given options to each
// request. These options are applied after the parent client's options (if there
// is one), and before any request-specific options.
-func NewBetaService(opts ...option.RequestOption) (r *BetaService) {
- r = &BetaService{}
+func NewBetaService(opts ...option.RequestOption) (r BetaService) {
+ r = BetaService{}
r.Options = opts
r.Models = NewBetaModelService(opts...)
r.Messages = NewBetaMessageService(opts...)
@@ -47,509 +48,303 @@ const (
)
type BetaAPIError struct {
- Message string `json:"message,required"`
- Type BetaAPIErrorType `json:"type,required"`
- JSON betaAPIErrorJSON `json:"-"`
-}
-
-// betaAPIErrorJSON contains the JSON metadata for the struct [BetaAPIError]
-type betaAPIErrorJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaAPIError) UnmarshalJSON(data []byte) (err error) {
+ Message string `json:"message,required"`
+ Type constant.APIError `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaAPIError) RawJSON() string { return r.JSON.raw }
+func (r *BetaAPIError) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaAPIErrorJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaAPIError) implementsBetaError() {}
-
-type BetaAPIErrorType string
-
-const (
- BetaAPIErrorTypeAPIError BetaAPIErrorType = "api_error"
-)
-
-func (r BetaAPIErrorType) IsKnown() bool {
- switch r {
- case BetaAPIErrorTypeAPIError:
- return true
- }
- return false
-}
-
type BetaAuthenticationError struct {
- Message string `json:"message,required"`
- Type BetaAuthenticationErrorType `json:"type,required"`
- JSON betaAuthenticationErrorJSON `json:"-"`
-}
-
-// betaAuthenticationErrorJSON contains the JSON metadata for the struct
-// [BetaAuthenticationError]
-type betaAuthenticationErrorJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaAuthenticationError) UnmarshalJSON(data []byte) (err error) {
+ Message string `json:"message,required"`
+ Type constant.AuthenticationError `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaAuthenticationError) RawJSON() string { return r.JSON.raw }
+func (r *BetaAuthenticationError) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaAuthenticationErrorJSON) RawJSON() string {
- return r.raw
+type BetaBillingError struct {
+ Message string `json:"message,required"`
+ Type constant.BillingError `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaBillingError) RawJSON() string { return r.JSON.raw }
+func (r *BetaBillingError) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-func (r BetaAuthenticationError) implementsBetaError() {}
-
-type BetaAuthenticationErrorType string
-
-const (
- BetaAuthenticationErrorTypeAuthenticationError BetaAuthenticationErrorType = "authentication_error"
-)
-
-func (r BetaAuthenticationErrorType) IsKnown() bool {
- switch r {
- case BetaAuthenticationErrorTypeAuthenticationError:
- return true
+// BetaErrorUnion contains all possible properties and values from
+// [BetaInvalidRequestError], [BetaAuthenticationError], [BetaBillingError],
+// [BetaPermissionError], [BetaNotFoundError], [BetaRateLimitError],
+// [BetaGatewayTimeoutError], [BetaAPIError], [BetaOverloadedError].
+//
+// Use the [BetaErrorUnion.AsAny] method to switch on the variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type BetaErrorUnion struct {
+ Message string `json:"message"`
+ // Any of "invalid_request_error", "authentication_error", "billing_error",
+ // "permission_error", "not_found_error", "rate_limit_error", "timeout_error",
+ // "api_error", "overloaded_error".
+ Type string `json:"type"`
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := BetaErrorUnion.AsAny().(type) {
+// case BetaInvalidRequestError:
+// case BetaAuthenticationError:
+// case BetaBillingError:
+// case BetaPermissionError:
+// case BetaNotFoundError:
+// case BetaRateLimitError:
+// case BetaGatewayTimeoutError:
+// case BetaAPIError:
+// case BetaOverloadedError:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u BetaErrorUnion) AsAny() any {
+ switch u.Type {
+ case "invalid_request_error":
+ return u.AsInvalidRequestError()
+ case "authentication_error":
+ return u.AsAuthenticationError()
+ case "billing_error":
+ return u.AsBillingError()
+ case "permission_error":
+ return u.AsPermissionError()
+ case "not_found_error":
+ return u.AsNotFoundError()
+ case "rate_limit_error":
+ return u.AsRateLimitError()
+ case "timeout_error":
+ return u.AsGatewayTimeoutError()
+ case "api_error":
+ return u.AsAPIError()
+ case "overloaded_error":
+ return u.AsOverloadedError()
}
- return false
+ return nil
}
-type BetaBillingError struct {
- Message string `json:"message,required"`
- Type BetaBillingErrorType `json:"type,required"`
- JSON betaBillingErrorJSON `json:"-"`
+func (u BetaErrorUnion) AsInvalidRequestError() (v BetaInvalidRequestError) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// betaBillingErrorJSON contains the JSON metadata for the struct
-// [BetaBillingError]
-type betaBillingErrorJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func (u BetaErrorUnion) AsAuthenticationError() (v BetaAuthenticationError) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r *BetaBillingError) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+func (u BetaErrorUnion) AsBillingError() (v BetaBillingError) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r betaBillingErrorJSON) RawJSON() string {
- return r.raw
+func (u BetaErrorUnion) AsPermissionError() (v BetaPermissionError) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r BetaBillingError) implementsBetaError() {}
-
-type BetaBillingErrorType string
-
-const (
- BetaBillingErrorTypeBillingError BetaBillingErrorType = "billing_error"
-)
-
-func (r BetaBillingErrorType) IsKnown() bool {
- switch r {
- case BetaBillingErrorTypeBillingError:
- return true
- }
- return false
+func (u BetaErrorUnion) AsNotFoundError() (v BetaNotFoundError) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaError struct {
- Message string `json:"message,required"`
- Type BetaErrorType `json:"type,required"`
- JSON betaErrorJSON `json:"-"`
- union BetaErrorUnion
+func (u BetaErrorUnion) AsRateLimitError() (v BetaRateLimitError) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// betaErrorJSON contains the JSON metadata for the struct [BetaError]
-type betaErrorJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func (u BetaErrorUnion) AsGatewayTimeoutError() (v BetaGatewayTimeoutError) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r betaErrorJSON) RawJSON() string {
- return r.raw
+func (u BetaErrorUnion) AsAPIError() (v BetaAPIError) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r *BetaError) UnmarshalJSON(data []byte) (err error) {
- *r = BetaError{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
- }
- return apijson.Port(r.union, &r)
+func (u BetaErrorUnion) AsOverloadedError() (v BetaOverloadedError) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// AsUnion returns a [BetaErrorUnion] interface which you can cast to the specific
-// types for more type safety.
-//
-// Possible runtime types of the union are [BetaInvalidRequestError],
-// [BetaAuthenticationError], [BetaBillingError], [BetaPermissionError],
-// [BetaNotFoundError], [BetaRateLimitError], [BetaGatewayTimeoutError],
-// [BetaAPIError], [BetaOverloadedError].
-func (r BetaError) AsUnion() BetaErrorUnion {
- return r.union
-}
-
-// Union satisfied by [BetaInvalidRequestError], [BetaAuthenticationError],
-// [BetaBillingError], [BetaPermissionError], [BetaNotFoundError],
-// [BetaRateLimitError], [BetaGatewayTimeoutError], [BetaAPIError] or
-// [BetaOverloadedError].
-type BetaErrorUnion interface {
- implementsBetaError()
-}
-
-func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*BetaErrorUnion)(nil)).Elem(),
- "type",
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaInvalidRequestError{}),
- DiscriminatorValue: "invalid_request_error",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaAuthenticationError{}),
- DiscriminatorValue: "authentication_error",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaBillingError{}),
- DiscriminatorValue: "billing_error",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaPermissionError{}),
- DiscriminatorValue: "permission_error",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaNotFoundError{}),
- DiscriminatorValue: "not_found_error",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaRateLimitError{}),
- DiscriminatorValue: "rate_limit_error",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaGatewayTimeoutError{}),
- DiscriminatorValue: "timeout_error",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaAPIError{}),
- DiscriminatorValue: "api_error",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaOverloadedError{}),
- DiscriminatorValue: "overloaded_error",
- },
- )
-}
-
-type BetaErrorType string
-
-const (
- BetaErrorTypeInvalidRequestError BetaErrorType = "invalid_request_error"
- BetaErrorTypeAuthenticationError BetaErrorType = "authentication_error"
- BetaErrorTypeBillingError BetaErrorType = "billing_error"
- BetaErrorTypePermissionError BetaErrorType = "permission_error"
- BetaErrorTypeNotFoundError BetaErrorType = "not_found_error"
- BetaErrorTypeRateLimitError BetaErrorType = "rate_limit_error"
- BetaErrorTypeTimeoutError BetaErrorType = "timeout_error"
- BetaErrorTypeAPIError BetaErrorType = "api_error"
- BetaErrorTypeOverloadedError BetaErrorType = "overloaded_error"
-)
+// Returns the unmodified JSON received from the API
+func (u BetaErrorUnion) RawJSON() string { return u.JSON.raw }
-func (r BetaErrorType) IsKnown() bool {
- switch r {
- case BetaErrorTypeInvalidRequestError, BetaErrorTypeAuthenticationError, BetaErrorTypeBillingError, BetaErrorTypePermissionError, BetaErrorTypeNotFoundError, BetaErrorTypeRateLimitError, BetaErrorTypeTimeoutError, BetaErrorTypeAPIError, BetaErrorTypeOverloadedError:
- return true
- }
- return false
+func (r *BetaErrorUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
type BetaErrorResponse struct {
- Error BetaError `json:"error,required"`
- Type BetaErrorResponseType `json:"type,required"`
- JSON betaErrorResponseJSON `json:"-"`
-}
-
-// betaErrorResponseJSON contains the JSON metadata for the struct
-// [BetaErrorResponse]
-type betaErrorResponseJSON struct {
- Error apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaErrorResponse) UnmarshalJSON(data []byte) (err error) {
+ Error BetaErrorUnion `json:"error,required"`
+ Type constant.Error `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Error resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaErrorResponse) RawJSON() string { return r.JSON.raw }
+func (r *BetaErrorResponse) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaErrorResponseJSON) RawJSON() string {
- return r.raw
-}
-
-type BetaErrorResponseType string
-
-const (
- BetaErrorResponseTypeError BetaErrorResponseType = "error"
-)
-
-func (r BetaErrorResponseType) IsKnown() bool {
- switch r {
- case BetaErrorResponseTypeError:
- return true
- }
- return false
-}
-
type BetaGatewayTimeoutError struct {
- Message string `json:"message,required"`
- Type BetaGatewayTimeoutErrorType `json:"type,required"`
- JSON betaGatewayTimeoutErrorJSON `json:"-"`
-}
-
-// betaGatewayTimeoutErrorJSON contains the JSON metadata for the struct
-// [BetaGatewayTimeoutError]
-type betaGatewayTimeoutErrorJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaGatewayTimeoutError) UnmarshalJSON(data []byte) (err error) {
+ Message string `json:"message,required"`
+ Type constant.TimeoutError `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaGatewayTimeoutError) RawJSON() string { return r.JSON.raw }
+func (r *BetaGatewayTimeoutError) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaGatewayTimeoutErrorJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaGatewayTimeoutError) implementsBetaError() {}
-
-type BetaGatewayTimeoutErrorType string
-
-const (
- BetaGatewayTimeoutErrorTypeTimeoutError BetaGatewayTimeoutErrorType = "timeout_error"
-)
-
-func (r BetaGatewayTimeoutErrorType) IsKnown() bool {
- switch r {
- case BetaGatewayTimeoutErrorTypeTimeoutError:
- return true
- }
- return false
-}
-
type BetaInvalidRequestError struct {
- Message string `json:"message,required"`
- Type BetaInvalidRequestErrorType `json:"type,required"`
- JSON betaInvalidRequestErrorJSON `json:"-"`
-}
-
-// betaInvalidRequestErrorJSON contains the JSON metadata for the struct
-// [BetaInvalidRequestError]
-type betaInvalidRequestErrorJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaInvalidRequestError) UnmarshalJSON(data []byte) (err error) {
+ Message string `json:"message,required"`
+ Type constant.InvalidRequestError `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaInvalidRequestError) RawJSON() string { return r.JSON.raw }
+func (r *BetaInvalidRequestError) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaInvalidRequestErrorJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaInvalidRequestError) implementsBetaError() {}
-
-type BetaInvalidRequestErrorType string
-
-const (
- BetaInvalidRequestErrorTypeInvalidRequestError BetaInvalidRequestErrorType = "invalid_request_error"
-)
-
-func (r BetaInvalidRequestErrorType) IsKnown() bool {
- switch r {
- case BetaInvalidRequestErrorTypeInvalidRequestError:
- return true
- }
- return false
-}
-
type BetaNotFoundError struct {
- Message string `json:"message,required"`
- Type BetaNotFoundErrorType `json:"type,required"`
- JSON betaNotFoundErrorJSON `json:"-"`
-}
-
-// betaNotFoundErrorJSON contains the JSON metadata for the struct
-// [BetaNotFoundError]
-type betaNotFoundErrorJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaNotFoundError) UnmarshalJSON(data []byte) (err error) {
+ Message string `json:"message,required"`
+ Type constant.NotFoundError `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaNotFoundError) RawJSON() string { return r.JSON.raw }
+func (r *BetaNotFoundError) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaNotFoundErrorJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaNotFoundError) implementsBetaError() {}
-
-type BetaNotFoundErrorType string
-
-const (
- BetaNotFoundErrorTypeNotFoundError BetaNotFoundErrorType = "not_found_error"
-)
-
-func (r BetaNotFoundErrorType) IsKnown() bool {
- switch r {
- case BetaNotFoundErrorTypeNotFoundError:
- return true
- }
- return false
-}
-
type BetaOverloadedError struct {
- Message string `json:"message,required"`
- Type BetaOverloadedErrorType `json:"type,required"`
- JSON betaOverloadedErrorJSON `json:"-"`
-}
-
-// betaOverloadedErrorJSON contains the JSON metadata for the struct
-// [BetaOverloadedError]
-type betaOverloadedErrorJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaOverloadedError) UnmarshalJSON(data []byte) (err error) {
+ Message string `json:"message,required"`
+ Type constant.OverloadedError `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaOverloadedError) RawJSON() string { return r.JSON.raw }
+func (r *BetaOverloadedError) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaOverloadedErrorJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaOverloadedError) implementsBetaError() {}
-
-type BetaOverloadedErrorType string
-
-const (
- BetaOverloadedErrorTypeOverloadedError BetaOverloadedErrorType = "overloaded_error"
-)
-
-func (r BetaOverloadedErrorType) IsKnown() bool {
- switch r {
- case BetaOverloadedErrorTypeOverloadedError:
- return true
- }
- return false
-}
-
type BetaPermissionError struct {
- Message string `json:"message,required"`
- Type BetaPermissionErrorType `json:"type,required"`
- JSON betaPermissionErrorJSON `json:"-"`
-}
-
-// betaPermissionErrorJSON contains the JSON metadata for the struct
-// [BetaPermissionError]
-type betaPermissionErrorJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaPermissionError) UnmarshalJSON(data []byte) (err error) {
+ Message string `json:"message,required"`
+ Type constant.PermissionError `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaPermissionError) RawJSON() string { return r.JSON.raw }
+func (r *BetaPermissionError) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaPermissionErrorJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaPermissionError) implementsBetaError() {}
-
-type BetaPermissionErrorType string
-
-const (
- BetaPermissionErrorTypePermissionError BetaPermissionErrorType = "permission_error"
-)
-
-func (r BetaPermissionErrorType) IsKnown() bool {
- switch r {
- case BetaPermissionErrorTypePermissionError:
- return true
- }
- return false
-}
-
type BetaRateLimitError struct {
- Message string `json:"message,required"`
- Type BetaRateLimitErrorType `json:"type,required"`
- JSON betaRateLimitErrorJSON `json:"-"`
-}
-
-// betaRateLimitErrorJSON contains the JSON metadata for the struct
-// [BetaRateLimitError]
-type betaRateLimitErrorJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaRateLimitError) UnmarshalJSON(data []byte) (err error) {
+ Message string `json:"message,required"`
+ Type constant.RateLimitError `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaRateLimitError) RawJSON() string { return r.JSON.raw }
+func (r *BetaRateLimitError) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-
-func (r betaRateLimitErrorJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaRateLimitError) implementsBetaError() {}
-
-type BetaRateLimitErrorType string
-
-const (
- BetaRateLimitErrorTypeRateLimitError BetaRateLimitErrorType = "rate_limit_error"
-)
-
-func (r BetaRateLimitErrorType) IsKnown() bool {
- switch r {
- case BetaRateLimitErrorTypeRateLimitError:
- return true
- }
- return false
-}
diff --git a/betamessage.go b/betamessage.go
index 8e8a4b0..e03467c 100644
--- a/betamessage.go
+++ b/betamessage.go
@@ -4,15 +4,18 @@ package anthropic
import (
"context"
+ "encoding/json"
"fmt"
"net/http"
"reflect"
"github.com/anthropics/anthropic-sdk-go/internal/apijson"
- "github.com/anthropics/anthropic-sdk-go/internal/param"
"github.com/anthropics/anthropic-sdk-go/internal/requestconfig"
"github.com/anthropics/anthropic-sdk-go/option"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
"github.com/anthropics/anthropic-sdk-go/packages/ssestream"
+ "github.com/anthropics/anthropic-sdk-go/shared/constant"
"github.com/tidwall/gjson"
)
@@ -24,14 +27,14 @@ import (
// the [NewBetaMessageService] method instead.
type BetaMessageService struct {
Options []option.RequestOption
- Batches *BetaMessageBatchService
+ Batches BetaMessageBatchService
}
// NewBetaMessageService generates a new service that applies the given options to
// each request. These options are applied after the parent client's options (if
// there is one), and before any request-specific options.
-func NewBetaMessageService(opts ...option.RequestOption) (r *BetaMessageService) {
- r = &BetaMessageService{}
+func NewBetaMessageService(opts ...option.RequestOption) (r BetaMessageService) {
+ r = BetaMessageService{}
r.Options = opts
r.Batches = NewBetaMessageBatchService(opts...)
return
@@ -47,23 +50,12 @@ func NewBetaMessageService(opts ...option.RequestOption) (r *BetaMessageService)
//
// Note: If you choose to set a timeout for this request, we recommend 10 minutes.
func (r *BetaMessageService) New(ctx context.Context, params BetaMessageNewParams, opts ...option.RequestOption) (res *BetaMessage, err error) {
- for _, v := range params.Betas.Value {
+ for _, v := range params.Betas {
opts = append(opts, option.WithHeaderAdd("anthropic-beta", fmt.Sprintf("%s", v)))
}
opts = append(r.Options[:], opts...)
path := "v1/messages?beta=true"
-
- cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodPost, path, params, &res, opts...)
- if err != nil {
- return
- }
-
- err = checkLongRequest(ctx, cfg, int(params.MaxTokens.Value))
- if err != nil {
- return
- }
-
- err = cfg.Execute()
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &res, opts...)
return
}
@@ -76,19 +68,19 @@ func (r *BetaMessageService) New(ctx context.Context, params BetaMessageNewParam
// Learn more about the Messages API in our [user guide](/en/docs/initial-setup)
//
// Note: If you choose to set a timeout for this request, we recommend 10 minutes.
-func (r *BetaMessageService) NewStreaming(ctx context.Context, params BetaMessageNewParams, opts ...option.RequestOption) (stream *ssestream.Stream[BetaRawMessageStreamEvent]) {
+func (r *BetaMessageService) NewStreaming(ctx context.Context, params BetaMessageNewParams, opts ...option.RequestOption) (stream *ssestream.Stream[BetaRawMessageStreamEventUnion]) {
var (
raw *http.Response
err error
)
- for _, v := range params.Betas.Value {
+ for _, v := range params.Betas {
opts = append(opts, option.WithHeaderAdd("anthropic-beta", fmt.Sprintf("%s", v)))
}
opts = append(r.Options[:], opts...)
opts = append([]option.RequestOption{option.WithJSONSet("stream", true)}, opts...)
path := "v1/messages?beta=true"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, params, &raw, opts...)
- return ssestream.NewStream[BetaRawMessageStreamEvent](ssestream.NewDecoder(raw), err)
+ return ssestream.NewStream[BetaRawMessageStreamEventUnion](ssestream.NewDecoder(raw), err)
}
// Count the number of tokens in a Message.
@@ -99,7 +91,7 @@ func (r *BetaMessageService) NewStreaming(ctx context.Context, params BetaMessag
// Learn more about token counting in our
// [user guide](/en/docs/build-with-claude/token-counting)
func (r *BetaMessageService) CountTokens(ctx context.Context, params BetaMessageCountTokensParams, opts ...option.RequestOption) (res *BetaMessageTokensCount, err error) {
- for _, v := range params.Betas.Value {
+ for _, v := range params.Betas {
opts = append(opts, option.WithHeaderAdd("anthropic-beta", fmt.Sprintf("%s", v)))
}
opts = append(r.Options[:], opts...)
@@ -108,18 +100,24 @@ func (r *BetaMessageService) CountTokens(ctx context.Context, params BetaMessage
return
}
+// The properties Data, MediaType, Type are required.
type BetaBase64ImageSourceParam struct {
- Data param.Field[string] `json:"data,required" format:"byte"`
- MediaType param.Field[BetaBase64ImageSourceMediaType] `json:"media_type,required"`
- Type param.Field[BetaBase64ImageSourceType] `json:"type,required"`
+ Data string `json:"data,required" format:"byte"`
+ // Any of "image/jpeg", "image/png", "image/gif", "image/webp".
+ MediaType BetaBase64ImageSourceMediaType `json:"media_type,omitzero,required"`
+ // This field can be elided, and will marshal its zero value as "base64".
+ Type constant.Base64 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaBase64ImageSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaBase64ImageSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaBase64ImageSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r BetaBase64ImageSourceParam) implementsBetaImageBlockParamSourceUnion() {}
-
type BetaBase64ImageSourceMediaType string
const (
@@ -129,864 +127,1121 @@ const (
BetaBase64ImageSourceMediaTypeImageWebP BetaBase64ImageSourceMediaType = "image/webp"
)
-func (r BetaBase64ImageSourceMediaType) IsKnown() bool {
- switch r {
- case BetaBase64ImageSourceMediaTypeImageJPEG, BetaBase64ImageSourceMediaTypeImagePNG, BetaBase64ImageSourceMediaTypeImageGIF, BetaBase64ImageSourceMediaTypeImageWebP:
- return true
- }
- return false
-}
-
-type BetaBase64ImageSourceType string
-
-const (
- BetaBase64ImageSourceTypeBase64 BetaBase64ImageSourceType = "base64"
-)
-
-func (r BetaBase64ImageSourceType) IsKnown() bool {
- switch r {
- case BetaBase64ImageSourceTypeBase64:
- return true
- }
- return false
-}
-
+// The properties Source, Type are required.
type BetaBase64PDFBlockParam struct {
- Source param.Field[BetaBase64PDFBlockSourceUnionParam] `json:"source,required"`
- Type param.Field[BetaBase64PDFBlockType] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
- Citations param.Field[BetaCitationsConfigParam] `json:"citations"`
- Context param.Field[string] `json:"context"`
- Title param.Field[string] `json:"title"`
-}
-
+ Source BetaBase64PDFBlockSourceUnionParam `json:"source,omitzero,required"`
+ Context param.Opt[string] `json:"context,omitzero"`
+ Title param.Opt[string] `json:"title,omitzero"`
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
+ Citations BetaCitationsConfigParam `json:"citations,omitzero"`
+ // This field can be elided, and will marshal its zero value as "document".
+ Type constant.Document `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaBase64PDFBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaBase64PDFBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaBase64PDFBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r BetaBase64PDFBlockParam) implementsBetaContentBlockParamUnion() {}
-
-type BetaBase64PDFBlockSourceParam struct {
- Type param.Field[BetaBase64PDFBlockSourceType] `json:"type,required"`
- Content param.Field[interface{}] `json:"content"`
- Data param.Field[string] `json:"data" format:"byte"`
- MediaType param.Field[BetaBase64PDFBlockSourceMediaType] `json:"media_type"`
- URL param.Field[string] `json:"url"`
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaBase64PDFBlockSourceUnionParam struct {
+ OfBase64PDFSource *BetaBase64PDFSourceParam `json:",omitzero,inline"`
+ OfPlainTextSource *BetaPlainTextSourceParam `json:",omitzero,inline"`
+ OfContentBlockSource *BetaContentBlockSourceParam `json:",omitzero,inline"`
+ OfUrlpdfSource *BetaURLPDFSourceParam `json:",omitzero,inline"`
+ paramUnion
}
-func (r BetaBase64PDFBlockSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaBase64PDFBlockSourceUnionParam) IsPresent() bool {
+ return !param.IsOmitted(u) && !u.IsNull()
}
-
-func (r BetaBase64PDFBlockSourceParam) implementsBetaBase64PDFBlockSourceUnionParam() {}
-
-// Satisfied by [BetaBase64PDFSourceParam], [BetaPlainTextSourceParam],
-// [BetaContentBlockSourceParam], [BetaURLPDFSourceParam],
-// [BetaBase64PDFBlockSourceParam].
-type BetaBase64PDFBlockSourceUnionParam interface {
- implementsBetaBase64PDFBlockSourceUnionParam()
+func (u BetaBase64PDFBlockSourceUnionParam) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaBase64PDFBlockSourceUnionParam](u.OfBase64PDFSource, u.OfPlainTextSource, u.OfContentBlockSource, u.OfUrlpdfSource)
}
-type BetaBase64PDFBlockSourceType string
-
-const (
- BetaBase64PDFBlockSourceTypeBase64 BetaBase64PDFBlockSourceType = "base64"
- BetaBase64PDFBlockSourceTypeText BetaBase64PDFBlockSourceType = "text"
- BetaBase64PDFBlockSourceTypeContent BetaBase64PDFBlockSourceType = "content"
- BetaBase64PDFBlockSourceTypeURL BetaBase64PDFBlockSourceType = "url"
-)
-
-func (r BetaBase64PDFBlockSourceType) IsKnown() bool {
- switch r {
- case BetaBase64PDFBlockSourceTypeBase64, BetaBase64PDFBlockSourceTypeText, BetaBase64PDFBlockSourceTypeContent, BetaBase64PDFBlockSourceTypeURL:
- return true
+func (u *BetaBase64PDFBlockSourceUnionParam) asAny() any {
+ if !param.IsOmitted(u.OfBase64PDFSource) {
+ return u.OfBase64PDFSource
+ } else if !param.IsOmitted(u.OfPlainTextSource) {
+ return u.OfPlainTextSource
+ } else if !param.IsOmitted(u.OfContentBlockSource) {
+ return u.OfContentBlockSource
+ } else if !param.IsOmitted(u.OfUrlpdfSource) {
+ return u.OfUrlpdfSource
}
- return false
+ return nil
}
-type BetaBase64PDFBlockSourceMediaType string
-
-const (
- BetaBase64PDFBlockSourceMediaTypeApplicationPDF BetaBase64PDFBlockSourceMediaType = "application/pdf"
- BetaBase64PDFBlockSourceMediaTypeTextPlain BetaBase64PDFBlockSourceMediaType = "text/plain"
-)
-
-func (r BetaBase64PDFBlockSourceMediaType) IsKnown() bool {
- switch r {
- case BetaBase64PDFBlockSourceMediaTypeApplicationPDF, BetaBase64PDFBlockSourceMediaTypeTextPlain:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaBase64PDFBlockSourceUnionParam) GetContent() *BetaContentBlockSourceContentUnionParam {
+ if vt := u.OfContentBlockSource; vt != nil {
+ return &vt.Content
}
- return false
+ return nil
}
-type BetaBase64PDFBlockType string
-
-const (
- BetaBase64PDFBlockTypeDocument BetaBase64PDFBlockType = "document"
-)
-
-func (r BetaBase64PDFBlockType) IsKnown() bool {
- switch r {
- case BetaBase64PDFBlockTypeDocument:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaBase64PDFBlockSourceUnionParam) GetURL() *string {
+ if vt := u.OfUrlpdfSource; vt != nil {
+ return &vt.URL
}
- return false
+ return nil
}
-type BetaBase64PDFSourceParam struct {
- Data param.Field[string] `json:"data,required" format:"byte"`
- MediaType param.Field[BetaBase64PDFSourceMediaType] `json:"media_type,required"`
- Type param.Field[BetaBase64PDFSourceType] `json:"type,required"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaBase64PDFBlockSourceUnionParam) GetData() *string {
+ if vt := u.OfBase64PDFSource; vt != nil {
+ return (*string)(&vt.Data)
+ } else if vt := u.OfPlainTextSource; vt != nil {
+ return (*string)(&vt.Data)
+ }
+ return nil
}
-func (r BetaBase64PDFSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaBase64PDFBlockSourceUnionParam) GetMediaType() *string {
+ if vt := u.OfBase64PDFSource; vt != nil {
+ return (*string)(&vt.MediaType)
+ } else if vt := u.OfPlainTextSource; vt != nil {
+ return (*string)(&vt.MediaType)
+ }
+ return nil
}
-func (r BetaBase64PDFSourceParam) implementsBetaBase64PDFBlockSourceUnionParam() {}
-
-type BetaBase64PDFSourceMediaType string
-
-const (
- BetaBase64PDFSourceMediaTypeApplicationPDF BetaBase64PDFSourceMediaType = "application/pdf"
-)
-
-func (r BetaBase64PDFSourceMediaType) IsKnown() bool {
- switch r {
- case BetaBase64PDFSourceMediaTypeApplicationPDF:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaBase64PDFBlockSourceUnionParam) GetType() *string {
+ if vt := u.OfBase64PDFSource; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfPlainTextSource; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfContentBlockSource; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfUrlpdfSource; vt != nil {
+ return (*string)(&vt.Type)
}
- return false
+ return nil
}
-type BetaBase64PDFSourceType string
+func init() {
+ apijson.RegisterUnion[BetaBase64PDFBlockSourceUnionParam](
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaBase64PDFSourceParam{}),
+ DiscriminatorValue: "base64",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaPlainTextSourceParam{}),
+ DiscriminatorValue: "text",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaContentBlockSourceParam{}),
+ DiscriminatorValue: "content",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaURLPDFSourceParam{}),
+ DiscriminatorValue: "url",
+ },
+ )
+}
-const (
- BetaBase64PDFSourceTypeBase64 BetaBase64PDFSourceType = "base64"
-)
+// The properties Data, MediaType, Type are required.
+type BetaBase64PDFSourceParam struct {
+ Data string `json:"data,required" format:"byte"`
+ // This field can be elided, and will marshal its zero value as "application/pdf".
+ MediaType constant.ApplicationPDF `json:"media_type,required"`
+ // This field can be elided, and will marshal its zero value as "base64".
+ Type constant.Base64 `json:"type,required"`
+ paramObj
+}
-func (r BetaBase64PDFSourceType) IsKnown() bool {
- switch r {
- case BetaBase64PDFSourceTypeBase64:
- return true
- }
- return false
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaBase64PDFSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r BetaBase64PDFSourceParam) MarshalJSON() (data []byte, err error) {
+ type shadow BetaBase64PDFSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The property Type is required.
type BetaCacheControlEphemeralParam struct {
- Type param.Field[BetaCacheControlEphemeralType] `json:"type,required"`
+ // This field can be elided, and will marshal its zero value as "ephemeral".
+ Type constant.Ephemeral `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaCacheControlEphemeralParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaCacheControlEphemeralParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaCacheControlEphemeralParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-type BetaCacheControlEphemeralType string
-
-const (
- BetaCacheControlEphemeralTypeEphemeral BetaCacheControlEphemeralType = "ephemeral"
-)
+type BetaCitationCharLocation struct {
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ DocumentTitle string `json:"document_title,required"`
+ EndCharIndex int64 `json:"end_char_index,required"`
+ StartCharIndex int64 `json:"start_char_index,required"`
+ Type constant.CharLocation `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ CitedText resp.Field
+ DocumentIndex resp.Field
+ DocumentTitle resp.Field
+ EndCharIndex resp.Field
+ StartCharIndex resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaCitationCharLocation) RawJSON() string { return r.JSON.raw }
+func (r *BetaCitationCharLocation) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-func (r BetaCacheControlEphemeralType) IsKnown() bool {
- switch r {
- case BetaCacheControlEphemeralTypeEphemeral:
- return true
- }
- return false
+// The properties CitedText, DocumentIndex, DocumentTitle, EndCharIndex,
+// StartCharIndex, Type are required.
+type BetaCitationCharLocationParam struct {
+ DocumentTitle param.Opt[string] `json:"document_title,omitzero,required"`
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ EndCharIndex int64 `json:"end_char_index,required"`
+ StartCharIndex int64 `json:"start_char_index,required"`
+ // This field can be elided, and will marshal its zero value as "char_location".
+ Type constant.CharLocation `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaCitationCharLocationParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r BetaCitationCharLocationParam) MarshalJSON() (data []byte, err error) {
+ type shadow BetaCitationCharLocationParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-type BetaCitationCharLocation struct {
- CitedText string `json:"cited_text,required"`
- DocumentIndex int64 `json:"document_index,required"`
- DocumentTitle string `json:"document_title,required,nullable"`
- EndCharIndex int64 `json:"end_char_index,required"`
- StartCharIndex int64 `json:"start_char_index,required"`
- Type BetaCitationCharLocationType `json:"type,required"`
- JSON betaCitationCharLocationJSON `json:"-"`
-}
-
-// betaCitationCharLocationJSON contains the JSON metadata for the struct
-// [BetaCitationCharLocation]
-type betaCitationCharLocationJSON struct {
- CitedText apijson.Field
- DocumentIndex apijson.Field
- DocumentTitle apijson.Field
- EndCharIndex apijson.Field
- StartCharIndex apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaCitationCharLocation) UnmarshalJSON(data []byte) (err error) {
+type BetaCitationContentBlockLocation struct {
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ DocumentTitle string `json:"document_title,required"`
+ EndBlockIndex int64 `json:"end_block_index,required"`
+ StartBlockIndex int64 `json:"start_block_index,required"`
+ Type constant.ContentBlockLocation `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ CitedText resp.Field
+ DocumentIndex resp.Field
+ DocumentTitle resp.Field
+ EndBlockIndex resp.Field
+ StartBlockIndex resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaCitationContentBlockLocation) RawJSON() string { return r.JSON.raw }
+func (r *BetaCitationContentBlockLocation) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaCitationCharLocationJSON) RawJSON() string {
- return r.raw
+// The properties CitedText, DocumentIndex, DocumentTitle, EndBlockIndex,
+// StartBlockIndex, Type are required.
+type BetaCitationContentBlockLocationParam struct {
+ DocumentTitle param.Opt[string] `json:"document_title,omitzero,required"`
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ EndBlockIndex int64 `json:"end_block_index,required"`
+ StartBlockIndex int64 `json:"start_block_index,required"`
+ // This field can be elided, and will marshal its zero value as
+ // "content_block_location".
+ Type constant.ContentBlockLocation `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaCitationContentBlockLocationParam) IsPresent() bool {
+ return !param.IsOmitted(f) && !f.IsNull()
+}
+func (r BetaCitationContentBlockLocationParam) MarshalJSON() (data []byte, err error) {
+ type shadow BetaCitationContentBlockLocationParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r BetaCitationCharLocation) implementsBetaCitationsDeltaCitation() {}
+type BetaCitationPageLocation struct {
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ DocumentTitle string `json:"document_title,required"`
+ EndPageNumber int64 `json:"end_page_number,required"`
+ StartPageNumber int64 `json:"start_page_number,required"`
+ Type constant.PageLocation `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ CitedText resp.Field
+ DocumentIndex resp.Field
+ DocumentTitle resp.Field
+ EndPageNumber resp.Field
+ StartPageNumber resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaCitationPageLocation) RawJSON() string { return r.JSON.raw }
+func (r *BetaCitationPageLocation) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-func (r BetaCitationCharLocation) implementsBetaTextCitation() {}
+// The properties CitedText, DocumentIndex, DocumentTitle, EndPageNumber,
+// StartPageNumber, Type are required.
+type BetaCitationPageLocationParam struct {
+ DocumentTitle param.Opt[string] `json:"document_title,omitzero,required"`
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ EndPageNumber int64 `json:"end_page_number,required"`
+ StartPageNumber int64 `json:"start_page_number,required"`
+ // This field can be elided, and will marshal its zero value as "page_location".
+ Type constant.PageLocation `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaCitationPageLocationParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r BetaCitationPageLocationParam) MarshalJSON() (data []byte, err error) {
+ type shadow BetaCitationPageLocationParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
-type BetaCitationCharLocationType string
+type BetaCitationsConfigParam struct {
+ Enabled param.Opt[bool] `json:"enabled,omitzero"`
+ paramObj
+}
-const (
- BetaCitationCharLocationTypeCharLocation BetaCitationCharLocationType = "char_location"
-)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaCitationsConfigParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r BetaCitationsConfigParam) MarshalJSON() (data []byte, err error) {
+ type shadow BetaCitationsConfigParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
-func (r BetaCitationCharLocationType) IsKnown() bool {
- switch r {
- case BetaCitationCharLocationTypeCharLocation:
- return true
- }
- return false
+type BetaCitationsDelta struct {
+ Citation BetaCitationsDeltaCitationUnion `json:"citation,required"`
+ Type constant.CitationsDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Citation resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaCitationsDelta) RawJSON() string { return r.JSON.raw }
+func (r *BetaCitationsDelta) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-type BetaCitationCharLocationParam struct {
- CitedText param.Field[string] `json:"cited_text,required"`
- DocumentIndex param.Field[int64] `json:"document_index,required"`
- DocumentTitle param.Field[string] `json:"document_title,required"`
- EndCharIndex param.Field[int64] `json:"end_char_index,required"`
- StartCharIndex param.Field[int64] `json:"start_char_index,required"`
- Type param.Field[BetaCitationCharLocationParamType] `json:"type,required"`
+// BetaCitationsDeltaCitationUnion contains all possible properties and values from
+// [BetaCitationCharLocation], [BetaCitationPageLocation],
+// [BetaCitationContentBlockLocation].
+//
+// Use the [BetaCitationsDeltaCitationUnion.AsAny] method to switch on the variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type BetaCitationsDeltaCitationUnion struct {
+ CitedText string `json:"cited_text"`
+ DocumentIndex int64 `json:"document_index"`
+ DocumentTitle string `json:"document_title"`
+ // This field is from variant [BetaCitationCharLocation].
+ EndCharIndex int64 `json:"end_char_index"`
+ // This field is from variant [BetaCitationCharLocation].
+ StartCharIndex int64 `json:"start_char_index"`
+ // Any of "char_location", "page_location", "content_block_location".
+ Type string `json:"type"`
+ // This field is from variant [BetaCitationPageLocation].
+ EndPageNumber int64 `json:"end_page_number"`
+ // This field is from variant [BetaCitationPageLocation].
+ StartPageNumber int64 `json:"start_page_number"`
+ // This field is from variant [BetaCitationContentBlockLocation].
+ EndBlockIndex int64 `json:"end_block_index"`
+ // This field is from variant [BetaCitationContentBlockLocation].
+ StartBlockIndex int64 `json:"start_block_index"`
+ JSON struct {
+ CitedText resp.Field
+ DocumentIndex resp.Field
+ DocumentTitle resp.Field
+ EndCharIndex resp.Field
+ StartCharIndex resp.Field
+ Type resp.Field
+ EndPageNumber resp.Field
+ StartPageNumber resp.Field
+ EndBlockIndex resp.Field
+ StartBlockIndex resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := BetaCitationsDeltaCitationUnion.AsAny().(type) {
+// case BetaCitationCharLocation:
+// case BetaCitationPageLocation:
+// case BetaCitationContentBlockLocation:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u BetaCitationsDeltaCitationUnion) AsAny() any {
+ switch u.Type {
+ case "char_location":
+ return u.AsResponseCharLocationCitation()
+ case "page_location":
+ return u.AsResponsePageLocationCitation()
+ case "content_block_location":
+ return u.AsResponseContentBlockLocationCitation()
+ }
+ return nil
+}
+
+func (u BetaCitationsDeltaCitationUnion) AsResponseCharLocationCitation() (v BetaCitationCharLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r BetaCitationCharLocationParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+func (u BetaCitationsDeltaCitationUnion) AsResponsePageLocationCitation() (v BetaCitationPageLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r BetaCitationCharLocationParam) implementsBetaTextCitationParamUnion() {}
+func (u BetaCitationsDeltaCitationUnion) AsResponseContentBlockLocationCitation() (v BetaCitationContentBlockLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
+}
-type BetaCitationCharLocationParamType string
+// Returns the unmodified JSON received from the API
+func (u BetaCitationsDeltaCitationUnion) RawJSON() string { return u.JSON.raw }
-const (
- BetaCitationCharLocationParamTypeCharLocation BetaCitationCharLocationParamType = "char_location"
-)
+func (r *BetaCitationsDeltaCitationUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-func (r BetaCitationCharLocationParamType) IsKnown() bool {
- switch r {
- case BetaCitationCharLocationParamTypeCharLocation:
- return true
- }
- return false
+// BetaContentBlockUnion contains all possible properties and values from
+// [BetaTextBlock], [BetaToolUseBlock], [BetaThinkingBlock],
+// [BetaRedactedThinkingBlock].
+//
+// Use the [BetaContentBlockUnion.AsAny] method to switch on the variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type BetaContentBlockUnion struct {
+ // This field is from variant [BetaTextBlock].
+ Citations []BetaTextCitationUnion `json:"citations"`
+ // This field is from variant [BetaTextBlock].
+ Text string `json:"text"`
+ // Any of "text", "tool_use", "thinking", "redacted_thinking".
+ Type string `json:"type"`
+ // This field is from variant [BetaToolUseBlock].
+ ID string `json:"id"`
+ // This field is from variant [BetaToolUseBlock].
+ Input interface{} `json:"input"`
+ // This field is from variant [BetaToolUseBlock].
+ Name string `json:"name"`
+ // This field is from variant [BetaThinkingBlock].
+ Signature string `json:"signature"`
+ // This field is from variant [BetaThinkingBlock].
+ Thinking string `json:"thinking"`
+ // This field is from variant [BetaRedactedThinkingBlock].
+ Data string `json:"data"`
+ JSON struct {
+ Citations resp.Field
+ Text resp.Field
+ Type resp.Field
+ ID resp.Field
+ Input resp.Field
+ Name resp.Field
+ Signature resp.Field
+ Thinking resp.Field
+ Data resp.Field
+ raw string
+ } `json:"-"`
+}
+
+func (r BetaContentBlockUnion) ToParam() BetaContentBlockParamUnion {
+ switch variant := r.AsAny().(type) {
+ case BetaTextBlock:
+ p := variant.ToParam()
+ return BetaContentBlockParamUnion{OfRequestTextBlock: &p}
+ case BetaToolUseBlock:
+ p := variant.ToParam()
+ return BetaContentBlockParamUnion{OfRequestToolUseBlock: &p}
+ case BetaThinkingBlock:
+ p := variant.ToParam()
+ return BetaContentBlockParamUnion{OfRequestThinkingBlock: &p}
+ case BetaRedactedThinkingBlock:
+ p := variant.ToParam()
+ return BetaContentBlockParamUnion{OfRequestRedactedThinkingBlock: &p}
+ }
+ return BetaContentBlockParamUnion{}
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := BetaContentBlockUnion.AsAny().(type) {
+// case BetaTextBlock:
+// case BetaToolUseBlock:
+// case BetaThinkingBlock:
+// case BetaRedactedThinkingBlock:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u BetaContentBlockUnion) AsAny() any {
+ switch u.Type {
+ case "text":
+ return u.AsResponseTextBlock()
+ case "tool_use":
+ return u.AsResponseToolUseBlock()
+ case "thinking":
+ return u.AsResponseThinkingBlock()
+ case "redacted_thinking":
+ return u.AsResponseRedactedThinkingBlock()
+ }
+ return nil
+}
+
+func (u BetaContentBlockUnion) AsResponseTextBlock() (v BetaTextBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaCitationContentBlockLocation struct {
- CitedText string `json:"cited_text,required"`
- DocumentIndex int64 `json:"document_index,required"`
- DocumentTitle string `json:"document_title,required,nullable"`
- EndBlockIndex int64 `json:"end_block_index,required"`
- StartBlockIndex int64 `json:"start_block_index,required"`
- Type BetaCitationContentBlockLocationType `json:"type,required"`
- JSON betaCitationContentBlockLocationJSON `json:"-"`
-}
-
-// betaCitationContentBlockLocationJSON contains the JSON metadata for the struct
-// [BetaCitationContentBlockLocation]
-type betaCitationContentBlockLocationJSON struct {
- CitedText apijson.Field
- DocumentIndex apijson.Field
- DocumentTitle apijson.Field
- EndBlockIndex apijson.Field
- StartBlockIndex apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaCitationContentBlockLocation) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+func (u BetaContentBlockUnion) AsResponseToolUseBlock() (v BetaToolUseBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r betaCitationContentBlockLocationJSON) RawJSON() string {
- return r.raw
+func (u BetaContentBlockUnion) AsResponseThinkingBlock() (v BetaThinkingBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r BetaCitationContentBlockLocation) implementsBetaCitationsDeltaCitation() {}
+func (u BetaContentBlockUnion) AsResponseRedactedThinkingBlock() (v BetaRedactedThinkingBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
+}
-func (r BetaCitationContentBlockLocation) implementsBetaTextCitation() {}
+// Returns the unmodified JSON received from the API
+func (u BetaContentBlockUnion) RawJSON() string { return u.JSON.raw }
-type BetaCitationContentBlockLocationType string
+func (r *BetaContentBlockUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-const (
- BetaCitationContentBlockLocationTypeContentBlockLocation BetaCitationContentBlockLocationType = "content_block_location"
-)
+func BetaContentBlockParamOfRequestTextBlock(text string) BetaContentBlockParamUnion {
+ var variant BetaTextBlockParam
+ variant.Text = text
+ return BetaContentBlockParamUnion{OfRequestTextBlock: &variant}
+}
-func (r BetaCitationContentBlockLocationType) IsKnown() bool {
- switch r {
- case BetaCitationContentBlockLocationTypeContentBlockLocation:
- return true
+func BetaContentBlockParamOfRequestImageBlock[
+ T BetaBase64ImageSourceParam | BetaURLImageSourceParam,
+](source T) BetaContentBlockParamUnion {
+ var variant BetaImageBlockParam
+ switch v := any(source).(type) {
+ case BetaBase64ImageSourceParam:
+ variant.Source.OfBase64ImageSource = &v
+ case BetaURLImageSourceParam:
+ variant.Source.OfURLImageSource = &v
}
- return false
+ return BetaContentBlockParamUnion{OfRequestImageBlock: &variant}
}
-type BetaCitationContentBlockLocationParam struct {
- CitedText param.Field[string] `json:"cited_text,required"`
- DocumentIndex param.Field[int64] `json:"document_index,required"`
- DocumentTitle param.Field[string] `json:"document_title,required"`
- EndBlockIndex param.Field[int64] `json:"end_block_index,required"`
- StartBlockIndex param.Field[int64] `json:"start_block_index,required"`
- Type param.Field[BetaCitationContentBlockLocationParamType] `json:"type,required"`
+func BetaContentBlockParamOfRequestToolUseBlock(id string, input interface{}, name string) BetaContentBlockParamUnion {
+ var variant BetaToolUseBlockParam
+ variant.ID = id
+ variant.Input = input
+ variant.Name = name
+ return BetaContentBlockParamUnion{OfRequestToolUseBlock: &variant}
}
-func (r BetaCitationContentBlockLocationParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+func BetaContentBlockParamOfRequestToolResultBlock(toolUseID string) BetaContentBlockParamUnion {
+ var variant BetaToolResultBlockParam
+ variant.ToolUseID = toolUseID
+ return BetaContentBlockParamUnion{OfRequestToolResultBlock: &variant}
}
-func (r BetaCitationContentBlockLocationParam) implementsBetaTextCitationParamUnion() {}
-
-type BetaCitationContentBlockLocationParamType string
-
-const (
- BetaCitationContentBlockLocationParamTypeContentBlockLocation BetaCitationContentBlockLocationParamType = "content_block_location"
-)
-
-func (r BetaCitationContentBlockLocationParamType) IsKnown() bool {
- switch r {
- case BetaCitationContentBlockLocationParamTypeContentBlockLocation:
- return true
+func BetaContentBlockParamOfRequestDocumentBlock[
+ T BetaBase64PDFSourceParam | BetaPlainTextSourceParam | BetaContentBlockSourceParam | BetaURLPDFSourceParam,
+](source T) BetaContentBlockParamUnion {
+ var variant BetaBase64PDFBlockParam
+ switch v := any(source).(type) {
+ case BetaBase64PDFSourceParam:
+ variant.Source.OfBase64PDFSource = &v
+ case BetaPlainTextSourceParam:
+ variant.Source.OfPlainTextSource = &v
+ case BetaContentBlockSourceParam:
+ variant.Source.OfContentBlockSource = &v
+ case BetaURLPDFSourceParam:
+ variant.Source.OfUrlpdfSource = &v
}
- return false
+ return BetaContentBlockParamUnion{OfRequestDocumentBlock: &variant}
}
-type BetaCitationPageLocation struct {
- CitedText string `json:"cited_text,required"`
- DocumentIndex int64 `json:"document_index,required"`
- DocumentTitle string `json:"document_title,required,nullable"`
- EndPageNumber int64 `json:"end_page_number,required"`
- StartPageNumber int64 `json:"start_page_number,required"`
- Type BetaCitationPageLocationType `json:"type,required"`
- JSON betaCitationPageLocationJSON `json:"-"`
-}
-
-// betaCitationPageLocationJSON contains the JSON metadata for the struct
-// [BetaCitationPageLocation]
-type betaCitationPageLocationJSON struct {
- CitedText apijson.Field
- DocumentIndex apijson.Field
- DocumentTitle apijson.Field
- EndPageNumber apijson.Field
- StartPageNumber apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaCitationPageLocation) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+func BetaContentBlockParamOfRequestThinkingBlock(signature string, thinking string) BetaContentBlockParamUnion {
+ var variant BetaThinkingBlockParam
+ variant.Signature = signature
+ variant.Thinking = thinking
+ return BetaContentBlockParamUnion{OfRequestThinkingBlock: &variant}
}
-func (r betaCitationPageLocationJSON) RawJSON() string {
- return r.raw
+func BetaContentBlockParamOfRequestRedactedThinkingBlock(data string) BetaContentBlockParamUnion {
+ var variant BetaRedactedThinkingBlockParam
+ variant.Data = data
+ return BetaContentBlockParamUnion{OfRequestRedactedThinkingBlock: &variant}
}
-func (r BetaCitationPageLocation) implementsBetaCitationsDeltaCitation() {}
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaContentBlockParamUnion struct {
+ OfRequestTextBlock *BetaTextBlockParam `json:",omitzero,inline"`
+ OfRequestImageBlock *BetaImageBlockParam `json:",omitzero,inline"`
+ OfRequestToolUseBlock *BetaToolUseBlockParam `json:",omitzero,inline"`
+ OfRequestToolResultBlock *BetaToolResultBlockParam `json:",omitzero,inline"`
+ OfRequestDocumentBlock *BetaBase64PDFBlockParam `json:",omitzero,inline"`
+ OfRequestThinkingBlock *BetaThinkingBlockParam `json:",omitzero,inline"`
+ OfRequestRedactedThinkingBlock *BetaRedactedThinkingBlockParam `json:",omitzero,inline"`
+ paramUnion
+}
-func (r BetaCitationPageLocation) implementsBetaTextCitation() {}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaContentBlockParamUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u BetaContentBlockParamUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaContentBlockParamUnion](u.OfRequestTextBlock,
+ u.OfRequestImageBlock,
+ u.OfRequestToolUseBlock,
+ u.OfRequestToolResultBlock,
+ u.OfRequestDocumentBlock,
+ u.OfRequestThinkingBlock,
+ u.OfRequestRedactedThinkingBlock)
+}
-type BetaCitationPageLocationType string
+func (u *BetaContentBlockParamUnion) asAny() any {
+ if !param.IsOmitted(u.OfRequestTextBlock) {
+ return u.OfRequestTextBlock
+ } else if !param.IsOmitted(u.OfRequestImageBlock) {
+ return u.OfRequestImageBlock
+ } else if !param.IsOmitted(u.OfRequestToolUseBlock) {
+ return u.OfRequestToolUseBlock
+ } else if !param.IsOmitted(u.OfRequestToolResultBlock) {
+ return u.OfRequestToolResultBlock
+ } else if !param.IsOmitted(u.OfRequestDocumentBlock) {
+ return u.OfRequestDocumentBlock
+ } else if !param.IsOmitted(u.OfRequestThinkingBlock) {
+ return u.OfRequestThinkingBlock
+ } else if !param.IsOmitted(u.OfRequestRedactedThinkingBlock) {
+ return u.OfRequestRedactedThinkingBlock
+ }
+ return nil
+}
-const (
- BetaCitationPageLocationTypePageLocation BetaCitationPageLocationType = "page_location"
-)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetText() *string {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return &vt.Text
+ }
+ return nil
+}
-func (r BetaCitationPageLocationType) IsKnown() bool {
- switch r {
- case BetaCitationPageLocationTypePageLocation:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetID() *string {
+ if vt := u.OfRequestToolUseBlock; vt != nil {
+ return &vt.ID
}
- return false
+ return nil
}
-type BetaCitationPageLocationParam struct {
- CitedText param.Field[string] `json:"cited_text,required"`
- DocumentIndex param.Field[int64] `json:"document_index,required"`
- DocumentTitle param.Field[string] `json:"document_title,required"`
- EndPageNumber param.Field[int64] `json:"end_page_number,required"`
- StartPageNumber param.Field[int64] `json:"start_page_number,required"`
- Type param.Field[BetaCitationPageLocationParamType] `json:"type,required"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetInput() *interface{} {
+ if vt := u.OfRequestToolUseBlock; vt != nil {
+ return &vt.Input
+ }
+ return nil
}
-func (r BetaCitationPageLocationParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetName() *string {
+ if vt := u.OfRequestToolUseBlock; vt != nil {
+ return &vt.Name
+ }
+ return nil
}
-func (r BetaCitationPageLocationParam) implementsBetaTextCitationParamUnion() {}
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetToolUseID() *string {
+ if vt := u.OfRequestToolResultBlock; vt != nil {
+ return &vt.ToolUseID
+ }
+ return nil
+}
-type BetaCitationPageLocationParamType string
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetContent() *[]BetaToolResultBlockParamContentUnion {
+ if vt := u.OfRequestToolResultBlock; vt != nil {
+ return &vt.Content
+ }
+ return nil
+}
-const (
- BetaCitationPageLocationParamTypePageLocation BetaCitationPageLocationParamType = "page_location"
-)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetIsError() *bool {
+ if vt := u.OfRequestToolResultBlock; vt != nil && vt.IsError.IsPresent() {
+ return &vt.IsError.Value
+ }
+ return nil
+}
-func (r BetaCitationPageLocationParamType) IsKnown() bool {
- switch r {
- case BetaCitationPageLocationParamTypePageLocation:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetContext() *string {
+ if vt := u.OfRequestDocumentBlock; vt != nil && vt.Context.IsPresent() {
+ return &vt.Context.Value
}
- return false
+ return nil
}
-type BetaCitationsConfigParam struct {
- Enabled param.Field[bool] `json:"enabled"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetTitle() *string {
+ if vt := u.OfRequestDocumentBlock; vt != nil && vt.Title.IsPresent() {
+ return &vt.Title.Value
+ }
+ return nil
}
-func (r BetaCitationsConfigParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetSignature() *string {
+ if vt := u.OfRequestThinkingBlock; vt != nil {
+ return &vt.Signature
+ }
+ return nil
}
-type BetaCitationsDelta struct {
- Citation BetaCitationsDeltaCitation `json:"citation,required"`
- Type BetaCitationsDeltaType `json:"type,required"`
- JSON betaCitationsDeltaJSON `json:"-"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetThinking() *string {
+ if vt := u.OfRequestThinkingBlock; vt != nil {
+ return &vt.Thinking
+ }
+ return nil
}
-// betaCitationsDeltaJSON contains the JSON metadata for the struct
-// [BetaCitationsDelta]
-type betaCitationsDeltaJSON struct {
- Citation apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetData() *string {
+ if vt := u.OfRequestRedactedThinkingBlock; vt != nil {
+ return &vt.Data
+ }
+ return nil
}
-func (r *BetaCitationsDelta) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaContentBlockParamUnion) GetType() *string {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestImageBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestToolUseBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestToolResultBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestDocumentBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestThinkingBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestRedactedThinkingBlock; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
}
-func (r betaCitationsDeltaJSON) RawJSON() string {
- return r.raw
+// Returns a pointer to the underlying variant's CacheControl property, if present.
+func (u BetaContentBlockParamUnion) GetCacheControl() *BetaCacheControlEphemeralParam {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfRequestImageBlock; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfRequestToolUseBlock; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfRequestToolResultBlock; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfRequestDocumentBlock; vt != nil {
+ return &vt.CacheControl
+ }
+ return nil
}
-func (r BetaCitationsDelta) implementsBetaRawContentBlockDeltaEventDelta() {}
+// Returns a subunion which exports methods to access subproperties
+//
+// Or use AsAny() to get the underlying value
+func (u BetaContentBlockParamUnion) GetCitations() (res betaContentBlockParamUnionCitations) {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ res.ofBetaTextBlockCitations = &vt.Citations
+ } else if vt := u.OfRequestDocumentBlock; vt != nil {
+ res.ofBetaCitationsConfig = &vt.Citations
+ }
+ return
+}
-type BetaCitationsDeltaCitation struct {
- CitedText string `json:"cited_text,required"`
- DocumentIndex int64 `json:"document_index,required"`
- DocumentTitle string `json:"document_title,required,nullable"`
- Type BetaCitationsDeltaCitationType `json:"type,required"`
- EndBlockIndex int64 `json:"end_block_index"`
- EndCharIndex int64 `json:"end_char_index"`
- EndPageNumber int64 `json:"end_page_number"`
- StartBlockIndex int64 `json:"start_block_index"`
- StartCharIndex int64 `json:"start_char_index"`
- StartPageNumber int64 `json:"start_page_number"`
- JSON betaCitationsDeltaCitationJSON `json:"-"`
- union BetaCitationsDeltaCitationUnion
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type betaContentBlockParamUnionCitations struct {
+ ofBetaTextBlockCitations *[]BetaTextCitationParamUnion
+ ofBetaCitationsConfig *BetaCitationsConfigParam
}
-// betaCitationsDeltaCitationJSON contains the JSON metadata for the struct
-// [BetaCitationsDeltaCitation]
-type betaCitationsDeltaCitationJSON struct {
- CitedText apijson.Field
- DocumentIndex apijson.Field
- DocumentTitle apijson.Field
- Type apijson.Field
- EndBlockIndex apijson.Field
- EndCharIndex apijson.Field
- EndPageNumber apijson.Field
- StartBlockIndex apijson.Field
- StartCharIndex apijson.Field
- StartPageNumber apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+// Use the following switch statement to get the type of the union:
+//
+// switch u.AsAny().(type) {
+// case *[]anthropic.BetaTextCitationParamUnion:
+// case *anthropic.BetaCitationsConfigParam:
+// default:
+// fmt.Errorf("not present")
+// }
+func (u betaContentBlockParamUnionCitations) AsAny() any {
+ if !param.IsOmitted(u.ofBetaTextBlockCitations) {
+ return u.ofBetaTextBlockCitations
+ } else if !param.IsOmitted(u.ofBetaCitationsConfig) {
+ return u.ofBetaCitationsConfig
+ }
+ return nil
}
-func (r betaCitationsDeltaCitationJSON) RawJSON() string {
- return r.raw
+// Returns a pointer to the underlying variant's property, if present.
+func (u betaContentBlockParamUnionCitations) GetEnabled() *bool {
+ if vt := u.ofBetaCitationsConfig; vt != nil && vt.Enabled.IsPresent() {
+ return &vt.Enabled.Value
+ }
+ return nil
}
-func (r *BetaCitationsDeltaCitation) UnmarshalJSON(data []byte) (err error) {
- *r = BetaCitationsDeltaCitation{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
+// Returns a subunion which exports methods to access subproperties
+//
+// Or use AsAny() to get the underlying value
+func (u BetaContentBlockParamUnion) GetSource() (res betaContentBlockParamUnionSource) {
+ if vt := u.OfRequestImageBlock; vt != nil {
+ res.ofBetaImageBlockSource = &vt.Source
+ } else if vt := u.OfRequestDocumentBlock; vt != nil {
+ res.ofBetaBase64PDFBlockSourceUnion = &vt.Source
}
- return apijson.Port(r.union, &r)
+ return
}
-// AsUnion returns a [BetaCitationsDeltaCitationUnion] interface which you can cast
-// to the specific types for more type safety.
+// Only one field can be non-zero.
//
-// Possible runtime types of the union are [BetaCitationCharLocation],
-// [BetaCitationPageLocation], [BetaCitationContentBlockLocation].
-func (r BetaCitationsDeltaCitation) AsUnion() BetaCitationsDeltaCitationUnion {
- return r.union
+// Use [param.IsOmitted] to confirm if a field is set.
+type betaContentBlockParamUnionSource struct {
+ ofBetaImageBlockSource *BetaImageBlockParamSourceUnion
+ ofBetaBase64PDFBlockSourceUnion *BetaBase64PDFBlockSourceUnionParam
}
-// Union satisfied by [BetaCitationCharLocation], [BetaCitationPageLocation] or
-// [BetaCitationContentBlockLocation].
-type BetaCitationsDeltaCitationUnion interface {
- implementsBetaCitationsDeltaCitation()
+// Use the following switch statement to get the type of the union:
+//
+// switch u.AsAny().(type) {
+// case *anthropic.BetaBase64ImageSourceParam:
+// case *anthropic.BetaURLImageSourceParam:
+// case *anthropic.BetaBase64PDFSourceParam:
+// case *anthropic.BetaPlainTextSourceParam:
+// case *anthropic.BetaContentBlockSourceParam:
+// case *anthropic.BetaURLPDFSourceParam:
+// default:
+// fmt.Errorf("not present")
+// }
+func (u betaContentBlockParamUnionSource) AsAny() any {
+ if !param.IsOmitted(u.ofBetaImageBlockSource) {
+ return u.ofBetaImageBlockSource.asAny()
+ } else if !param.IsOmitted(u.ofBetaBase64PDFBlockSourceUnion) {
+ return u.ofBetaBase64PDFBlockSourceUnion.asAny()
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u betaContentBlockParamUnionSource) GetContent() *BetaContentBlockSourceContentUnionParam {
+ if u.ofBetaBase64PDFBlockSourceUnion != nil {
+ return u.ofBetaBase64PDFBlockSourceUnion.GetContent()
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u betaContentBlockParamUnionSource) GetData() *string {
+ if u.ofBetaImageBlockSource != nil {
+ return u.ofBetaImageBlockSource.GetData()
+ } else if u.ofBetaBase64PDFBlockSourceUnion != nil {
+ return u.ofBetaBase64PDFBlockSourceUnion.GetData()
+ } else if u.ofBetaBase64PDFBlockSourceUnion != nil {
+ return u.ofBetaBase64PDFBlockSourceUnion.GetData()
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u betaContentBlockParamUnionSource) GetMediaType() *string {
+ if u.ofBetaImageBlockSource != nil {
+ return u.ofBetaImageBlockSource.GetMediaType()
+ } else if u.ofBetaBase64PDFBlockSourceUnion != nil {
+ return u.ofBetaBase64PDFBlockSourceUnion.GetMediaType()
+ } else if u.ofBetaBase64PDFBlockSourceUnion != nil {
+ return u.ofBetaBase64PDFBlockSourceUnion.GetMediaType()
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u betaContentBlockParamUnionSource) GetType() *string {
+ if u.ofBetaImageBlockSource != nil {
+ return u.ofBetaImageBlockSource.GetType()
+ } else if u.ofBetaImageBlockSource != nil {
+ return u.ofBetaImageBlockSource.GetType()
+ } else if u.ofBetaBase64PDFBlockSourceUnion != nil {
+ return u.ofBetaBase64PDFBlockSourceUnion.GetType()
+ } else if u.ofBetaBase64PDFBlockSourceUnion != nil {
+ return u.ofBetaBase64PDFBlockSourceUnion.GetType()
+ } else if u.ofBetaBase64PDFBlockSourceUnion != nil {
+ return u.ofBetaBase64PDFBlockSourceUnion.GetType()
+ } else if u.ofBetaBase64PDFBlockSourceUnion != nil {
+ return u.ofBetaBase64PDFBlockSourceUnion.GetType()
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u betaContentBlockParamUnionSource) GetURL() *string {
+ if u.ofBetaImageBlockSource != nil {
+ return u.ofBetaImageBlockSource.GetURL()
+ } else if u.ofBetaBase64PDFBlockSourceUnion != nil {
+ return u.ofBetaBase64PDFBlockSourceUnion.GetURL()
+ }
+ return nil
}
func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*BetaCitationsDeltaCitationUnion)(nil)).Elem(),
+ apijson.RegisterUnion[BetaContentBlockParamUnion](
"type",
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaCitationCharLocation{}),
- DiscriminatorValue: "char_location",
+ Type: reflect.TypeOf(BetaTextBlockParam{}),
+ DiscriminatorValue: "text",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaCitationPageLocation{}),
- DiscriminatorValue: "page_location",
+ Type: reflect.TypeOf(BetaImageBlockParam{}),
+ DiscriminatorValue: "image",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaCitationContentBlockLocation{}),
- DiscriminatorValue: "content_block_location",
+ Type: reflect.TypeOf(BetaToolUseBlockParam{}),
+ DiscriminatorValue: "tool_use",
},
- )
-}
-
-type BetaCitationsDeltaCitationType string
-
-const (
- BetaCitationsDeltaCitationTypeCharLocation BetaCitationsDeltaCitationType = "char_location"
- BetaCitationsDeltaCitationTypePageLocation BetaCitationsDeltaCitationType = "page_location"
- BetaCitationsDeltaCitationTypeContentBlockLocation BetaCitationsDeltaCitationType = "content_block_location"
-)
-
-func (r BetaCitationsDeltaCitationType) IsKnown() bool {
- switch r {
- case BetaCitationsDeltaCitationTypeCharLocation, BetaCitationsDeltaCitationTypePageLocation, BetaCitationsDeltaCitationTypeContentBlockLocation:
- return true
- }
- return false
-}
-
-type BetaCitationsDeltaType string
-
-const (
- BetaCitationsDeltaTypeCitationsDelta BetaCitationsDeltaType = "citations_delta"
-)
-
-func (r BetaCitationsDeltaType) IsKnown() bool {
- switch r {
- case BetaCitationsDeltaTypeCitationsDelta:
- return true
- }
- return false
-}
-
-type BetaContentBlock struct {
- Type BetaContentBlockType `json:"type,required"`
- ID string `json:"id"`
- // This field can have the runtime type of [[]BetaTextCitation].
- Citations interface{} `json:"citations"`
- Data string `json:"data"`
- // This field can have the runtime type of [interface{}].
- Input interface{} `json:"input"`
- Name string `json:"name"`
- Signature string `json:"signature"`
- Text string `json:"text"`
- Thinking string `json:"thinking"`
- JSON betaContentBlockJSON `json:"-"`
- union BetaContentBlockUnion
-}
-
-// betaContentBlockJSON contains the JSON metadata for the struct
-// [BetaContentBlock]
-type betaContentBlockJSON struct {
- Type apijson.Field
- ID apijson.Field
- Citations apijson.Field
- Data apijson.Field
- Input apijson.Field
- Name apijson.Field
- Signature apijson.Field
- Text apijson.Field
- Thinking apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r betaContentBlockJSON) RawJSON() string {
- return r.raw
-}
-
-func (r *BetaContentBlock) UnmarshalJSON(data []byte) (err error) {
- *r = BetaContentBlock{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
- }
- return apijson.Port(r.union, &r)
-}
-
-// AsUnion returns a [BetaContentBlockUnion] interface which you can cast to the
-// specific types for more type safety.
-//
-// Possible runtime types of the union are [BetaTextBlock], [BetaToolUseBlock],
-// [BetaThinkingBlock], [BetaRedactedThinkingBlock].
-func (r BetaContentBlock) AsUnion() BetaContentBlockUnion {
- return r.union
-}
-
-// Union satisfied by [BetaTextBlock], [BetaToolUseBlock], [BetaThinkingBlock] or
-// [BetaRedactedThinkingBlock].
-type BetaContentBlockUnion interface {
- implementsBetaContentBlock()
-}
-
-func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*BetaContentBlockUnion)(nil)).Elem(),
- "type",
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaTextBlock{}),
- DiscriminatorValue: "text",
+ Type: reflect.TypeOf(BetaToolResultBlockParam{}),
+ DiscriminatorValue: "tool_result",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaToolUseBlock{}),
- DiscriminatorValue: "tool_use",
+ Type: reflect.TypeOf(BetaBase64PDFBlockParam{}),
+ DiscriminatorValue: "document",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaThinkingBlock{}),
+ Type: reflect.TypeOf(BetaThinkingBlockParam{}),
DiscriminatorValue: "thinking",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaRedactedThinkingBlock{}),
+ Type: reflect.TypeOf(BetaRedactedThinkingBlockParam{}),
DiscriminatorValue: "redacted_thinking",
},
)
}
-type BetaContentBlockType string
-
-const (
- BetaContentBlockTypeText BetaContentBlockType = "text"
- BetaContentBlockTypeToolUse BetaContentBlockType = "tool_use"
- BetaContentBlockTypeThinking BetaContentBlockType = "thinking"
- BetaContentBlockTypeRedactedThinking BetaContentBlockType = "redacted_thinking"
-)
-
-func (r BetaContentBlockType) IsKnown() bool {
- switch r {
- case BetaContentBlockTypeText, BetaContentBlockTypeToolUse, BetaContentBlockTypeThinking, BetaContentBlockTypeRedactedThinking:
- return true
- }
- return false
-}
-
-type BetaContentBlockParam struct {
- Type param.Field[BetaContentBlockParamType] `json:"type,required"`
- ID param.Field[string] `json:"id"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
- Citations param.Field[interface{}] `json:"citations"`
- Content param.Field[interface{}] `json:"content"`
- Context param.Field[string] `json:"context"`
- Data param.Field[string] `json:"data"`
- Input param.Field[interface{}] `json:"input"`
- IsError param.Field[bool] `json:"is_error"`
- Name param.Field[string] `json:"name"`
- Signature param.Field[string] `json:"signature"`
- Source param.Field[interface{}] `json:"source"`
- Text param.Field[string] `json:"text"`
- Thinking param.Field[string] `json:"thinking"`
- Title param.Field[string] `json:"title"`
- ToolUseID param.Field[string] `json:"tool_use_id"`
-}
-
-func (r BetaContentBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaContentBlockParam) implementsBetaContentBlockParamUnion() {}
-
-// Satisfied by [BetaTextBlockParam], [BetaImageBlockParam],
-// [BetaToolUseBlockParam], [BetaToolResultBlockParam], [BetaBase64PDFBlockParam],
-// [BetaThinkingBlockParam], [BetaRedactedThinkingBlockParam],
-// [BetaContentBlockParam].
-type BetaContentBlockParamUnion interface {
- implementsBetaContentBlockParamUnion()
-}
-
-type BetaContentBlockParamType string
-
-const (
- BetaContentBlockParamTypeText BetaContentBlockParamType = "text"
- BetaContentBlockParamTypeImage BetaContentBlockParamType = "image"
- BetaContentBlockParamTypeToolUse BetaContentBlockParamType = "tool_use"
- BetaContentBlockParamTypeToolResult BetaContentBlockParamType = "tool_result"
- BetaContentBlockParamTypeDocument BetaContentBlockParamType = "document"
- BetaContentBlockParamTypeThinking BetaContentBlockParamType = "thinking"
- BetaContentBlockParamTypeRedactedThinking BetaContentBlockParamType = "redacted_thinking"
-)
-
-func (r BetaContentBlockParamType) IsKnown() bool {
- switch r {
- case BetaContentBlockParamTypeText, BetaContentBlockParamTypeImage, BetaContentBlockParamTypeToolUse, BetaContentBlockParamTypeToolResult, BetaContentBlockParamTypeDocument, BetaContentBlockParamTypeThinking, BetaContentBlockParamTypeRedactedThinking:
- return true
- }
- return false
-}
-
+// The properties Content, Type are required.
type BetaContentBlockSourceParam struct {
- Content param.Field[BetaContentBlockSourceContentUnionParam] `json:"content,required"`
- Type param.Field[BetaContentBlockSourceType] `json:"type,required"`
+ Content BetaContentBlockSourceContentUnionParam `json:"content,omitzero,required"`
+ // This field can be elided, and will marshal its zero value as "content".
+ Type constant.Content `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaContentBlockSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaContentBlockSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaContentBlockSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r BetaContentBlockSourceParam) implementsBetaBase64PDFBlockSourceUnionParam() {}
-
-// Satisfied by [shared.UnionString],
-// [BetaContentBlockSourceContentBetaContentBlockSourceContentParam].
-type BetaContentBlockSourceContentUnionParam interface {
- ImplementsBetaContentBlockSourceContentUnionParam()
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaContentBlockSourceContentUnionParam struct {
+ OfString param.Opt[string] `json:",omitzero,inline"`
+ OfBetaContentBlockSourceContent []BetaContentBlockSourceContentUnionParam `json:",omitzero,inline"`
+ paramUnion
}
-type BetaContentBlockSourceContentBetaContentBlockSourceContentParam []BetaContentBlockSourceContentUnionParam
-
-func (r BetaContentBlockSourceContentBetaContentBlockSourceContentParam) ImplementsBetaContentBlockSourceContentUnionParam() {
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaContentBlockSourceContentUnionParam) IsPresent() bool {
+ return !param.IsOmitted(u) && !u.IsNull()
+}
+func (u BetaContentBlockSourceContentUnionParam) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaContentBlockSourceContentUnionParam](u.OfString, u.OfBetaContentBlockSourceContent)
}
-type BetaContentBlockSourceType string
-
-const (
- BetaContentBlockSourceTypeContent BetaContentBlockSourceType = "content"
-)
-
-func (r BetaContentBlockSourceType) IsKnown() bool {
- switch r {
- case BetaContentBlockSourceTypeContent:
- return true
+func (u *BetaContentBlockSourceContentUnionParam) asAny() any {
+ if !param.IsOmitted(u.OfString) {
+ return &u.OfString.Value
+ } else if !param.IsOmitted(u.OfBetaContentBlockSourceContent) {
+ return &u.OfBetaContentBlockSourceContent
}
- return false
+ return nil
}
+// The properties Source, Type are required.
type BetaImageBlockParam struct {
- Source param.Field[BetaImageBlockParamSourceUnion] `json:"source,required"`
- Type param.Field[BetaImageBlockParamType] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
+ Source BetaImageBlockParamSourceUnion `json:"source,omitzero,required"`
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
+ // This field can be elided, and will marshal its zero value as "image".
+ Type constant.Image `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaImageBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaImageBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaImageBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r BetaImageBlockParam) implementsBetaContentBlockParamUnion() {}
-
-func (r BetaImageBlockParam) implementsBetaContentBlockSourceContentUnionParam() {}
-
-func (r BetaImageBlockParam) implementsBetaToolResultBlockParamContentUnion() {}
-
-type BetaImageBlockParamSource struct {
- Type param.Field[BetaImageBlockParamSourceType] `json:"type,required"`
- Data param.Field[string] `json:"data" format:"byte"`
- MediaType param.Field[BetaImageBlockParamSourceMediaType] `json:"media_type"`
- URL param.Field[string] `json:"url"`
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaImageBlockParamSourceUnion struct {
+ OfBase64ImageSource *BetaBase64ImageSourceParam `json:",omitzero,inline"`
+ OfURLImageSource *BetaURLImageSourceParam `json:",omitzero,inline"`
+ paramUnion
}
-func (r BetaImageBlockParamSource) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaImageBlockParamSourceUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u BetaImageBlockParamSourceUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaImageBlockParamSourceUnion](u.OfBase64ImageSource, u.OfURLImageSource)
}
-func (r BetaImageBlockParamSource) implementsBetaImageBlockParamSourceUnion() {}
-
-// Satisfied by [BetaBase64ImageSourceParam], [BetaURLImageSourceParam],
-// [BetaImageBlockParamSource].
-type BetaImageBlockParamSourceUnion interface {
- implementsBetaImageBlockParamSourceUnion()
+func (u *BetaImageBlockParamSourceUnion) asAny() any {
+ if !param.IsOmitted(u.OfBase64ImageSource) {
+ return u.OfBase64ImageSource
+ } else if !param.IsOmitted(u.OfURLImageSource) {
+ return u.OfURLImageSource
+ }
+ return nil
}
-type BetaImageBlockParamSourceType string
-
-const (
- BetaImageBlockParamSourceTypeBase64 BetaImageBlockParamSourceType = "base64"
- BetaImageBlockParamSourceTypeURL BetaImageBlockParamSourceType = "url"
-)
-
-func (r BetaImageBlockParamSourceType) IsKnown() bool {
- switch r {
- case BetaImageBlockParamSourceTypeBase64, BetaImageBlockParamSourceTypeURL:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaImageBlockParamSourceUnion) GetData() *string {
+ if vt := u.OfBase64ImageSource; vt != nil {
+ return &vt.Data
}
- return false
+ return nil
}
-type BetaImageBlockParamSourceMediaType string
-
-const (
- BetaImageBlockParamSourceMediaTypeImageJPEG BetaImageBlockParamSourceMediaType = "image/jpeg"
- BetaImageBlockParamSourceMediaTypeImagePNG BetaImageBlockParamSourceMediaType = "image/png"
- BetaImageBlockParamSourceMediaTypeImageGIF BetaImageBlockParamSourceMediaType = "image/gif"
- BetaImageBlockParamSourceMediaTypeImageWebP BetaImageBlockParamSourceMediaType = "image/webp"
-)
-
-func (r BetaImageBlockParamSourceMediaType) IsKnown() bool {
- switch r {
- case BetaImageBlockParamSourceMediaTypeImageJPEG, BetaImageBlockParamSourceMediaTypeImagePNG, BetaImageBlockParamSourceMediaTypeImageGIF, BetaImageBlockParamSourceMediaTypeImageWebP:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaImageBlockParamSourceUnion) GetMediaType() *string {
+ if vt := u.OfBase64ImageSource; vt != nil {
+ return (*string)(&vt.MediaType)
}
- return false
+ return nil
}
-type BetaImageBlockParamType string
-
-const (
- BetaImageBlockParamTypeImage BetaImageBlockParamType = "image"
-)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaImageBlockParamSourceUnion) GetURL() *string {
+ if vt := u.OfURLImageSource; vt != nil {
+ return &vt.URL
+ }
+ return nil
+}
-func (r BetaImageBlockParamType) IsKnown() bool {
- switch r {
- case BetaImageBlockParamTypeImage:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaImageBlockParamSourceUnion) GetType() *string {
+ if vt := u.OfBase64ImageSource; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfURLImageSource; vt != nil {
+ return (*string)(&vt.Type)
}
- return false
+ return nil
}
-type BetaInputJSONDelta struct {
- PartialJSON string `json:"partial_json,required"`
- Type BetaInputJSONDeltaType `json:"type,required"`
- JSON betaInputJSONDeltaJSON `json:"-"`
-}
-
-// betaInputJSONDeltaJSON contains the JSON metadata for the struct
-// [BetaInputJSONDelta]
-type betaInputJSONDeltaJSON struct {
- PartialJSON apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func init() {
+ apijson.RegisterUnion[BetaImageBlockParamSourceUnion](
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaBase64ImageSourceParam{}),
+ DiscriminatorValue: "base64",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaURLImageSourceParam{}),
+ DiscriminatorValue: "url",
+ },
+ )
}
-func (r *BetaInputJSONDelta) UnmarshalJSON(data []byte) (err error) {
+type BetaInputJSONDelta struct {
+ PartialJSON string `json:"partial_json,required"`
+ Type constant.InputJSONDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ PartialJSON resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaInputJSONDelta) RawJSON() string { return r.JSON.raw }
+func (r *BetaInputJSONDelta) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaInputJSONDeltaJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaInputJSONDelta) implementsBetaRawContentBlockDeltaEventDelta() {}
-
-type BetaInputJSONDeltaType string
-
-const (
- BetaInputJSONDeltaTypeInputJSONDelta BetaInputJSONDeltaType = "input_json_delta"
-)
-
-func (r BetaInputJSONDeltaType) IsKnown() bool {
- switch r {
- case BetaInputJSONDeltaTypeInputJSONDelta:
- return true
- }
- return false
-}
-
type BetaMessage struct {
// Unique object identifier.
//
@@ -1026,7 +1281,7 @@ type BetaMessage struct {
// ```json
// [{ "type": "text", "text": "B)" }]
// ```
- Content []BetaContentBlock `json:"content,required"`
+ Content []BetaContentBlockUnion `json:"content,required"`
// The model that will complete your prompt.\n\nSee
// [models](https://docs.anthropic.com/en/docs/models-overview) for additional
// details and options.
@@ -1034,7 +1289,7 @@ type BetaMessage struct {
// Conversational role of the generated message.
//
// This will always be `"assistant"`.
- Role BetaMessageRole `json:"role,required"`
+ Role constant.Assistant `json:"role,required"`
// The reason that we stopped.
//
// This may be one the following values:
@@ -1046,16 +1301,18 @@ type BetaMessage struct {
//
// In non-streaming mode this value is always non-null. In streaming mode, it is
// null in the `message_start` event and non-null otherwise.
- StopReason BetaMessageStopReason `json:"stop_reason,required,nullable"`
+ //
+ // Any of "end_turn", "max_tokens", "stop_sequence", "tool_use".
+ StopReason BetaMessageStopReason `json:"stop_reason,required"`
// Which custom stop sequence was generated, if any.
//
// This value will be a non-null string if one of your custom stop sequences was
// generated.
- StopSequence string `json:"stop_sequence,required,nullable"`
+ StopSequence string `json:"stop_sequence,required"`
// Object type.
//
// For Messages, this is always `"message"`.
- Type BetaMessageType `json:"type,required"`
+ Type constant.Message `json:"type,required"`
// Billing and rate-limit usage.
//
// Anthropic's API bills and rate-limits by token counts, as tokens represent the
@@ -1071,47 +1328,38 @@ type BetaMessage struct {
//
// Total input tokens in a request is the summation of `input_tokens`,
// `cache_creation_input_tokens`, and `cache_read_input_tokens`.
- Usage BetaUsage `json:"usage,required"`
- JSON betaMessageJSON `json:"-"`
-}
-
-// betaMessageJSON contains the JSON metadata for the struct [BetaMessage]
-type betaMessageJSON struct {
- ID apijson.Field
- Content apijson.Field
- Model apijson.Field
- Role apijson.Field
- StopReason apijson.Field
- StopSequence apijson.Field
- Type apijson.Field
- Usage apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaMessage) UnmarshalJSON(data []byte) (err error) {
+ Usage BetaUsage `json:"usage,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ Content resp.Field
+ Model resp.Field
+ Role resp.Field
+ StopReason resp.Field
+ StopSequence resp.Field
+ Type resp.Field
+ Usage resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaMessage) RawJSON() string { return r.JSON.raw }
+func (r *BetaMessage) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaMessageJSON) RawJSON() string {
- return r.raw
-}
-
-// Conversational role of the generated message.
-//
-// This will always be `"assistant"`.
-type BetaMessageRole string
-
-const (
- BetaMessageRoleAssistant BetaMessageRole = "assistant"
-)
-
-func (r BetaMessageRole) IsKnown() bool {
- switch r {
- case BetaMessageRoleAssistant:
- return true
+func (r BetaMessage) ToParam() BetaMessageParam {
+ var p BetaMessageParam
+ p.Role = BetaMessageParamRole(r.Role)
+ p.Content = make([]BetaContentBlockParamUnion, len(r.Content))
+ for i, c := range r.Content {
+ contentParams := c.ToParam()
+ p.Content[i] = contentParams
}
- return false
+ return p
}
// The reason that we stopped.
@@ -1134,60 +1382,38 @@ const (
BetaMessageStopReasonToolUse BetaMessageStopReason = "tool_use"
)
-func (r BetaMessageStopReason) IsKnown() bool {
- switch r {
- case BetaMessageStopReasonEndTurn, BetaMessageStopReasonMaxTokens, BetaMessageStopReasonStopSequence, BetaMessageStopReasonToolUse:
- return true
- }
- return false
-}
-
-// Object type.
-//
-// For Messages, this is always `"message"`.
-type BetaMessageType string
-
-const (
- BetaMessageTypeMessage BetaMessageType = "message"
-)
-
-func (r BetaMessageType) IsKnown() bool {
- switch r {
- case BetaMessageTypeMessage:
- return true
- }
- return false
-}
-
type BetaMessageDeltaUsage struct {
// The cumulative number of output tokens which were used.
- OutputTokens int64 `json:"output_tokens,required"`
- JSON betaMessageDeltaUsageJSON `json:"-"`
-}
-
-// betaMessageDeltaUsageJSON contains the JSON metadata for the struct
-// [BetaMessageDeltaUsage]
-type betaMessageDeltaUsageJSON struct {
- OutputTokens apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaMessageDeltaUsage) UnmarshalJSON(data []byte) (err error) {
+ OutputTokens int64 `json:"output_tokens,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ OutputTokens resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaMessageDeltaUsage) RawJSON() string { return r.JSON.raw }
+func (r *BetaMessageDeltaUsage) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaMessageDeltaUsageJSON) RawJSON() string {
- return r.raw
-}
-
+// The properties Content, Role are required.
type BetaMessageParam struct {
- Content param.Field[[]BetaContentBlockParamUnion] `json:"content,required"`
- Role param.Field[BetaMessageParamRole] `json:"role,required"`
+ Content []BetaContentBlockParamUnion `json:"content,omitzero,required"`
+ // Any of "user", "assistant".
+ Role BetaMessageParamRole `json:"role,omitzero,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaMessageParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaMessageParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
type BetaMessageParamRole string
@@ -1197,421 +1423,309 @@ const (
BetaMessageParamRoleAssistant BetaMessageParamRole = "assistant"
)
-func (r BetaMessageParamRole) IsKnown() bool {
- switch r {
- case BetaMessageParamRoleUser, BetaMessageParamRoleAssistant:
- return true
- }
- return false
-}
-
type BetaMessageTokensCount struct {
// The total number of tokens across the provided list of messages, system prompt,
// and tools.
- InputTokens int64 `json:"input_tokens,required"`
- JSON betaMessageTokensCountJSON `json:"-"`
-}
-
-// betaMessageTokensCountJSON contains the JSON metadata for the struct
-// [BetaMessageTokensCount]
-type betaMessageTokensCountJSON struct {
- InputTokens apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaMessageTokensCount) UnmarshalJSON(data []byte) (err error) {
+ InputTokens int64 `json:"input_tokens,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ InputTokens resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaMessageTokensCount) RawJSON() string { return r.JSON.raw }
+func (r *BetaMessageTokensCount) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaMessageTokensCountJSON) RawJSON() string {
- return r.raw
-}
-
type BetaMetadataParam struct {
// An external identifier for the user who is associated with the request.
//
// This should be a uuid, hash value, or other opaque identifier. Anthropic may use
// this id to help detect abuse. Do not include any identifying information such as
// name, email address, or phone number.
- UserID param.Field[string] `json:"user_id"`
+ UserID param.Opt[string] `json:"user_id,omitzero"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMetadataParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaMetadataParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaMetadataParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties Data, MediaType, Type are required.
type BetaPlainTextSourceParam struct {
- Data param.Field[string] `json:"data,required"`
- MediaType param.Field[BetaPlainTextSourceMediaType] `json:"media_type,required"`
- Type param.Field[BetaPlainTextSourceType] `json:"type,required"`
+ Data string `json:"data,required"`
+ // This field can be elided, and will marshal its zero value as "text/plain".
+ MediaType constant.TextPlain `json:"media_type,required"`
+ // This field can be elided, and will marshal its zero value as "text".
+ Type constant.Text `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaPlainTextSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaPlainTextSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaPlainTextSourceParam) implementsBetaBase64PDFBlockSourceUnionParam() {}
-
-type BetaPlainTextSourceMediaType string
-
-const (
- BetaPlainTextSourceMediaTypeTextPlain BetaPlainTextSourceMediaType = "text/plain"
-)
-
-func (r BetaPlainTextSourceMediaType) IsKnown() bool {
- switch r {
- case BetaPlainTextSourceMediaTypeTextPlain:
- return true
- }
- return false
-}
-
-type BetaPlainTextSourceType string
-
-const (
- BetaPlainTextSourceTypeText BetaPlainTextSourceType = "text"
-)
-
-func (r BetaPlainTextSourceType) IsKnown() bool {
- switch r {
- case BetaPlainTextSourceTypeText:
- return true
- }
- return false
+ type shadow BetaPlainTextSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
type BetaRawContentBlockDeltaEvent struct {
- Delta BetaRawContentBlockDeltaEventDelta `json:"delta,required"`
- Index int64 `json:"index,required"`
- Type BetaRawContentBlockDeltaEventType `json:"type,required"`
- JSON betaRawContentBlockDeltaEventJSON `json:"-"`
-}
-
-// betaRawContentBlockDeltaEventJSON contains the JSON metadata for the struct
-// [BetaRawContentBlockDeltaEvent]
-type betaRawContentBlockDeltaEventJSON struct {
- Delta apijson.Field
- Index apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaRawContentBlockDeltaEvent) UnmarshalJSON(data []byte) (err error) {
+ Delta BetaRawContentBlockDeltaEventDeltaUnion `json:"delta,required"`
+ Index int64 `json:"index,required"`
+ Type constant.ContentBlockDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Delta resp.Field
+ Index resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaRawContentBlockDeltaEvent) RawJSON() string { return r.JSON.raw }
+func (r *BetaRawContentBlockDeltaEvent) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaRawContentBlockDeltaEventJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaRawContentBlockDeltaEvent) implementsBetaRawMessageStreamEvent() {}
-
-type BetaRawContentBlockDeltaEventDelta struct {
- Type BetaRawContentBlockDeltaEventDeltaType `json:"type,required"`
- // This field can have the runtime type of [BetaCitationsDeltaCitation].
- Citation interface{} `json:"citation"`
- PartialJSON string `json:"partial_json"`
- Signature string `json:"signature"`
- Text string `json:"text"`
- Thinking string `json:"thinking"`
- JSON betaRawContentBlockDeltaEventDeltaJSON `json:"-"`
- union BetaRawContentBlockDeltaEventDeltaUnion
-}
-
-// betaRawContentBlockDeltaEventDeltaJSON contains the JSON metadata for the struct
-// [BetaRawContentBlockDeltaEventDelta]
-type betaRawContentBlockDeltaEventDeltaJSON struct {
- Type apijson.Field
- Citation apijson.Field
- PartialJSON apijson.Field
- Signature apijson.Field
- Text apijson.Field
- Thinking apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r betaRawContentBlockDeltaEventDeltaJSON) RawJSON() string {
- return r.raw
-}
-
-func (r *BetaRawContentBlockDeltaEventDelta) UnmarshalJSON(data []byte) (err error) {
- *r = BetaRawContentBlockDeltaEventDelta{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
- }
- return apijson.Port(r.union, &r)
-}
-
-// AsUnion returns a [BetaRawContentBlockDeltaEventDeltaUnion] interface which you
-// can cast to the specific types for more type safety.
+// BetaRawContentBlockDeltaEventDeltaUnion contains all possible properties and
+// values from [BetaTextDelta], [BetaInputJSONDelta], [BetaCitationsDelta],
+// [BetaThinkingDelta], [BetaSignatureDelta].
//
-// Possible runtime types of the union are [BetaTextDelta], [BetaInputJSONDelta],
-// [BetaCitationsDelta], [BetaThinkingDelta], [BetaSignatureDelta].
-func (r BetaRawContentBlockDeltaEventDelta) AsUnion() BetaRawContentBlockDeltaEventDeltaUnion {
- return r.union
-}
-
-// Union satisfied by [BetaTextDelta], [BetaInputJSONDelta], [BetaCitationsDelta],
-// [BetaThinkingDelta] or [BetaSignatureDelta].
-type BetaRawContentBlockDeltaEventDeltaUnion interface {
- implementsBetaRawContentBlockDeltaEventDelta()
+// Use the [BetaRawContentBlockDeltaEventDeltaUnion.AsAny] method to switch on the
+// variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type BetaRawContentBlockDeltaEventDeltaUnion struct {
+ // This field is from variant [BetaTextDelta].
+ Text string `json:"text"`
+ // Any of "text_delta", "input_json_delta", "citations_delta", "thinking_delta",
+ // "signature_delta".
+ Type string `json:"type"`
+ // This field is from variant [BetaInputJSONDelta].
+ PartialJSON string `json:"partial_json"`
+ // This field is from variant [BetaCitationsDelta].
+ Citation BetaCitationsDeltaCitationUnion `json:"citation"`
+ // This field is from variant [BetaThinkingDelta].
+ Thinking string `json:"thinking"`
+ // This field is from variant [BetaSignatureDelta].
+ Signature string `json:"signature"`
+ JSON struct {
+ Text resp.Field
+ Type resp.Field
+ PartialJSON resp.Field
+ Citation resp.Field
+ Thinking resp.Field
+ Signature resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := BetaRawContentBlockDeltaEventDeltaUnion.AsAny().(type) {
+// case BetaTextDelta:
+// case BetaInputJSONDelta:
+// case BetaCitationsDelta:
+// case BetaThinkingDelta:
+// case BetaSignatureDelta:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u BetaRawContentBlockDeltaEventDeltaUnion) AsAny() any {
+ switch u.Type {
+ case "text_delta":
+ return u.AsTextContentBlockDelta()
+ case "input_json_delta":
+ return u.AsInputJSONContentBlockDelta()
+ case "citations_delta":
+ return u.AsCitationsDelta()
+ case "thinking_delta":
+ return u.AsThinkingContentBlockDelta()
+ case "signature_delta":
+ return u.AsSignatureContentBlockDelta()
+ }
+ return nil
+}
+
+func (u BetaRawContentBlockDeltaEventDeltaUnion) AsTextContentBlockDelta() (v BetaTextDelta) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*BetaRawContentBlockDeltaEventDeltaUnion)(nil)).Elem(),
- "type",
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaTextDelta{}),
- DiscriminatorValue: "text_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaInputJSONDelta{}),
- DiscriminatorValue: "input_json_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaCitationsDelta{}),
- DiscriminatorValue: "citations_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaThinkingDelta{}),
- DiscriminatorValue: "thinking_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaSignatureDelta{}),
- DiscriminatorValue: "signature_delta",
- },
- )
+func (u BetaRawContentBlockDeltaEventDeltaUnion) AsInputJSONContentBlockDelta() (v BetaInputJSONDelta) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaRawContentBlockDeltaEventDeltaType string
-
-const (
- BetaRawContentBlockDeltaEventDeltaTypeTextDelta BetaRawContentBlockDeltaEventDeltaType = "text_delta"
- BetaRawContentBlockDeltaEventDeltaTypeInputJSONDelta BetaRawContentBlockDeltaEventDeltaType = "input_json_delta"
- BetaRawContentBlockDeltaEventDeltaTypeCitationsDelta BetaRawContentBlockDeltaEventDeltaType = "citations_delta"
- BetaRawContentBlockDeltaEventDeltaTypeThinkingDelta BetaRawContentBlockDeltaEventDeltaType = "thinking_delta"
- BetaRawContentBlockDeltaEventDeltaTypeSignatureDelta BetaRawContentBlockDeltaEventDeltaType = "signature_delta"
-)
-
-func (r BetaRawContentBlockDeltaEventDeltaType) IsKnown() bool {
- switch r {
- case BetaRawContentBlockDeltaEventDeltaTypeTextDelta, BetaRawContentBlockDeltaEventDeltaTypeInputJSONDelta, BetaRawContentBlockDeltaEventDeltaTypeCitationsDelta, BetaRawContentBlockDeltaEventDeltaTypeThinkingDelta, BetaRawContentBlockDeltaEventDeltaTypeSignatureDelta:
- return true
- }
- return false
+func (u BetaRawContentBlockDeltaEventDeltaUnion) AsCitationsDelta() (v BetaCitationsDelta) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaRawContentBlockDeltaEventType string
-
-const (
- BetaRawContentBlockDeltaEventTypeContentBlockDelta BetaRawContentBlockDeltaEventType = "content_block_delta"
-)
-
-func (r BetaRawContentBlockDeltaEventType) IsKnown() bool {
- switch r {
- case BetaRawContentBlockDeltaEventTypeContentBlockDelta:
- return true
- }
- return false
+func (u BetaRawContentBlockDeltaEventDeltaUnion) AsThinkingContentBlockDelta() (v BetaThinkingDelta) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaRawContentBlockStartEvent struct {
- ContentBlock BetaRawContentBlockStartEventContentBlock `json:"content_block,required"`
- Index int64 `json:"index,required"`
- Type BetaRawContentBlockStartEventType `json:"type,required"`
- JSON betaRawContentBlockStartEventJSON `json:"-"`
+func (u BetaRawContentBlockDeltaEventDeltaUnion) AsSignatureContentBlockDelta() (v BetaSignatureDelta) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// betaRawContentBlockStartEventJSON contains the JSON metadata for the struct
-// [BetaRawContentBlockStartEvent]
-type betaRawContentBlockStartEventJSON struct {
- ContentBlock apijson.Field
- Index apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
+// Returns the unmodified JSON received from the API
+func (u BetaRawContentBlockDeltaEventDeltaUnion) RawJSON() string { return u.JSON.raw }
-func (r *BetaRawContentBlockStartEvent) UnmarshalJSON(data []byte) (err error) {
+func (r *BetaRawContentBlockDeltaEventDeltaUnion) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaRawContentBlockStartEventJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaRawContentBlockStartEvent) implementsBetaRawMessageStreamEvent() {}
-
-type BetaRawContentBlockStartEventContentBlock struct {
- Type BetaRawContentBlockStartEventContentBlockType `json:"type,required"`
- ID string `json:"id"`
- // This field can have the runtime type of [[]BetaTextCitation].
- Citations interface{} `json:"citations"`
- Data string `json:"data"`
- // This field can have the runtime type of [interface{}].
- Input interface{} `json:"input"`
- Name string `json:"name"`
- Signature string `json:"signature"`
- Text string `json:"text"`
- Thinking string `json:"thinking"`
- JSON betaRawContentBlockStartEventContentBlockJSON `json:"-"`
- union BetaRawContentBlockStartEventContentBlockUnion
-}
-
-// betaRawContentBlockStartEventContentBlockJSON contains the JSON metadata for the
-// struct [BetaRawContentBlockStartEventContentBlock]
-type betaRawContentBlockStartEventContentBlockJSON struct {
- Type apijson.Field
- ID apijson.Field
- Citations apijson.Field
- Data apijson.Field
- Input apijson.Field
- Name apijson.Field
- Signature apijson.Field
- Text apijson.Field
- Thinking apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r betaRawContentBlockStartEventContentBlockJSON) RawJSON() string {
- return r.raw
-}
-
-func (r *BetaRawContentBlockStartEventContentBlock) UnmarshalJSON(data []byte) (err error) {
- *r = BetaRawContentBlockStartEventContentBlock{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
- }
- return apijson.Port(r.union, &r)
+type BetaRawContentBlockStartEvent struct {
+ ContentBlock BetaRawContentBlockStartEventContentBlockUnion `json:"content_block,required"`
+ Index int64 `json:"index,required"`
+ Type constant.ContentBlockStart `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ContentBlock resp.Field
+ Index resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaRawContentBlockStartEvent) RawJSON() string { return r.JSON.raw }
+func (r *BetaRawContentBlockStartEvent) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-// AsUnion returns a [BetaRawContentBlockStartEventContentBlockUnion] interface
-// which you can cast to the specific types for more type safety.
+// BetaRawContentBlockStartEventContentBlockUnion contains all possible properties
+// and values from [BetaTextBlock], [BetaToolUseBlock], [BetaThinkingBlock],
+// [BetaRedactedThinkingBlock].
+//
+// Use the [BetaRawContentBlockStartEventContentBlockUnion.AsAny] method to switch
+// on the variant.
//
-// Possible runtime types of the union are [BetaTextBlock], [BetaToolUseBlock],
-// [BetaThinkingBlock], [BetaRedactedThinkingBlock].
-func (r BetaRawContentBlockStartEventContentBlock) AsUnion() BetaRawContentBlockStartEventContentBlockUnion {
- return r.union
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type BetaRawContentBlockStartEventContentBlockUnion struct {
+ // This field is from variant [BetaTextBlock].
+ Citations []BetaTextCitationUnion `json:"citations"`
+ // This field is from variant [BetaTextBlock].
+ Text string `json:"text"`
+ // Any of "text", "tool_use", "thinking", "redacted_thinking".
+ Type string `json:"type"`
+ // This field is from variant [BetaToolUseBlock].
+ ID string `json:"id"`
+ // This field is from variant [BetaToolUseBlock].
+ Input interface{} `json:"input"`
+ // This field is from variant [BetaToolUseBlock].
+ Name string `json:"name"`
+ // This field is from variant [BetaThinkingBlock].
+ Signature string `json:"signature"`
+ // This field is from variant [BetaThinkingBlock].
+ Thinking string `json:"thinking"`
+ // This field is from variant [BetaRedactedThinkingBlock].
+ Data string `json:"data"`
+ JSON struct {
+ Citations resp.Field
+ Text resp.Field
+ Type resp.Field
+ ID resp.Field
+ Input resp.Field
+ Name resp.Field
+ Signature resp.Field
+ Thinking resp.Field
+ Data resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := BetaRawContentBlockStartEventContentBlockUnion.AsAny().(type) {
+// case BetaTextBlock:
+// case BetaToolUseBlock:
+// case BetaThinkingBlock:
+// case BetaRedactedThinkingBlock:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u BetaRawContentBlockStartEventContentBlockUnion) AsAny() any {
+ switch u.Type {
+ case "text":
+ return u.AsResponseTextBlock()
+ case "tool_use":
+ return u.AsResponseToolUseBlock()
+ case "thinking":
+ return u.AsResponseThinkingBlock()
+ case "redacted_thinking":
+ return u.AsResponseRedactedThinkingBlock()
+ }
+ return nil
+}
+
+func (u BetaRawContentBlockStartEventContentBlockUnion) AsResponseTextBlock() (v BetaTextBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// Union satisfied by [BetaTextBlock], [BetaToolUseBlock], [BetaThinkingBlock] or
-// [BetaRedactedThinkingBlock].
-type BetaRawContentBlockStartEventContentBlockUnion interface {
- implementsBetaRawContentBlockStartEventContentBlock()
+func (u BetaRawContentBlockStartEventContentBlockUnion) AsResponseToolUseBlock() (v BetaToolUseBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*BetaRawContentBlockStartEventContentBlockUnion)(nil)).Elem(),
- "type",
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaTextBlock{}),
- DiscriminatorValue: "text",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaToolUseBlock{}),
- DiscriminatorValue: "tool_use",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaThinkingBlock{}),
- DiscriminatorValue: "thinking",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaRedactedThinkingBlock{}),
- DiscriminatorValue: "redacted_thinking",
- },
- )
+func (u BetaRawContentBlockStartEventContentBlockUnion) AsResponseThinkingBlock() (v BetaThinkingBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaRawContentBlockStartEventContentBlockType string
-
-const (
- BetaRawContentBlockStartEventContentBlockTypeText BetaRawContentBlockStartEventContentBlockType = "text"
- BetaRawContentBlockStartEventContentBlockTypeToolUse BetaRawContentBlockStartEventContentBlockType = "tool_use"
- BetaRawContentBlockStartEventContentBlockTypeThinking BetaRawContentBlockStartEventContentBlockType = "thinking"
- BetaRawContentBlockStartEventContentBlockTypeRedactedThinking BetaRawContentBlockStartEventContentBlockType = "redacted_thinking"
-)
-
-func (r BetaRawContentBlockStartEventContentBlockType) IsKnown() bool {
- switch r {
- case BetaRawContentBlockStartEventContentBlockTypeText, BetaRawContentBlockStartEventContentBlockTypeToolUse, BetaRawContentBlockStartEventContentBlockTypeThinking, BetaRawContentBlockStartEventContentBlockTypeRedactedThinking:
- return true
- }
- return false
+func (u BetaRawContentBlockStartEventContentBlockUnion) AsResponseRedactedThinkingBlock() (v BetaRedactedThinkingBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaRawContentBlockStartEventType string
+// Returns the unmodified JSON received from the API
+func (u BetaRawContentBlockStartEventContentBlockUnion) RawJSON() string { return u.JSON.raw }
-const (
- BetaRawContentBlockStartEventTypeContentBlockStart BetaRawContentBlockStartEventType = "content_block_start"
-)
-
-func (r BetaRawContentBlockStartEventType) IsKnown() bool {
- switch r {
- case BetaRawContentBlockStartEventTypeContentBlockStart:
- return true
- }
- return false
+func (r *BetaRawContentBlockStartEventContentBlockUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
type BetaRawContentBlockStopEvent struct {
- Index int64 `json:"index,required"`
- Type BetaRawContentBlockStopEventType `json:"type,required"`
- JSON betaRawContentBlockStopEventJSON `json:"-"`
-}
-
-// betaRawContentBlockStopEventJSON contains the JSON metadata for the struct
-// [BetaRawContentBlockStopEvent]
-type betaRawContentBlockStopEventJSON struct {
- Index apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaRawContentBlockStopEvent) UnmarshalJSON(data []byte) (err error) {
+ Index int64 `json:"index,required"`
+ Type constant.ContentBlockStop `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Index resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaRawContentBlockStopEvent) RawJSON() string { return r.JSON.raw }
+func (r *BetaRawContentBlockStopEvent) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaRawContentBlockStopEventJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaRawContentBlockStopEvent) implementsBetaRawMessageStreamEvent() {}
-
-type BetaRawContentBlockStopEventType string
-
-const (
- BetaRawContentBlockStopEventTypeContentBlockStop BetaRawContentBlockStopEventType = "content_block_stop"
-)
-
-func (r BetaRawContentBlockStopEventType) IsKnown() bool {
- switch r {
- case BetaRawContentBlockStopEventTypeContentBlockStop:
- return true
- }
- return false
-}
-
type BetaRawMessageDeltaEvent struct {
Delta BetaRawMessageDeltaEventDelta `json:"delta,required"`
- Type BetaRawMessageDeltaEventType `json:"type,required"`
+ Type constant.MessageDelta `json:"type,required"`
// Billing and rate-limit usage.
//
// Anthropic's API bills and rate-limits by token counts, as tokens represent the
@@ -1627,743 +1741,672 @@ type BetaRawMessageDeltaEvent struct {
//
// Total input tokens in a request is the summation of `input_tokens`,
// `cache_creation_input_tokens`, and `cache_read_input_tokens`.
- Usage BetaMessageDeltaUsage `json:"usage,required"`
- JSON betaRawMessageDeltaEventJSON `json:"-"`
+ Usage BetaMessageDeltaUsage `json:"usage,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Delta resp.Field
+ Type resp.Field
+ Usage resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaRawMessageDeltaEvent) RawJSON() string { return r.JSON.raw }
+func (r *BetaRawMessageDeltaEvent) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-// betaRawMessageDeltaEventJSON contains the JSON metadata for the struct
-// [BetaRawMessageDeltaEvent]
-type betaRawMessageDeltaEventJSON struct {
- Delta apijson.Field
- Type apijson.Field
- Usage apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+type BetaRawMessageDeltaEventDelta struct {
+ // Any of "end_turn", "max_tokens", "stop_sequence", "tool_use".
+ StopReason string `json:"stop_reason,required"`
+ StopSequence string `json:"stop_sequence,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ StopReason resp.Field
+ StopSequence resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaRawMessageDeltaEventDelta) RawJSON() string { return r.JSON.raw }
+func (r *BetaRawMessageDeltaEventDelta) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-func (r *BetaRawMessageDeltaEvent) UnmarshalJSON(data []byte) (err error) {
+type BetaRawMessageStartEvent struct {
+ Message BetaMessage `json:"message,required"`
+ Type constant.MessageStart `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaRawMessageStartEvent) RawJSON() string { return r.JSON.raw }
+func (r *BetaRawMessageStartEvent) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaRawMessageDeltaEventJSON) RawJSON() string {
- return r.raw
+type BetaRawMessageStopEvent struct {
+ Type constant.MessageStop `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaRawMessageStopEvent) RawJSON() string { return r.JSON.raw }
+func (r *BetaRawMessageStopEvent) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-func (r BetaRawMessageDeltaEvent) implementsBetaRawMessageStreamEvent() {}
-
-type BetaRawMessageDeltaEventDelta struct {
- StopReason BetaRawMessageDeltaEventDeltaStopReason `json:"stop_reason,required,nullable"`
- StopSequence string `json:"stop_sequence,required,nullable"`
- JSON betaRawMessageDeltaEventDeltaJSON `json:"-"`
+// BetaRawMessageStreamEventUnion contains all possible properties and values from
+// [BetaRawMessageStartEvent], [BetaRawMessageDeltaEvent],
+// [BetaRawMessageStopEvent], [BetaRawContentBlockStartEvent],
+// [BetaRawContentBlockDeltaEvent], [BetaRawContentBlockStopEvent].
+//
+// Use the [BetaRawMessageStreamEventUnion.AsAny] method to switch on the variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type BetaRawMessageStreamEventUnion struct {
+ // This field is from variant [BetaRawMessageStartEvent].
+ Message BetaMessage `json:"message"`
+ // Any of "message_start", "message_delta", "message_stop", "content_block_start",
+ // "content_block_delta", "content_block_stop".
+ Type string `json:"type"`
+ // This field is a union of [BetaRawMessageDeltaEventDelta],
+ // [BetaRawContentBlockDeltaEventDeltaUnion]
+ Delta BetaRawMessageStreamEventUnionDelta `json:"delta"`
+ // This field is from variant [BetaRawMessageDeltaEvent].
+ Usage BetaMessageDeltaUsage `json:"usage"`
+ // This field is from variant [BetaRawContentBlockStartEvent].
+ ContentBlock BetaRawContentBlockStartEventContentBlockUnion `json:"content_block"`
+ Index int64 `json:"index"`
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ Delta resp.Field
+ Usage resp.Field
+ ContentBlock resp.Field
+ Index resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := BetaRawMessageStreamEventUnion.AsAny().(type) {
+// case BetaRawMessageStartEvent:
+// case BetaRawMessageDeltaEvent:
+// case BetaRawMessageStopEvent:
+// case BetaRawContentBlockStartEvent:
+// case BetaRawContentBlockDeltaEvent:
+// case BetaRawContentBlockStopEvent:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u BetaRawMessageStreamEventUnion) AsAny() any {
+ switch u.Type {
+ case "message_start":
+ return u.AsMessageStartEvent()
+ case "message_delta":
+ return u.AsMessageDeltaEvent()
+ case "message_stop":
+ return u.AsMessageStopEvent()
+ case "content_block_start":
+ return u.AsContentBlockStartEvent()
+ case "content_block_delta":
+ return u.AsContentBlockDeltaEvent()
+ case "content_block_stop":
+ return u.AsContentBlockStopEvent()
+ }
+ return nil
+}
+
+func (u BetaRawMessageStreamEventUnion) AsMessageStartEvent() (v BetaRawMessageStartEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// betaRawMessageDeltaEventDeltaJSON contains the JSON metadata for the struct
-// [BetaRawMessageDeltaEventDelta]
-type betaRawMessageDeltaEventDeltaJSON struct {
- StopReason apijson.Field
- StopSequence apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func (u BetaRawMessageStreamEventUnion) AsMessageDeltaEvent() (v BetaRawMessageDeltaEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r *BetaRawMessageDeltaEventDelta) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+func (u BetaRawMessageStreamEventUnion) AsMessageStopEvent() (v BetaRawMessageStopEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r betaRawMessageDeltaEventDeltaJSON) RawJSON() string {
- return r.raw
+func (u BetaRawMessageStreamEventUnion) AsContentBlockStartEvent() (v BetaRawContentBlockStartEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaRawMessageDeltaEventDeltaStopReason string
-
-const (
- BetaRawMessageDeltaEventDeltaStopReasonEndTurn BetaRawMessageDeltaEventDeltaStopReason = "end_turn"
- BetaRawMessageDeltaEventDeltaStopReasonMaxTokens BetaRawMessageDeltaEventDeltaStopReason = "max_tokens"
- BetaRawMessageDeltaEventDeltaStopReasonStopSequence BetaRawMessageDeltaEventDeltaStopReason = "stop_sequence"
- BetaRawMessageDeltaEventDeltaStopReasonToolUse BetaRawMessageDeltaEventDeltaStopReason = "tool_use"
-)
-
-func (r BetaRawMessageDeltaEventDeltaStopReason) IsKnown() bool {
- switch r {
- case BetaRawMessageDeltaEventDeltaStopReasonEndTurn, BetaRawMessageDeltaEventDeltaStopReasonMaxTokens, BetaRawMessageDeltaEventDeltaStopReasonStopSequence, BetaRawMessageDeltaEventDeltaStopReasonToolUse:
- return true
- }
- return false
+func (u BetaRawMessageStreamEventUnion) AsContentBlockDeltaEvent() (v BetaRawContentBlockDeltaEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaRawMessageDeltaEventType string
-
-const (
- BetaRawMessageDeltaEventTypeMessageDelta BetaRawMessageDeltaEventType = "message_delta"
-)
-
-func (r BetaRawMessageDeltaEventType) IsKnown() bool {
- switch r {
- case BetaRawMessageDeltaEventTypeMessageDelta:
- return true
- }
- return false
+func (u BetaRawMessageStreamEventUnion) AsContentBlockStopEvent() (v BetaRawContentBlockStopEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaRawMessageStartEvent struct {
- Message BetaMessage `json:"message,required"`
- Type BetaRawMessageStartEventType `json:"type,required"`
- JSON betaRawMessageStartEventJSON `json:"-"`
-}
+// Returns the unmodified JSON received from the API
+func (u BetaRawMessageStreamEventUnion) RawJSON() string { return u.JSON.raw }
-// betaRawMessageStartEventJSON contains the JSON metadata for the struct
-// [BetaRawMessageStartEvent]
-type betaRawMessageStartEventJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func (r *BetaRawMessageStreamEventUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-func (r *BetaRawMessageStartEvent) UnmarshalJSON(data []byte) (err error) {
+// BetaRawMessageStreamEventUnionDelta is an implicit subunion of
+// [BetaRawMessageStreamEventUnion]. BetaRawMessageStreamEventUnionDelta provides
+// convenient access to the sub-properties of the union.
+//
+// For type safety it is recommended to directly use a variant of the
+// [BetaRawMessageStreamEventUnion].
+type BetaRawMessageStreamEventUnionDelta struct {
+ // This field is from variant [BetaRawMessageDeltaEventDelta].
+ StopReason string `json:"stop_reason"`
+ // This field is from variant [BetaRawMessageDeltaEventDelta].
+ StopSequence string `json:"stop_sequence"`
+ // This field is from variant [BetaRawContentBlockDeltaEventDeltaUnion].
+ Text string `json:"text"`
+ Type string `json:"type"`
+ // This field is from variant [BetaRawContentBlockDeltaEventDeltaUnion].
+ PartialJSON string `json:"partial_json"`
+ // This field is from variant [BetaRawContentBlockDeltaEventDeltaUnion].
+ Citation BetaCitationsDeltaCitationUnion `json:"citation"`
+ // This field is from variant [BetaRawContentBlockDeltaEventDeltaUnion].
+ Thinking string `json:"thinking"`
+ // This field is from variant [BetaRawContentBlockDeltaEventDeltaUnion].
+ Signature string `json:"signature"`
+ JSON struct {
+ StopReason resp.Field
+ StopSequence resp.Field
+ Text resp.Field
+ Type resp.Field
+ PartialJSON resp.Field
+ Citation resp.Field
+ Thinking resp.Field
+ Signature resp.Field
+ raw string
+ } `json:"-"`
+}
+
+func (r *BetaRawMessageStreamEventUnionDelta) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaRawMessageStartEventJSON) RawJSON() string {
- return r.raw
+type BetaRedactedThinkingBlock struct {
+ Data string `json:"data,required"`
+ Type constant.RedactedThinking `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Data resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaRedactedThinkingBlock) RawJSON() string { return r.JSON.raw }
+func (r *BetaRedactedThinkingBlock) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-func (r BetaRawMessageStartEvent) implementsBetaRawMessageStreamEvent() {}
-
-type BetaRawMessageStartEventType string
-
-const (
- BetaRawMessageStartEventTypeMessageStart BetaRawMessageStartEventType = "message_start"
-)
-
-func (r BetaRawMessageStartEventType) IsKnown() bool {
- switch r {
- case BetaRawMessageStartEventTypeMessageStart:
- return true
- }
- return false
+func (r BetaRedactedThinkingBlock) ToParam() BetaRedactedThinkingBlockParam {
+ var p BetaRedactedThinkingBlockParam
+ p.Type = r.Type
+ p.Data = r.Data
+ return p
}
-type BetaRawMessageStopEvent struct {
- Type BetaRawMessageStopEventType `json:"type,required"`
- JSON betaRawMessageStopEventJSON `json:"-"`
+// The properties Data, Type are required.
+type BetaRedactedThinkingBlockParam struct {
+ Data string `json:"data,required"`
+ // This field can be elided, and will marshal its zero value as
+ // "redacted_thinking".
+ Type constant.RedactedThinking `json:"type,required"`
+ paramObj
}
-// betaRawMessageStopEventJSON contains the JSON metadata for the struct
-// [BetaRawMessageStopEvent]
-type betaRawMessageStopEventJSON struct {
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaRedactedThinkingBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r BetaRedactedThinkingBlockParam) MarshalJSON() (data []byte, err error) {
+ type shadow BetaRedactedThinkingBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r *BetaRawMessageStopEvent) UnmarshalJSON(data []byte) (err error) {
+type BetaSignatureDelta struct {
+ Signature string `json:"signature,required"`
+ Type constant.SignatureDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Signature resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaSignatureDelta) RawJSON() string { return r.JSON.raw }
+func (r *BetaSignatureDelta) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaRawMessageStopEventJSON) RawJSON() string {
- return r.raw
+type BetaTextBlock struct {
+ // Citations supporting the text block.
+ //
+ // The type of citation returned will depend on the type of document being cited.
+ // Citing a PDF results in `page_location`, plain text results in `char_location`,
+ // and content document results in `content_block_location`.
+ Citations []BetaTextCitationUnion `json:"citations,required"`
+ Text string `json:"text,required"`
+ Type constant.Text `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Citations resp.Field
+ Text resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaTextBlock) RawJSON() string { return r.JSON.raw }
+func (r *BetaTextBlock) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-func (r BetaRawMessageStopEvent) implementsBetaRawMessageStreamEvent() {}
-
-type BetaRawMessageStopEventType string
-
-const (
- BetaRawMessageStopEventTypeMessageStop BetaRawMessageStopEventType = "message_stop"
-)
+func (r BetaTextBlock) ToParam() BetaTextBlockParam {
+ var p BetaTextBlockParam
+ p.Type = r.Type
+ p.Text = r.Text
+ p.Citations = make([]BetaTextCitationParamUnion, len(r.Citations))
+ for i, citation := range r.Citations {
+ switch citationVariant := citation.AsAny().(type) {
+ case BetaCitationCharLocation:
+ var citationParam BetaCitationCharLocationParam
+ citationParam.Type = citationVariant.Type
+ citationParam.DocumentTitle = toParam(citationVariant.DocumentTitle, citationVariant.JSON.DocumentTitle)
+ citationParam.CitedText = citationVariant.CitedText
+ citationParam.DocumentIndex = citationVariant.DocumentIndex
+ citationParam.EndCharIndex = citationVariant.EndCharIndex
+ citationParam.StartCharIndex = citationVariant.StartCharIndex
+ p.Citations[i] = BetaTextCitationParamUnion{OfRequestCharLocationCitation: &citationParam}
+ case BetaCitationPageLocation:
+ var citationParam BetaCitationPageLocationParam
+ citationParam.Type = citationVariant.Type
+ citationParam.DocumentTitle = toParam(citationVariant.DocumentTitle, citationVariant.JSON.DocumentTitle)
+ citationParam.DocumentIndex = citationVariant.DocumentIndex
+ citationParam.EndPageNumber = citationVariant.EndPageNumber
+ citationParam.StartPageNumber = citationVariant.StartPageNumber
+ p.Citations[i] = BetaTextCitationParamUnion{OfRequestPageLocationCitation: &citationParam}
+ case BetaCitationContentBlockLocation:
+ var citationParam BetaCitationContentBlockLocationParam
+ citationParam.Type = citationVariant.Type
+ citationParam.DocumentTitle = toParam(citationVariant.DocumentTitle, citationVariant.JSON.DocumentTitle)
+ citationParam.CitedText = citationVariant.CitedText
+ citationParam.DocumentIndex = citationVariant.DocumentIndex
+ citationParam.EndBlockIndex = citationVariant.EndBlockIndex
+ citationParam.StartBlockIndex = citationVariant.StartBlockIndex
+ p.Citations[i] = BetaTextCitationParamUnion{OfRequestContentBlockLocationCitation: &citationParam}
+ }
+ }
+ return p
+}
+
+// The properties Text, Type are required.
+type BetaTextBlockParam struct {
+ Text string `json:"text,required"`
+ Citations []BetaTextCitationParamUnion `json:"citations,omitzero"`
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
+ // This field can be elided, and will marshal its zero value as "text".
+ Type constant.Text `json:"type,required"`
+ paramObj
+}
-func (r BetaRawMessageStopEventType) IsKnown() bool {
- switch r {
- case BetaRawMessageStopEventTypeMessageStop:
- return true
- }
- return false
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaTextBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r BetaTextBlockParam) MarshalJSON() (data []byte, err error) {
+ type shadow BetaTextBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-type BetaRawMessageStreamEvent struct {
- Type BetaRawMessageStreamEventType `json:"type,required"`
- // This field can have the runtime type of
- // [BetaRawContentBlockStartEventContentBlock].
- ContentBlock interface{} `json:"content_block"`
- // This field can have the runtime type of [BetaRawMessageDeltaEventDelta],
- // [BetaRawContentBlockDeltaEventDelta].
- Delta interface{} `json:"delta"`
- Index int64 `json:"index"`
- Message BetaMessage `json:"message"`
- // Billing and rate-limit usage.
- //
- // Anthropic's API bills and rate-limits by token counts, as tokens represent the
- // underlying cost to our systems.
- //
- // Under the hood, the API transforms requests into a format suitable for the
- // model. The model's output then goes through a parsing stage before becoming an
- // API response. As a result, the token counts in `usage` will not match one-to-one
- // with the exact visible content of an API request or response.
- //
- // For example, `output_tokens` will be non-zero, even for an empty string response
- // from Claude.
- //
- // Total input tokens in a request is the summation of `input_tokens`,
- // `cache_creation_input_tokens`, and `cache_read_input_tokens`.
- Usage BetaMessageDeltaUsage `json:"usage"`
- JSON betaRawMessageStreamEventJSON `json:"-"`
- union BetaRawMessageStreamEventUnion
-}
-
-// betaRawMessageStreamEventJSON contains the JSON metadata for the struct
-// [BetaRawMessageStreamEvent]
-type betaRawMessageStreamEventJSON struct {
- Type apijson.Field
- ContentBlock apijson.Field
- Delta apijson.Field
- Index apijson.Field
- Message apijson.Field
- Usage apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r betaRawMessageStreamEventJSON) RawJSON() string {
- return r.raw
-}
-
-func (r *BetaRawMessageStreamEvent) UnmarshalJSON(data []byte) (err error) {
- *r = BetaRawMessageStreamEvent{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
- }
- return apijson.Port(r.union, &r)
-}
-
-// AsUnion returns a [BetaRawMessageStreamEventUnion] interface which you can cast
-// to the specific types for more type safety.
+// BetaTextCitationUnion contains all possible properties and values from
+// [BetaCitationCharLocation], [BetaCitationPageLocation],
+// [BetaCitationContentBlockLocation].
//
-// Possible runtime types of the union are [BetaRawMessageStartEvent],
-// [BetaRawMessageDeltaEvent], [BetaRawMessageStopEvent],
-// [BetaRawContentBlockStartEvent], [BetaRawContentBlockDeltaEvent],
-// [BetaRawContentBlockStopEvent].
-func (r BetaRawMessageStreamEvent) AsUnion() BetaRawMessageStreamEventUnion {
- return r.union
-}
-
-// Union satisfied by [BetaRawMessageStartEvent], [BetaRawMessageDeltaEvent],
-// [BetaRawMessageStopEvent], [BetaRawContentBlockStartEvent],
-// [BetaRawContentBlockDeltaEvent] or [BetaRawContentBlockStopEvent].
-type BetaRawMessageStreamEventUnion interface {
- implementsBetaRawMessageStreamEvent()
-}
-
-func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*BetaRawMessageStreamEventUnion)(nil)).Elem(),
- "type",
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaRawMessageStartEvent{}),
- DiscriminatorValue: "message_start",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaRawMessageDeltaEvent{}),
- DiscriminatorValue: "message_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaRawMessageStopEvent{}),
- DiscriminatorValue: "message_stop",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaRawContentBlockStartEvent{}),
- DiscriminatorValue: "content_block_start",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaRawContentBlockDeltaEvent{}),
- DiscriminatorValue: "content_block_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaRawContentBlockStopEvent{}),
- DiscriminatorValue: "content_block_stop",
- },
- )
+// Use the [BetaTextCitationUnion.AsAny] method to switch on the variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type BetaTextCitationUnion struct {
+ CitedText string `json:"cited_text"`
+ DocumentIndex int64 `json:"document_index"`
+ DocumentTitle string `json:"document_title"`
+ // This field is from variant [BetaCitationCharLocation].
+ EndCharIndex int64 `json:"end_char_index"`
+ // This field is from variant [BetaCitationCharLocation].
+ StartCharIndex int64 `json:"start_char_index"`
+ // Any of "char_location", "page_location", "content_block_location".
+ Type string `json:"type"`
+ // This field is from variant [BetaCitationPageLocation].
+ EndPageNumber int64 `json:"end_page_number"`
+ // This field is from variant [BetaCitationPageLocation].
+ StartPageNumber int64 `json:"start_page_number"`
+ // This field is from variant [BetaCitationContentBlockLocation].
+ EndBlockIndex int64 `json:"end_block_index"`
+ // This field is from variant [BetaCitationContentBlockLocation].
+ StartBlockIndex int64 `json:"start_block_index"`
+ JSON struct {
+ CitedText resp.Field
+ DocumentIndex resp.Field
+ DocumentTitle resp.Field
+ EndCharIndex resp.Field
+ StartCharIndex resp.Field
+ Type resp.Field
+ EndPageNumber resp.Field
+ StartPageNumber resp.Field
+ EndBlockIndex resp.Field
+ StartBlockIndex resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := BetaTextCitationUnion.AsAny().(type) {
+// case BetaCitationCharLocation:
+// case BetaCitationPageLocation:
+// case BetaCitationContentBlockLocation:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u BetaTextCitationUnion) AsAny() any {
+ switch u.Type {
+ case "char_location":
+ return u.AsResponseCharLocationCitation()
+ case "page_location":
+ return u.AsResponsePageLocationCitation()
+ case "content_block_location":
+ return u.AsResponseContentBlockLocationCitation()
+ }
+ return nil
+}
+
+func (u BetaTextCitationUnion) AsResponseCharLocationCitation() (v BetaCitationCharLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaRawMessageStreamEventType string
-
-const (
- BetaRawMessageStreamEventTypeMessageStart BetaRawMessageStreamEventType = "message_start"
- BetaRawMessageStreamEventTypeMessageDelta BetaRawMessageStreamEventType = "message_delta"
- BetaRawMessageStreamEventTypeMessageStop BetaRawMessageStreamEventType = "message_stop"
- BetaRawMessageStreamEventTypeContentBlockStart BetaRawMessageStreamEventType = "content_block_start"
- BetaRawMessageStreamEventTypeContentBlockDelta BetaRawMessageStreamEventType = "content_block_delta"
- BetaRawMessageStreamEventTypeContentBlockStop BetaRawMessageStreamEventType = "content_block_stop"
-)
-
-func (r BetaRawMessageStreamEventType) IsKnown() bool {
- switch r {
- case BetaRawMessageStreamEventTypeMessageStart, BetaRawMessageStreamEventTypeMessageDelta, BetaRawMessageStreamEventTypeMessageStop, BetaRawMessageStreamEventTypeContentBlockStart, BetaRawMessageStreamEventTypeContentBlockDelta, BetaRawMessageStreamEventTypeContentBlockStop:
- return true
- }
- return false
+func (u BetaTextCitationUnion) AsResponsePageLocationCitation() (v BetaCitationPageLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type BetaRedactedThinkingBlock struct {
- Data string `json:"data,required"`
- Type BetaRedactedThinkingBlockType `json:"type,required"`
- JSON betaRedactedThinkingBlockJSON `json:"-"`
+func (u BetaTextCitationUnion) AsResponseContentBlockLocationCitation() (v BetaCitationContentBlockLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// betaRedactedThinkingBlockJSON contains the JSON metadata for the struct
-// [BetaRedactedThinkingBlock]
-type betaRedactedThinkingBlockJSON struct {
- Data apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
+// Returns the unmodified JSON received from the API
+func (u BetaTextCitationUnion) RawJSON() string { return u.JSON.raw }
-func (r *BetaRedactedThinkingBlock) UnmarshalJSON(data []byte) (err error) {
+func (r *BetaTextCitationUnion) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaRedactedThinkingBlockJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaRedactedThinkingBlock) implementsBetaContentBlock() {}
-
-func (r BetaRedactedThinkingBlock) implementsBetaRawContentBlockStartEventContentBlock() {}
-
-type BetaRedactedThinkingBlockType string
-
-const (
- BetaRedactedThinkingBlockTypeRedactedThinking BetaRedactedThinkingBlockType = "redacted_thinking"
-)
-
-func (r BetaRedactedThinkingBlockType) IsKnown() bool {
- switch r {
- case BetaRedactedThinkingBlockTypeRedactedThinking:
- return true
- }
- return false
-}
-
-type BetaRedactedThinkingBlockParam struct {
- Data param.Field[string] `json:"data,required"`
- Type param.Field[BetaRedactedThinkingBlockParamType] `json:"type,required"`
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaTextCitationParamUnion struct {
+ OfRequestCharLocationCitation *BetaCitationCharLocationParam `json:",omitzero,inline"`
+ OfRequestPageLocationCitation *BetaCitationPageLocationParam `json:",omitzero,inline"`
+ OfRequestContentBlockLocationCitation *BetaCitationContentBlockLocationParam `json:",omitzero,inline"`
+ paramUnion
}
-func (r BetaRedactedThinkingBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaTextCitationParamUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u BetaTextCitationParamUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaTextCitationParamUnion](u.OfRequestCharLocationCitation, u.OfRequestPageLocationCitation, u.OfRequestContentBlockLocationCitation)
}
-func (r BetaRedactedThinkingBlockParam) implementsBetaContentBlockParamUnion() {}
-
-type BetaRedactedThinkingBlockParamType string
-
-const (
- BetaRedactedThinkingBlockParamTypeRedactedThinking BetaRedactedThinkingBlockParamType = "redacted_thinking"
-)
-
-func (r BetaRedactedThinkingBlockParamType) IsKnown() bool {
- switch r {
- case BetaRedactedThinkingBlockParamTypeRedactedThinking:
- return true
+func (u *BetaTextCitationParamUnion) asAny() any {
+ if !param.IsOmitted(u.OfRequestCharLocationCitation) {
+ return u.OfRequestCharLocationCitation
+ } else if !param.IsOmitted(u.OfRequestPageLocationCitation) {
+ return u.OfRequestPageLocationCitation
+ } else if !param.IsOmitted(u.OfRequestContentBlockLocationCitation) {
+ return u.OfRequestContentBlockLocationCitation
}
- return false
-}
-
-type BetaSignatureDelta struct {
- Signature string `json:"signature,required"`
- Type BetaSignatureDeltaType `json:"type,required"`
- JSON betaSignatureDeltaJSON `json:"-"`
+ return nil
}
-// betaSignatureDeltaJSON contains the JSON metadata for the struct
-// [BetaSignatureDelta]
-type betaSignatureDeltaJSON struct {
- Signature apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaSignatureDelta) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
-}
-
-func (r betaSignatureDeltaJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaSignatureDelta) implementsBetaRawContentBlockDeltaEventDelta() {}
-
-type BetaSignatureDeltaType string
-
-const (
- BetaSignatureDeltaTypeSignatureDelta BetaSignatureDeltaType = "signature_delta"
-)
-
-func (r BetaSignatureDeltaType) IsKnown() bool {
- switch r {
- case BetaSignatureDeltaTypeSignatureDelta:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaTextCitationParamUnion) GetEndCharIndex() *int64 {
+ if vt := u.OfRequestCharLocationCitation; vt != nil {
+ return &vt.EndCharIndex
}
- return false
+ return nil
}
-type BetaTextBlock struct {
- // Citations supporting the text block.
- //
- // The type of citation returned will depend on the type of document being cited.
- // Citing a PDF results in `page_location`, plain text results in `char_location`,
- // and content document results in `content_block_location`.
- Citations []BetaTextCitation `json:"citations,required,nullable"`
- Text string `json:"text,required"`
- Type BetaTextBlockType `json:"type,required"`
- JSON betaTextBlockJSON `json:"-"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaTextCitationParamUnion) GetStartCharIndex() *int64 {
+ if vt := u.OfRequestCharLocationCitation; vt != nil {
+ return &vt.StartCharIndex
+ }
+ return nil
}
-// betaTextBlockJSON contains the JSON metadata for the struct [BetaTextBlock]
-type betaTextBlockJSON struct {
- Citations apijson.Field
- Text apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaTextCitationParamUnion) GetEndPageNumber() *int64 {
+ if vt := u.OfRequestPageLocationCitation; vt != nil {
+ return &vt.EndPageNumber
+ }
+ return nil
}
-func (r *BetaTextBlock) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaTextCitationParamUnion) GetStartPageNumber() *int64 {
+ if vt := u.OfRequestPageLocationCitation; vt != nil {
+ return &vt.StartPageNumber
+ }
+ return nil
}
-func (r betaTextBlockJSON) RawJSON() string {
- return r.raw
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaTextCitationParamUnion) GetEndBlockIndex() *int64 {
+ if vt := u.OfRequestContentBlockLocationCitation; vt != nil {
+ return &vt.EndBlockIndex
+ }
+ return nil
}
-func (r BetaTextBlock) implementsBetaContentBlock() {}
-
-func (r BetaTextBlock) implementsBetaRawContentBlockStartEventContentBlock() {}
-
-type BetaTextBlockType string
-
-const (
- BetaTextBlockTypeText BetaTextBlockType = "text"
-)
-
-func (r BetaTextBlockType) IsKnown() bool {
- switch r {
- case BetaTextBlockTypeText:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaTextCitationParamUnion) GetStartBlockIndex() *int64 {
+ if vt := u.OfRequestContentBlockLocationCitation; vt != nil {
+ return &vt.StartBlockIndex
}
- return false
+ return nil
}
-type BetaTextBlockParam struct {
- Text param.Field[string] `json:"text,required"`
- Type param.Field[BetaTextBlockParamType] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
- Citations param.Field[[]BetaTextCitationParamUnion] `json:"citations"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaTextCitationParamUnion) GetCitedText() *string {
+ if vt := u.OfRequestCharLocationCitation; vt != nil {
+ return (*string)(&vt.CitedText)
+ } else if vt := u.OfRequestPageLocationCitation; vt != nil {
+ return (*string)(&vt.CitedText)
+ } else if vt := u.OfRequestContentBlockLocationCitation; vt != nil {
+ return (*string)(&vt.CitedText)
+ }
+ return nil
}
-func (r BetaTextBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaTextCitationParamUnion) GetDocumentIndex() *int64 {
+ if vt := u.OfRequestCharLocationCitation; vt != nil {
+ return (*int64)(&vt.DocumentIndex)
+ } else if vt := u.OfRequestPageLocationCitation; vt != nil {
+ return (*int64)(&vt.DocumentIndex)
+ } else if vt := u.OfRequestContentBlockLocationCitation; vt != nil {
+ return (*int64)(&vt.DocumentIndex)
+ }
+ return nil
}
-func (r BetaTextBlockParam) implementsBetaContentBlockParamUnion() {}
-
-func (r BetaTextBlockParam) implementsBetaContentBlockSourceContentUnionParam() {}
-
-func (r BetaTextBlockParam) implementsBetaToolResultBlockParamContentUnion() {}
-
-type BetaTextBlockParamType string
-
-const (
- BetaTextBlockParamTypeText BetaTextBlockParamType = "text"
-)
-
-func (r BetaTextBlockParamType) IsKnown() bool {
- switch r {
- case BetaTextBlockParamTypeText:
- return true
- }
- return false
-}
-
-type BetaTextCitation struct {
- CitedText string `json:"cited_text,required"`
- DocumentIndex int64 `json:"document_index,required"`
- DocumentTitle string `json:"document_title,required,nullable"`
- Type BetaTextCitationType `json:"type,required"`
- EndBlockIndex int64 `json:"end_block_index"`
- EndCharIndex int64 `json:"end_char_index"`
- EndPageNumber int64 `json:"end_page_number"`
- StartBlockIndex int64 `json:"start_block_index"`
- StartCharIndex int64 `json:"start_char_index"`
- StartPageNumber int64 `json:"start_page_number"`
- JSON betaTextCitationJSON `json:"-"`
- union BetaTextCitationUnion
-}
-
-// betaTextCitationJSON contains the JSON metadata for the struct
-// [BetaTextCitation]
-type betaTextCitationJSON struct {
- CitedText apijson.Field
- DocumentIndex apijson.Field
- DocumentTitle apijson.Field
- Type apijson.Field
- EndBlockIndex apijson.Field
- EndCharIndex apijson.Field
- EndPageNumber apijson.Field
- StartBlockIndex apijson.Field
- StartCharIndex apijson.Field
- StartPageNumber apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r betaTextCitationJSON) RawJSON() string {
- return r.raw
-}
-
-func (r *BetaTextCitation) UnmarshalJSON(data []byte) (err error) {
- *r = BetaTextCitation{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
- }
- return apijson.Port(r.union, &r)
-}
-
-// AsUnion returns a [BetaTextCitationUnion] interface which you can cast to the
-// specific types for more type safety.
-//
-// Possible runtime types of the union are [BetaCitationCharLocation],
-// [BetaCitationPageLocation], [BetaCitationContentBlockLocation].
-func (r BetaTextCitation) AsUnion() BetaTextCitationUnion {
- return r.union
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaTextCitationParamUnion) GetDocumentTitle() *string {
+ if vt := u.OfRequestCharLocationCitation; vt != nil && vt.DocumentTitle.IsPresent() {
+ return &vt.DocumentTitle.Value
+ } else if vt := u.OfRequestPageLocationCitation; vt != nil && vt.DocumentTitle.IsPresent() {
+ return &vt.DocumentTitle.Value
+ } else if vt := u.OfRequestContentBlockLocationCitation; vt != nil && vt.DocumentTitle.IsPresent() {
+ return &vt.DocumentTitle.Value
+ }
+ return nil
}
-// Union satisfied by [BetaCitationCharLocation], [BetaCitationPageLocation] or
-// [BetaCitationContentBlockLocation].
-type BetaTextCitationUnion interface {
- implementsBetaTextCitation()
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaTextCitationParamUnion) GetType() *string {
+ if vt := u.OfRequestCharLocationCitation; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestPageLocationCitation; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestContentBlockLocationCitation; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
}
func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*BetaTextCitationUnion)(nil)).Elem(),
+ apijson.RegisterUnion[BetaTextCitationParamUnion](
"type",
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaCitationCharLocation{}),
+ Type: reflect.TypeOf(BetaCitationCharLocationParam{}),
DiscriminatorValue: "char_location",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaCitationPageLocation{}),
+ Type: reflect.TypeOf(BetaCitationPageLocationParam{}),
DiscriminatorValue: "page_location",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaCitationContentBlockLocation{}),
+ Type: reflect.TypeOf(BetaCitationContentBlockLocationParam{}),
DiscriminatorValue: "content_block_location",
},
)
}
-type BetaTextCitationType string
-
-const (
- BetaTextCitationTypeCharLocation BetaTextCitationType = "char_location"
- BetaTextCitationTypePageLocation BetaTextCitationType = "page_location"
- BetaTextCitationTypeContentBlockLocation BetaTextCitationType = "content_block_location"
-)
-
-func (r BetaTextCitationType) IsKnown() bool {
- switch r {
- case BetaTextCitationTypeCharLocation, BetaTextCitationTypePageLocation, BetaTextCitationTypeContentBlockLocation:
- return true
- }
- return false
-}
-
-type BetaTextCitationParam struct {
- CitedText param.Field[string] `json:"cited_text,required"`
- DocumentIndex param.Field[int64] `json:"document_index,required"`
- DocumentTitle param.Field[string] `json:"document_title,required"`
- Type param.Field[BetaTextCitationParamType] `json:"type,required"`
- EndBlockIndex param.Field[int64] `json:"end_block_index"`
- EndCharIndex param.Field[int64] `json:"end_char_index"`
- EndPageNumber param.Field[int64] `json:"end_page_number"`
- StartBlockIndex param.Field[int64] `json:"start_block_index"`
- StartCharIndex param.Field[int64] `json:"start_char_index"`
- StartPageNumber param.Field[int64] `json:"start_page_number"`
-}
-
-func (r BetaTextCitationParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaTextCitationParam) implementsBetaTextCitationParamUnion() {}
-
-// Satisfied by [BetaCitationCharLocationParam], [BetaCitationPageLocationParam],
-// [BetaCitationContentBlockLocationParam], [BetaTextCitationParam].
-type BetaTextCitationParamUnion interface {
- implementsBetaTextCitationParamUnion()
-}
-
-type BetaTextCitationParamType string
-
-const (
- BetaTextCitationParamTypeCharLocation BetaTextCitationParamType = "char_location"
- BetaTextCitationParamTypePageLocation BetaTextCitationParamType = "page_location"
- BetaTextCitationParamTypeContentBlockLocation BetaTextCitationParamType = "content_block_location"
-)
-
-func (r BetaTextCitationParamType) IsKnown() bool {
- switch r {
- case BetaTextCitationParamTypeCharLocation, BetaTextCitationParamTypePageLocation, BetaTextCitationParamTypeContentBlockLocation:
- return true
- }
- return false
-}
-
type BetaTextDelta struct {
- Text string `json:"text,required"`
- Type BetaTextDeltaType `json:"type,required"`
- JSON betaTextDeltaJSON `json:"-"`
-}
-
-// betaTextDeltaJSON contains the JSON metadata for the struct [BetaTextDelta]
-type betaTextDeltaJSON struct {
- Text apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaTextDelta) UnmarshalJSON(data []byte) (err error) {
+ Text string `json:"text,required"`
+ Type constant.TextDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Text resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaTextDelta) RawJSON() string { return r.JSON.raw }
+func (r *BetaTextDelta) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaTextDeltaJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaTextDelta) implementsBetaRawContentBlockDeltaEventDelta() {}
-
-type BetaTextDeltaType string
-
-const (
- BetaTextDeltaTypeTextDelta BetaTextDeltaType = "text_delta"
-)
-
-func (r BetaTextDeltaType) IsKnown() bool {
- switch r {
- case BetaTextDeltaTypeTextDelta:
- return true
- }
- return false
-}
-
type BetaThinkingBlock struct {
- Signature string `json:"signature,required"`
- Thinking string `json:"thinking,required"`
- Type BetaThinkingBlockType `json:"type,required"`
- JSON betaThinkingBlockJSON `json:"-"`
-}
-
-// betaThinkingBlockJSON contains the JSON metadata for the struct
-// [BetaThinkingBlock]
-type betaThinkingBlockJSON struct {
- Signature apijson.Field
- Thinking apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaThinkingBlock) UnmarshalJSON(data []byte) (err error) {
+ Signature string `json:"signature,required"`
+ Thinking string `json:"thinking,required"`
+ Type constant.Thinking `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Signature resp.Field
+ Thinking resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaThinkingBlock) RawJSON() string { return r.JSON.raw }
+func (r *BetaThinkingBlock) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaThinkingBlockJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaThinkingBlock) implementsBetaContentBlock() {}
-
-func (r BetaThinkingBlock) implementsBetaRawContentBlockStartEventContentBlock() {}
-
-type BetaThinkingBlockType string
-
-const (
- BetaThinkingBlockTypeThinking BetaThinkingBlockType = "thinking"
-)
-
-func (r BetaThinkingBlockType) IsKnown() bool {
- switch r {
- case BetaThinkingBlockTypeThinking:
- return true
- }
- return false
+func (r BetaThinkingBlock) ToParam() BetaThinkingBlockParam {
+ var p BetaThinkingBlockParam
+ p.Type = r.Type
+ p.Signature = r.Signature
+ p.Thinking = r.Thinking
+ return p
}
+// The properties Signature, Thinking, Type are required.
type BetaThinkingBlockParam struct {
- Signature param.Field[string] `json:"signature,required"`
- Thinking param.Field[string] `json:"thinking,required"`
- Type param.Field[BetaThinkingBlockParamType] `json:"type,required"`
+ Signature string `json:"signature,required"`
+ Thinking string `json:"thinking,required"`
+ // This field can be elided, and will marshal its zero value as "thinking".
+ Type constant.Thinking `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaThinkingBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaThinkingBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaThinkingBlockParam) implementsBetaContentBlockParamUnion() {}
-
-type BetaThinkingBlockParamType string
-
-const (
- BetaThinkingBlockParamTypeThinking BetaThinkingBlockParamType = "thinking"
-)
-
-func (r BetaThinkingBlockParamType) IsKnown() bool {
- switch r {
- case BetaThinkingBlockParamTypeThinking:
- return true
- }
- return false
+ type shadow BetaThinkingBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The property Type is required.
type BetaThinkingConfigDisabledParam struct {
- Type param.Field[BetaThinkingConfigDisabledType] `json:"type,required"`
+ // This field can be elided, and will marshal its zero value as "disabled".
+ Type constant.Disabled `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaThinkingConfigDisabledParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaThinkingConfigDisabledParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaThinkingConfigDisabledParam) implementsBetaThinkingConfigParamUnion() {}
-
-type BetaThinkingConfigDisabledType string
-
-const (
- BetaThinkingConfigDisabledTypeDisabled BetaThinkingConfigDisabledType = "disabled"
-)
-
-func (r BetaThinkingConfigDisabledType) IsKnown() bool {
- switch r {
- case BetaThinkingConfigDisabledTypeDisabled:
- return true
- }
- return false
+ type shadow BetaThinkingConfigDisabledParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties BudgetTokens, Type are required.
type BetaThinkingConfigEnabledParam struct {
// Determines how many tokens Claude can use for its internal reasoning process.
// Larger budgets can enable more thorough analysis for complex problems, improving
@@ -2374,184 +2417,156 @@ type BetaThinkingConfigEnabledParam struct {
// See
// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
// for details.
- BudgetTokens param.Field[int64] `json:"budget_tokens,required"`
- Type param.Field[BetaThinkingConfigEnabledType] `json:"type,required"`
+ BudgetTokens int64 `json:"budget_tokens,required"`
+ // This field can be elided, and will marshal its zero value as "enabled".
+ Type constant.Enabled `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaThinkingConfigEnabledParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaThinkingConfigEnabledParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaThinkingConfigEnabledParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r BetaThinkingConfigEnabledParam) implementsBetaThinkingConfigParamUnion() {}
-
-type BetaThinkingConfigEnabledType string
-
-const (
- BetaThinkingConfigEnabledTypeEnabled BetaThinkingConfigEnabledType = "enabled"
-)
-
-func (r BetaThinkingConfigEnabledType) IsKnown() bool {
- switch r {
- case BetaThinkingConfigEnabledTypeEnabled:
- return true
- }
- return false
+func BetaThinkingConfigParamOfThinkingConfigEnabled(budgetTokens int64) BetaThinkingConfigParamUnion {
+ var variant BetaThinkingConfigEnabledParam
+ variant.BudgetTokens = budgetTokens
+ return BetaThinkingConfigParamUnion{OfThinkingConfigEnabled: &variant}
}
-// Configuration for enabling Claude's extended thinking.
+// Only one field can be non-zero.
//
-// When enabled, responses include `thinking` content blocks showing Claude's
-// thinking process before the final answer. Requires a minimum budget of 1,024
-// tokens and counts towards your `max_tokens` limit.
-//
-// See
-// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
-// for details.
-type BetaThinkingConfigParam struct {
- Type param.Field[BetaThinkingConfigParamType] `json:"type,required"`
- // Determines how many tokens Claude can use for its internal reasoning process.
- // Larger budgets can enable more thorough analysis for complex problems, improving
- // response quality.
- //
- // Must be ≥1024 and less than `max_tokens`.
- //
- // See
- // [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
- // for details.
- BudgetTokens param.Field[int64] `json:"budget_tokens"`
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaThinkingConfigParamUnion struct {
+ OfThinkingConfigEnabled *BetaThinkingConfigEnabledParam `json:",omitzero,inline"`
+ OfThinkingConfigDisabled *BetaThinkingConfigDisabledParam `json:",omitzero,inline"`
+ paramUnion
}
-func (r BetaThinkingConfigParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaThinkingConfigParamUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u BetaThinkingConfigParamUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaThinkingConfigParamUnion](u.OfThinkingConfigEnabled, u.OfThinkingConfigDisabled)
}
-func (r BetaThinkingConfigParam) implementsBetaThinkingConfigParamUnion() {}
-
-// Configuration for enabling Claude's extended thinking.
-//
-// When enabled, responses include `thinking` content blocks showing Claude's
-// thinking process before the final answer. Requires a minimum budget of 1,024
-// tokens and counts towards your `max_tokens` limit.
-//
-// See
-// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
-// for details.
-//
-// Satisfied by [BetaThinkingConfigEnabledParam],
-// [BetaThinkingConfigDisabledParam], [BetaThinkingConfigParam].
-type BetaThinkingConfigParamUnion interface {
- implementsBetaThinkingConfigParamUnion()
+func (u *BetaThinkingConfigParamUnion) asAny() any {
+ if !param.IsOmitted(u.OfThinkingConfigEnabled) {
+ return u.OfThinkingConfigEnabled
+ } else if !param.IsOmitted(u.OfThinkingConfigDisabled) {
+ return u.OfThinkingConfigDisabled
+ }
+ return nil
}
-type BetaThinkingConfigParamType string
-
-const (
- BetaThinkingConfigParamTypeEnabled BetaThinkingConfigParamType = "enabled"
- BetaThinkingConfigParamTypeDisabled BetaThinkingConfigParamType = "disabled"
-)
-
-func (r BetaThinkingConfigParamType) IsKnown() bool {
- switch r {
- case BetaThinkingConfigParamTypeEnabled, BetaThinkingConfigParamTypeDisabled:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaThinkingConfigParamUnion) GetBudgetTokens() *int64 {
+ if vt := u.OfThinkingConfigEnabled; vt != nil {
+ return &vt.BudgetTokens
}
- return false
+ return nil
}
-type BetaThinkingDelta struct {
- Thinking string `json:"thinking,required"`
- Type BetaThinkingDeltaType `json:"type,required"`
- JSON betaThinkingDeltaJSON `json:"-"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaThinkingConfigParamUnion) GetType() *string {
+ if vt := u.OfThinkingConfigEnabled; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfThinkingConfigDisabled; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
}
-// betaThinkingDeltaJSON contains the JSON metadata for the struct
-// [BetaThinkingDelta]
-type betaThinkingDeltaJSON struct {
- Thinking apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func init() {
+ apijson.RegisterUnion[BetaThinkingConfigParamUnion](
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaThinkingConfigEnabledParam{}),
+ DiscriminatorValue: "enabled",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaThinkingConfigDisabledParam{}),
+ DiscriminatorValue: "disabled",
+ },
+ )
}
-func (r *BetaThinkingDelta) UnmarshalJSON(data []byte) (err error) {
+type BetaThinkingDelta struct {
+ Thinking string `json:"thinking,required"`
+ Type constant.ThinkingDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Thinking resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaThinkingDelta) RawJSON() string { return r.JSON.raw }
+func (r *BetaThinkingDelta) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaThinkingDeltaJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaThinkingDelta) implementsBetaRawContentBlockDeltaEventDelta() {}
-
-type BetaThinkingDeltaType string
-
-const (
- BetaThinkingDeltaTypeThinkingDelta BetaThinkingDeltaType = "thinking_delta"
-)
-
-func (r BetaThinkingDeltaType) IsKnown() bool {
- switch r {
- case BetaThinkingDeltaTypeThinkingDelta:
- return true
- }
- return false
-}
-
+// The properties InputSchema, Name are required.
type BetaToolParam struct {
// [JSON schema](https://json-schema.org/draft/2020-12) for this tool's input.
//
// This defines the shape of the `input` that your tool accepts and that the model
// will produce.
- InputSchema param.Field[BetaToolInputSchemaParam] `json:"input_schema,required"`
+ InputSchema BetaToolInputSchemaParam `json:"input_schema,omitzero,required"`
// Name of the tool.
//
// This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[string] `json:"name,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
+ Name string `json:"name,required"`
// Description of what this tool does.
//
// Tool descriptions should be as detailed as possible. The more information that
// the model has about what the tool is and how to use it, the better it will
// perform. You can use natural language descriptions to reinforce important
// aspects of the tool input JSON schema.
- Description param.Field[string] `json:"description"`
- Type param.Field[BetaToolType] `json:"type"`
+ Description param.Opt[string] `json:"description,omitzero"`
+ // Any of "custom".
+ Type BetaToolType `json:"type,omitzero"`
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaToolParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r BetaToolParam) implementsBetaToolUnionUnionParam() {}
-
-func (r BetaToolParam) implementsBetaMessageCountTokensParamsToolUnion() {}
-
// [JSON schema](https://json-schema.org/draft/2020-12) for this tool's input.
//
// This defines the shape of the `input` that your tool accepts and that the model
// will produce.
+//
+// The property Type is required.
type BetaToolInputSchemaParam struct {
- Type param.Field[BetaToolInputSchemaType] `json:"type,required"`
- Properties param.Field[interface{}] `json:"properties"`
- ExtraFields map[string]interface{} `json:"-,extras"`
+ Properties interface{} `json:"properties,omitzero"`
+ // This field can be elided, and will marshal its zero value as "object".
+ Type constant.Object `json:"type,required"`
+ ExtraFields map[string]interface{} `json:"-,extras"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolInputSchemaParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolInputSchemaParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-type BetaToolInputSchemaType string
-
-const (
- BetaToolInputSchemaTypeObject BetaToolInputSchemaType = "object"
-)
-
-func (r BetaToolInputSchemaType) IsKnown() bool {
- switch r {
- case BetaToolInputSchemaTypeObject:
- return true
- }
- return false
+ type shadow BetaToolInputSchemaParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
type BetaToolType string
@@ -2560,749 +2575,727 @@ const (
BetaToolTypeCustom BetaToolType = "custom"
)
-func (r BetaToolType) IsKnown() bool {
- switch r {
- case BetaToolTypeCustom:
- return true
- }
- return false
-}
-
+// The properties Name, Type are required.
type BetaToolBash20241022Param struct {
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
// Name of the tool.
//
// This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[BetaToolBash20241022Name] `json:"name,required"`
- Type param.Field[BetaToolBash20241022Type] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
+ //
+ // This field can be elided, and will marshal its zero value as "bash".
+ Name constant.Bash `json:"name,required"`
+ // This field can be elided, and will marshal its zero value as "bash_20241022".
+ Type constant.Bash20241022 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolBash20241022Param) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolBash20241022Param) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaToolBash20241022Param) implementsBetaToolUnionUnionParam() {}
-
-func (r BetaToolBash20241022Param) implementsBetaMessageCountTokensParamsToolUnion() {}
-
-// Name of the tool.
-//
-// This is how the tool will be called by the model and in tool_use blocks.
-type BetaToolBash20241022Name string
-
-const (
- BetaToolBash20241022NameBash BetaToolBash20241022Name = "bash"
-)
-
-func (r BetaToolBash20241022Name) IsKnown() bool {
- switch r {
- case BetaToolBash20241022NameBash:
- return true
- }
- return false
-}
-
-type BetaToolBash20241022Type string
-
-const (
- BetaToolBash20241022TypeBash20241022 BetaToolBash20241022Type = "bash_20241022"
-)
-
-func (r BetaToolBash20241022Type) IsKnown() bool {
- switch r {
- case BetaToolBash20241022TypeBash20241022:
- return true
- }
- return false
+ type shadow BetaToolBash20241022Param
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties Name, Type are required.
type BetaToolBash20250124Param struct {
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
// Name of the tool.
//
// This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[BetaToolBash20250124Name] `json:"name,required"`
- Type param.Field[BetaToolBash20250124Type] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
+ //
+ // This field can be elided, and will marshal its zero value as "bash".
+ Name constant.Bash `json:"name,required"`
+ // This field can be elided, and will marshal its zero value as "bash_20250124".
+ Type constant.Bash20250124 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolBash20250124Param) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolBash20250124Param) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaToolBash20250124Param
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r BetaToolBash20250124Param) implementsBetaToolUnionUnionParam() {}
-
-func (r BetaToolBash20250124Param) implementsBetaMessageCountTokensParamsToolUnion() {}
+func BetaToolChoiceParamOfToolChoiceTool(name string) BetaToolChoiceUnionParam {
+ var variant BetaToolChoiceToolParam
+ variant.Name = name
+ return BetaToolChoiceUnionParam{OfToolChoiceTool: &variant}
+}
-// Name of the tool.
+// Only one field can be non-zero.
//
-// This is how the tool will be called by the model and in tool_use blocks.
-type BetaToolBash20250124Name string
-
-const (
- BetaToolBash20250124NameBash BetaToolBash20250124Name = "bash"
-)
-
-func (r BetaToolBash20250124Name) IsKnown() bool {
- switch r {
- case BetaToolBash20250124NameBash:
- return true
- }
- return false
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaToolChoiceUnionParam struct {
+ OfToolChoiceAuto *BetaToolChoiceAutoParam `json:",omitzero,inline"`
+ OfToolChoiceAny *BetaToolChoiceAnyParam `json:",omitzero,inline"`
+ OfToolChoiceTool *BetaToolChoiceToolParam `json:",omitzero,inline"`
+ OfToolChoiceNone *BetaToolChoiceNoneParam `json:",omitzero,inline"`
+ paramUnion
}
-type BetaToolBash20250124Type string
-
-const (
- BetaToolBash20250124TypeBash20250124 BetaToolBash20250124Type = "bash_20250124"
-)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaToolChoiceUnionParam) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u BetaToolChoiceUnionParam) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaToolChoiceUnionParam](u.OfToolChoiceAuto, u.OfToolChoiceAny, u.OfToolChoiceTool, u.OfToolChoiceNone)
+}
-func (r BetaToolBash20250124Type) IsKnown() bool {
- switch r {
- case BetaToolBash20250124TypeBash20250124:
- return true
+func (u *BetaToolChoiceUnionParam) asAny() any {
+ if !param.IsOmitted(u.OfToolChoiceAuto) {
+ return u.OfToolChoiceAuto
+ } else if !param.IsOmitted(u.OfToolChoiceAny) {
+ return u.OfToolChoiceAny
+ } else if !param.IsOmitted(u.OfToolChoiceTool) {
+ return u.OfToolChoiceTool
+ } else if !param.IsOmitted(u.OfToolChoiceNone) {
+ return u.OfToolChoiceNone
}
- return false
+ return nil
}
-// How the model should use the provided tools. The model can use a specific tool,
-// any available tool, decide by itself, or not use tools at all.
-type BetaToolChoiceParam struct {
- Type param.Field[BetaToolChoiceType] `json:"type,required"`
- // Whether to disable parallel tool use.
- //
- // Defaults to `false`. If set to `true`, the model will output at most one tool
- // use.
- DisableParallelToolUse param.Field[bool] `json:"disable_parallel_tool_use"`
- // The name of the tool to use.
- Name param.Field[string] `json:"name"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolChoiceUnionParam) GetName() *string {
+ if vt := u.OfToolChoiceTool; vt != nil {
+ return &vt.Name
+ }
+ return nil
}
-func (r BetaToolChoiceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolChoiceUnionParam) GetType() *string {
+ if vt := u.OfToolChoiceAuto; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfToolChoiceAny; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfToolChoiceTool; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfToolChoiceNone; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
}
-func (r BetaToolChoiceParam) implementsBetaToolChoiceUnionParam() {}
-
-// How the model should use the provided tools. The model can use a specific tool,
-// any available tool, decide by itself, or not use tools at all.
-//
-// Satisfied by [BetaToolChoiceAutoParam], [BetaToolChoiceAnyParam],
-// [BetaToolChoiceToolParam], [BetaToolChoiceNoneParam], [BetaToolChoiceParam].
-type BetaToolChoiceUnionParam interface {
- implementsBetaToolChoiceUnionParam()
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolChoiceUnionParam) GetDisableParallelToolUse() *bool {
+ if vt := u.OfToolChoiceAuto; vt != nil && vt.DisableParallelToolUse.IsPresent() {
+ return &vt.DisableParallelToolUse.Value
+ } else if vt := u.OfToolChoiceAny; vt != nil && vt.DisableParallelToolUse.IsPresent() {
+ return &vt.DisableParallelToolUse.Value
+ } else if vt := u.OfToolChoiceTool; vt != nil && vt.DisableParallelToolUse.IsPresent() {
+ return &vt.DisableParallelToolUse.Value
+ }
+ return nil
}
-type BetaToolChoiceType string
-
-const (
- BetaToolChoiceTypeAuto BetaToolChoiceType = "auto"
- BetaToolChoiceTypeAny BetaToolChoiceType = "any"
- BetaToolChoiceTypeTool BetaToolChoiceType = "tool"
- BetaToolChoiceTypeNone BetaToolChoiceType = "none"
-)
-
-func (r BetaToolChoiceType) IsKnown() bool {
- switch r {
- case BetaToolChoiceTypeAuto, BetaToolChoiceTypeAny, BetaToolChoiceTypeTool, BetaToolChoiceTypeNone:
- return true
- }
- return false
+func init() {
+ apijson.RegisterUnion[BetaToolChoiceUnionParam](
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaToolChoiceAutoParam{}),
+ DiscriminatorValue: "auto",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaToolChoiceAnyParam{}),
+ DiscriminatorValue: "any",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaToolChoiceToolParam{}),
+ DiscriminatorValue: "tool",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaToolChoiceNoneParam{}),
+ DiscriminatorValue: "none",
+ },
+ )
}
// The model will use any available tools.
+//
+// The property Type is required.
type BetaToolChoiceAnyParam struct {
- Type param.Field[BetaToolChoiceAnyType] `json:"type,required"`
// Whether to disable parallel tool use.
//
// Defaults to `false`. If set to `true`, the model will output exactly one tool
// use.
- DisableParallelToolUse param.Field[bool] `json:"disable_parallel_tool_use"`
+ DisableParallelToolUse param.Opt[bool] `json:"disable_parallel_tool_use,omitzero"`
+ // This field can be elided, and will marshal its zero value as "any".
+ Type constant.Any `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolChoiceAnyParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolChoiceAnyParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaToolChoiceAnyParam) implementsBetaToolChoiceUnionParam() {}
-
-type BetaToolChoiceAnyType string
-
-const (
- BetaToolChoiceAnyTypeAny BetaToolChoiceAnyType = "any"
-)
-
-func (r BetaToolChoiceAnyType) IsKnown() bool {
- switch r {
- case BetaToolChoiceAnyTypeAny:
- return true
- }
- return false
+ type shadow BetaToolChoiceAnyParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
// The model will automatically decide whether to use tools.
+//
+// The property Type is required.
type BetaToolChoiceAutoParam struct {
- Type param.Field[BetaToolChoiceAutoType] `json:"type,required"`
// Whether to disable parallel tool use.
//
// Defaults to `false`. If set to `true`, the model will output at most one tool
// use.
- DisableParallelToolUse param.Field[bool] `json:"disable_parallel_tool_use"`
+ DisableParallelToolUse param.Opt[bool] `json:"disable_parallel_tool_use,omitzero"`
+ // This field can be elided, and will marshal its zero value as "auto".
+ Type constant.Auto `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolChoiceAutoParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolChoiceAutoParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaToolChoiceAutoParam) implementsBetaToolChoiceUnionParam() {}
-
-type BetaToolChoiceAutoType string
-
-const (
- BetaToolChoiceAutoTypeAuto BetaToolChoiceAutoType = "auto"
-)
-
-func (r BetaToolChoiceAutoType) IsKnown() bool {
- switch r {
- case BetaToolChoiceAutoTypeAuto:
- return true
- }
- return false
+ type shadow BetaToolChoiceAutoParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
// The model will not be allowed to use tools.
-type BetaToolChoiceNoneParam struct {
- Type param.Field[BetaToolChoiceNoneType] `json:"type,required"`
-}
-
-func (r BetaToolChoiceNoneParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaToolChoiceNoneParam) implementsBetaToolChoiceUnionParam() {}
-
-type BetaToolChoiceNoneType string
-
-const (
- BetaToolChoiceNoneTypeNone BetaToolChoiceNoneType = "none"
-)
+//
+// The property Type is required.
+type BetaToolChoiceNoneParam struct {
+ // This field can be elided, and will marshal its zero value as "none".
+ Type constant.None `json:"type,required"`
+ paramObj
+}
-func (r BetaToolChoiceNoneType) IsKnown() bool {
- switch r {
- case BetaToolChoiceNoneTypeNone:
- return true
- }
- return false
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolChoiceNoneParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r BetaToolChoiceNoneParam) MarshalJSON() (data []byte, err error) {
+ type shadow BetaToolChoiceNoneParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
// The model will use the specified tool with `tool_choice.name`.
+//
+// The properties Name, Type are required.
type BetaToolChoiceToolParam struct {
// The name of the tool to use.
- Name param.Field[string] `json:"name,required"`
- Type param.Field[BetaToolChoiceToolType] `json:"type,required"`
+ Name string `json:"name,required"`
// Whether to disable parallel tool use.
//
// Defaults to `false`. If set to `true`, the model will output exactly one tool
// use.
- DisableParallelToolUse param.Field[bool] `json:"disable_parallel_tool_use"`
+ DisableParallelToolUse param.Opt[bool] `json:"disable_parallel_tool_use,omitzero"`
+ // This field can be elided, and will marshal its zero value as "tool".
+ Type constant.Tool `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolChoiceToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolChoiceToolParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaToolChoiceToolParam) implementsBetaToolChoiceUnionParam() {}
-
-type BetaToolChoiceToolType string
-
-const (
- BetaToolChoiceToolTypeTool BetaToolChoiceToolType = "tool"
-)
-
-func (r BetaToolChoiceToolType) IsKnown() bool {
- switch r {
- case BetaToolChoiceToolTypeTool:
- return true
- }
- return false
+ type shadow BetaToolChoiceToolParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties DisplayHeightPx, DisplayWidthPx, Name, Type are required.
type BetaToolComputerUse20241022Param struct {
// The height of the display in pixels.
- DisplayHeightPx param.Field[int64] `json:"display_height_px,required"`
+ DisplayHeightPx int64 `json:"display_height_px,required"`
// The width of the display in pixels.
- DisplayWidthPx param.Field[int64] `json:"display_width_px,required"`
+ DisplayWidthPx int64 `json:"display_width_px,required"`
+ // The X11 display number (e.g. 0, 1) for the display.
+ DisplayNumber param.Opt[int64] `json:"display_number,omitzero"`
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
// Name of the tool.
//
// This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[BetaToolComputerUse20241022Name] `json:"name,required"`
- Type param.Field[BetaToolComputerUse20241022Type] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
- // The X11 display number (e.g. 0, 1) for the display.
- DisplayNumber param.Field[int64] `json:"display_number"`
+ //
+ // This field can be elided, and will marshal its zero value as "computer".
+ Name constant.Computer `json:"name,required"`
+ // This field can be elided, and will marshal its zero value as
+ // "computer_20241022".
+ Type constant.Computer20241022 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolComputerUse20241022Param) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolComputerUse20241022Param) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaToolComputerUse20241022Param) implementsBetaToolUnionUnionParam() {}
-
-func (r BetaToolComputerUse20241022Param) implementsBetaMessageCountTokensParamsToolUnion() {}
-
-// Name of the tool.
-//
-// This is how the tool will be called by the model and in tool_use blocks.
-type BetaToolComputerUse20241022Name string
-
-const (
- BetaToolComputerUse20241022NameComputer BetaToolComputerUse20241022Name = "computer"
-)
-
-func (r BetaToolComputerUse20241022Name) IsKnown() bool {
- switch r {
- case BetaToolComputerUse20241022NameComputer:
- return true
- }
- return false
-}
-
-type BetaToolComputerUse20241022Type string
-
-const (
- BetaToolComputerUse20241022TypeComputer20241022 BetaToolComputerUse20241022Type = "computer_20241022"
-)
-
-func (r BetaToolComputerUse20241022Type) IsKnown() bool {
- switch r {
- case BetaToolComputerUse20241022TypeComputer20241022:
- return true
- }
- return false
+ type shadow BetaToolComputerUse20241022Param
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties DisplayHeightPx, DisplayWidthPx, Name, Type are required.
type BetaToolComputerUse20250124Param struct {
// The height of the display in pixels.
- DisplayHeightPx param.Field[int64] `json:"display_height_px,required"`
+ DisplayHeightPx int64 `json:"display_height_px,required"`
// The width of the display in pixels.
- DisplayWidthPx param.Field[int64] `json:"display_width_px,required"`
+ DisplayWidthPx int64 `json:"display_width_px,required"`
+ // The X11 display number (e.g. 0, 1) for the display.
+ DisplayNumber param.Opt[int64] `json:"display_number,omitzero"`
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
// Name of the tool.
//
// This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[BetaToolComputerUse20250124Name] `json:"name,required"`
- Type param.Field[BetaToolComputerUse20250124Type] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
- // The X11 display number (e.g. 0, 1) for the display.
- DisplayNumber param.Field[int64] `json:"display_number"`
+ //
+ // This field can be elided, and will marshal its zero value as "computer".
+ Name constant.Computer `json:"name,required"`
+ // This field can be elided, and will marshal its zero value as
+ // "computer_20250124".
+ Type constant.Computer20250124 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolComputerUse20250124Param) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolComputerUse20250124Param) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaToolComputerUse20250124Param
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r BetaToolComputerUse20250124Param) implementsBetaToolUnionUnionParam() {}
-
-func (r BetaToolComputerUse20250124Param) implementsBetaMessageCountTokensParamsToolUnion() {}
+// The properties ToolUseID, Type are required.
+type BetaToolResultBlockParam struct {
+ ToolUseID string `json:"tool_use_id,required"`
+ IsError param.Opt[bool] `json:"is_error,omitzero"`
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
+ Content []BetaToolResultBlockParamContentUnion `json:"content,omitzero"`
+ // This field can be elided, and will marshal its zero value as "tool_result".
+ Type constant.ToolResult `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolResultBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r BetaToolResultBlockParam) MarshalJSON() (data []byte, err error) {
+ type shadow BetaToolResultBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
-// Name of the tool.
+// Only one field can be non-zero.
//
-// This is how the tool will be called by the model and in tool_use blocks.
-type BetaToolComputerUse20250124Name string
-
-const (
- BetaToolComputerUse20250124NameComputer BetaToolComputerUse20250124Name = "computer"
-)
-
-func (r BetaToolComputerUse20250124Name) IsKnown() bool {
- switch r {
- case BetaToolComputerUse20250124NameComputer:
- return true
- }
- return false
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaToolResultBlockParamContentUnion struct {
+ OfRequestTextBlock *BetaTextBlockParam `json:",omitzero,inline"`
+ OfRequestImageBlock *BetaImageBlockParam `json:",omitzero,inline"`
+ paramUnion
}
-type BetaToolComputerUse20250124Type string
-
-const (
- BetaToolComputerUse20250124TypeComputer20250124 BetaToolComputerUse20250124Type = "computer_20250124"
-)
-
-func (r BetaToolComputerUse20250124Type) IsKnown() bool {
- switch r {
- case BetaToolComputerUse20250124TypeComputer20250124:
- return true
- }
- return false
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaToolResultBlockParamContentUnion) IsPresent() bool {
+ return !param.IsOmitted(u) && !u.IsNull()
}
-
-type BetaToolResultBlockParam struct {
- ToolUseID param.Field[string] `json:"tool_use_id,required"`
- Type param.Field[BetaToolResultBlockParamType] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
- Content param.Field[[]BetaToolResultBlockParamContentUnion] `json:"content"`
- IsError param.Field[bool] `json:"is_error"`
+func (u BetaToolResultBlockParamContentUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaToolResultBlockParamContentUnion](u.OfRequestTextBlock, u.OfRequestImageBlock)
}
-func (r BetaToolResultBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+func (u *BetaToolResultBlockParamContentUnion) asAny() any {
+ if !param.IsOmitted(u.OfRequestTextBlock) {
+ return u.OfRequestTextBlock
+ } else if !param.IsOmitted(u.OfRequestImageBlock) {
+ return u.OfRequestImageBlock
+ }
+ return nil
}
-func (r BetaToolResultBlockParam) implementsBetaContentBlockParamUnion() {}
-
-type BetaToolResultBlockParamType string
-
-const (
- BetaToolResultBlockParamTypeToolResult BetaToolResultBlockParamType = "tool_result"
-)
-
-func (r BetaToolResultBlockParamType) IsKnown() bool {
- switch r {
- case BetaToolResultBlockParamTypeToolResult:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolResultBlockParamContentUnion) GetText() *string {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return &vt.Text
}
- return false
+ return nil
}
-type BetaToolResultBlockParamContent struct {
- Type param.Field[BetaToolResultBlockParamContentType] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
- Citations param.Field[interface{}] `json:"citations"`
- Source param.Field[interface{}] `json:"source"`
- Text param.Field[string] `json:"text"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolResultBlockParamContentUnion) GetCitations() []BetaTextCitationParamUnion {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return vt.Citations
+ }
+ return nil
}
-func (r BetaToolResultBlockParamContent) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolResultBlockParamContentUnion) GetSource() *BetaImageBlockParamSourceUnion {
+ if vt := u.OfRequestImageBlock; vt != nil {
+ return &vt.Source
+ }
+ return nil
}
-func (r BetaToolResultBlockParamContent) implementsBetaToolResultBlockParamContentUnion() {}
-
-// Satisfied by [BetaTextBlockParam], [BetaImageBlockParam],
-// [BetaToolResultBlockParamContent].
-type BetaToolResultBlockParamContentUnion interface {
- implementsBetaToolResultBlockParamContentUnion()
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolResultBlockParamContentUnion) GetType() *string {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestImageBlock; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
}
-type BetaToolResultBlockParamContentType string
-
-const (
- BetaToolResultBlockParamContentTypeText BetaToolResultBlockParamContentType = "text"
- BetaToolResultBlockParamContentTypeImage BetaToolResultBlockParamContentType = "image"
-)
-
-func (r BetaToolResultBlockParamContentType) IsKnown() bool {
- switch r {
- case BetaToolResultBlockParamContentTypeText, BetaToolResultBlockParamContentTypeImage:
- return true
+// Returns a pointer to the underlying variant's CacheControl property, if present.
+func (u BetaToolResultBlockParamContentUnion) GetCacheControl() *BetaCacheControlEphemeralParam {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfRequestImageBlock; vt != nil {
+ return &vt.CacheControl
}
- return false
+ return nil
+}
+
+func init() {
+ apijson.RegisterUnion[BetaToolResultBlockParamContentUnion](
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaTextBlockParam{}),
+ DiscriminatorValue: "text",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(BetaImageBlockParam{}),
+ DiscriminatorValue: "image",
+ },
+ )
}
+// The properties Name, Type are required.
type BetaToolTextEditor20241022Param struct {
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
// Name of the tool.
//
// This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[BetaToolTextEditor20241022Name] `json:"name,required"`
- Type param.Field[BetaToolTextEditor20241022Type] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
+ //
+ // This field can be elided, and will marshal its zero value as
+ // "str_replace_editor".
+ Name constant.StrReplaceEditor `json:"name,required"`
+ // This field can be elided, and will marshal its zero value as
+ // "text_editor_20241022".
+ Type constant.TextEditor20241022 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolTextEditor20241022Param) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolTextEditor20241022Param) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaToolTextEditor20241022Param) implementsBetaToolUnionUnionParam() {}
-
-func (r BetaToolTextEditor20241022Param) implementsBetaMessageCountTokensParamsToolUnion() {}
-
-// Name of the tool.
-//
-// This is how the tool will be called by the model and in tool_use blocks.
-type BetaToolTextEditor20241022Name string
-
-const (
- BetaToolTextEditor20241022NameStrReplaceEditor BetaToolTextEditor20241022Name = "str_replace_editor"
-)
-
-func (r BetaToolTextEditor20241022Name) IsKnown() bool {
- switch r {
- case BetaToolTextEditor20241022NameStrReplaceEditor:
- return true
- }
- return false
-}
-
-type BetaToolTextEditor20241022Type string
-
-const (
- BetaToolTextEditor20241022TypeTextEditor20241022 BetaToolTextEditor20241022Type = "text_editor_20241022"
-)
-
-func (r BetaToolTextEditor20241022Type) IsKnown() bool {
- switch r {
- case BetaToolTextEditor20241022TypeTextEditor20241022:
- return true
- }
- return false
+ type shadow BetaToolTextEditor20241022Param
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties Name, Type are required.
type BetaToolTextEditor20250124Param struct {
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
// Name of the tool.
//
// This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[BetaToolTextEditor20250124Name] `json:"name,required"`
- Type param.Field[BetaToolTextEditor20250124Type] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
+ //
+ // This field can be elided, and will marshal its zero value as
+ // "str_replace_editor".
+ Name constant.StrReplaceEditor `json:"name,required"`
+ // This field can be elided, and will marshal its zero value as
+ // "text_editor_20250124".
+ Type constant.TextEditor20250124 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolTextEditor20250124Param) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolTextEditor20250124Param) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaToolTextEditor20250124Param) implementsBetaToolUnionUnionParam() {}
-
-func (r BetaToolTextEditor20250124Param) implementsBetaMessageCountTokensParamsToolUnion() {}
-
-// Name of the tool.
-//
-// This is how the tool will be called by the model and in tool_use blocks.
-type BetaToolTextEditor20250124Name string
-
-const (
- BetaToolTextEditor20250124NameStrReplaceEditor BetaToolTextEditor20250124Name = "str_replace_editor"
-)
-
-func (r BetaToolTextEditor20250124Name) IsKnown() bool {
- switch r {
- case BetaToolTextEditor20250124NameStrReplaceEditor:
- return true
- }
- return false
-}
-
-type BetaToolTextEditor20250124Type string
-
-const (
- BetaToolTextEditor20250124TypeTextEditor20250124 BetaToolTextEditor20250124Type = "text_editor_20250124"
-)
-
-func (r BetaToolTextEditor20250124Type) IsKnown() bool {
- switch r {
- case BetaToolTextEditor20250124TypeTextEditor20250124:
- return true
- }
- return false
+ type shadow BetaToolTextEditor20250124Param
+ return param.MarshalObject(r, (*shadow)(&r))
}
-type BetaToolUnionParam struct {
- // Name of the tool.
- //
- // This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[string] `json:"name,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
- // Description of what this tool does.
- //
- // Tool descriptions should be as detailed as possible. The more information that
- // the model has about what the tool is and how to use it, the better it will
- // perform. You can use natural language descriptions to reinforce important
- // aspects of the tool input JSON schema.
- Description param.Field[string] `json:"description"`
- // The height of the display in pixels.
- DisplayHeightPx param.Field[int64] `json:"display_height_px"`
- // The X11 display number (e.g. 0, 1) for the display.
- DisplayNumber param.Field[int64] `json:"display_number"`
- // The width of the display in pixels.
- DisplayWidthPx param.Field[int64] `json:"display_width_px"`
- InputSchema param.Field[interface{}] `json:"input_schema"`
- Type param.Field[BetaToolUnionType] `json:"type"`
+func BetaToolUnionParamOfTool(inputSchema BetaToolInputSchemaParam, name string) BetaToolUnionParam {
+ var variant BetaToolParam
+ variant.InputSchema = inputSchema
+ variant.Name = name
+ return BetaToolUnionParam{OfTool: &variant}
}
-func (r BetaToolUnionParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+func BetaToolUnionParamOfComputerUseTool20241022(displayHeightPx int64, displayWidthPx int64) BetaToolUnionParam {
+ var variant BetaToolComputerUse20241022Param
+ variant.DisplayHeightPx = displayHeightPx
+ variant.DisplayWidthPx = displayWidthPx
+ return BetaToolUnionParam{OfComputerUseTool20241022: &variant}
}
-func (r BetaToolUnionParam) implementsBetaToolUnionUnionParam() {}
-
-// Satisfied by [BetaToolParam], [BetaToolComputerUse20241022Param],
-// [BetaToolBash20241022Param], [BetaToolTextEditor20241022Param],
-// [BetaToolComputerUse20250124Param], [BetaToolBash20250124Param],
-// [BetaToolTextEditor20250124Param], [BetaToolUnionParam].
-type BetaToolUnionUnionParam interface {
- implementsBetaToolUnionUnionParam()
+func BetaToolUnionParamOfComputerUseTool20250124(displayHeightPx int64, displayWidthPx int64) BetaToolUnionParam {
+ var variant BetaToolComputerUse20250124Param
+ variant.DisplayHeightPx = displayHeightPx
+ variant.DisplayWidthPx = displayWidthPx
+ return BetaToolUnionParam{OfComputerUseTool20250124: &variant}
}
-type BetaToolUnionType string
-
-const (
- BetaToolUnionTypeCustom BetaToolUnionType = "custom"
- BetaToolUnionTypeComputer20241022 BetaToolUnionType = "computer_20241022"
- BetaToolUnionTypeBash20241022 BetaToolUnionType = "bash_20241022"
- BetaToolUnionTypeTextEditor20241022 BetaToolUnionType = "text_editor_20241022"
- BetaToolUnionTypeComputer20250124 BetaToolUnionType = "computer_20250124"
- BetaToolUnionTypeBash20250124 BetaToolUnionType = "bash_20250124"
- BetaToolUnionTypeTextEditor20250124 BetaToolUnionType = "text_editor_20250124"
-)
-
-func (r BetaToolUnionType) IsKnown() bool {
- switch r {
- case BetaToolUnionTypeCustom, BetaToolUnionTypeComputer20241022, BetaToolUnionTypeBash20241022, BetaToolUnionTypeTextEditor20241022, BetaToolUnionTypeComputer20250124, BetaToolUnionTypeBash20250124, BetaToolUnionTypeTextEditor20250124:
- return true
- }
- return false
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaToolUnionParam struct {
+ OfTool *BetaToolParam `json:",omitzero,inline"`
+ OfComputerUseTool20241022 *BetaToolComputerUse20241022Param `json:",omitzero,inline"`
+ OfBashTool20241022 *BetaToolBash20241022Param `json:",omitzero,inline"`
+ OfTextEditor20241022 *BetaToolTextEditor20241022Param `json:",omitzero,inline"`
+ OfComputerUseTool20250124 *BetaToolComputerUse20250124Param `json:",omitzero,inline"`
+ OfBashTool20250124 *BetaToolBash20250124Param `json:",omitzero,inline"`
+ OfTextEditor20250124 *BetaToolTextEditor20250124Param `json:",omitzero,inline"`
+ paramUnion
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaToolUnionParam) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u BetaToolUnionParam) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaToolUnionParam](u.OfTool,
+ u.OfComputerUseTool20241022,
+ u.OfBashTool20241022,
+ u.OfTextEditor20241022,
+ u.OfComputerUseTool20250124,
+ u.OfBashTool20250124,
+ u.OfTextEditor20250124)
+}
+
+func (u *BetaToolUnionParam) asAny() any {
+ if !param.IsOmitted(u.OfTool) {
+ return u.OfTool
+ } else if !param.IsOmitted(u.OfComputerUseTool20241022) {
+ return u.OfComputerUseTool20241022
+ } else if !param.IsOmitted(u.OfBashTool20241022) {
+ return u.OfBashTool20241022
+ } else if !param.IsOmitted(u.OfTextEditor20241022) {
+ return u.OfTextEditor20241022
+ } else if !param.IsOmitted(u.OfComputerUseTool20250124) {
+ return u.OfComputerUseTool20250124
+ } else if !param.IsOmitted(u.OfBashTool20250124) {
+ return u.OfBashTool20250124
+ } else if !param.IsOmitted(u.OfTextEditor20250124) {
+ return u.OfTextEditor20250124
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolUnionParam) GetInputSchema() *BetaToolInputSchemaParam {
+ if vt := u.OfTool; vt != nil {
+ return &vt.InputSchema
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolUnionParam) GetDescription() *string {
+ if vt := u.OfTool; vt != nil && vt.Description.IsPresent() {
+ return &vt.Description.Value
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolUnionParam) GetName() *string {
+ if vt := u.OfTool; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfComputerUseTool20241022; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfBashTool20241022; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfTextEditor20241022; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfComputerUseTool20250124; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfBashTool20250124; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return (*string)(&vt.Name)
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolUnionParam) GetType() *string {
+ if vt := u.OfTool; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfComputerUseTool20241022; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfBashTool20241022; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfTextEditor20241022; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfComputerUseTool20250124; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfBashTool20250124; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolUnionParam) GetDisplayHeightPx() *int64 {
+ if vt := u.OfComputerUseTool20241022; vt != nil {
+ return (*int64)(&vt.DisplayHeightPx)
+ } else if vt := u.OfComputerUseTool20250124; vt != nil {
+ return (*int64)(&vt.DisplayHeightPx)
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolUnionParam) GetDisplayWidthPx() *int64 {
+ if vt := u.OfComputerUseTool20241022; vt != nil {
+ return (*int64)(&vt.DisplayWidthPx)
+ } else if vt := u.OfComputerUseTool20250124; vt != nil {
+ return (*int64)(&vt.DisplayWidthPx)
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaToolUnionParam) GetDisplayNumber() *int64 {
+ if vt := u.OfComputerUseTool20241022; vt != nil && vt.DisplayNumber.IsPresent() {
+ return &vt.DisplayNumber.Value
+ } else if vt := u.OfComputerUseTool20250124; vt != nil && vt.DisplayNumber.IsPresent() {
+ return &vt.DisplayNumber.Value
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's CacheControl property, if present.
+func (u BetaToolUnionParam) GetCacheControl() *BetaCacheControlEphemeralParam {
+ if vt := u.OfTool; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfComputerUseTool20241022; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfBashTool20241022; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfTextEditor20241022; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfComputerUseTool20250124; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfBashTool20250124; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return &vt.CacheControl
+ }
+ return nil
}
type BetaToolUseBlock struct {
- ID string `json:"id,required"`
- Input interface{} `json:"input,required"`
- Name string `json:"name,required"`
- Type BetaToolUseBlockType `json:"type,required"`
- JSON betaToolUseBlockJSON `json:"-"`
-}
-
-// betaToolUseBlockJSON contains the JSON metadata for the struct
-// [BetaToolUseBlock]
-type betaToolUseBlockJSON struct {
- ID apijson.Field
- Input apijson.Field
- Name apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaToolUseBlock) UnmarshalJSON(data []byte) (err error) {
+ ID string `json:"id,required"`
+ Input interface{} `json:"input,required"`
+ Name string `json:"name,required"`
+ Type constant.ToolUse `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ Input resp.Field
+ Name resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaToolUseBlock) RawJSON() string { return r.JSON.raw }
+func (r *BetaToolUseBlock) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaToolUseBlockJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaToolUseBlock) implementsBetaContentBlock() {}
-
-func (r BetaToolUseBlock) implementsBetaRawContentBlockStartEventContentBlock() {}
-
-type BetaToolUseBlockType string
-
-const (
- BetaToolUseBlockTypeToolUse BetaToolUseBlockType = "tool_use"
-)
-
-func (r BetaToolUseBlockType) IsKnown() bool {
- switch r {
- case BetaToolUseBlockTypeToolUse:
- return true
- }
- return false
+func (r BetaToolUseBlock) ToParam() BetaToolUseBlockParam {
+ var p BetaToolUseBlockParam
+ p.Type = r.Type
+ p.ID = r.ID
+ p.Input = r.Input
+ p.Name = r.Name
+ return p
}
+// The properties ID, Input, Name, Type are required.
type BetaToolUseBlockParam struct {
- ID param.Field[string] `json:"id,required"`
- Input param.Field[interface{}] `json:"input,required"`
- Name param.Field[string] `json:"name,required"`
- Type param.Field[BetaToolUseBlockParamType] `json:"type,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
-}
-
+ ID string `json:"id,required"`
+ Input interface{} `json:"input,omitzero,required"`
+ Name string `json:"name,required"`
+ CacheControl BetaCacheControlEphemeralParam `json:"cache_control,omitzero"`
+ // This field can be elided, and will marshal its zero value as "tool_use".
+ Type constant.ToolUse `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaToolUseBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaToolUseBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaToolUseBlockParam) implementsBetaContentBlockParamUnion() {}
-
-type BetaToolUseBlockParamType string
-
-const (
- BetaToolUseBlockParamTypeToolUse BetaToolUseBlockParamType = "tool_use"
-)
-
-func (r BetaToolUseBlockParamType) IsKnown() bool {
- switch r {
- case BetaToolUseBlockParamTypeToolUse:
- return true
- }
- return false
+ type shadow BetaToolUseBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties Type, URL are required.
type BetaURLImageSourceParam struct {
- Type param.Field[BetaURLImageSourceType] `json:"type,required"`
- URL param.Field[string] `json:"url,required"`
+ URL string `json:"url,required"`
+ // This field can be elided, and will marshal its zero value as "url".
+ Type constant.URL `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaURLImageSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaURLImageSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaURLImageSourceParam) implementsBetaImageBlockParamSourceUnion() {}
-
-type BetaURLImageSourceType string
-
-const (
- BetaURLImageSourceTypeURL BetaURLImageSourceType = "url"
-)
-
-func (r BetaURLImageSourceType) IsKnown() bool {
- switch r {
- case BetaURLImageSourceTypeURL:
- return true
- }
- return false
+ type shadow BetaURLImageSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties Type, URL are required.
type BetaURLPDFSourceParam struct {
- Type param.Field[BetaURLPDFSourceType] `json:"type,required"`
- URL param.Field[string] `json:"url,required"`
+ URL string `json:"url,required"`
+ // This field can be elided, and will marshal its zero value as "url".
+ Type constant.URL `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaURLPDFSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaURLPDFSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r BetaURLPDFSourceParam) implementsBetaBase64PDFBlockSourceUnionParam() {}
-
-type BetaURLPDFSourceType string
-
-const (
- BetaURLPDFSourceTypeURL BetaURLPDFSourceType = "url"
-)
-
-func (r BetaURLPDFSourceType) IsKnown() bool {
- switch r {
- case BetaURLPDFSourceTypeURL:
- return true
- }
- return false
+ type shadow BetaURLPDFSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
type BetaUsage struct {
// The number of input tokens used to create the cache entry.
- CacheCreationInputTokens int64 `json:"cache_creation_input_tokens,required,nullable"`
+ CacheCreationInputTokens int64 `json:"cache_creation_input_tokens,required"`
// The number of input tokens read from the cache.
- CacheReadInputTokens int64 `json:"cache_read_input_tokens,required,nullable"`
+ CacheReadInputTokens int64 `json:"cache_read_input_tokens,required"`
// The number of input tokens which were used.
InputTokens int64 `json:"input_tokens,required"`
// The number of output tokens which were used.
- OutputTokens int64 `json:"output_tokens,required"`
- JSON betaUsageJSON `json:"-"`
-}
-
-// betaUsageJSON contains the JSON metadata for the struct [BetaUsage]
-type betaUsageJSON struct {
- CacheCreationInputTokens apijson.Field
- CacheReadInputTokens apijson.Field
- InputTokens apijson.Field
- OutputTokens apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaUsage) UnmarshalJSON(data []byte) (err error) {
+ OutputTokens int64 `json:"output_tokens,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ CacheCreationInputTokens resp.Field
+ CacheReadInputTokens resp.Field
+ InputTokens resp.Field
+ OutputTokens resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaUsage) RawJSON() string { return r.JSON.raw }
+func (r *BetaUsage) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaUsageJSON) RawJSON() string {
- return r.raw
-}
-
type BetaMessageNewParams struct {
// The maximum number of tokens to generate before stopping.
//
@@ -3311,7 +3304,7 @@ type BetaMessageNewParams struct {
//
// Different models have different maximum values for this parameter. See
// [models](https://docs.anthropic.com/en/docs/models-overview) for details.
- MaxTokens param.Field[int64] `json:"max_tokens,required"`
+ MaxTokens int64 `json:"max_tokens,required"`
// Input messages.
//
// Our models are trained to operate on alternating `user` and `assistant`
@@ -3404,13 +3397,40 @@ type BetaMessageNewParams struct {
// [system prompt](https://docs.anthropic.com/en/docs/system-prompts), you can use
// the top-level `system` parameter — there is no `"system"` role for input
// messages in the Messages API.
- Messages param.Field[[]BetaMessageParam] `json:"messages,required"`
+ Messages []BetaMessageParam `json:"messages,omitzero,required"`
// The model that will complete your prompt.\n\nSee
// [models](https://docs.anthropic.com/en/docs/models-overview) for additional
// details and options.
- Model param.Field[Model] `json:"model,required"`
+ Model Model `json:"model,omitzero,required"`
+ // Amount of randomness injected into the response.
+ //
+ // Defaults to `1.0`. Ranges from `0.0` to `1.0`. Use `temperature` closer to `0.0`
+ // for analytical / multiple choice, and closer to `1.0` for creative and
+ // generative tasks.
+ //
+ // Note that even with `temperature` of `0.0`, the results will not be fully
+ // deterministic.
+ Temperature param.Opt[float64] `json:"temperature,omitzero"`
+ // Only sample from the top K options for each subsequent token.
+ //
+ // Used to remove "long tail" low probability responses.
+ // [Learn more technical details here](https://towardsdatascience.com/how-to-sample-from-language-models-682bceb97277).
+ //
+ // Recommended for advanced use cases only. You usually only need to use
+ // `temperature`.
+ TopK param.Opt[int64] `json:"top_k,omitzero"`
+ // Use nucleus sampling.
+ //
+ // In nucleus sampling, we compute the cumulative distribution over all the options
+ // for each subsequent token in decreasing probability order and cut it off once it
+ // reaches a particular probability specified by `top_p`. You should either alter
+ // `temperature` or `top_p`, but not both.
+ //
+ // Recommended for advanced use cases only. You usually only need to use
+ // `temperature`.
+ TopP param.Opt[float64] `json:"top_p,omitzero"`
// An object describing metadata about the request.
- Metadata param.Field[BetaMetadataParam] `json:"metadata"`
+ Metadata BetaMetadataParam `json:"metadata,omitzero"`
// Custom text sequences that will cause the model to stop generating.
//
// Our models will normally stop when they have naturally completed their turn,
@@ -3420,22 +3440,13 @@ type BetaMessageNewParams struct {
// text, you can use the `stop_sequences` parameter. If the model encounters one of
// the custom sequences, the response `stop_reason` value will be `"stop_sequence"`
// and the response `stop_sequence` value will contain the matched stop sequence.
- StopSequences param.Field[[]string] `json:"stop_sequences"`
+ StopSequences []string `json:"stop_sequences,omitzero"`
// System prompt.
//
// A system prompt is a way of providing context and instructions to Claude, such
// as specifying a particular goal or role. See our
// [guide to system prompts](https://docs.anthropic.com/en/docs/system-prompts).
- System param.Field[[]BetaTextBlockParam] `json:"system"`
- // Amount of randomness injected into the response.
- //
- // Defaults to `1.0`. Ranges from `0.0` to `1.0`. Use `temperature` closer to `0.0`
- // for analytical / multiple choice, and closer to `1.0` for creative and
- // generative tasks.
- //
- // Note that even with `temperature` of `0.0`, the results will not be fully
- // deterministic.
- Temperature param.Field[float64] `json:"temperature"`
+ System []BetaTextBlockParam `json:"system,omitzero"`
// Configuration for enabling Claude's extended thinking.
//
// When enabled, responses include `thinking` content blocks showing Claude's
@@ -3445,10 +3456,10 @@ type BetaMessageNewParams struct {
// See
// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
// for details.
- Thinking param.Field[BetaThinkingConfigParamUnion] `json:"thinking"`
+ Thinking BetaThinkingConfigParamUnion `json:"thinking,omitzero"`
// How the model should use the provided tools. The model can use a specific tool,
// any available tool, decide by itself, or not use tools at all.
- ToolChoice param.Field[BetaToolChoiceUnionParam] `json:"tool_choice"`
+ ToolChoice BetaToolChoiceUnionParam `json:"tool_choice,omitzero"`
// Definitions of tools that the model may use.
//
// If you include `tools` in your API request, the model may return `tool_use`
@@ -3524,31 +3535,19 @@ type BetaMessageNewParams struct {
// JSON structure of output.
//
// See our [guide](https://docs.anthropic.com/en/docs/tool-use) for more details.
- Tools param.Field[[]BetaToolUnionUnionParam] `json:"tools"`
- // Only sample from the top K options for each subsequent token.
- //
- // Used to remove "long tail" low probability responses.
- // [Learn more technical details here](https://towardsdatascience.com/how-to-sample-from-language-models-682bceb97277).
- //
- // Recommended for advanced use cases only. You usually only need to use
- // `temperature`.
- TopK param.Field[int64] `json:"top_k"`
- // Use nucleus sampling.
- //
- // In nucleus sampling, we compute the cumulative distribution over all the options
- // for each subsequent token in decreasing probability order and cut it off once it
- // reaches a particular probability specified by `top_p`. You should either alter
- // `temperature` or `top_p`, but not both.
- //
- // Recommended for advanced use cases only. You usually only need to use
- // `temperature`.
- TopP param.Field[float64] `json:"top_p"`
+ Tools []BetaToolUnionParam `json:"tools,omitzero"`
// Optional header to specify the beta version(s) you want to use.
- Betas param.Field[[]AnthropicBeta] `header:"anthropic-beta"`
+ Betas []AnthropicBeta `header:"anthropic-beta,omitzero" json:"-"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
func (r BetaMessageNewParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaMessageNewParams
+ return param.MarshalObject(r, (*shadow)(&r))
}
type BetaMessageCountTokensParams struct {
@@ -3644,17 +3643,17 @@ type BetaMessageCountTokensParams struct {
// [system prompt](https://docs.anthropic.com/en/docs/system-prompts), you can use
// the top-level `system` parameter — there is no `"system"` role for input
// messages in the Messages API.
- Messages param.Field[[]BetaMessageParam] `json:"messages,required"`
+ Messages []BetaMessageParam `json:"messages,omitzero,required"`
// The model that will complete your prompt.\n\nSee
// [models](https://docs.anthropic.com/en/docs/models-overview) for additional
// details and options.
- Model param.Field[Model] `json:"model,required"`
+ Model Model `json:"model,omitzero,required"`
// System prompt.
//
// A system prompt is a way of providing context and instructions to Claude, such
// as specifying a particular goal or role. See our
// [guide to system prompts](https://docs.anthropic.com/en/docs/system-prompts).
- System param.Field[BetaMessageCountTokensParamsSystemUnion] `json:"system"`
+ System BetaMessageCountTokensParamsSystemUnion `json:"system,omitzero"`
// Configuration for enabling Claude's extended thinking.
//
// When enabled, responses include `thinking` content blocks showing Claude's
@@ -3664,10 +3663,10 @@ type BetaMessageCountTokensParams struct {
// See
// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
// for details.
- Thinking param.Field[BetaThinkingConfigParamUnion] `json:"thinking"`
+ Thinking BetaThinkingConfigParamUnion `json:"thinking,omitzero"`
// How the model should use the provided tools. The model can use a specific tool,
// any available tool, decide by itself, or not use tools at all.
- ToolChoice param.Field[BetaToolChoiceUnionParam] `json:"tool_choice"`
+ ToolChoice BetaToolChoiceUnionParam `json:"tool_choice,omitzero"`
// Definitions of tools that the model may use.
//
// If you include `tools` in your API request, the model may return `tool_use`
@@ -3743,84 +3742,198 @@ type BetaMessageCountTokensParams struct {
// JSON structure of output.
//
// See our [guide](https://docs.anthropic.com/en/docs/tool-use) for more details.
- Tools param.Field[[]BetaMessageCountTokensParamsToolUnion] `json:"tools"`
+ Tools []BetaMessageCountTokensParamsToolUnion `json:"tools,omitzero"`
// Optional header to specify the beta version(s) you want to use.
- Betas param.Field[[]AnthropicBeta] `header:"anthropic-beta"`
+ Betas []AnthropicBeta `header:"anthropic-beta,omitzero" json:"-"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageCountTokensParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
func (r BetaMessageCountTokensParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaMessageCountTokensParams
+ return param.MarshalObject(r, (*shadow)(&r))
}
-// System prompt.
-//
-// A system prompt is a way of providing context and instructions to Claude, such
-// as specifying a particular goal or role. See our
-// [guide to system prompts](https://docs.anthropic.com/en/docs/system-prompts).
+// Only one field can be non-zero.
//
-// Satisfied by [shared.UnionString], [BetaMessageCountTokensParamsSystemArray].
-type BetaMessageCountTokensParamsSystemUnion interface {
- ImplementsBetaMessageCountTokensParamsSystemUnion()
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaMessageCountTokensParamsSystemUnion struct {
+ OfString param.Opt[string] `json:",omitzero,inline"`
+ OfBetaMessageCountTokenssSystemArray []BetaTextBlockParam `json:",omitzero,inline"`
+ paramUnion
}
-type BetaMessageCountTokensParamsSystemArray []BetaTextBlockParam
-
-func (r BetaMessageCountTokensParamsSystemArray) ImplementsBetaMessageCountTokensParamsSystemUnion() {
-}
-
-type BetaMessageCountTokensParamsTool struct {
- // Name of the tool.
- //
- // This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[string] `json:"name,required"`
- CacheControl param.Field[BetaCacheControlEphemeralParam] `json:"cache_control"`
- // Description of what this tool does.
- //
- // Tool descriptions should be as detailed as possible. The more information that
- // the model has about what the tool is and how to use it, the better it will
- // perform. You can use natural language descriptions to reinforce important
- // aspects of the tool input JSON schema.
- Description param.Field[string] `json:"description"`
- // The height of the display in pixels.
- DisplayHeightPx param.Field[int64] `json:"display_height_px"`
- // The X11 display number (e.g. 0, 1) for the display.
- DisplayNumber param.Field[int64] `json:"display_number"`
- // The width of the display in pixels.
- DisplayWidthPx param.Field[int64] `json:"display_width_px"`
- InputSchema param.Field[interface{}] `json:"input_schema"`
- Type param.Field[BetaMessageCountTokensParamsToolsType] `json:"type"`
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaMessageCountTokensParamsSystemUnion) IsPresent() bool {
+ return !param.IsOmitted(u) && !u.IsNull()
}
-
-func (r BetaMessageCountTokensParamsTool) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+func (u BetaMessageCountTokensParamsSystemUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaMessageCountTokensParamsSystemUnion](u.OfString, u.OfBetaMessageCountTokenssSystemArray)
}
-func (r BetaMessageCountTokensParamsTool) implementsBetaMessageCountTokensParamsToolUnion() {}
-
-// Satisfied by [BetaToolParam], [BetaToolComputerUse20241022Param],
-// [BetaToolBash20241022Param], [BetaToolTextEditor20241022Param],
-// [BetaToolComputerUse20250124Param], [BetaToolBash20250124Param],
-// [BetaToolTextEditor20250124Param], [BetaMessageCountTokensParamsTool].
-type BetaMessageCountTokensParamsToolUnion interface {
- implementsBetaMessageCountTokensParamsToolUnion()
+func (u *BetaMessageCountTokensParamsSystemUnion) asAny() any {
+ if !param.IsOmitted(u.OfString) {
+ return &u.OfString.Value
+ } else if !param.IsOmitted(u.OfBetaMessageCountTokenssSystemArray) {
+ return &u.OfBetaMessageCountTokenssSystemArray
+ }
+ return nil
}
-type BetaMessageCountTokensParamsToolsType string
-
-const (
- BetaMessageCountTokensParamsToolsTypeCustom BetaMessageCountTokensParamsToolsType = "custom"
- BetaMessageCountTokensParamsToolsTypeComputer20241022 BetaMessageCountTokensParamsToolsType = "computer_20241022"
- BetaMessageCountTokensParamsToolsTypeBash20241022 BetaMessageCountTokensParamsToolsType = "bash_20241022"
- BetaMessageCountTokensParamsToolsTypeTextEditor20241022 BetaMessageCountTokensParamsToolsType = "text_editor_20241022"
- BetaMessageCountTokensParamsToolsTypeComputer20250124 BetaMessageCountTokensParamsToolsType = "computer_20250124"
- BetaMessageCountTokensParamsToolsTypeBash20250124 BetaMessageCountTokensParamsToolsType = "bash_20250124"
- BetaMessageCountTokensParamsToolsTypeTextEditor20250124 BetaMessageCountTokensParamsToolsType = "text_editor_20250124"
-)
-
-func (r BetaMessageCountTokensParamsToolsType) IsKnown() bool {
- switch r {
- case BetaMessageCountTokensParamsToolsTypeCustom, BetaMessageCountTokensParamsToolsTypeComputer20241022, BetaMessageCountTokensParamsToolsTypeBash20241022, BetaMessageCountTokensParamsToolsTypeTextEditor20241022, BetaMessageCountTokensParamsToolsTypeComputer20250124, BetaMessageCountTokensParamsToolsTypeBash20250124, BetaMessageCountTokensParamsToolsTypeTextEditor20250124:
- return true
- }
- return false
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type BetaMessageCountTokensParamsToolUnion struct {
+ OfTool *BetaToolParam `json:",omitzero,inline"`
+ OfComputerUseTool20241022 *BetaToolComputerUse20241022Param `json:",omitzero,inline"`
+ OfBashTool20241022 *BetaToolBash20241022Param `json:",omitzero,inline"`
+ OfTextEditor20241022 *BetaToolTextEditor20241022Param `json:",omitzero,inline"`
+ OfComputerUseTool20250124 *BetaToolComputerUse20250124Param `json:",omitzero,inline"`
+ OfBashTool20250124 *BetaToolBash20250124Param `json:",omitzero,inline"`
+ OfTextEditor20250124 *BetaToolTextEditor20250124Param `json:",omitzero,inline"`
+ paramUnion
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u BetaMessageCountTokensParamsToolUnion) IsPresent() bool {
+ return !param.IsOmitted(u) && !u.IsNull()
+}
+func (u BetaMessageCountTokensParamsToolUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[BetaMessageCountTokensParamsToolUnion](u.OfTool,
+ u.OfComputerUseTool20241022,
+ u.OfBashTool20241022,
+ u.OfTextEditor20241022,
+ u.OfComputerUseTool20250124,
+ u.OfBashTool20250124,
+ u.OfTextEditor20250124)
+}
+
+func (u *BetaMessageCountTokensParamsToolUnion) asAny() any {
+ if !param.IsOmitted(u.OfTool) {
+ return u.OfTool
+ } else if !param.IsOmitted(u.OfComputerUseTool20241022) {
+ return u.OfComputerUseTool20241022
+ } else if !param.IsOmitted(u.OfBashTool20241022) {
+ return u.OfBashTool20241022
+ } else if !param.IsOmitted(u.OfTextEditor20241022) {
+ return u.OfTextEditor20241022
+ } else if !param.IsOmitted(u.OfComputerUseTool20250124) {
+ return u.OfComputerUseTool20250124
+ } else if !param.IsOmitted(u.OfBashTool20250124) {
+ return u.OfBashTool20250124
+ } else if !param.IsOmitted(u.OfTextEditor20250124) {
+ return u.OfTextEditor20250124
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaMessageCountTokensParamsToolUnion) GetInputSchema() *BetaToolInputSchemaParam {
+ if vt := u.OfTool; vt != nil {
+ return &vt.InputSchema
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaMessageCountTokensParamsToolUnion) GetDescription() *string {
+ if vt := u.OfTool; vt != nil && vt.Description.IsPresent() {
+ return &vt.Description.Value
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaMessageCountTokensParamsToolUnion) GetName() *string {
+ if vt := u.OfTool; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfComputerUseTool20241022; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfBashTool20241022; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfTextEditor20241022; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfComputerUseTool20250124; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfBashTool20250124; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return (*string)(&vt.Name)
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaMessageCountTokensParamsToolUnion) GetType() *string {
+ if vt := u.OfTool; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfComputerUseTool20241022; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfBashTool20241022; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfTextEditor20241022; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfComputerUseTool20250124; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfBashTool20250124; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaMessageCountTokensParamsToolUnion) GetDisplayHeightPx() *int64 {
+ if vt := u.OfComputerUseTool20241022; vt != nil {
+ return (*int64)(&vt.DisplayHeightPx)
+ } else if vt := u.OfComputerUseTool20250124; vt != nil {
+ return (*int64)(&vt.DisplayHeightPx)
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaMessageCountTokensParamsToolUnion) GetDisplayWidthPx() *int64 {
+ if vt := u.OfComputerUseTool20241022; vt != nil {
+ return (*int64)(&vt.DisplayWidthPx)
+ } else if vt := u.OfComputerUseTool20250124; vt != nil {
+ return (*int64)(&vt.DisplayWidthPx)
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's property, if present.
+func (u BetaMessageCountTokensParamsToolUnion) GetDisplayNumber() *int64 {
+ if vt := u.OfComputerUseTool20241022; vt != nil && vt.DisplayNumber.IsPresent() {
+ return &vt.DisplayNumber.Value
+ } else if vt := u.OfComputerUseTool20250124; vt != nil && vt.DisplayNumber.IsPresent() {
+ return &vt.DisplayNumber.Value
+ }
+ return nil
+}
+
+// Returns a pointer to the underlying variant's CacheControl property, if present.
+func (u BetaMessageCountTokensParamsToolUnion) GetCacheControl() *BetaCacheControlEphemeralParam {
+ if vt := u.OfTool; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfComputerUseTool20241022; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfBashTool20241022; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfTextEditor20241022; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfComputerUseTool20250124; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfBashTool20250124; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return &vt.CacheControl
+ }
+ return nil
}
diff --git a/betamessage_test.go b/betamessage_test.go
index e479321..d46a047 100644
--- a/betamessage_test.go
+++ b/betamessage_test.go
@@ -26,50 +26,57 @@ func TestBetaMessageNewWithOptionalParams(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Beta.Messages.New(context.TODO(), anthropic.BetaMessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.BetaMessageParam{{
- Content: anthropic.F([]anthropic.BetaContentBlockParamUnion{anthropic.BetaTextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.BetaTextBlockParamTypeText), CacheControl: anthropic.F(anthropic.BetaCacheControlEphemeralParam{Type: anthropic.F(anthropic.BetaCacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.BetaTextCitationParamUnion{anthropic.BetaCitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.BetaCitationCharLocationParamTypeCharLocation)}})}}),
- Role: anthropic.F(anthropic.BetaMessageParamRoleUser),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- Metadata: anthropic.F(anthropic.BetaMetadataParam{
- UserID: anthropic.F("13803d75-b4b5-4c3e-b2a2-6f21399b021b"),
- }),
- StopSequences: anthropic.F([]string{"string"}),
- System: anthropic.F([]anthropic.BetaTextBlockParam{{Text: anthropic.F("x"), Type: anthropic.F(anthropic.BetaTextBlockParamTypeText), CacheControl: anthropic.F(anthropic.BetaCacheControlEphemeralParam{Type: anthropic.F(anthropic.BetaCacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.BetaTextCitationParamUnion{anthropic.BetaCitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.BetaCitationCharLocationParamTypeCharLocation)}})}}),
- Temperature: anthropic.F(1.000000),
- Thinking: anthropic.F[anthropic.BetaThinkingConfigParamUnion](anthropic.BetaThinkingConfigEnabledParam{
- BudgetTokens: anthropic.F(int64(1024)),
- Type: anthropic.F(anthropic.BetaThinkingConfigEnabledTypeEnabled),
- }),
- ToolChoice: anthropic.F[anthropic.BetaToolChoiceUnionParam](anthropic.BetaToolChoiceAutoParam{
- Type: anthropic.F(anthropic.BetaToolChoiceAutoTypeAuto),
- DisableParallelToolUse: anthropic.F(true),
- }),
- Tools: anthropic.F([]anthropic.BetaToolUnionUnionParam{anthropic.BetaToolParam{
- InputSchema: anthropic.F(anthropic.BetaToolInputSchemaParam{
- Type: anthropic.F(anthropic.BetaToolInputSchemaTypeObject),
- Properties: anthropic.F[any](map[string]interface{}{
- "location": map[string]interface{}{
- "description": "The city and state, e.g. San Francisco, CA",
- "type": "string",
+ MaxTokens: 1024,
+ Messages: []anthropic.BetaMessageParam{{
+ Content: []anthropic.BetaContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.BetaTextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.BetaCacheControlEphemeralParam{}, Citations: []anthropic.BetaTextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.BetaCitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ Role: anthropic.BetaMessageParamRoleUser,
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ Metadata: anthropic.BetaMetadataParam{
+ UserID: anthropic.String("13803d75-b4b5-4c3e-b2a2-6f21399b021b"),
+ },
+ StopSequences: []string{"string"},
+ System: []anthropic.BetaTextBlockParam{{Text: "x", CacheControl: anthropic.BetaCacheControlEphemeralParam{}, Citations: []anthropic.BetaTextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.BetaCitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}}},
+ Temperature: anthropic.Float(1),
+ Thinking: anthropic.BetaThinkingConfigParamUnion{
+ OfThinkingConfigEnabled: &anthropic.BetaThinkingConfigEnabledParam{
+ BudgetTokens: 1024,
+ },
+ },
+ ToolChoice: anthropic.BetaToolChoiceUnionParam{
+ OfToolChoiceAuto: &anthropic.BetaToolChoiceAutoParam{
+ DisableParallelToolUse: anthropic.Bool(true),
+ },
+ },
+ Tools: []anthropic.BetaToolUnionParam{{
+ OfTool: &anthropic.BetaToolParam{
+ InputSchema: anthropic.BetaToolInputSchemaParam{
+ Properties: map[string]interface{}{
+ "location": map[string]interface{}{
+ "description": "The city and state, e.g. San Francisco, CA",
+ "type": "string",
+ },
+ "unit": map[string]interface{}{
+ "description": "Unit for the output - one of (celsius, fahrenheit)",
+ "type": "string",
+ },
},
- "unit": map[string]interface{}{
- "description": "Unit for the output - one of (celsius, fahrenheit)",
- "type": "string",
- },
- }),
- }),
- Name: anthropic.F("name"),
- CacheControl: anthropic.F(anthropic.BetaCacheControlEphemeralParam{
- Type: anthropic.F(anthropic.BetaCacheControlEphemeralTypeEphemeral),
- }),
- Description: anthropic.F("Get the current weather in a given location"),
- Type: anthropic.F(anthropic.BetaToolTypeCustom),
- }}),
- TopK: anthropic.F(int64(5)),
- TopP: anthropic.F(0.700000),
- Betas: anthropic.F([]anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24}),
+ },
+ Name: "name",
+ CacheControl: anthropic.BetaCacheControlEphemeralParam{},
+ Description: anthropic.String("Get the current weather in a given location"),
+ Type: anthropic.BetaToolTypeCustom,
+ },
+ }},
+ TopK: anthropic.Int(5),
+ TopP: anthropic.Float(0.7),
+ Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24},
})
if err != nil {
var apierr *anthropic.Error
@@ -93,56 +100,61 @@ func TestBetaMessageCountTokensWithOptionalParams(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Beta.Messages.CountTokens(context.TODO(), anthropic.BetaMessageCountTokensParams{
- Messages: anthropic.F([]anthropic.BetaMessageParam{{
- Content: anthropic.F([]anthropic.BetaContentBlockParamUnion{anthropic.BetaTextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.BetaTextBlockParamTypeText), CacheControl: anthropic.F(anthropic.BetaCacheControlEphemeralParam{Type: anthropic.F(anthropic.BetaCacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.BetaTextCitationParamUnion{anthropic.BetaCitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.BetaCitationCharLocationParamTypeCharLocation)}})}}),
- Role: anthropic.F(anthropic.BetaMessageParamRoleUser),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- System: anthropic.F[anthropic.BetaMessageCountTokensParamsSystemUnion](anthropic.BetaMessageCountTokensParamsSystemArray([]anthropic.BetaTextBlockParam{{
- Text: anthropic.F("Today's date is 2024-06-01."),
- Type: anthropic.F(anthropic.BetaTextBlockParamTypeText),
- CacheControl: anthropic.F(anthropic.BetaCacheControlEphemeralParam{
- Type: anthropic.F(anthropic.BetaCacheControlEphemeralTypeEphemeral),
- }),
- Citations: anthropic.F([]anthropic.BetaTextCitationParamUnion{anthropic.BetaCitationCharLocationParam{
- CitedText: anthropic.F("cited_text"),
- DocumentIndex: anthropic.F(int64(0)),
- DocumentTitle: anthropic.F("x"),
- EndCharIndex: anthropic.F(int64(0)),
- StartCharIndex: anthropic.F(int64(0)),
- Type: anthropic.F(anthropic.BetaCitationCharLocationParamTypeCharLocation),
- }}),
- }})),
- Thinking: anthropic.F[anthropic.BetaThinkingConfigParamUnion](anthropic.BetaThinkingConfigEnabledParam{
- BudgetTokens: anthropic.F(int64(1024)),
- Type: anthropic.F(anthropic.BetaThinkingConfigEnabledTypeEnabled),
- }),
- ToolChoice: anthropic.F[anthropic.BetaToolChoiceUnionParam](anthropic.BetaToolChoiceAutoParam{
- Type: anthropic.F(anthropic.BetaToolChoiceAutoTypeAuto),
- DisableParallelToolUse: anthropic.F(true),
- }),
- Tools: anthropic.F([]anthropic.BetaMessageCountTokensParamsToolUnion{anthropic.BetaToolParam{
- InputSchema: anthropic.F(anthropic.BetaToolInputSchemaParam{
- Type: anthropic.F(anthropic.BetaToolInputSchemaTypeObject),
- Properties: anthropic.F[any](map[string]interface{}{
- "location": map[string]interface{}{
- "description": "The city and state, e.g. San Francisco, CA",
- "type": "string",
+ Messages: []anthropic.BetaMessageParam{{
+ Content: []anthropic.BetaContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.BetaTextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.BetaCacheControlEphemeralParam{}, Citations: []anthropic.BetaTextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.BetaCitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ Role: anthropic.BetaMessageParamRoleUser,
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ System: anthropic.BetaMessageCountTokensParamsSystemUnion{
+ OfBetaMessageCountTokenssSystemArray: []anthropic.BetaTextBlockParam{{
+ Text: "Today's date is 2024-06-01.",
+ CacheControl: anthropic.BetaCacheControlEphemeralParam{},
+ Citations: []anthropic.BetaTextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.BetaCitationCharLocationParam{
+ CitedText: "cited_text",
+ DocumentIndex: 0,
+ DocumentTitle: anthropic.String("x"),
+ EndCharIndex: 0,
+ StartCharIndex: 0,
},
- "unit": map[string]interface{}{
- "description": "Unit for the output - one of (celsius, fahrenheit)",
- "type": "string",
+ }},
+ }},
+ },
+ Thinking: anthropic.BetaThinkingConfigParamUnion{
+ OfThinkingConfigEnabled: &anthropic.BetaThinkingConfigEnabledParam{
+ BudgetTokens: 1024,
+ },
+ },
+ ToolChoice: anthropic.BetaToolChoiceUnionParam{
+ OfToolChoiceAuto: &anthropic.BetaToolChoiceAutoParam{
+ DisableParallelToolUse: anthropic.Bool(true),
+ },
+ },
+ Tools: []anthropic.BetaMessageCountTokensParamsToolUnion{{
+ OfTool: &anthropic.BetaToolParam{
+ InputSchema: anthropic.BetaToolInputSchemaParam{
+ Properties: map[string]interface{}{
+ "location": map[string]interface{}{
+ "description": "The city and state, e.g. San Francisco, CA",
+ "type": "string",
+ },
+ "unit": map[string]interface{}{
+ "description": "Unit for the output - one of (celsius, fahrenheit)",
+ "type": "string",
+ },
},
- }),
- }),
- Name: anthropic.F("name"),
- CacheControl: anthropic.F(anthropic.BetaCacheControlEphemeralParam{
- Type: anthropic.F(anthropic.BetaCacheControlEphemeralTypeEphemeral),
- }),
- Description: anthropic.F("Get the current weather in a given location"),
- Type: anthropic.F(anthropic.BetaToolTypeCustom),
- }}),
- Betas: anthropic.F([]anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24}),
+ },
+ Name: "name",
+ CacheControl: anthropic.BetaCacheControlEphemeralParam{},
+ Description: anthropic.String("Get the current weather in a given location"),
+ Type: anthropic.BetaToolTypeCustom,
+ },
+ }},
+ Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24},
})
if err != nil {
var apierr *anthropic.Error
diff --git a/betamessagebatch.go b/betamessagebatch.go
index 74e765e..52cea48 100644
--- a/betamessagebatch.go
+++ b/betamessagebatch.go
@@ -4,21 +4,22 @@ package anthropic
import (
"context"
+ "encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
- "reflect"
"time"
"github.com/anthropics/anthropic-sdk-go/internal/apijson"
"github.com/anthropics/anthropic-sdk-go/internal/apiquery"
- "github.com/anthropics/anthropic-sdk-go/internal/param"
"github.com/anthropics/anthropic-sdk-go/internal/requestconfig"
"github.com/anthropics/anthropic-sdk-go/option"
"github.com/anthropics/anthropic-sdk-go/packages/jsonl"
"github.com/anthropics/anthropic-sdk-go/packages/pagination"
- "github.com/tidwall/gjson"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
+ "github.com/anthropics/anthropic-sdk-go/shared/constant"
)
// BetaMessageBatchService contains methods and other services that help with
@@ -34,8 +35,8 @@ type BetaMessageBatchService struct {
// NewBetaMessageBatchService generates a new service that applies the given
// options to each request. These options are applied after the parent client's
// options (if there is one), and before any request-specific options.
-func NewBetaMessageBatchService(opts ...option.RequestOption) (r *BetaMessageBatchService) {
- r = &BetaMessageBatchService{}
+func NewBetaMessageBatchService(opts ...option.RequestOption) (r BetaMessageBatchService) {
+ r = BetaMessageBatchService{}
r.Options = opts
return
}
@@ -49,7 +50,7 @@ func NewBetaMessageBatchService(opts ...option.RequestOption) (r *BetaMessageBat
// Learn more about the Message Batches API in our
// [user guide](/en/docs/build-with-claude/batch-processing)
func (r *BetaMessageBatchService) New(ctx context.Context, params BetaMessageBatchNewParams, opts ...option.RequestOption) (res *BetaMessageBatch, err error) {
- for _, v := range params.Betas.Value {
+ for _, v := range params.Betas {
opts = append(opts, option.WithHeaderAdd("anthropic-beta", fmt.Sprintf("%s", v)))
}
opts = append(r.Options[:], opts...)
@@ -66,7 +67,7 @@ func (r *BetaMessageBatchService) New(ctx context.Context, params BetaMessageBat
// Learn more about the Message Batches API in our
// [user guide](/en/docs/build-with-claude/batch-processing)
func (r *BetaMessageBatchService) Get(ctx context.Context, messageBatchID string, query BetaMessageBatchGetParams, opts ...option.RequestOption) (res *BetaMessageBatch, err error) {
- for _, v := range query.Betas.Value {
+ for _, v := range query.Betas {
opts = append(opts, option.WithHeaderAdd("anthropic-beta", fmt.Sprintf("%s", v)))
}
opts = append(r.Options[:], opts...)
@@ -87,7 +88,7 @@ func (r *BetaMessageBatchService) Get(ctx context.Context, messageBatchID string
// [user guide](/en/docs/build-with-claude/batch-processing)
func (r *BetaMessageBatchService) List(ctx context.Context, params BetaMessageBatchListParams, opts ...option.RequestOption) (res *pagination.Page[BetaMessageBatch], err error) {
var raw *http.Response
- for _, v := range params.Betas.Value {
+ for _, v := range params.Betas {
opts = append(opts, option.WithHeaderAdd("anthropic-beta", fmt.Sprintf("%s", v)))
}
opts = append(r.Options[:], opts...)
@@ -122,7 +123,7 @@ func (r *BetaMessageBatchService) ListAutoPaging(ctx context.Context, params Bet
// Learn more about the Message Batches API in our
// [user guide](/en/docs/build-with-claude/batch-processing)
func (r *BetaMessageBatchService) Delete(ctx context.Context, messageBatchID string, body BetaMessageBatchDeleteParams, opts ...option.RequestOption) (res *BetaDeletedMessageBatch, err error) {
- for _, v := range body.Betas.Value {
+ for _, v := range body.Betas {
opts = append(opts, option.WithHeaderAdd("anthropic-beta", fmt.Sprintf("%s", v)))
}
opts = append(r.Options[:], opts...)
@@ -149,7 +150,7 @@ func (r *BetaMessageBatchService) Delete(ctx context.Context, messageBatchID str
// Learn more about the Message Batches API in our
// [user guide](/en/docs/build-with-claude/batch-processing)
func (r *BetaMessageBatchService) Cancel(ctx context.Context, messageBatchID string, body BetaMessageBatchCancelParams, opts ...option.RequestOption) (res *BetaMessageBatch, err error) {
- for _, v := range body.Betas.Value {
+ for _, v := range body.Betas {
opts = append(opts, option.WithHeaderAdd("anthropic-beta", fmt.Sprintf("%s", v)))
}
opts = append(r.Options[:], opts...)
@@ -176,7 +177,7 @@ func (r *BetaMessageBatchService) ResultsStreaming(ctx context.Context, messageB
raw *http.Response
err error
)
- for _, v := range query.Betas.Value {
+ for _, v := range query.Betas {
opts = append(opts, option.WithHeaderAdd("anthropic-beta", fmt.Sprintf("%s", v)))
}
opts = append(r.Options[:], opts...)
@@ -196,44 +197,23 @@ type BetaDeletedMessageBatch struct {
// Deleted object type.
//
// For Message Batches, this is always `"message_batch_deleted"`.
- Type BetaDeletedMessageBatchType `json:"type,required"`
- JSON betaDeletedMessageBatchJSON `json:"-"`
-}
-
-// betaDeletedMessageBatchJSON contains the JSON metadata for the struct
-// [BetaDeletedMessageBatch]
-type betaDeletedMessageBatchJSON struct {
- ID apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaDeletedMessageBatch) UnmarshalJSON(data []byte) (err error) {
+ Type constant.MessageBatchDeleted `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaDeletedMessageBatch) RawJSON() string { return r.JSON.raw }
+func (r *BetaDeletedMessageBatch) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaDeletedMessageBatchJSON) RawJSON() string {
- return r.raw
-}
-
-// Deleted object type.
-//
-// For Message Batches, this is always `"message_batch_deleted"`.
-type BetaDeletedMessageBatchType string
-
-const (
- BetaDeletedMessageBatchTypeMessageBatchDeleted BetaDeletedMessageBatchType = "message_batch_deleted"
-)
-
-func (r BetaDeletedMessageBatchType) IsKnown() bool {
- switch r {
- case BetaDeletedMessageBatchTypeMessageBatchDeleted:
- return true
- }
- return false
-}
-
type BetaMessageBatch struct {
// Unique object identifier.
//
@@ -241,10 +221,10 @@ type BetaMessageBatch struct {
ID string `json:"id,required"`
// RFC 3339 datetime string representing the time at which the Message Batch was
// archived and its results became unavailable.
- ArchivedAt time.Time `json:"archived_at,required,nullable" format:"date-time"`
+ ArchivedAt time.Time `json:"archived_at,required" format:"date-time"`
// RFC 3339 datetime string representing the time at which cancellation was
// initiated for the Message Batch. Specified only if cancellation was initiated.
- CancelInitiatedAt time.Time `json:"cancel_initiated_at,required,nullable" format:"date-time"`
+ CancelInitiatedAt time.Time `json:"cancel_initiated_at,required" format:"date-time"`
// RFC 3339 datetime string representing the time at which the Message Batch was
// created.
CreatedAt time.Time `json:"created_at,required" format:"date-time"`
@@ -253,11 +233,13 @@ type BetaMessageBatch struct {
//
// Processing ends when every request in a Message Batch has either succeeded,
// errored, canceled, or expired.
- EndedAt time.Time `json:"ended_at,required,nullable" format:"date-time"`
+ EndedAt time.Time `json:"ended_at,required" format:"date-time"`
// RFC 3339 datetime string representing the time at which the Message Batch will
// expire and end processing, which is 24 hours after creation.
ExpiresAt time.Time `json:"expires_at,required" format:"date-time"`
// Processing status of the Message Batch.
+ //
+ // Any of "in_progress", "canceling", "ended".
ProcessingStatus BetaMessageBatchProcessingStatus `json:"processing_status,required"`
// Tallies requests within the Message Batch, categorized by their status.
//
@@ -270,39 +252,35 @@ type BetaMessageBatch struct {
//
// Results in the file are not guaranteed to be in the same order as requests. Use
// the `custom_id` field to match results to requests.
- ResultsURL string `json:"results_url,required,nullable"`
+ ResultsURL string `json:"results_url,required"`
// Object type.
//
// For Message Batches, this is always `"message_batch"`.
- Type BetaMessageBatchType `json:"type,required"`
- JSON betaMessageBatchJSON `json:"-"`
-}
-
-// betaMessageBatchJSON contains the JSON metadata for the struct
-// [BetaMessageBatch]
-type betaMessageBatchJSON struct {
- ID apijson.Field
- ArchivedAt apijson.Field
- CancelInitiatedAt apijson.Field
- CreatedAt apijson.Field
- EndedAt apijson.Field
- ExpiresAt apijson.Field
- ProcessingStatus apijson.Field
- RequestCounts apijson.Field
- ResultsURL apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaMessageBatch) UnmarshalJSON(data []byte) (err error) {
+ Type constant.MessageBatch `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ ArchivedAt resp.Field
+ CancelInitiatedAt resp.Field
+ CreatedAt resp.Field
+ EndedAt resp.Field
+ ExpiresAt resp.Field
+ ProcessingStatus resp.Field
+ RequestCounts resp.Field
+ ResultsURL resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaMessageBatch) RawJSON() string { return r.JSON.raw }
+func (r *BetaMessageBatch) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaMessageBatchJSON) RawJSON() string {
- return r.raw
-}
-
// Processing status of the Message Batch.
type BetaMessageBatchProcessingStatus string
@@ -312,144 +290,59 @@ const (
BetaMessageBatchProcessingStatusEnded BetaMessageBatchProcessingStatus = "ended"
)
-func (r BetaMessageBatchProcessingStatus) IsKnown() bool {
- switch r {
- case BetaMessageBatchProcessingStatusInProgress, BetaMessageBatchProcessingStatusCanceling, BetaMessageBatchProcessingStatusEnded:
- return true
- }
- return false
-}
-
-// Object type.
-//
-// For Message Batches, this is always `"message_batch"`.
-type BetaMessageBatchType string
-
-const (
- BetaMessageBatchTypeMessageBatch BetaMessageBatchType = "message_batch"
-)
-
-func (r BetaMessageBatchType) IsKnown() bool {
- switch r {
- case BetaMessageBatchTypeMessageBatch:
- return true
- }
- return false
-}
-
type BetaMessageBatchCanceledResult struct {
- Type BetaMessageBatchCanceledResultType `json:"type,required"`
- JSON betaMessageBatchCanceledResultJSON `json:"-"`
-}
-
-// betaMessageBatchCanceledResultJSON contains the JSON metadata for the struct
-// [BetaMessageBatchCanceledResult]
-type betaMessageBatchCanceledResultJSON struct {
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaMessageBatchCanceledResult) UnmarshalJSON(data []byte) (err error) {
+ Type constant.Canceled `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaMessageBatchCanceledResult) RawJSON() string { return r.JSON.raw }
+func (r *BetaMessageBatchCanceledResult) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaMessageBatchCanceledResultJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaMessageBatchCanceledResult) implementsBetaMessageBatchResult() {}
-
-type BetaMessageBatchCanceledResultType string
-
-const (
- BetaMessageBatchCanceledResultTypeCanceled BetaMessageBatchCanceledResultType = "canceled"
-)
-
-func (r BetaMessageBatchCanceledResultType) IsKnown() bool {
- switch r {
- case BetaMessageBatchCanceledResultTypeCanceled:
- return true
- }
- return false
-}
-
type BetaMessageBatchErroredResult struct {
- Error BetaErrorResponse `json:"error,required"`
- Type BetaMessageBatchErroredResultType `json:"type,required"`
- JSON betaMessageBatchErroredResultJSON `json:"-"`
-}
-
-// betaMessageBatchErroredResultJSON contains the JSON metadata for the struct
-// [BetaMessageBatchErroredResult]
-type betaMessageBatchErroredResultJSON struct {
- Error apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaMessageBatchErroredResult) UnmarshalJSON(data []byte) (err error) {
+ Error BetaErrorResponse `json:"error,required"`
+ Type constant.Errored `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Error resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaMessageBatchErroredResult) RawJSON() string { return r.JSON.raw }
+func (r *BetaMessageBatchErroredResult) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaMessageBatchErroredResultJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaMessageBatchErroredResult) implementsBetaMessageBatchResult() {}
-
-type BetaMessageBatchErroredResultType string
-
-const (
- BetaMessageBatchErroredResultTypeErrored BetaMessageBatchErroredResultType = "errored"
-)
-
-func (r BetaMessageBatchErroredResultType) IsKnown() bool {
- switch r {
- case BetaMessageBatchErroredResultTypeErrored:
- return true
- }
- return false
-}
-
type BetaMessageBatchExpiredResult struct {
- Type BetaMessageBatchExpiredResultType `json:"type,required"`
- JSON betaMessageBatchExpiredResultJSON `json:"-"`
-}
-
-// betaMessageBatchExpiredResultJSON contains the JSON metadata for the struct
-// [BetaMessageBatchExpiredResult]
-type betaMessageBatchExpiredResultJSON struct {
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaMessageBatchExpiredResult) UnmarshalJSON(data []byte) (err error) {
+ Type constant.Expired `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaMessageBatchExpiredResult) RawJSON() string { return r.JSON.raw }
+func (r *BetaMessageBatchExpiredResult) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaMessageBatchExpiredResultJSON) RawJSON() string {
- return r.raw
-}
-
-func (r BetaMessageBatchExpiredResult) implementsBetaMessageBatchResult() {}
-
-type BetaMessageBatchExpiredResultType string
-
-const (
- BetaMessageBatchExpiredResultTypeExpired BetaMessageBatchExpiredResultType = "expired"
-)
-
-func (r BetaMessageBatchExpiredResultType) IsKnown() bool {
- switch r {
- case BetaMessageBatchExpiredResultTypeExpired:
- return true
- }
- return false
-}
-
// This is a single line in the response `.jsonl` file and does not represent the
// response as a whole.
type BetaMessageBatchIndividualResponse struct {
@@ -463,27 +356,23 @@ type BetaMessageBatchIndividualResponse struct {
// Contains a Message output if processing was successful, an error response if
// processing failed, or the reason why processing was not attempted, such as
// cancellation or expiration.
- Result BetaMessageBatchResult `json:"result,required"`
- JSON betaMessageBatchIndividualResponseJSON `json:"-"`
-}
-
-// betaMessageBatchIndividualResponseJSON contains the JSON metadata for the struct
-// [BetaMessageBatchIndividualResponse]
-type betaMessageBatchIndividualResponseJSON struct {
- CustomID apijson.Field
- Result apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaMessageBatchIndividualResponse) UnmarshalJSON(data []byte) (err error) {
+ Result BetaMessageBatchResultUnion `json:"result,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ CustomID resp.Field
+ Result resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaMessageBatchIndividualResponse) RawJSON() string { return r.JSON.raw }
+func (r *BetaMessageBatchIndividualResponse) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaMessageBatchIndividualResponseJSON) RawJSON() string {
- return r.raw
-}
-
type BetaMessageBatchRequestCounts struct {
// Number of requests in the Message Batch that have been canceled.
//
@@ -502,206 +391,166 @@ type BetaMessageBatchRequestCounts struct {
// Number of requests in the Message Batch that have completed successfully.
//
// This is zero until processing of the entire Message Batch has ended.
- Succeeded int64 `json:"succeeded,required"`
- JSON betaMessageBatchRequestCountsJSON `json:"-"`
-}
-
-// betaMessageBatchRequestCountsJSON contains the JSON metadata for the struct
-// [BetaMessageBatchRequestCounts]
-type betaMessageBatchRequestCountsJSON struct {
- Canceled apijson.Field
- Errored apijson.Field
- Expired apijson.Field
- Processing apijson.Field
- Succeeded apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaMessageBatchRequestCounts) UnmarshalJSON(data []byte) (err error) {
+ Succeeded int64 `json:"succeeded,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Canceled resp.Field
+ Errored resp.Field
+ Expired resp.Field
+ Processing resp.Field
+ Succeeded resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaMessageBatchRequestCounts) RawJSON() string { return r.JSON.raw }
+func (r *BetaMessageBatchRequestCounts) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaMessageBatchRequestCountsJSON) RawJSON() string {
- return r.raw
-}
-
-// Processing result for this request.
+// BetaMessageBatchResultUnion contains all possible properties and values from
+// [BetaMessageBatchSucceededResult], [BetaMessageBatchErroredResult],
+// [BetaMessageBatchCanceledResult], [BetaMessageBatchExpiredResult].
//
-// Contains a Message output if processing was successful, an error response if
-// processing failed, or the reason why processing was not attempted, such as
-// cancellation or expiration.
-type BetaMessageBatchResult struct {
- Type BetaMessageBatchResultType `json:"type,required"`
- Error BetaErrorResponse `json:"error"`
- Message BetaMessage `json:"message"`
- JSON betaMessageBatchResultJSON `json:"-"`
- union BetaMessageBatchResultUnion
-}
-
-// betaMessageBatchResultJSON contains the JSON metadata for the struct
-// [BetaMessageBatchResult]
-type betaMessageBatchResultJSON struct {
- Type apijson.Field
- Error apijson.Field
- Message apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r betaMessageBatchResultJSON) RawJSON() string {
- return r.raw
-}
-
-func (r *BetaMessageBatchResult) UnmarshalJSON(data []byte) (err error) {
- *r = BetaMessageBatchResult{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
- }
- return apijson.Port(r.union, &r)
-}
-
-// AsUnion returns a [BetaMessageBatchResultUnion] interface which you can cast to
-// the specific types for more type safety.
+// Use the [BetaMessageBatchResultUnion.AsAny] method to switch on the variant.
//
-// Possible runtime types of the union are [BetaMessageBatchSucceededResult],
-// [BetaMessageBatchErroredResult], [BetaMessageBatchCanceledResult],
-// [BetaMessageBatchExpiredResult].
-func (r BetaMessageBatchResult) AsUnion() BetaMessageBatchResultUnion {
- return r.union
-}
-
-// Processing result for this request.
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type BetaMessageBatchResultUnion struct {
+ // This field is from variant [BetaMessageBatchSucceededResult].
+ Message BetaMessage `json:"message"`
+ // Any of "succeeded", "errored", "canceled", "expired".
+ Type string `json:"type"`
+ // This field is from variant [BetaMessageBatchErroredResult].
+ Error BetaErrorResponse `json:"error"`
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ Error resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
//
-// Contains a Message output if processing was successful, an error response if
-// processing failed, or the reason why processing was not attempted, such as
-// cancellation or expiration.
-//
-// Union satisfied by [BetaMessageBatchSucceededResult],
-// [BetaMessageBatchErroredResult], [BetaMessageBatchCanceledResult] or
-// [BetaMessageBatchExpiredResult].
-type BetaMessageBatchResultUnion interface {
- implementsBetaMessageBatchResult()
-}
-
-func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*BetaMessageBatchResultUnion)(nil)).Elem(),
- "type",
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaMessageBatchSucceededResult{}),
- DiscriminatorValue: "succeeded",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaMessageBatchErroredResult{}),
- DiscriminatorValue: "errored",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaMessageBatchCanceledResult{}),
- DiscriminatorValue: "canceled",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(BetaMessageBatchExpiredResult{}),
- DiscriminatorValue: "expired",
- },
- )
-}
-
-type BetaMessageBatchResultType string
-
-const (
- BetaMessageBatchResultTypeSucceeded BetaMessageBatchResultType = "succeeded"
- BetaMessageBatchResultTypeErrored BetaMessageBatchResultType = "errored"
- BetaMessageBatchResultTypeCanceled BetaMessageBatchResultType = "canceled"
- BetaMessageBatchResultTypeExpired BetaMessageBatchResultType = "expired"
-)
-
-func (r BetaMessageBatchResultType) IsKnown() bool {
- switch r {
- case BetaMessageBatchResultTypeSucceeded, BetaMessageBatchResultTypeErrored, BetaMessageBatchResultTypeCanceled, BetaMessageBatchResultTypeExpired:
- return true
+// switch variant := BetaMessageBatchResultUnion.AsAny().(type) {
+// case BetaMessageBatchSucceededResult:
+// case BetaMessageBatchErroredResult:
+// case BetaMessageBatchCanceledResult:
+// case BetaMessageBatchExpiredResult:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u BetaMessageBatchResultUnion) AsAny() any {
+ switch u.Type {
+ case "succeeded":
+ return u.AsSucceededResult()
+ case "errored":
+ return u.AsErroredResult()
+ case "canceled":
+ return u.AsCanceledResult()
+ case "expired":
+ return u.AsExpiredResult()
}
- return false
+ return nil
}
-type BetaMessageBatchSucceededResult struct {
- Message BetaMessage `json:"message,required"`
- Type BetaMessageBatchSucceededResultType `json:"type,required"`
- JSON betaMessageBatchSucceededResultJSON `json:"-"`
+func (u BetaMessageBatchResultUnion) AsSucceededResult() (v BetaMessageBatchSucceededResult) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// betaMessageBatchSucceededResultJSON contains the JSON metadata for the struct
-// [BetaMessageBatchSucceededResult]
-type betaMessageBatchSucceededResultJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func (u BetaMessageBatchResultUnion) AsErroredResult() (v BetaMessageBatchErroredResult) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r *BetaMessageBatchSucceededResult) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+func (u BetaMessageBatchResultUnion) AsCanceledResult() (v BetaMessageBatchCanceledResult) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r betaMessageBatchSucceededResultJSON) RawJSON() string {
- return r.raw
+func (u BetaMessageBatchResultUnion) AsExpiredResult() (v BetaMessageBatchExpiredResult) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r BetaMessageBatchSucceededResult) implementsBetaMessageBatchResult() {}
+// Returns the unmodified JSON received from the API
+func (u BetaMessageBatchResultUnion) RawJSON() string { return u.JSON.raw }
-type BetaMessageBatchSucceededResultType string
-
-const (
- BetaMessageBatchSucceededResultTypeSucceeded BetaMessageBatchSucceededResultType = "succeeded"
-)
+func (r *BetaMessageBatchResultUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-func (r BetaMessageBatchSucceededResultType) IsKnown() bool {
- switch r {
- case BetaMessageBatchSucceededResultTypeSucceeded:
- return true
- }
- return false
+type BetaMessageBatchSucceededResult struct {
+ Message BetaMessage `json:"message,required"`
+ Type constant.Succeeded `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r BetaMessageBatchSucceededResult) RawJSON() string { return r.JSON.raw }
+func (r *BetaMessageBatchSucceededResult) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
type BetaMessageBatchNewParams struct {
// List of requests for prompt completion. Each is an individual request to create
// a Message.
- Requests param.Field[[]BetaMessageBatchNewParamsRequest] `json:"requests,required"`
+ Requests []BetaMessageBatchNewParamsRequest `json:"requests,omitzero,required"`
// Optional header to specify the beta version(s) you want to use.
- Betas param.Field[[]AnthropicBeta] `header:"anthropic-beta"`
+ Betas []AnthropicBeta `header:"anthropic-beta,omitzero" json:"-"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageBatchNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
func (r BetaMessageBatchNewParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaMessageBatchNewParams
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties CustomID, Params are required.
type BetaMessageBatchNewParamsRequest struct {
// Developer-provided ID created for each request in a Message Batch. Useful for
// matching results to requests, as results may be given out of request order.
//
// Must be unique for each request within the Message Batch.
- CustomID param.Field[string] `json:"custom_id,required"`
+ CustomID string `json:"custom_id,required"`
// Messages API creation parameters for the individual request.
//
// See the [Messages API reference](/en/api/messages) for full documentation on
// available parameters.
- Params param.Field[BetaMessageBatchNewParamsRequestsParams] `json:"params,required"`
+ Params BetaMessageBatchNewParamsRequestParams `json:"params,omitzero,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageBatchNewParamsRequest) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r BetaMessageBatchNewParamsRequest) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow BetaMessageBatchNewParamsRequest
+ return param.MarshalObject(r, (*shadow)(&r))
}
// Messages API creation parameters for the individual request.
//
// See the [Messages API reference](/en/api/messages) for full documentation on
// available parameters.
-type BetaMessageBatchNewParamsRequestsParams struct {
+//
+// The properties MaxTokens, Messages, Model are required.
+type BetaMessageBatchNewParamsRequestParams struct {
// The maximum number of tokens to generate before stopping.
//
// Note that our models may stop _before_ reaching this maximum. This parameter
@@ -709,7 +558,7 @@ type BetaMessageBatchNewParamsRequestsParams struct {
//
// Different models have different maximum values for this parameter. See
// [models](https://docs.anthropic.com/en/docs/models-overview) for details.
- MaxTokens param.Field[int64] `json:"max_tokens,required"`
+ MaxTokens int64 `json:"max_tokens,required"`
// Input messages.
//
// Our models are trained to operate on alternating `user` and `assistant`
@@ -802,13 +651,45 @@ type BetaMessageBatchNewParamsRequestsParams struct {
// [system prompt](https://docs.anthropic.com/en/docs/system-prompts), you can use
// the top-level `system` parameter — there is no `"system"` role for input
// messages in the Messages API.
- Messages param.Field[[]BetaMessageParam] `json:"messages,required"`
+ Messages []BetaMessageParam `json:"messages,omitzero,required"`
// The model that will complete your prompt.\n\nSee
// [models](https://docs.anthropic.com/en/docs/models-overview) for additional
// details and options.
- Model param.Field[Model] `json:"model,required"`
+ Model Model `json:"model,omitzero,required"`
+ // Whether to incrementally stream the response using server-sent events.
+ //
+ // See [streaming](https://docs.anthropic.com/en/api/messages-streaming) for
+ // details.
+ Stream param.Opt[bool] `json:"stream,omitzero"`
+ // Amount of randomness injected into the response.
+ //
+ // Defaults to `1.0`. Ranges from `0.0` to `1.0`. Use `temperature` closer to `0.0`
+ // for analytical / multiple choice, and closer to `1.0` for creative and
+ // generative tasks.
+ //
+ // Note that even with `temperature` of `0.0`, the results will not be fully
+ // deterministic.
+ Temperature param.Opt[float64] `json:"temperature,omitzero"`
+ // Only sample from the top K options for each subsequent token.
+ //
+ // Used to remove "long tail" low probability responses.
+ // [Learn more technical details here](https://towardsdatascience.com/how-to-sample-from-language-models-682bceb97277).
+ //
+ // Recommended for advanced use cases only. You usually only need to use
+ // `temperature`.
+ TopK param.Opt[int64] `json:"top_k,omitzero"`
+ // Use nucleus sampling.
+ //
+ // In nucleus sampling, we compute the cumulative distribution over all the options
+ // for each subsequent token in decreasing probability order and cut it off once it
+ // reaches a particular probability specified by `top_p`. You should either alter
+ // `temperature` or `top_p`, but not both.
+ //
+ // Recommended for advanced use cases only. You usually only need to use
+ // `temperature`.
+ TopP param.Opt[float64] `json:"top_p,omitzero"`
// An object describing metadata about the request.
- Metadata param.Field[BetaMetadataParam] `json:"metadata"`
+ Metadata BetaMetadataParam `json:"metadata,omitzero"`
// Custom text sequences that will cause the model to stop generating.
//
// Our models will normally stop when they have naturally completed their turn,
@@ -818,27 +699,13 @@ type BetaMessageBatchNewParamsRequestsParams struct {
// text, you can use the `stop_sequences` parameter. If the model encounters one of
// the custom sequences, the response `stop_reason` value will be `"stop_sequence"`
// and the response `stop_sequence` value will contain the matched stop sequence.
- StopSequences param.Field[[]string] `json:"stop_sequences"`
- // Whether to incrementally stream the response using server-sent events.
- //
- // See [streaming](https://docs.anthropic.com/en/api/messages-streaming) for
- // details.
- Stream param.Field[bool] `json:"stream"`
+ StopSequences []string `json:"stop_sequences,omitzero"`
// System prompt.
//
// A system prompt is a way of providing context and instructions to Claude, such
// as specifying a particular goal or role. See our
// [guide to system prompts](https://docs.anthropic.com/en/docs/system-prompts).
- System param.Field[[]BetaTextBlockParam] `json:"system"`
- // Amount of randomness injected into the response.
- //
- // Defaults to `1.0`. Ranges from `0.0` to `1.0`. Use `temperature` closer to `0.0`
- // for analytical / multiple choice, and closer to `1.0` for creative and
- // generative tasks.
- //
- // Note that even with `temperature` of `0.0`, the results will not be fully
- // deterministic.
- Temperature param.Field[float64] `json:"temperature"`
+ System []BetaTextBlockParam `json:"system,omitzero"`
// Configuration for enabling Claude's extended thinking.
//
// When enabled, responses include `thinking` content blocks showing Claude's
@@ -848,10 +715,10 @@ type BetaMessageBatchNewParamsRequestsParams struct {
// See
// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
// for details.
- Thinking param.Field[BetaThinkingConfigParamUnion] `json:"thinking"`
+ Thinking BetaThinkingConfigParamUnion `json:"thinking,omitzero"`
// How the model should use the provided tools. The model can use a specific tool,
// any available tool, decide by itself, or not use tools at all.
- ToolChoice param.Field[BetaToolChoiceUnionParam] `json:"tool_choice"`
+ ToolChoice BetaToolChoiceUnionParam `json:"tool_choice,omitzero"`
// Definitions of tools that the model may use.
//
// If you include `tools` in your API request, the model may return `tool_use`
@@ -927,51 +794,50 @@ type BetaMessageBatchNewParamsRequestsParams struct {
// JSON structure of output.
//
// See our [guide](https://docs.anthropic.com/en/docs/tool-use) for more details.
- Tools param.Field[[]BetaToolUnionUnionParam] `json:"tools"`
- // Only sample from the top K options for each subsequent token.
- //
- // Used to remove "long tail" low probability responses.
- // [Learn more technical details here](https://towardsdatascience.com/how-to-sample-from-language-models-682bceb97277).
- //
- // Recommended for advanced use cases only. You usually only need to use
- // `temperature`.
- TopK param.Field[int64] `json:"top_k"`
- // Use nucleus sampling.
- //
- // In nucleus sampling, we compute the cumulative distribution over all the options
- // for each subsequent token in decreasing probability order and cut it off once it
- // reaches a particular probability specified by `top_p`. You should either alter
- // `temperature` or `top_p`, but not both.
- //
- // Recommended for advanced use cases only. You usually only need to use
- // `temperature`.
- TopP param.Field[float64] `json:"top_p"`
+ Tools []BetaToolUnionParam `json:"tools,omitzero"`
+ paramObj
}
-func (r BetaMessageBatchNewParamsRequestsParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageBatchNewParamsRequestParams) IsPresent() bool {
+ return !param.IsOmitted(f) && !f.IsNull()
+}
+func (r BetaMessageBatchNewParamsRequestParams) MarshalJSON() (data []byte, err error) {
+ type shadow BetaMessageBatchNewParamsRequestParams
+ return param.MarshalObject(r, (*shadow)(&r))
}
type BetaMessageBatchGetParams struct {
// Optional header to specify the beta version(s) you want to use.
- Betas param.Field[[]AnthropicBeta] `header:"anthropic-beta"`
+ Betas []AnthropicBeta `header:"anthropic-beta,omitzero" json:"-"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageBatchGetParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
type BetaMessageBatchListParams struct {
// ID of the object to use as a cursor for pagination. When provided, returns the
// page of results immediately after this object.
- AfterID param.Field[string] `query:"after_id"`
+ AfterID param.Opt[string] `query:"after_id,omitzero" json:"-"`
// ID of the object to use as a cursor for pagination. When provided, returns the
// page of results immediately before this object.
- BeforeID param.Field[string] `query:"before_id"`
+ BeforeID param.Opt[string] `query:"before_id,omitzero" json:"-"`
// Number of items to return per page.
//
// Defaults to `20`. Ranges from `1` to `1000`.
- Limit param.Field[int64] `query:"limit"`
+ Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
// Optional header to specify the beta version(s) you want to use.
- Betas param.Field[[]AnthropicBeta] `header:"anthropic-beta"`
+ Betas []AnthropicBeta `header:"anthropic-beta,omitzero" json:"-"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageBatchListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
// URLQuery serializes [BetaMessageBatchListParams]'s query parameters as
// `url.Values`.
func (r BetaMessageBatchListParams) URLQuery() (v url.Values) {
@@ -983,15 +849,30 @@ func (r BetaMessageBatchListParams) URLQuery() (v url.Values) {
type BetaMessageBatchDeleteParams struct {
// Optional header to specify the beta version(s) you want to use.
- Betas param.Field[[]AnthropicBeta] `header:"anthropic-beta"`
+ Betas []AnthropicBeta `header:"anthropic-beta,omitzero" json:"-"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageBatchDeleteParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
type BetaMessageBatchCancelParams struct {
// Optional header to specify the beta version(s) you want to use.
- Betas param.Field[[]AnthropicBeta] `header:"anthropic-beta"`
+ Betas []AnthropicBeta `header:"anthropic-beta,omitzero" json:"-"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageBatchCancelParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
type BetaMessageBatchResultsParams struct {
// Optional header to specify the beta version(s) you want to use.
- Betas param.Field[[]AnthropicBeta] `header:"anthropic-beta"`
+ Betas []AnthropicBeta `header:"anthropic-beta,omitzero" json:"-"`
+ paramObj
}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaMessageBatchResultsParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
diff --git a/betamessagebatch_test.go b/betamessagebatch_test.go
index 6a82651..c11eb26 100644
--- a/betamessagebatch_test.go
+++ b/betamessagebatch_test.go
@@ -26,56 +26,63 @@ func TestBetaMessageBatchNewWithOptionalParams(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Beta.Messages.Batches.New(context.TODO(), anthropic.BetaMessageBatchNewParams{
- Requests: anthropic.F([]anthropic.BetaMessageBatchNewParamsRequest{{
- CustomID: anthropic.F("my-custom-id-1"),
- Params: anthropic.F(anthropic.BetaMessageBatchNewParamsRequestsParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.BetaMessageParam{{
- Content: anthropic.F([]anthropic.BetaContentBlockParamUnion{anthropic.BetaTextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.BetaTextBlockParamTypeText), CacheControl: anthropic.F(anthropic.BetaCacheControlEphemeralParam{Type: anthropic.F(anthropic.BetaCacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.BetaTextCitationParamUnion{anthropic.BetaCitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.BetaCitationCharLocationParamTypeCharLocation)}})}}),
- Role: anthropic.F(anthropic.BetaMessageParamRoleUser),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- Metadata: anthropic.F(anthropic.BetaMetadataParam{
- UserID: anthropic.F("13803d75-b4b5-4c3e-b2a2-6f21399b021b"),
- }),
- StopSequences: anthropic.F([]string{"string"}),
- Stream: anthropic.F(true),
- System: anthropic.F([]anthropic.BetaTextBlockParam{{Text: anthropic.F("x"), Type: anthropic.F(anthropic.BetaTextBlockParamTypeText), CacheControl: anthropic.F(anthropic.BetaCacheControlEphemeralParam{Type: anthropic.F(anthropic.BetaCacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.BetaTextCitationParamUnion{anthropic.BetaCitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.BetaCitationCharLocationParamTypeCharLocation)}})}}),
- Temperature: anthropic.F(1.000000),
- Thinking: anthropic.F[anthropic.BetaThinkingConfigParamUnion](anthropic.BetaThinkingConfigEnabledParam{
- BudgetTokens: anthropic.F(int64(1024)),
- Type: anthropic.F(anthropic.BetaThinkingConfigEnabledTypeEnabled),
- }),
- ToolChoice: anthropic.F[anthropic.BetaToolChoiceUnionParam](anthropic.BetaToolChoiceAutoParam{
- Type: anthropic.F(anthropic.BetaToolChoiceAutoTypeAuto),
- DisableParallelToolUse: anthropic.F(true),
- }),
- Tools: anthropic.F([]anthropic.BetaToolUnionUnionParam{anthropic.BetaToolParam{
- InputSchema: anthropic.F(anthropic.BetaToolInputSchemaParam{
- Type: anthropic.F(anthropic.BetaToolInputSchemaTypeObject),
- Properties: anthropic.F[any](map[string]interface{}{
- "location": map[string]interface{}{
- "description": "The city and state, e.g. San Francisco, CA",
- "type": "string",
+ Requests: []anthropic.BetaMessageBatchNewParamsRequest{{
+ CustomID: "my-custom-id-1",
+ Params: anthropic.BetaMessageBatchNewParamsRequestParams{
+ MaxTokens: 1024,
+ Messages: []anthropic.BetaMessageParam{{
+ Content: []anthropic.BetaContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.BetaTextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.BetaCacheControlEphemeralParam{}, Citations: []anthropic.BetaTextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.BetaCitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ Role: anthropic.BetaMessageParamRoleUser,
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ Metadata: anthropic.BetaMetadataParam{
+ UserID: anthropic.String("13803d75-b4b5-4c3e-b2a2-6f21399b021b"),
+ },
+ StopSequences: []string{"string"},
+ Stream: anthropic.Bool(true),
+ System: []anthropic.BetaTextBlockParam{{Text: "x", CacheControl: anthropic.BetaCacheControlEphemeralParam{}, Citations: []anthropic.BetaTextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.BetaCitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}}},
+ Temperature: anthropic.Float(1),
+ Thinking: anthropic.BetaThinkingConfigParamUnion{
+ OfThinkingConfigEnabled: &anthropic.BetaThinkingConfigEnabledParam{
+ BudgetTokens: 1024,
+ },
+ },
+ ToolChoice: anthropic.BetaToolChoiceUnionParam{
+ OfToolChoiceAuto: &anthropic.BetaToolChoiceAutoParam{
+ DisableParallelToolUse: anthropic.Bool(true),
+ },
+ },
+ Tools: []anthropic.BetaToolUnionParam{{
+ OfTool: &anthropic.BetaToolParam{
+ InputSchema: anthropic.BetaToolInputSchemaParam{
+ Properties: map[string]interface{}{
+ "location": map[string]interface{}{
+ "description": "The city and state, e.g. San Francisco, CA",
+ "type": "string",
+ },
+ "unit": map[string]interface{}{
+ "description": "Unit for the output - one of (celsius, fahrenheit)",
+ "type": "string",
+ },
},
- "unit": map[string]interface{}{
- "description": "Unit for the output - one of (celsius, fahrenheit)",
- "type": "string",
- },
- }),
- }),
- Name: anthropic.F("name"),
- CacheControl: anthropic.F(anthropic.BetaCacheControlEphemeralParam{
- Type: anthropic.F(anthropic.BetaCacheControlEphemeralTypeEphemeral),
- }),
- Description: anthropic.F("Get the current weather in a given location"),
- Type: anthropic.F(anthropic.BetaToolTypeCustom),
- }}),
- TopK: anthropic.F(int64(5)),
- TopP: anthropic.F(0.700000),
- }),
- }}),
- Betas: anthropic.F([]anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24}),
+ },
+ Name: "name",
+ CacheControl: anthropic.BetaCacheControlEphemeralParam{},
+ Description: anthropic.String("Get the current weather in a given location"),
+ Type: anthropic.BetaToolTypeCustom,
+ },
+ }},
+ TopK: anthropic.Int(5),
+ TopP: anthropic.Float(0.7),
+ },
+ }},
+ Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24},
})
if err != nil {
var apierr *anthropic.Error
@@ -102,7 +109,7 @@ func TestBetaMessageBatchGetWithOptionalParams(t *testing.T) {
context.TODO(),
"message_batch_id",
anthropic.BetaMessageBatchGetParams{
- Betas: anthropic.F([]anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24}),
+ Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24},
},
)
if err != nil {
@@ -127,10 +134,10 @@ func TestBetaMessageBatchListWithOptionalParams(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Beta.Messages.Batches.List(context.TODO(), anthropic.BetaMessageBatchListParams{
- AfterID: anthropic.F("after_id"),
- BeforeID: anthropic.F("before_id"),
- Limit: anthropic.F(int64(1)),
- Betas: anthropic.F([]anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24}),
+ AfterID: anthropic.String("after_id"),
+ BeforeID: anthropic.String("before_id"),
+ Limit: anthropic.Int(1),
+ Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24},
})
if err != nil {
var apierr *anthropic.Error
@@ -157,7 +164,7 @@ func TestBetaMessageBatchDeleteWithOptionalParams(t *testing.T) {
context.TODO(),
"message_batch_id",
anthropic.BetaMessageBatchDeleteParams{
- Betas: anthropic.F([]anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24}),
+ Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24},
},
)
if err != nil {
@@ -185,7 +192,7 @@ func TestBetaMessageBatchCancelWithOptionalParams(t *testing.T) {
context.TODO(),
"message_batch_id",
anthropic.BetaMessageBatchCancelParams{
- Betas: anthropic.F([]anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24}),
+ Betas: []anthropic.AnthropicBeta{anthropic.AnthropicBetaMessageBatches2024_09_24},
},
)
if err != nil {
diff --git a/betamodel.go b/betamodel.go
index 76d3e64..b9fec3e 100644
--- a/betamodel.go
+++ b/betamodel.go
@@ -12,10 +12,12 @@ import (
"github.com/anthropics/anthropic-sdk-go/internal/apijson"
"github.com/anthropics/anthropic-sdk-go/internal/apiquery"
- "github.com/anthropics/anthropic-sdk-go/internal/param"
"github.com/anthropics/anthropic-sdk-go/internal/requestconfig"
"github.com/anthropics/anthropic-sdk-go/option"
"github.com/anthropics/anthropic-sdk-go/packages/pagination"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
+ "github.com/anthropics/anthropic-sdk-go/shared/constant"
)
// BetaModelService contains methods and other services that help with interacting
@@ -31,8 +33,8 @@ type BetaModelService struct {
// NewBetaModelService generates a new service that applies the given options to
// each request. These options are applied after the parent client's options (if
// there is one), and before any request-specific options.
-func NewBetaModelService(opts ...option.RequestOption) (r *BetaModelService) {
- r = &BetaModelService{}
+func NewBetaModelService(opts ...option.RequestOption) (r BetaModelService) {
+ r = BetaModelService{}
r.Options = opts
return
}
@@ -92,58 +94,43 @@ type BetaModelInfo struct {
// Object type.
//
// For Models, this is always `"model"`.
- Type BetaModelInfoType `json:"type,required"`
- JSON betaModelInfoJSON `json:"-"`
+ Type constant.Model `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ CreatedAt resp.Field
+ DisplayName resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
}
-// betaModelInfoJSON contains the JSON metadata for the struct [BetaModelInfo]
-type betaModelInfoJSON struct {
- ID apijson.Field
- CreatedAt apijson.Field
- DisplayName apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *BetaModelInfo) UnmarshalJSON(data []byte) (err error) {
+// Returns the unmodified JSON received from the API
+func (r BetaModelInfo) RawJSON() string { return r.JSON.raw }
+func (r *BetaModelInfo) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r betaModelInfoJSON) RawJSON() string {
- return r.raw
-}
-
-// Object type.
-//
-// For Models, this is always `"model"`.
-type BetaModelInfoType string
-
-const (
- BetaModelInfoTypeModel BetaModelInfoType = "model"
-)
-
-func (r BetaModelInfoType) IsKnown() bool {
- switch r {
- case BetaModelInfoTypeModel:
- return true
- }
- return false
-}
-
type BetaModelListParams struct {
// ID of the object to use as a cursor for pagination. When provided, returns the
// page of results immediately after this object.
- AfterID param.Field[string] `query:"after_id"`
+ AfterID param.Opt[string] `query:"after_id,omitzero" json:"-"`
// ID of the object to use as a cursor for pagination. When provided, returns the
// page of results immediately before this object.
- BeforeID param.Field[string] `query:"before_id"`
+ BeforeID param.Opt[string] `query:"before_id,omitzero" json:"-"`
// Number of items to return per page.
//
// Defaults to `20`. Ranges from `1` to `1000`.
- Limit param.Field[int64] `query:"limit"`
+ Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f BetaModelListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
// URLQuery serializes [BetaModelListParams]'s query parameters as `url.Values`.
func (r BetaModelListParams) URLQuery() (v url.Values) {
return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
diff --git a/betamodel_test.go b/betamodel_test.go
index 77bf1a8..1cb6042 100644
--- a/betamodel_test.go
+++ b/betamodel_test.go
@@ -48,9 +48,9 @@ func TestBetaModelListWithOptionalParams(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Beta.Models.List(context.TODO(), anthropic.BetaModelListParams{
- AfterID: anthropic.F("after_id"),
- BeforeID: anthropic.F("before_id"),
- Limit: anthropic.F(int64(1)),
+ AfterID: anthropic.String("after_id"),
+ BeforeID: anthropic.String("before_id"),
+ Limit: anthropic.Int(1),
})
if err != nil {
var apierr *anthropic.Error
diff --git a/client.go b/client.go
index 8ece40c..d5549a9 100644
--- a/client.go
+++ b/client.go
@@ -16,17 +16,15 @@ import (
// directly, and instead use the [NewClient] method instead.
type Client struct {
Options []option.RequestOption
- Completions *CompletionService
- Messages *MessageService
- Models *ModelService
- Beta *BetaService
+ Completions CompletionService
+ Messages MessageService
+ Models ModelService
+ Beta BetaService
}
-// NewClient generates a new client with the default option read from the
-// environment (ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN). The option passed in as
-// arguments are applied after these default arguments, and all option will be
-// passed down to the services and requests that this client makes.
-func NewClient(opts ...option.RequestOption) (r *Client) {
+// DefaultClientOptions read from the environment (ANTHROPIC_API_KEY,
+// ANTHROPIC_AUTH_TOKEN). This should be used to initialize new clients.
+func DefaultClientOptions() []option.RequestOption {
defaults := []option.RequestOption{option.WithEnvironmentProduction()}
if o, ok := os.LookupEnv("ANTHROPIC_API_KEY"); ok {
defaults = append(defaults, option.WithAPIKey(o))
@@ -34,9 +32,17 @@ func NewClient(opts ...option.RequestOption) (r *Client) {
if o, ok := os.LookupEnv("ANTHROPIC_AUTH_TOKEN"); ok {
defaults = append(defaults, option.WithAuthToken(o))
}
- opts = append(defaults, opts...)
+ return defaults
+}
+
+// NewClient generates a new client with the default option read from the
+// environment (ANTHROPIC_API_KEY, ANTHROPIC_AUTH_TOKEN). The option passed in as
+// arguments are applied after these default arguments, and all option will be
+// passed down to the services and requests that this client makes.
+func NewClient(opts ...option.RequestOption) (r Client) {
+ opts = append(DefaultClientOptions(), opts...)
- r = &Client{Options: opts}
+ r = Client{Options: opts}
r.Completions = NewCompletionService(opts...)
r.Messages = NewMessageService(opts...)
diff --git a/client_test.go b/client_test.go
index 7cd6621..50774e4 100644
--- a/client_test.go
+++ b/client_test.go
@@ -27,6 +27,7 @@ func (t *closureTransport) RoundTrip(req *http.Request) (*http.Response, error)
func TestUserAgentHeader(t *testing.T) {
var userAgent string
client := anthropic.NewClient(
+ option.WithAPIKey("my-anthropic-api-key"),
option.WithHTTPClient(&http.Client{
Transport: &closureTransport{
fn: func(req *http.Request) (*http.Response, error) {
@@ -39,12 +40,16 @@ func TestUserAgentHeader(t *testing.T) {
}),
)
client.Messages.New(context.Background(), anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
if userAgent != fmt.Sprintf("Anthropic/Go %s", internal.PackageVersion) {
t.Errorf("Expected User-Agent to be correct, but got: %#v", userAgent)
@@ -54,6 +59,7 @@ func TestUserAgentHeader(t *testing.T) {
func TestRetryAfter(t *testing.T) {
retryCountHeaders := make([]string, 0)
client := anthropic.NewClient(
+ option.WithAPIKey("my-anthropic-api-key"),
option.WithHTTPClient(&http.Client{
Transport: &closureTransport{
fn: func(req *http.Request) (*http.Response, error) {
@@ -69,12 +75,16 @@ func TestRetryAfter(t *testing.T) {
}),
)
_, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
if err == nil {
t.Error("Expected there to be a cancel error")
@@ -94,6 +104,7 @@ func TestRetryAfter(t *testing.T) {
func TestDeleteRetryCountHeader(t *testing.T) {
retryCountHeaders := make([]string, 0)
client := anthropic.NewClient(
+ option.WithAPIKey("my-anthropic-api-key"),
option.WithHTTPClient(&http.Client{
Transport: &closureTransport{
fn: func(req *http.Request) (*http.Response, error) {
@@ -110,12 +121,16 @@ func TestDeleteRetryCountHeader(t *testing.T) {
option.WithHeaderDel("X-Stainless-Retry-Count"),
)
_, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
if err == nil {
t.Error("Expected there to be a cancel error")
@@ -130,6 +145,7 @@ func TestDeleteRetryCountHeader(t *testing.T) {
func TestOverwriteRetryCountHeader(t *testing.T) {
retryCountHeaders := make([]string, 0)
client := anthropic.NewClient(
+ option.WithAPIKey("my-anthropic-api-key"),
option.WithHTTPClient(&http.Client{
Transport: &closureTransport{
fn: func(req *http.Request) (*http.Response, error) {
@@ -146,12 +162,16 @@ func TestOverwriteRetryCountHeader(t *testing.T) {
option.WithHeader("X-Stainless-Retry-Count", "42"),
)
_, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
if err == nil {
t.Error("Expected there to be a cancel error")
@@ -166,6 +186,7 @@ func TestOverwriteRetryCountHeader(t *testing.T) {
func TestRetryAfterMs(t *testing.T) {
attempts := 0
client := anthropic.NewClient(
+ option.WithAPIKey("my-anthropic-api-key"),
option.WithHTTPClient(&http.Client{
Transport: &closureTransport{
fn: func(req *http.Request) (*http.Response, error) {
@@ -181,12 +202,16 @@ func TestRetryAfterMs(t *testing.T) {
}),
)
_, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
if err == nil {
t.Error("Expected there to be a cancel error")
@@ -198,6 +223,7 @@ func TestRetryAfterMs(t *testing.T) {
func TestContextCancel(t *testing.T) {
client := anthropic.NewClient(
+ option.WithAPIKey("my-anthropic-api-key"),
option.WithHTTPClient(&http.Client{
Transport: &closureTransport{
fn: func(req *http.Request) (*http.Response, error) {
@@ -210,12 +236,16 @@ func TestContextCancel(t *testing.T) {
cancelCtx, cancel := context.WithCancel(context.Background())
cancel()
_, err := client.Messages.New(cancelCtx, anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
if err == nil {
t.Error("Expected there to be a cancel error")
@@ -224,6 +254,7 @@ func TestContextCancel(t *testing.T) {
func TestContextCancelDelay(t *testing.T) {
client := anthropic.NewClient(
+ option.WithAPIKey("my-anthropic-api-key"),
option.WithHTTPClient(&http.Client{
Transport: &closureTransport{
fn: func(req *http.Request) (*http.Response, error) {
@@ -236,12 +267,16 @@ func TestContextCancelDelay(t *testing.T) {
cancelCtx, cancel := context.WithTimeout(context.Background(), 2*time.Millisecond)
defer cancel()
_, err := client.Messages.New(cancelCtx, anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
if err == nil {
t.Error("expected there to be a cancel error")
@@ -258,6 +293,7 @@ func TestContextDeadline(t *testing.T) {
go func() {
client := anthropic.NewClient(
+ option.WithAPIKey("my-anthropic-api-key"),
option.WithHTTPClient(&http.Client{
Transport: &closureTransport{
fn: func(req *http.Request) (*http.Response, error) {
@@ -268,12 +304,16 @@ func TestContextDeadline(t *testing.T) {
}),
)
_, err := client.Messages.New(deadlineCtx, anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Role: anthropic.MessageParamRoleUser,
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
if err == nil {
t.Error("expected there to be a deadline error")
@@ -301,6 +341,7 @@ func TestContextDeadlineStreaming(t *testing.T) {
go func() {
client := anthropic.NewClient(
+ option.WithAPIKey("my-anthropic-api-key"),
option.WithHTTPClient(&http.Client{
Transport: &closureTransport{
fn: func(req *http.Request) (*http.Response, error) {
@@ -319,12 +360,16 @@ func TestContextDeadlineStreaming(t *testing.T) {
}),
)
stream := client.Messages.NewStreaming(deadlineCtx, anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ Role: anthropic.MessageParamRoleUser,
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
})
for stream.Next() {
_ = stream.Current()
@@ -352,6 +397,7 @@ func TestContextDeadlineStreamingWithRequestTimeout(t *testing.T) {
go func() {
client := anthropic.NewClient(
+ option.WithAPIKey("my-anthropic-api-key"),
option.WithHTTPClient(&http.Client{
Transport: &closureTransport{
fn: func(req *http.Request) (*http.Response, error) {
@@ -372,12 +418,16 @@ func TestContextDeadlineStreamingWithRequestTimeout(t *testing.T) {
stream := client.Messages.NewStreaming(
context.Background(),
anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ Role: anthropic.MessageParamRoleUser,
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
},
option.WithRequestTimeout((100 * time.Millisecond)),
)
diff --git a/completion.go b/completion.go
index 4489146..e768ab2 100644
--- a/completion.go
+++ b/completion.go
@@ -7,10 +7,12 @@ import (
"net/http"
"github.com/anthropics/anthropic-sdk-go/internal/apijson"
- "github.com/anthropics/anthropic-sdk-go/internal/param"
"github.com/anthropics/anthropic-sdk-go/internal/requestconfig"
"github.com/anthropics/anthropic-sdk-go/option"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
"github.com/anthropics/anthropic-sdk-go/packages/ssestream"
+ "github.com/anthropics/anthropic-sdk-go/shared/constant"
)
// CompletionService contains methods and other services that help with interacting
@@ -26,8 +28,8 @@ type CompletionService struct {
// NewCompletionService generates a new service that applies the given options to
// each request. These options are applied after the parent client's options (if
// there is one), and before any request-specific options.
-func NewCompletionService(opts ...option.RequestOption) (r *CompletionService) {
- r = &CompletionService{}
+func NewCompletionService(opts ...option.RequestOption) (r CompletionService) {
+ r = CompletionService{}
r.Options = opts
return
}
@@ -89,60 +91,40 @@ type Completion struct {
// - `"stop_sequence"`: we reached a stop sequence — either provided by you via the
// `stop_sequences` parameter, or a stop sequence built into the model
// - `"max_tokens"`: we exceeded `max_tokens_to_sample` or the model's maximum
- StopReason string `json:"stop_reason,required,nullable"`
+ StopReason string `json:"stop_reason,required"`
// Object type.
//
// For Text Completions, this is always `"completion"`.
- Type CompletionType `json:"type,required"`
- JSON completionJSON `json:"-"`
+ Type constant.Completion `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ Completion resp.Field
+ Model resp.Field
+ StopReason resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
}
-// completionJSON contains the JSON metadata for the struct [Completion]
-type completionJSON struct {
- ID apijson.Field
- Completion apijson.Field
- Model apijson.Field
- StopReason apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *Completion) UnmarshalJSON(data []byte) (err error) {
+// Returns the unmodified JSON received from the API
+func (r Completion) RawJSON() string { return r.JSON.raw }
+func (r *Completion) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r completionJSON) RawJSON() string {
- return r.raw
-}
-
-// Object type.
-//
-// For Text Completions, this is always `"completion"`.
-type CompletionType string
-
-const (
- CompletionTypeCompletion CompletionType = "completion"
-)
-
-func (r CompletionType) IsKnown() bool {
- switch r {
- case CompletionTypeCompletion:
- return true
- }
- return false
-}
-
type CompletionNewParams struct {
// The maximum number of tokens to generate before stopping.
//
// Note that our models may stop _before_ reaching this maximum. This parameter
// only specifies the absolute maximum number of tokens to generate.
- MaxTokensToSample param.Field[int64] `json:"max_tokens_to_sample,required"`
+ MaxTokensToSample int64 `json:"max_tokens_to_sample,required"`
// The model that will complete your prompt.\n\nSee
// [models](https://docs.anthropic.com/en/docs/models-overview) for additional
// details and options.
- Model param.Field[Model] `json:"model,required"`
+ Model Model `json:"model,omitzero,required"`
// The prompt that you want Claude to complete.
//
// For proper response generation you will need to format your prompt using
@@ -156,15 +138,7 @@ type CompletionNewParams struct {
// our guide to
// [prompt design](https://docs.anthropic.com/en/docs/intro-to-prompting) for more
// details.
- Prompt param.Field[string] `json:"prompt,required"`
- // An object describing metadata about the request.
- Metadata param.Field[MetadataParam] `json:"metadata"`
- // Sequences that will cause the model to stop generating.
- //
- // Our models stop on `"\n\nHuman:"`, and may include additional built-in stop
- // sequences in the future. By providing the stop_sequences parameter, you may
- // include additional strings that will cause the model to stop generating.
- StopSequences param.Field[[]string] `json:"stop_sequences"`
+ Prompt string `json:"prompt,required"`
// Amount of randomness injected into the response.
//
// Defaults to `1.0`. Ranges from `0.0` to `1.0`. Use `temperature` closer to `0.0`
@@ -173,7 +147,7 @@ type CompletionNewParams struct {
//
// Note that even with `temperature` of `0.0`, the results will not be fully
// deterministic.
- Temperature param.Field[float64] `json:"temperature"`
+ Temperature param.Opt[float64] `json:"temperature,omitzero"`
// Only sample from the top K options for each subsequent token.
//
// Used to remove "long tail" low probability responses.
@@ -181,7 +155,7 @@ type CompletionNewParams struct {
//
// Recommended for advanced use cases only. You usually only need to use
// `temperature`.
- TopK param.Field[int64] `json:"top_k"`
+ TopK param.Opt[int64] `json:"top_k,omitzero"`
// Use nucleus sampling.
//
// In nucleus sampling, we compute the cumulative distribution over all the options
@@ -191,9 +165,23 @@ type CompletionNewParams struct {
//
// Recommended for advanced use cases only. You usually only need to use
// `temperature`.
- TopP param.Field[float64] `json:"top_p"`
+ TopP param.Opt[float64] `json:"top_p,omitzero"`
+ // An object describing metadata about the request.
+ Metadata MetadataParam `json:"metadata,omitzero"`
+ // Sequences that will cause the model to stop generating.
+ //
+ // Our models stop on `"\n\nHuman:"`, and may include additional built-in stop
+ // sequences in the future. By providing the stop_sequences parameter, you may
+ // include additional strings that will cause the model to stop generating.
+ StopSequences []string `json:"stop_sequences,omitzero"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f CompletionNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
func (r CompletionNewParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow CompletionNewParams
+ return param.MarshalObject(r, (*shadow)(&r))
}
diff --git a/completion_test.go b/completion_test.go
index 708008b..edc613b 100644
--- a/completion_test.go
+++ b/completion_test.go
@@ -26,16 +26,16 @@ func TestCompletionNewWithOptionalParams(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Completions.New(context.TODO(), anthropic.CompletionNewParams{
- MaxTokensToSample: anthropic.F(int64(256)),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- Prompt: anthropic.F("\n\nHuman: Hello, world!\n\nAssistant:"),
- Metadata: anthropic.F(anthropic.MetadataParam{
- UserID: anthropic.F("13803d75-b4b5-4c3e-b2a2-6f21399b021b"),
- }),
- StopSequences: anthropic.F([]string{"string"}),
- Temperature: anthropic.F(1.000000),
- TopK: anthropic.F(int64(5)),
- TopP: anthropic.F(0.700000),
+ MaxTokensToSample: 256,
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ Prompt: "\n\nHuman: Hello, world!\n\nAssistant:",
+ Metadata: anthropic.MetadataParam{
+ UserID: anthropic.String("13803d75-b4b5-4c3e-b2a2-6f21399b021b"),
+ },
+ StopSequences: []string{"string"},
+ Temperature: anthropic.Float(1),
+ TopK: anthropic.Int(5),
+ TopP: anthropic.Float(0.7),
})
if err != nil {
var apierr *anthropic.Error
diff --git a/examples/bedrock-streaming/main.go b/examples/bedrock-streaming/main.go
index 3cbde70..6579376 100644
--- a/examples/bedrock-streaming/main.go
+++ b/examples/bedrock-streaming/main.go
@@ -2,7 +2,6 @@ package main
import (
"context"
-
"github.com/anthropics/anthropic-sdk-go"
"github.com/anthropics/anthropic-sdk-go/bedrock"
)
@@ -17,12 +16,12 @@ func main() {
println("[user]: " + content)
stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F([]anthropic.MessageParam{
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
- }),
- Model: anthropic.F("anthropic.claude-3-sonnet-20240229-v1:0"),
- StopSequences: anthropic.F([]string{"```\n"}),
+ },
+ Model: "us.anthropic.claude-3-5-haiku-20241022-v1:0",
+ StopSequences: []string{"```\n"},
})
print("[assistant]: ")
@@ -30,14 +29,13 @@ func main() {
for stream.Next() {
event := stream.Current()
- switch delta := event.Delta.(type) {
- case anthropic.ContentBlockDeltaEventDelta:
- if delta.Text != "" {
- print(delta.Text)
- }
- case anthropic.MessageDeltaEventDelta:
- if delta.StopSequence != "" {
- print(delta.StopSequence)
+ switch eventVariant := event.AsAny().(type) {
+ case anthropic.MessageDeltaEvent:
+ print(eventVariant.Delta.StopSequence)
+ case anthropic.ContentBlockDeltaEvent:
+ switch deltaVariant := eventVariant.Delta.AsAny().(type) {
+ case anthropic.TextDelta:
+ print(deltaVariant.Text)
}
}
}
diff --git a/examples/bedrock/main.go b/examples/bedrock/main.go
index f5a955c..f854be8 100644
--- a/examples/bedrock/main.go
+++ b/examples/bedrock/main.go
@@ -17,12 +17,12 @@ func main() {
println("[user]: " + content)
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F([]anthropic.MessageParam{
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
- }),
- Model: anthropic.F("anthropic.claude-3-sonnet-20240229-v1:0"),
- StopSequences: anthropic.F([]string{"```\n"}),
+ },
+ Model: "us.anthropic.claude-3-5-haiku-20241022-v1:0",
+ StopSequences: []string{"```\n"},
})
if err != nil {
panic(err)
diff --git a/examples/message-streaming/main.go b/examples/message-streaming/main.go
index 4ec65c8..9a69d1a 100644
--- a/examples/message-streaming/main.go
+++ b/examples/message-streaming/main.go
@@ -2,6 +2,7 @@ package main
import (
"context"
+ "fmt"
"github.com/anthropics/anthropic-sdk-go"
)
@@ -14,12 +15,12 @@ func main() {
println("[user]: " + content)
stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F([]anthropic.MessageParam{
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
- }),
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- StopSequences: anthropic.F([]string{"```\n"}),
+ },
+ Model: anthropic.ModelClaude_3_5_Sonnet_20240620,
+ StopSequences: []string{"```\n"},
})
print("[assistant]: ")
@@ -27,14 +28,13 @@ func main() {
for stream.Next() {
event := stream.Current()
- switch delta := event.Delta.(type) {
- case anthropic.ContentBlockDeltaEventDelta:
- if delta.Text != "" {
- print(delta.Text)
- }
- case anthropic.MessageDeltaEventDelta:
- if delta.StopSequence != "" {
- print(delta.StopSequence)
+ switch eventVariant := event.AsAny().(type) {
+ case anthropic.MessageDeltaEvent:
+ print(eventVariant.Delta.StopSequence)
+ case anthropic.ContentBlockDeltaEvent:
+ switch deltaVariant := eventVariant.Delta.AsAny().(type) {
+ case anthropic.TextDelta:
+ print(deltaVariant.Text)
}
}
}
diff --git a/examples/message/main.go b/examples/message/main.go
index 3c2a590..8d3b4c9 100644
--- a/examples/message/main.go
+++ b/examples/message/main.go
@@ -14,15 +14,12 @@ func main() {
println("[user]: " + content)
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.Int(1024),
- System: anthropic.F([]anthropic.TextBlockParam{
- anthropic.NewTextBlock("Be very serious"),
- }),
- Messages: anthropic.F([]anthropic.MessageParam{
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
- }),
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- StopSequences: anthropic.F([]string{"```\n"}),
+ },
+ Model: anthropic.ModelClaude_3_5_Sonnet_20240620,
+ StopSequences: []string{"```\n"},
})
if err != nil {
panic(err)
diff --git a/examples/multimodal/main.go b/examples/multimodal/main.go
index a58cc5a..00f9a6c 100644
--- a/examples/multimodal/main.go
+++ b/examples/multimodal/main.go
@@ -28,15 +28,15 @@ func main() {
fileEncoded := base64.StdEncoding.EncodeToString(fileBytes)
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F([]anthropic.MessageParam{
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(
anthropic.NewTextBlock(content),
anthropic.NewImageBlockBase64("image/png", fileEncoded),
),
- }),
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- StopSequences: anthropic.F([]string{"```\n"}),
+ },
+ Model: anthropic.ModelClaude_3_5_Sonnet_20240620,
+ StopSequences: []string{"```\n"},
})
if err != nil {
panic(err)
diff --git a/examples/multimodal/nine_dogs.png b/examples/multimodal/nine_dogs.png
new file mode 100644
index 0000000..1e211ce
Binary files /dev/null and b/examples/multimodal/nine_dogs.png differ
diff --git a/examples/tools-streaming-jsonschema/main.go b/examples/tools-streaming-jsonschema/main.go
index 33c7cad..6e5d080 100644
--- a/examples/tools-streaming-jsonschema/main.go
+++ b/examples/tools-streaming-jsonschema/main.go
@@ -20,29 +20,33 @@ func main() {
anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
}
- tools := []anthropic.ToolParam{
+ toolParams := []anthropic.ToolParam{
{
- Name: anthropic.F("get_coordinates"),
- Description: anthropic.F("Accepts a place as an address, then returns the latitude and longitude coordinates."),
- InputSchema: anthropic.F(GetCoordinatesInputSchema),
+ Name: "get_coordinates",
+ Description: anthropic.String("Accepts a place as an address, then returns the latitude and longitude coordinates."),
+ InputSchema: GetCoordinatesInputSchema,
},
{
- Name: anthropic.F("get_temperature_unit"),
- InputSchema: anthropic.F(GetTemperatureUnitInputSchema),
+ Name: "get_temperature_unit",
+ InputSchema: GetTemperatureUnitInputSchema,
},
{
- Name: anthropic.F("get_weather"),
- Description: anthropic.F("Get the weather at a specific location"),
- InputSchema: anthropic.F(GetWeatherInputSchema),
+ Name: "get_weather",
+ Description: anthropic.String("Get the weather at a specific location"),
+ InputSchema: GetWeatherInputSchema,
},
}
+ tools := make([]anthropic.ToolUnionParam, len(toolParams))
+ for i, toolParam := range toolParams {
+ tools[i] = anthropic.ToolUnionParam{OfTool: &toolParam}
+ }
for {
stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F(messages),
- Tools: anthropic.F(tools),
+ Model: anthropic.ModelClaude3_7Sonnet20250219,
+ MaxTokens: 1024,
+ Messages: messages,
+ Tools: tools,
})
print(color("[assistant]: "))
@@ -55,7 +59,7 @@ func main() {
panic(err)
}
- switch event := event.AsUnion().(type) {
+ switch event := event.AsAny().(type) {
case anthropic.ContentBlockStartEvent:
if event.ContentBlock.Name != "" {
print(event.ContentBlock.Name + ": ")
@@ -79,28 +83,29 @@ func main() {
toolResults := []anthropic.ContentBlockParamUnion{}
for _, block := range message.Content {
- if block.Type == anthropic.ContentBlockTypeToolUse {
+ switch variant := block.AsAny().(type) {
+ case anthropic.ToolUseBlock:
print(color("[user (" + block.Name + ")]: "))
var response interface{}
switch block.Name {
case "get_coordinates":
input := GetCoordinatesInput{}
- err := json.Unmarshal(block.Input, &input)
+ err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
if err != nil {
panic(err)
}
response = GetCoordinates(input.Location)
case "get_temperature_unit":
input := GetTemperatureUnitInput{}
- err := json.Unmarshal(block.Input, &input)
+ err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
if err != nil {
panic(err)
}
response = GetTemperatureUnit(input.Country)
case "get_weather":
input := GetWeatherInput{}
- err := json.Unmarshal(block.Input, &input)
+ err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
if err != nil {
panic(err)
}
@@ -122,10 +127,7 @@ func main() {
break
}
- messages = append(messages, anthropic.MessageParam{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F(toolResults),
- })
+ messages = append(messages, anthropic.NewUserMessage(toolResults...))
}
}
@@ -183,13 +185,18 @@ func GetWeather(lat, long float64, unit string) GetWeatherResponse {
}
}
-func GenerateSchema[T any]() interface{} {
+func GenerateSchema[T any]() anthropic.ToolInputSchemaParam {
reflector := jsonschema.Reflector{
AllowAdditionalProperties: false,
DoNotReference: true,
}
var v T
- return reflector.Reflect(v)
+
+ schema := reflector.Reflect(v)
+
+ return anthropic.ToolInputSchemaParam{
+ Properties: schema.Properties,
+ }
}
func color(s string) string {
diff --git a/examples/tools-streaming/main.go b/examples/tools-streaming/main.go
index b9b49d1..0e6f71d 100644
--- a/examples/tools-streaming/main.go
+++ b/examples/tools-streaming/main.go
@@ -19,38 +19,35 @@ func main() {
anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
}
- tools := []anthropic.ToolParam{
+ toolParams := []anthropic.ToolParam{
{
- Name: anthropic.F("get_coordinates"),
- Description: anthropic.F("Accepts a place as an address, then returns the latitude and longitude coordinates."),
- InputSchema: anthropic.F[interface{}](map[string]interface{}{
- "type": "object",
- "properties": map[string]interface{}{
+ Name: "get_coordinates",
+ Description: anthropic.String("Accepts a place as an address, then returns the latitude and longitude coordinates."),
+ InputSchema: anthropic.ToolInputSchemaParam{
+ Properties: map[string]interface{}{
"location": map[string]interface{}{
"type": "string",
"description": "The location to look up.",
},
},
- }),
+ },
},
{
- Name: anthropic.F("get_temperature_unit"),
- InputSchema: anthropic.F[interface{}](map[string]interface{}{
- "type": "object",
- "properties": map[string]interface{}{
+ Name: "get_temperature_unit",
+ InputSchema: anthropic.ToolInputSchemaParam{
+ Properties: map[string]interface{}{
"country": map[string]interface{}{
"type": "string",
"description": "The country",
},
},
- }),
+ },
},
{
- Name: anthropic.F("get_weather"),
- Description: anthropic.F("Get the weather at a specific location"),
- InputSchema: anthropic.F[interface{}](map[string]interface{}{
- "type": "object",
- "properties": map[string]interface{}{
+ Name: "get_weather",
+ Description: anthropic.String("Get the weather at a specific location"),
+ InputSchema: anthropic.ToolInputSchemaParam{
+ Properties: map[string]interface{}{
"lat": map[string]interface{}{
"type": "number",
"description": "The lattitude of the location to check weather.",
@@ -65,16 +62,20 @@ func main() {
"description": "Unit for the output",
},
},
- }),
+ },
},
}
+ tools := make([]anthropic.ToolUnionParam, len(toolParams))
+ for i, toolParam := range toolParams {
+ tools[i] = anthropic.ToolUnionParam{OfTool: &toolParam}
+ }
for {
stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F(messages),
- Tools: anthropic.F(tools),
+ Model: anthropic.ModelClaude3_7Sonnet20250219,
+ MaxTokens: 1024,
+ Messages: messages,
+ Tools: tools,
})
print(color("[assistant]: "))
@@ -87,7 +88,7 @@ func main() {
panic(err)
}
- switch event := event.AsUnion().(type) {
+ switch event := event.AsAny().(type) {
case anthropic.ContentBlockStartEvent:
if event.ContentBlock.Name != "" {
print(event.ContentBlock.Name + ": ")
@@ -111,7 +112,8 @@ func main() {
toolResults := []anthropic.ContentBlockParamUnion{}
for _, block := range message.Content {
- if block.Type == anthropic.ContentBlockTypeToolUse {
+ switch variant := block.AsAny().(type) {
+ case anthropic.ToolUseBlock:
print(color("[user (" + block.Name + ")]: "))
var response interface{}
@@ -120,7 +122,7 @@ func main() {
var input struct {
Location string `json:"location"`
}
- err := json.Unmarshal(block.Input, &input)
+ err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
if err != nil {
panic(err)
}
@@ -129,7 +131,7 @@ func main() {
var input struct {
Country string `json:"country"`
}
- err := json.Unmarshal(block.Input, &input)
+ err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
if err != nil {
panic(err)
}
@@ -140,7 +142,7 @@ func main() {
Long float64 `json:"long"`
Unit string `json:"unit"`
}
- err := json.Unmarshal(block.Input, &input)
+ err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
if err != nil {
panic(err)
}
@@ -162,10 +164,7 @@ func main() {
break
}
- messages = append(messages, anthropic.MessageParam{
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- Content: anthropic.F(toolResults),
- })
+ messages = append(messages, anthropic.NewUserMessage(toolResults...))
}
}
diff --git a/examples/tools/main.go b/examples/tools/main.go
index 864e622..a6274eb 100644
--- a/examples/tools/main.go
+++ b/examples/tools/main.go
@@ -19,38 +19,35 @@ func main() {
anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
}
- tools := []anthropic.ToolParam{
+ toolParams := []anthropic.ToolParam{
{
- Name: anthropic.F("get_coordinates"),
- Description: anthropic.F("Accepts a place as an address, then returns the latitude and longitude coordinates."),
- InputSchema: anthropic.F[interface{}](map[string]interface{}{
- "type": "object",
- "properties": map[string]interface{}{
+ Name: "get_coordinates",
+ Description: anthropic.String("Accepts a place as an address, then returns the latitude and longitude coordinates."),
+ InputSchema: anthropic.ToolInputSchemaParam{
+ Properties: map[string]interface{}{
"location": map[string]interface{}{
"type": "string",
"description": "The location to look up.",
},
},
- }),
+ },
},
{
- Name: anthropic.F("get_temperature_unit"),
- InputSchema: anthropic.F[interface{}](map[string]interface{}{
- "type": "object",
- "properties": map[string]interface{}{
+ Name: "get_temperature_unit",
+ InputSchema: anthropic.ToolInputSchemaParam{
+ Properties: map[string]interface{}{
"country": map[string]interface{}{
"type": "string",
"description": "The country",
},
},
- }),
+ },
},
{
- Name: anthropic.F("get_weather"),
- Description: anthropic.F("Get the weather at a specific location"),
- InputSchema: anthropic.F[interface{}](map[string]interface{}{
- "type": "object",
- "properties": map[string]interface{}{
+ Name: "get_weather",
+ Description: anthropic.String("Get the weather at a specific location"),
+ InputSchema: anthropic.ToolInputSchemaParam{
+ Properties: map[string]interface{}{
"lat": map[string]interface{}{
"type": "number",
"description": "The lattitude of the location to check weather.",
@@ -65,16 +62,20 @@ func main() {
"description": "Unit for the output",
},
},
- }),
+ },
},
}
+ tools := make([]anthropic.ToolUnionParam, len(toolParams))
+ for i, toolParam := range toolParams {
+ tools[i] = anthropic.ToolUnionParam{OfTool: &toolParam}
+ }
for {
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- Model: anthropic.F(anthropic.ModelClaude3_5SonnetLatest),
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F(messages),
- Tools: anthropic.F(tools),
+ Model: anthropic.ModelClaude_3_5_Sonnet_20240620,
+ MaxTokens: 1024,
+ Messages: messages,
+ Tools: tools,
})
if err != nil {
@@ -84,12 +85,13 @@ func main() {
print(color("[assistant]: "))
for _, block := range message.Content {
- switch block := block.AsUnion().(type) {
+ switch block := block.AsAny().(type) {
case anthropic.TextBlock:
println(block.Text)
println()
case anthropic.ToolUseBlock:
- println(block.Name + ": " + string(block.Input))
+ inputJSON, _ := json.Marshal(block.Input)
+ println(block.Name + ": " + string(inputJSON))
println()
}
}
@@ -99,7 +101,8 @@ func main() {
toolResults := []anthropic.ContentBlockParamUnion{}
for _, block := range message.Content {
- if block.Type == anthropic.ContentBlockTypeToolUse {
+ switch variant := block.AsAny().(type) {
+ case anthropic.ToolUseBlock:
print(color("[user (" + block.Name + ")]: "))
var response interface{}
@@ -108,16 +111,18 @@ func main() {
var input struct {
Location string `json:"location"`
}
- err := json.Unmarshal(block.Input, &input)
+
+ err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
if err != nil {
panic(err)
}
+
response = GetCoordinates(input.Location)
case "get_temperature_unit":
var input struct {
Country string `json:"country"`
}
- err := json.Unmarshal(block.Input, &input)
+ err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
if err != nil {
panic(err)
}
@@ -128,7 +133,7 @@ func main() {
Long float64 `json:"long"`
Unit string `json:"unit"`
}
- err := json.Unmarshal(block.Input, &input)
+ err := json.Unmarshal([]byte(variant.JSON.Input.Raw()), &input)
if err != nil {
panic(err)
}
diff --git a/examples/vertex-streaming/main.go b/examples/vertex-streaming/main.go
index 0256e66..33cd37f 100644
--- a/examples/vertex-streaming/main.go
+++ b/examples/vertex-streaming/main.go
@@ -2,14 +2,13 @@ package main
import (
"context"
-
"github.com/anthropics/anthropic-sdk-go"
"github.com/anthropics/anthropic-sdk-go/vertex"
)
func main() {
client := anthropic.NewClient(
- vertex.WithGoogleAuth(context.Background(), "us-central1", "stainless-399616"),
+ vertex.WithGoogleAuth(context.Background(), "us-central1", "id-xxx"),
)
content := "Write me a function to call the Anthropic message API in Node.js using the Anthropic Typescript SDK."
@@ -17,12 +16,12 @@ func main() {
println("[user]: " + content)
stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F([]anthropic.MessageParam{
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
- }),
- Model: anthropic.F("claude-3-sonnet@20240229"),
- StopSequences: anthropic.F([]string{"```\n"}),
+ },
+ Model: "claude-3-5-sonnet-v2@20241022",
+ StopSequences: []string{"```\n"},
})
print("[assistant]: ")
@@ -30,16 +29,17 @@ func main() {
for stream.Next() {
event := stream.Current()
- switch delta := event.Delta.(type) {
- case anthropic.ContentBlockDeltaEventDelta:
- if delta.Text != "" {
- print(delta.Text)
+ switch variant := event.AsAny().(type) {
+ case anthropic.ContentBlockDeltaEvent:
+ if variant.Delta.Text != "" {
+ print(variant.Delta.Text)
}
- case anthropic.MessageDeltaEventDelta:
- if delta.StopSequence != "" {
- print(delta.StopSequence)
+ case anthropic.MessageDeltaEvent:
+ if variant.Delta.StopSequence != "" {
+ print(variant.Delta.StopSequence)
}
}
+
}
println()
diff --git a/examples/vertex/main.go b/examples/vertex/main.go
index 092ecbd..6dc6d2e 100644
--- a/examples/vertex/main.go
+++ b/examples/vertex/main.go
@@ -2,27 +2,26 @@ package main
import (
"context"
+ "github.com/anthropics/anthropic-sdk-go/vertex"
"github.com/anthropics/anthropic-sdk-go"
- "github.com/anthropics/anthropic-sdk-go/vertex"
)
func main() {
client := anthropic.NewClient(
- vertex.WithGoogleAuth(context.Background(), "us-central1", "stainless-399616"),
+ vertex.WithGoogleAuth(context.Background(), "us-central1", "id-xxx"),
)
-
content := "Write me a function to call the Anthropic message API in Node.js using the Anthropic Typescript SDK."
println("[user]: " + content)
message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.Int(1024),
- Messages: anthropic.F([]anthropic.MessageParam{
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{
anthropic.NewUserMessage(anthropic.NewTextBlock(content)),
- }),
- Model: anthropic.F("claude-3-sonnet@20240229"),
- StopSequences: anthropic.F([]string{"```\n"}),
+ },
+ Model: "claude-3-5-sonnet-v2@20241022",
+ StopSequences: []string{"```\n"},
})
if err != nil {
panic(err)
diff --git a/field.go b/field.go
index ab83192..8c2fd50 100644
--- a/field.go
+++ b/field.go
@@ -1,43 +1,28 @@
package anthropic
import (
- "github.com/anthropics/anthropic-sdk-go/internal/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
"io"
+ "time"
)
-// F is a param field helper used to initialize a [param.Field] generic struct.
-// This helps specify null, zero values, and overrides, as well as normal values.
-// You can read more about this in our [README].
-//
-// [README]: https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#readme-request-fields
-func F[T any](value T) param.Field[T] { return param.Field[T]{Value: value, Present: true} }
+func String(s string) param.Opt[string] { return param.NewOpt(s) }
+func Int(i int64) param.Opt[int64] { return param.NewOpt(i) }
+func Bool(b bool) param.Opt[bool] { return param.NewOpt(b) }
+func Float(f float64) param.Opt[float64] { return param.NewOpt(f) }
+func Time(t time.Time) param.Opt[time.Time] { return param.NewOpt(t) }
-// Null is a param field helper which explicitly sends null to the API.
-func Null[T any]() param.Field[T] { return param.Field[T]{Null: true, Present: true} }
+func Opt[T comparable](v T) param.Opt[T] { return param.NewOpt(v) }
+func Ptr[T any](v T) *T { return &v }
-// Raw is a param field helper for specifying values for fields when the
-// type you are looking to send is different from the type that is specified in
-// the SDK. For example, if the type of the field is an integer, but you want
-// to send a float, you could do that by setting the corresponding field with
-// Raw[int](0.5).
-func Raw[T any](value any) param.Field[T] { return param.Field[T]{Raw: value, Present: true} }
+func IntPtr(v int64) *int64 { return &v }
+func BoolPtr(v bool) *bool { return &v }
+func FloatPtr(v float64) *float64 { return &v }
+func StringPtr(v string) *string { return &v }
+func TimePtr(v time.Time) *time.Time { return &v }
-// Int is a param field helper which helps specify integers. This is
-// particularly helpful when specifying integer constants for fields.
-func Int(value int64) param.Field[int64] { return F(value) }
-
-// String is a param field helper which helps specify strings.
-func String(value string) param.Field[string] { return F(value) }
-
-// Float is a param field helper which helps specify floats.
-func Float(value float64) param.Field[float64] { return F(value) }
-
-// Bool is a param field helper which helps specify bools.
-func Bool(value bool) param.Field[bool] { return F(value) }
-
-// FileParam is a param field helper which helps files with a mime content-type.
-func FileParam(reader io.Reader, filename string, contentType string) param.Field[io.Reader] {
- return F[io.Reader](&file{reader, filename, contentType})
+func File(rdr io.Reader, filename string, contentType string) file {
+ return file{rdr, filename, contentType}
}
type file struct {
@@ -46,5 +31,15 @@ type file struct {
contentType string
}
-func (f *file) ContentType() string { return f.contentType }
-func (f *file) Filename() string { return f.name }
+func (f file) Filename() string {
+ if f.name != "" {
+ return f.name
+ } else if named, ok := f.Reader.(interface{ Name() string }); ok {
+ return named.Name()
+ }
+ return ""
+}
+
+func (f file) ContentType() string {
+ return f.contentType
+}
diff --git a/go.mod b/go.mod
index 59d9048..8f37d06 100644
--- a/go.mod
+++ b/go.mod
@@ -2,13 +2,20 @@ module github.com/anthropics/anthropic-sdk-go
go 1.21
+require (
+ github.com/aws/aws-sdk-go-v2 v1.30.3
+ github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3
+ github.com/aws/aws-sdk-go-v2/config v1.27.27
+ github.com/tidwall/gjson v1.14.4
+ github.com/tidwall/sjson v1.2.5
+ golang.org/x/oauth2 v0.21.0
+ google.golang.org/api v0.189.0
+)
+
require (
cloud.google.com/go/auth v0.7.2 // indirect
cloud.google.com/go/auth/oauth2adapt v0.2.3 // indirect
cloud.google.com/go/compute/metadata v0.5.0 // indirect
- github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect
- github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
- github.com/aws/aws-sdk-go-v2/config v1.27.27 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect
@@ -26,12 +33,9 @@ require (
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/s2a-go v0.1.7 // indirect
- github.com/google/uuid v1.6.0 // indirect
github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect
- github.com/tidwall/gjson v1.14.4 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
- github.com/tidwall/sjson v1.2.5 // indirect
go.opencensus.io v0.24.0 // indirect
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
@@ -40,12 +44,10 @@ require (
go.opentelemetry.io/otel/trace v1.24.0 // indirect
golang.org/x/crypto v0.25.0 // indirect
golang.org/x/net v0.27.0 // indirect
- golang.org/x/oauth2 v0.21.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
- google.golang.org/api v0.189.0 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade // indirect
google.golang.org/grpc v1.64.1 // indirect
google.golang.org/protobuf v1.34.2 // indirect
diff --git a/go.sum b/go.sum
index 5d70b97..912e1aa 100644
--- a/go.sum
+++ b/go.sum
@@ -1,11 +1,8 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14=
cloud.google.com/go/auth v0.7.2 h1:uiha352VrCDMXg+yoBtaD0tUF4Kv9vrtrWPYXwutnDE=
cloud.google.com/go/auth v0.7.2/go.mod h1:VEc4p5NNxycWQTMQEDQF0bd6aTMb6VgYDXEwiJJQAbs=
cloud.google.com/go/auth/oauth2adapt v0.2.3 h1:MlxF+Pd3OmSudg/b1yZ5lJwoXCEaeedAguodky1PcKI=
cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I=
-cloud.google.com/go/compute/metadata v0.3.0 h1:Tz+eQXMEqDIKRsmY3cHTL6FVaynIjX2QxYC4trgAKZc=
-cloud.google.com/go/compute/metadata v0.3.0/go.mod h1:zFmK7XCadkQkj6TtorcaGlCW1hT1fIilQDwofLpJ20k=
cloud.google.com/go/compute/metadata v0.5.0 h1:Zr0eK8JbFv6+Wi4ilXAR8FJ3wyNdpxHKJNPos6LTZOY=
cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
@@ -41,6 +38,7 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
@@ -75,14 +73,14 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
+github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs=
github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
@@ -91,6 +89,8 @@ github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpE
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
+github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
+github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
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=
@@ -162,7 +162,6 @@ google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20240722135656-d784300faade h1:lKFsS7wpngDgSCeFn7MoLy+wBDQZ1UQIJD4UNM1Qvkg=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade h1:oCRSWfwGXQsqlVdErcyTt4A93Y8fo0/9D4b1gnI++qo=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -185,6 +184,7 @@ google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6h
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
diff --git a/internal/apierror/apierror.go b/internal/apierror/apierror.go
index c17aaf3..1c08c6e 100644
--- a/internal/apierror/apierror.go
+++ b/internal/apierror/apierror.go
@@ -8,35 +8,33 @@ import (
"net/http/httputil"
"github.com/anthropics/anthropic-sdk-go/internal/apijson"
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
)
// Error represents an error that originates from the API, i.e. when a request is
// made and the API returns a response with a HTTP status code. Other errors are
// not wrapped by this SDK.
type Error struct {
- JSON errorJSON `json:"-"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
StatusCode int
Request *http.Request
Response *http.Response
}
-// errorJSON contains the JSON metadata for the struct [Error]
-type errorJSON struct {
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *Error) UnmarshalJSON(data []byte) (err error) {
+// Returns the unmodified JSON received from the API
+func (r Error) RawJSON() string { return r.JSON.raw }
+func (r *Error) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r errorJSON) RawJSON() string {
- return r.raw
-}
-
func (r *Error) Error() string {
// Attempt to re-populate the response body
- return fmt.Sprintf("%s \"%s\": %d %s %s", r.Request.Method, r.Request.URL, r.Response.StatusCode, http.StatusText(r.Response.StatusCode), r.JSON.RawJSON())
+ return fmt.Sprintf("%s %q: %d %s %s", r.Request.Method, r.Request.URL, r.Response.StatusCode, http.StatusText(r.Response.StatusCode), r.JSON.raw)
}
func (r *Error) DumpRequest(body bool) []byte {
diff --git a/internal/apiform/encoder.go b/internal/apiform/encoder.go
index 707670c..164d260 100644
--- a/internal/apiform/encoder.go
+++ b/internal/apiform/encoder.go
@@ -13,7 +13,8 @@ import (
"sync"
"time"
- "github.com/anthropics/anthropic-sdk-go/internal/param"
+ internalparam "github.com/anthropics/anthropic-sdk-go/internal/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
)
var encoders sync.Map // map[encoderEntry]encoderFunc
@@ -180,10 +181,14 @@ func (e *encoder) newArrayTypeEncoder(t reflect.Type) encoderFunc {
}
func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
- if t.Implements(reflect.TypeOf((*param.FieldLike)(nil)).Elem()) {
+ if t.Implements(reflect.TypeOf((*internalparam.FieldLike)(nil)).Elem()) {
return e.newFieldTypeEncoder(t)
}
+ if idx, ok := param.OptionalPrimitiveTypes[t]; ok {
+ return e.newRichFieldTypeEncoder(t, idx)
+ }
+
encoderFields := []encoderField{}
extraEncoder := (*encoderField)(nil)
@@ -217,7 +222,7 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
extraEncoder = &encoderField{ptag, e.typeEncoder(field.Type.Elem()), idx}
continue
}
- if ptag.name == "-" {
+ if ptag.name == "-" || ptag.name == "" {
continue
}
@@ -231,7 +236,20 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
e.dateFormat = "2006-01-02"
}
}
- encoderFields = append(encoderFields, encoderField{ptag, e.typeEncoder(field.Type), idx})
+
+ var encoderFn encoderFunc
+ if ptag.omitzero {
+ typeEncoderFn := e.typeEncoder(field.Type)
+ encoderFn = func(key string, value reflect.Value, writer *multipart.Writer) error {
+ if value.IsZero() {
+ return nil
+ }
+ return typeEncoderFn(key, value, writer)
+ }
+ } else {
+ encoderFn = e.typeEncoder(field.Type)
+ }
+ encoderFields = append(encoderFields, encoderField{ptag, encoderFn, idx})
e.dateFormat = oldFormat
}
}
diff --git a/internal/apiform/richparam.go b/internal/apiform/richparam.go
new file mode 100644
index 0000000..929e51e
--- /dev/null
+++ b/internal/apiform/richparam.go
@@ -0,0 +1,20 @@
+package apiform
+
+import (
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "mime/multipart"
+ "reflect"
+)
+
+func (e *encoder) newRichFieldTypeEncoder(t reflect.Type, underlyingValueIdx []int) encoderFunc {
+ underlying := t.FieldByIndex(underlyingValueIdx)
+ primitiveEncoder := e.newPrimitiveTypeEncoder(underlying.Type)
+ return func(key string, value reflect.Value, writer *multipart.Writer) error {
+ if opt, ok := value.Interface().(param.Optional); ok && opt.IsPresent() {
+ return primitiveEncoder(key, value.FieldByIndex(underlyingValueIdx), writer)
+ } else if ok && opt.IsNull() {
+ return writer.WriteField(key, "null")
+ }
+ return nil
+ }
+}
diff --git a/internal/apiform/tag.go b/internal/apiform/tag.go
index b22e054..736fc1e 100644
--- a/internal/apiform/tag.go
+++ b/internal/apiform/tag.go
@@ -14,6 +14,7 @@ type parsedStructTag struct {
required bool
extras bool
metadata bool
+ omitzero bool
}
func parseFormStructTag(field reflect.StructField) (tag parsedStructTag, ok bool) {
@@ -37,6 +38,8 @@ func parseFormStructTag(field reflect.StructField) (tag parsedStructTag, ok bool
tag.extras = true
case "metadata":
tag.metadata = true
+ case "omitzero":
+ tag.omitzero = true
}
}
return
diff --git a/internal/apijson/decoder.go b/internal/apijson/decoder.go
index 68b7ed6..b3bd832 100644
--- a/internal/apijson/decoder.go
+++ b/internal/apijson/decoder.go
@@ -173,6 +173,9 @@ func (d *decoderBuilder) newTypeDecoder(t reflect.Type) decoderFunc {
return nil
}
case reflect.Struct:
+ if isEmbeddedUnion(t) {
+ return d.newEmbeddedUnionDecoder(t)
+ }
return d.newStructTypeDecoder(t)
case reflect.Array:
fallthrough
@@ -343,7 +346,7 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc {
decoderFields := map[string]decoderField{}
anonymousDecoders := []decoderField{}
extraDecoder := (*decoderField)(nil)
- inlineDecoder := (*decoderField)(nil)
+ var inlineDecoders []decoderField
for i := 0; i < t.NumField(); i++ {
idx := []int{i}
@@ -373,7 +376,8 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc {
continue
}
if ptag.inline {
- inlineDecoder = &decoderField{ptag, d.typeDecoder(field.Type), idx, field.Name}
+ df := decoderField{ptag, d.typeDecoder(field.Type), idx, field.Name}
+ inlineDecoders = append(inlineDecoders, df)
continue
}
if ptag.metadata {
@@ -406,12 +410,13 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc {
decoder.fn(node, value.FieldByIndex(decoder.idx), state)
}
- if inlineDecoder != nil {
+ for _, inlineDecoder := range inlineDecoders {
var meta Field
dest := value.FieldByIndex(inlineDecoder.idx)
isValid := false
if dest.IsValid() && node.Type != gjson.Null {
- err = inlineDecoder.fn(node, dest, state)
+ inlineState := decoderState{exactness: state.exactness, strict: true}
+ err = inlineDecoder.fn(node, dest, &inlineState)
if err == nil {
isValid = true
}
@@ -423,20 +428,18 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc {
status: null,
}
} else if !isValid {
- meta = Field{
- raw: node.Raw,
- status: invalid,
+ // If an inline decoder fails, unset the field and move on.
+ if dest.IsValid() {
+ dest.SetZero()
}
+ continue
} else if isValid {
meta = Field{
raw: node.Raw,
status: valid,
}
}
- if metadata := getSubField(value, inlineDecoder.idx, inlineDecoder.goname); metadata.IsValid() {
- metadata.Set(reflect.ValueOf(meta))
- }
- return err
+ setMetadataSubField(value, inlineDecoder.idx, inlineDecoder.goname, meta)
}
typedExtraType := reflect.Type(nil)
@@ -489,9 +492,7 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc {
}
if explicit {
- if metadata := getSubField(value, df.idx, df.goname); metadata.IsValid() {
- metadata.Set(reflect.ValueOf(meta))
- }
+ setMetadataSubField(value, df.idx, df.goname, meta)
}
if !explicit {
untypedExtraFields[fieldName] = meta
@@ -510,8 +511,8 @@ func (d *decoderBuilder) newStructTypeDecoder(t reflect.Type) decoderFunc {
state.exactness = extras
}
- if metadata := getSubField(value, []int{-1}, "ExtraFields"); metadata.IsValid() && len(untypedExtraFields) > 0 {
- metadata.Set(reflect.ValueOf(untypedExtraFields))
+ if len(untypedExtraFields) > 0 {
+ setMetadataExtraFields(value, []int{-1}, "ExtraFields", untypedExtraFields)
}
return nil
}
@@ -662,9 +663,17 @@ func canParseAsNumber(str string) bool {
return err == nil
}
+var stringType = reflect.TypeOf(string(""))
+
func guardUnknown(state *decoderState, v reflect.Value) bool {
if have, ok := v.Interface().(interface{ IsKnown() bool }); guardStrict(state, ok && !have.IsKnown()) {
return true
}
+
+ constantString, ok := v.Interface().(interface{ Default() string })
+ named := v.Type() != stringType
+ if guardStrict(state, ok && named && v.Equal(reflect.ValueOf(constantString.Default()))) {
+ return true
+ }
return false
}
diff --git a/internal/apijson/encoder.go b/internal/apijson/encoder.go
index 0ad0a12..0fb294f 100644
--- a/internal/apijson/encoder.go
+++ b/internal/apijson/encoder.go
@@ -381,7 +381,7 @@ func (e *encoder) encodeMapEntries(json []byte, v reflect.Value) ([]byte, error)
return json, nil
}
-func (e *encoder) newMapEncoder(t reflect.Type) encoderFunc {
+func (e *encoder) newMapEncoder(_ reflect.Type) encoderFunc {
return func(value reflect.Value) ([]byte, error) {
json := []byte("{}")
var err error
diff --git a/internal/apijson/enum.go b/internal/apijson/enum.go
new file mode 100644
index 0000000..ec98f8c
--- /dev/null
+++ b/internal/apijson/enum.go
@@ -0,0 +1,87 @@
+package apijson
+
+import (
+ "fmt"
+ "reflect"
+ "sync"
+)
+
+/********************/
+/* Validating Enums */
+/********************/
+
+type validationEntry struct {
+ field reflect.StructField
+ nullable bool
+ legalValues []reflect.Value
+}
+
+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, nullable bool, values ...V) {
+ var t T
+ parentType := reflect.TypeOf(t)
+
+ if _, ok := validationRegistry[parentType]; !ok {
+ validationRegistry[parentType] = []validationEntry{}
+ }
+
+ // The following checks run at initialization time,
+ // it is impossible for them to panic if any tests pass.
+ if parentType.Kind() != reflect.Struct {
+ panic(fmt.Sprintf("apijson: cannot initialize validator for non-struct %s", parentType.String()))
+ }
+ field, found := parentType.FieldByName(fieldName)
+ if !found {
+ panic(fmt.Sprintf("apijson: cannot initialize validator for unknown field %q in %s", fieldName, parentType.String()))
+ }
+
+ newEntry := validationEntry{field, nullable, make([]reflect.Value, len(values))}
+ for i, value := range values {
+ newEntry.legalValues[i] = reflect.ValueOf(value)
+ }
+
+ // Store the information necessary to create a validator, so that we can use it
+ // lazily create the validator function when did.
+ validationRegistry[parentType] = append(validationRegistry[parentType], newEntry)
+}
+
+// Enums are the only types which are validated
+func typeValidator(t reflect.Type) validatorFunc {
+ entry, ok := validationRegistry[t]
+ if !ok {
+ return nil
+ }
+
+ if fi, ok := validators.Load(t); ok {
+ return fi.(validatorFunc)
+ }
+
+ fi, _ := validators.LoadOrStore(t, validatorFunc(func(v reflect.Value) exactness {
+ return validateEnum(v, entry)
+ }))
+ return fi.(validatorFunc)
+}
+
+func validateEnum(v reflect.Value, entry []validationEntry) exactness {
+ if v.Kind() != reflect.Struct {
+ return loose
+ }
+
+ for _, check := range entry {
+ field := v.FieldByIndex(check.field.Index)
+ if !field.IsValid() {
+ return loose
+ }
+ for _, opt := range check.legalValues {
+ if field.Equal(opt) {
+ return exact
+ }
+ }
+ }
+
+ return loose
+}
diff --git a/internal/apijson/field.go b/internal/apijson/field.go
index 3ef207c..854d6dd 100644
--- a/internal/apijson/field.go
+++ b/internal/apijson/field.go
@@ -1,7 +1,5 @@
package apijson
-import "reflect"
-
type status uint8
const (
@@ -23,19 +21,3 @@ func (j Field) IsNull() bool { return j.status <= null }
func (j Field) IsMissing() bool { return j.status == missing }
func (j Field) IsInvalid() bool { return j.status == invalid }
func (j Field) Raw() string { return j.raw }
-
-func getSubField(root reflect.Value, index []int, name string) reflect.Value {
- strct := root.FieldByIndex(index[:len(index)-1])
- if !strct.IsValid() {
- panic("couldn't find encapsulating struct for field " + name)
- }
- meta := strct.FieldByName("JSON")
- if !meta.IsValid() {
- return reflect.Value{}
- }
- field := meta.FieldByName(name)
- if !field.IsValid() {
- return reflect.Value{}
- }
- return field
-}
diff --git a/internal/apijson/json_test.go b/internal/apijson/json_test.go
index e656344..0c4de11 100644
--- a/internal/apijson/json_test.go
+++ b/internal/apijson/json_test.go
@@ -86,8 +86,8 @@ type JSONFieldStruct struct {
B int64 `json:"b"`
C string `json:"c"`
D string `json:"d"`
- ExtraFields map[string]int64 `json:"-,extras"`
- JSON JSONFieldStructJSON `json:"-,metadata"`
+ ExtraFields map[string]int64 `json:",extras"`
+ JSON JSONFieldStructJSON `json:",metadata"`
}
type JSONFieldStructJSON struct {
@@ -112,13 +112,13 @@ type Union interface {
}
type Inline struct {
- InlineField Primitives `json:"-,inline"`
- JSON InlineJSON `json:"-,metadata"`
+ InlineField Primitives `json:",inline"`
+ JSON InlineJSON `json:",metadata"`
}
type InlineArray struct {
- InlineField []string `json:"-,inline"`
- JSON InlineJSON `json:"-,metadata"`
+ InlineField []string `json:",inline"`
+ JSON InlineJSON `json:",metadata"`
}
type InlineJSON struct {
@@ -150,7 +150,7 @@ type UnionTime time.Time
func (UnionTime) union() {}
func init() {
- RegisterUnion(reflect.TypeOf((*Union)(nil)).Elem(), "type",
+ RegisterUnion[Union]("type",
UnionVariant{
TypeFilter: gjson.String,
Type: reflect.TypeOf(UnionTime{}),
@@ -237,7 +237,7 @@ func (r *UnmarshalStruct) UnmarshalJSON(json []byte) error {
func (ComplexUnionTypeB) complexUnion() {}
func init() {
- RegisterUnion(reflect.TypeOf((*ComplexUnion)(nil)).Elem(), "",
+ RegisterUnion[ComplexUnion]("",
UnionVariant{
TypeFilter: gjson.JSON,
Type: reflect.TypeOf(ComplexUnionA{}),
@@ -300,8 +300,7 @@ func (r *MarshallingUnionB) UnmarshalJSON(data []byte) (err error) {
}
func init() {
- RegisterUnion(
- reflect.TypeOf((*MarshallingUnion)(nil)).Elem(),
+ RegisterUnion[MarshallingUnion](
"",
UnionVariant{
TypeFilter: gjson.JSON,
diff --git a/internal/apijson/port.go b/internal/apijson/port.go
index 502ab77..b40013c 100644
--- a/internal/apijson/port.go
+++ b/internal/apijson/port.go
@@ -53,7 +53,7 @@ func Port(from any, to any) error {
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
ptag, ok := parseJSONStructTag(field)
- if !ok || ptag.name == "-" {
+ if !ok || ptag.name == "-" || ptag.name == "" {
continue
}
values[ptag.name] = v.Field(i)
diff --git a/internal/apijson/registry.go b/internal/apijson/registry.go
index 119cc5f..e82c1d5 100644
--- a/internal/apijson/registry.go
+++ b/internal/apijson/registry.go
@@ -20,7 +20,8 @@ type unionEntry struct {
variants []UnionVariant
}
-func RegisterUnion(typ reflect.Type, discriminator string, variants ...UnionVariant) {
+func RegisterUnion[T any](discriminator string, variants ...UnionVariant) {
+ typ := reflect.TypeOf((*T)(nil)).Elem()
unionRegistry[typ] = unionEntry{
discriminatorKey: discriminator,
variants: variants,
diff --git a/internal/apijson/subfield.go b/internal/apijson/subfield.go
new file mode 100644
index 0000000..9785f60
--- /dev/null
+++ b/internal/apijson/subfield.go
@@ -0,0 +1,67 @@
+package apijson
+
+import (
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
+ "reflect"
+)
+
+func getSubField(root reflect.Value, index []int, name string) reflect.Value {
+ strct := root.FieldByIndex(index[:len(index)-1])
+ if !strct.IsValid() {
+ panic("couldn't find encapsulating struct for field " + name)
+ }
+ meta := strct.FieldByName("JSON")
+ if !meta.IsValid() {
+ return reflect.Value{}
+ }
+ field := meta.FieldByName(name)
+ if !field.IsValid() {
+ return reflect.Value{}
+ }
+ return field
+}
+
+func setMetadataSubField(root reflect.Value, index []int, name string, meta Field) {
+ target := getSubField(root, index, name)
+ if !target.IsValid() {
+ return
+ }
+
+ if target.Type() == reflect.TypeOf(meta) {
+ target.Set(reflect.ValueOf(meta))
+ } else if respMeta := meta.toRespField(); target.Type() == reflect.TypeOf(respMeta) {
+ target.Set(reflect.ValueOf(respMeta))
+ }
+}
+
+func setMetadataExtraFields(root reflect.Value, index []int, name string, metaExtras map[string]Field) {
+ target := getSubField(root, index, name)
+ if !target.IsValid() {
+ return
+ }
+
+ if target.Type() == reflect.TypeOf(metaExtras) {
+ target.Set(reflect.ValueOf(metaExtras))
+ return
+ }
+
+ newMap := make(map[string]resp.Field, len(metaExtras))
+ if target.Type() == reflect.TypeOf(newMap) {
+ for k, v := range metaExtras {
+ newMap[k] = v.toRespField()
+ }
+ target.Set(reflect.ValueOf(newMap))
+ }
+}
+
+func (f Field) toRespField() resp.Field {
+ if f.IsNull() {
+ return resp.NewNullField()
+ } else if f.IsMissing() {
+ return resp.Field{}
+ } else if f.IsInvalid() {
+ return resp.NewInvalidField(f.raw)
+ } else {
+ return resp.NewValidField(f.raw)
+ }
+}
diff --git a/internal/apijson/union.go b/internal/apijson/union.go
new file mode 100644
index 0000000..d1223cc
--- /dev/null
+++ b/internal/apijson/union.go
@@ -0,0 +1,101 @@
+package apijson
+
+import (
+ "errors"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "reflect"
+
+ "github.com/tidwall/gjson"
+)
+
+func isEmbeddedUnion(t reflect.Type) bool {
+ var apiunion param.APIUnion
+ for i := 0; i < t.NumField(); i++ {
+ if t.Field(i).Type == reflect.TypeOf(apiunion) && t.Field(i).Anonymous {
+ return true
+ }
+ }
+ return false
+}
+
+func RegisterDiscriminatedUnion[T any](key string, mappings map[string]reflect.Type) {
+ var t T
+ entry := unionEntry{
+ discriminatorKey: key,
+ variants: []UnionVariant{},
+ }
+ for k, typ := range mappings {
+ entry.variants = append(entry.variants, UnionVariant{
+ DiscriminatorValue: k,
+ Type: typ,
+ })
+ }
+ unionRegistry[reflect.TypeOf(t)] = entry
+}
+
+func (d *decoderBuilder) newEmbeddedUnionDecoder(t reflect.Type) decoderFunc {
+ decoders := []decoderFunc{}
+
+ for i := 0; i < t.NumField(); i++ {
+ variant := t.Field(i)
+ decoder := d.typeDecoder(variant.Type)
+ decoders = append(decoders, decoder)
+ }
+
+ unionEntry := unionEntry{
+ variants: []UnionVariant{},
+ }
+
+ return func(n gjson.Result, v reflect.Value, state *decoderState) error {
+ // If there is a discriminator match, circumvent the exactness logic entirely
+ for idx, variant := range unionEntry.variants {
+ decoder := decoders[idx]
+ if variant.TypeFilter != n.Type {
+ continue
+ }
+
+ if len(unionEntry.discriminatorKey) != 0 {
+ discriminatorValue := n.Get(unionEntry.discriminatorKey).Value()
+ if discriminatorValue == variant.DiscriminatorValue {
+ inner := reflect.New(variant.Type).Elem()
+ err := decoder(n, inner, state)
+ v.Set(inner)
+ return err
+ }
+ }
+ }
+
+ // Set bestExactness to worse than loose
+ bestExactness := loose - 1
+ for idx, variant := range unionEntry.variants {
+ decoder := decoders[idx]
+ if variant.TypeFilter != n.Type {
+ continue
+ }
+ sub := decoderState{strict: state.strict, exactness: exact}
+ inner := reflect.New(variant.Type).Elem()
+ err := decoder(n, inner, &sub)
+ if err != nil {
+ continue
+ }
+ if sub.exactness == exact {
+ v.Set(inner)
+ return nil
+ }
+ if sub.exactness > bestExactness {
+ v.Set(inner)
+ bestExactness = sub.exactness
+ }
+ }
+
+ if bestExactness < loose {
+ return errors.New("apijson: was not able to coerce type as union")
+ }
+
+ if guardStrict(state, bestExactness != exact) {
+ return errors.New("apijson: was not able to coerce type as union strictly")
+ }
+
+ return nil
+ }
+}
diff --git a/internal/apiquery/encoder.go b/internal/apiquery/encoder.go
index 9db8518..4277a1e 100644
--- a/internal/apiquery/encoder.go
+++ b/internal/apiquery/encoder.go
@@ -9,7 +9,8 @@ import (
"sync"
"time"
- "github.com/anthropics/anthropic-sdk-go/internal/param"
+ internalparam "github.com/anthropics/anthropic-sdk-go/internal/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
)
var encoders sync.Map // map[reflect.Type]encoderFunc
@@ -85,7 +86,8 @@ func (e *encoder) newTypeEncoder(t reflect.Type) encoderFunc {
if t.ConvertibleTo(reflect.TypeOf(time.Time{})) {
return e.newTimeTypeEncoder(t)
}
- if !e.root && t.Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) {
+
+ if !e.root && t.Implements(reflect.TypeOf((*json.Marshaler)(nil)).Elem()) && param.OptionalPrimitiveTypes[t] == nil {
return marshalerEncoder
}
e.root = false
@@ -115,10 +117,14 @@ func (e *encoder) newTypeEncoder(t reflect.Type) encoderFunc {
}
func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
- if t.Implements(reflect.TypeOf((*param.FieldLike)(nil)).Elem()) {
+ if t.Implements(reflect.TypeOf((*internalparam.FieldLike)(nil)).Elem()) {
return e.newFieldTypeEncoder(t)
}
+ if idx, ok := param.OptionalPrimitiveTypes[t]; ok {
+ return e.newRichFieldTypeEncoder(t, idx)
+ }
+
encoderFields := []encoderField{}
// This helper allows us to recursively collect field encoders into a flat
@@ -145,7 +151,7 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
continue
}
- if ptag.name == "-" && !ptag.inline {
+ if (ptag.name == "-" || ptag.name == "") && !ptag.inline {
continue
}
@@ -159,7 +165,19 @@ func (e *encoder) newStructTypeEncoder(t reflect.Type) encoderFunc {
e.dateFormat = "2006-01-02"
}
}
- encoderFields = append(encoderFields, encoderField{ptag, e.typeEncoder(field.Type), idx})
+ var encoderFn encoderFunc
+ if ptag.omitzero {
+ typeEncoderFn := e.typeEncoder(field.Type)
+ encoderFn = func(key string, value reflect.Value) []Pair {
+ if value.IsZero() {
+ return nil
+ }
+ return typeEncoderFn(key, value)
+ }
+ } else {
+ encoderFn = e.typeEncoder(field.Type)
+ }
+ encoderFields = append(encoderFields, encoderField{ptag, encoderFn, idx})
e.dateFormat = oldFormat
}
}
diff --git a/internal/apiquery/query_test.go b/internal/apiquery/query_test.go
index 1e740d6..98cb6c5 100644
--- a/internal/apiquery/query_test.go
+++ b/internal/apiquery/query_test.go
@@ -1,6 +1,7 @@
package apiquery
import (
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
"net/url"
"testing"
"time"
@@ -101,6 +102,15 @@ type DeeplyNested3 struct {
D *string `query:"d"`
}
+type RichPrimitives struct {
+ A param.Opt[string] `query:"a"`
+}
+
+type QueryOmitTest struct {
+ A param.Opt[string] `query:"a,omitzero"`
+ B string `query:"b,omitzero"`
+}
+
var tests = map[string]struct {
enc string
val interface{}
@@ -320,6 +330,29 @@ var tests = map[string]struct {
},
QuerySettings{NestedFormat: NestedQueryFormatDots},
},
+
+ "rich_primitives": {
+ `a=hello`,
+ RichPrimitives{
+ A: param.Opt[string]{Value: "hello"},
+ },
+ QuerySettings{},
+ },
+
+ "rich_primitives_omit": {
+ ``,
+ QueryOmitTest{
+ A: param.Opt[string]{},
+ },
+ QuerySettings{},
+ },
+ "query_omit": {
+ `a=hello`,
+ QueryOmitTest{
+ A: param.Opt[string]{Value: "hello"},
+ },
+ QuerySettings{},
+ },
}
func TestEncode(t *testing.T) {
diff --git a/internal/apiquery/richparam.go b/internal/apiquery/richparam.go
new file mode 100644
index 0000000..1f385b4
--- /dev/null
+++ b/internal/apiquery/richparam.go
@@ -0,0 +1,19 @@
+package apiquery
+
+import (
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "reflect"
+)
+
+func (e *encoder) newRichFieldTypeEncoder(t reflect.Type, underlyingValueIdx []int) encoderFunc {
+ underlying := t.FieldByIndex(underlyingValueIdx)
+ primitiveEncoder := e.newPrimitiveTypeEncoder(underlying.Type)
+ return func(key string, value reflect.Value) []Pair {
+ if fielder, ok := value.Interface().(param.Optional); ok && fielder.IsPresent() {
+ return primitiveEncoder(key, value.FieldByIndex(underlyingValueIdx))
+ } else if ok && fielder.IsNull() {
+ return []Pair{{key, "null"}}
+ }
+ return nil
+ }
+}
diff --git a/internal/apiquery/tag.go b/internal/apiquery/tag.go
index 7ccd739..772c40e 100644
--- a/internal/apiquery/tag.go
+++ b/internal/apiquery/tag.go
@@ -11,6 +11,7 @@ const formatStructTag = "format"
type parsedStructTag struct {
name string
omitempty bool
+ omitzero bool
inline bool
}
@@ -26,6 +27,8 @@ func parseQueryStructTag(field reflect.StructField) (tag parsedStructTag, ok boo
tag.name = parts[0]
for _, part := range parts[1:] {
switch part {
+ case "omitzero":
+ tag.omitzero = true
case "omitempty":
tag.omitempty = true
case "inline":
diff --git a/internal/encoding/json/decode.go b/internal/encoding/json/decode.go
new file mode 100644
index 0000000..f1c7ef5
--- /dev/null
+++ b/internal/encoding/json/decode.go
@@ -0,0 +1,1324 @@
+// Vendored from Go 1.24.0-pre-release
+// To find alterations, check package shims, and comments beginning in SHIM().
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Represents JSON data structure using native Go types: booleans, floats,
+// strings, arrays, and maps.
+
+package json
+
+import (
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "github.com/anthropics/anthropic-sdk-go/internal/encoding/json/shims"
+ "reflect"
+ "strconv"
+ "strings"
+ "unicode"
+ "unicode/utf16"
+ "unicode/utf8"
+ _ "unsafe" // for linkname
+)
+
+// Unmarshal parses the JSON-encoded data and stores the result
+// in the value pointed to by v. If v is nil or not a pointer,
+// Unmarshal returns an [InvalidUnmarshalError].
+//
+// Unmarshal uses the inverse of the encodings that
+// [Marshal] uses, allocating maps, slices, and pointers as necessary,
+// with the following additional rules:
+//
+// To unmarshal JSON into a pointer, Unmarshal first handles the case of
+// the JSON being the JSON literal null. In that case, Unmarshal sets
+// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into
+// the value pointed at by the pointer. If the pointer is nil, Unmarshal
+// allocates a new value for it to point to.
+//
+// To unmarshal JSON into a value implementing [Unmarshaler],
+// Unmarshal calls that value's [Unmarshaler.UnmarshalJSON] method, including
+// when the input is a JSON null.
+// Otherwise, if the value implements [encoding.TextUnmarshaler]
+// and the input is a JSON quoted string, Unmarshal calls
+// [encoding.TextUnmarshaler.UnmarshalText] with the unquoted form of the string.
+//
+// To unmarshal JSON into a struct, Unmarshal matches incoming object
+// keys to the keys used by [Marshal] (either the struct field name or its tag),
+// preferring an exact match but also accepting a case-insensitive match. By
+// default, object keys which don't have a corresponding struct field are
+// ignored (see [Decoder.DisallowUnknownFields] for an alternative).
+//
+// To unmarshal JSON into an interface value,
+// Unmarshal stores one of these in the interface value:
+//
+// - bool, for JSON booleans
+// - float64, for JSON numbers
+// - string, for JSON strings
+// - []any, for JSON arrays
+// - map[string]any, for JSON objects
+// - nil for JSON null
+//
+// To unmarshal a JSON array into a slice, Unmarshal resets the slice length
+// to zero and then appends each element to the slice.
+// As a special case, to unmarshal an empty JSON array into a slice,
+// Unmarshal replaces the slice with a new empty slice.
+//
+// To unmarshal a JSON array into a Go array, Unmarshal decodes
+// JSON array elements into corresponding Go array elements.
+// If the Go array is smaller than the JSON array,
+// the additional JSON array elements are discarded.
+// If the JSON array is smaller than the Go array,
+// the additional Go array elements are set to zero values.
+//
+// To unmarshal a JSON object into a map, Unmarshal first establishes a map to
+// use. If the map is nil, Unmarshal allocates a new map. Otherwise Unmarshal
+// reuses the existing map, keeping existing entries. Unmarshal then stores
+// key-value pairs from the JSON object into the map. The map's key type must
+// either be any string type, an integer, or implement [encoding.TextUnmarshaler].
+//
+// If the JSON-encoded data contain a syntax error, Unmarshal returns a [SyntaxError].
+//
+// If a JSON value is not appropriate for a given target type,
+// or if a JSON number overflows the target type, Unmarshal
+// skips that field and completes the unmarshaling as best it can.
+// If no more serious errors are encountered, Unmarshal returns
+// an [UnmarshalTypeError] describing the earliest such error. In any
+// case, it's not guaranteed that all the remaining fields following
+// the problematic one will be unmarshaled into the target object.
+//
+// The JSON null value unmarshals into an interface, map, pointer, or slice
+// by setting that Go value to nil. Because null is often used in JSON to mean
+// “not present,” unmarshaling a JSON null into any other Go type has no effect
+// on the value and produces no error.
+//
+// When unmarshaling quoted strings, invalid UTF-8 or
+// invalid UTF-16 surrogate pairs are not treated as an error.
+// Instead, they are replaced by the Unicode replacement
+// character U+FFFD.
+func Unmarshal(data []byte, v any) error {
+ // Check for well-formedness.
+ // Avoids filling out half a data structure
+ // before discovering a JSON syntax error.
+ var d decodeState
+ err := checkValid(data, &d.scan)
+ if err != nil {
+ return err
+ }
+
+ d.init(data)
+ return d.unmarshal(v)
+}
+
+// Unmarshaler is the interface implemented by types
+// that can unmarshal a JSON description of themselves.
+// The input can be assumed to be a valid encoding of
+// a JSON value. UnmarshalJSON must copy the JSON data
+// if it wishes to retain the data after returning.
+//
+// By convention, to approximate the behavior of [Unmarshal] itself,
+// Unmarshalers implement UnmarshalJSON([]byte("null")) as a no-op.
+type Unmarshaler interface {
+ UnmarshalJSON([]byte) error
+}
+
+// An UnmarshalTypeError describes a JSON value that was
+// not appropriate for a value of a specific Go type.
+type UnmarshalTypeError struct {
+ Value string // description of JSON value - "bool", "array", "number -5"
+ Type reflect.Type // type of Go value it could not be assigned to
+ Offset int64 // error occurred after reading Offset bytes
+ Struct string // name of the struct type containing the field
+ Field string // the full path from root node to the field, include embedded struct
+}
+
+func (e *UnmarshalTypeError) Error() string {
+ if e.Struct != "" || e.Field != "" {
+ return "json: cannot unmarshal " + e.Value + " into Go struct field " + e.Struct + "." + e.Field + " of type " + e.Type.String()
+ }
+ return "json: cannot unmarshal " + e.Value + " into Go value of type " + e.Type.String()
+}
+
+// An UnmarshalFieldError describes a JSON object key that
+// led to an unexported (and therefore unwritable) struct field.
+//
+// Deprecated: No longer used; kept for compatibility.
+type UnmarshalFieldError struct {
+ Key string
+ Type reflect.Type
+ Field reflect.StructField
+}
+
+func (e *UnmarshalFieldError) Error() string {
+ return "json: cannot unmarshal object key " + strconv.Quote(e.Key) + " into unexported field " + e.Field.Name + " of type " + e.Type.String()
+}
+
+// An InvalidUnmarshalError describes an invalid argument passed to [Unmarshal].
+// (The argument to [Unmarshal] must be a non-nil pointer.)
+type InvalidUnmarshalError struct {
+ Type reflect.Type
+}
+
+func (e *InvalidUnmarshalError) Error() string {
+ if e.Type == nil {
+ return "json: Unmarshal(nil)"
+ }
+
+ if e.Type.Kind() != reflect.Pointer {
+ return "json: Unmarshal(non-pointer " + e.Type.String() + ")"
+ }
+ return "json: Unmarshal(nil " + e.Type.String() + ")"
+}
+
+func (d *decodeState) unmarshal(v any) error {
+ rv := reflect.ValueOf(v)
+ if rv.Kind() != reflect.Pointer || rv.IsNil() {
+ return &InvalidUnmarshalError{reflect.TypeOf(v)}
+ }
+
+ d.scan.reset()
+ d.scanWhile(scanSkipSpace)
+ // We decode rv not rv.Elem because the Unmarshaler interface
+ // test must be applied at the top level of the value.
+ err := d.value(rv)
+ if err != nil {
+ return d.addErrorContext(err)
+ }
+ return d.savedError
+}
+
+// A Number represents a JSON number literal.
+type Number string
+
+// String returns the literal text of the number.
+func (n Number) String() string { return string(n) }
+
+// Float64 returns the number as a float64.
+func (n Number) Float64() (float64, error) {
+ return strconv.ParseFloat(string(n), 64)
+}
+
+// Int64 returns the number as an int64.
+func (n Number) Int64() (int64, error) {
+ return strconv.ParseInt(string(n), 10, 64)
+}
+
+// An errorContext provides context for type errors during decoding.
+type errorContext struct {
+ Struct reflect.Type
+ FieldStack []string
+}
+
+// decodeState represents the state while decoding a JSON value.
+type decodeState struct {
+ data []byte
+ off int // next read offset in data
+ opcode int // last read result
+ scan scanner
+ errorContext *errorContext
+ savedError error
+ useNumber bool
+ disallowUnknownFields bool
+}
+
+// readIndex returns the position of the last byte read.
+func (d *decodeState) readIndex() int {
+ return d.off - 1
+}
+
+// phasePanicMsg is used as a panic message when we end up with something that
+// shouldn't happen. It can indicate a bug in the JSON decoder, or that
+// something is editing the data slice while the decoder executes.
+const phasePanicMsg = "JSON decoder out of sync - data changing underfoot?"
+
+func (d *decodeState) init(data []byte) *decodeState {
+ d.data = data
+ d.off = 0
+ d.savedError = nil
+ if d.errorContext != nil {
+ d.errorContext.Struct = nil
+ // Reuse the allocated space for the FieldStack slice.
+ d.errorContext.FieldStack = d.errorContext.FieldStack[:0]
+ }
+ return d
+}
+
+// saveError saves the first err it is called with,
+// for reporting at the end of the unmarshal.
+func (d *decodeState) saveError(err error) {
+ if d.savedError == nil {
+ d.savedError = d.addErrorContext(err)
+ }
+}
+
+// addErrorContext returns a new error enhanced with information from d.errorContext
+func (d *decodeState) addErrorContext(err error) error {
+ if d.errorContext != nil && (d.errorContext.Struct != nil || len(d.errorContext.FieldStack) > 0) {
+ switch err := err.(type) {
+ case *UnmarshalTypeError:
+ err.Struct = d.errorContext.Struct.Name()
+ fieldStack := d.errorContext.FieldStack
+ if err.Field != "" {
+ fieldStack = append(fieldStack, err.Field)
+ }
+ err.Field = strings.Join(fieldStack, ".")
+ }
+ }
+ return err
+}
+
+// skip scans to the end of what was started.
+func (d *decodeState) skip() {
+ s, data, i := &d.scan, d.data, d.off
+ depth := len(s.parseState)
+ for {
+ op := s.step(s, data[i])
+ i++
+ if len(s.parseState) < depth {
+ d.off = i
+ d.opcode = op
+ return
+ }
+ }
+}
+
+// scanNext processes the byte at d.data[d.off].
+func (d *decodeState) scanNext() {
+ if d.off < len(d.data) {
+ d.opcode = d.scan.step(&d.scan, d.data[d.off])
+ d.off++
+ } else {
+ d.opcode = d.scan.eof()
+ d.off = len(d.data) + 1 // mark processed EOF with len+1
+ }
+}
+
+// scanWhile processes bytes in d.data[d.off:] until it
+// receives a scan code not equal to op.
+func (d *decodeState) scanWhile(op int) {
+ s, data, i := &d.scan, d.data, d.off
+ for i < len(data) {
+ newOp := s.step(s, data[i])
+ i++
+ if newOp != op {
+ d.opcode = newOp
+ d.off = i
+ return
+ }
+ }
+
+ d.off = len(data) + 1 // mark processed EOF with len+1
+ d.opcode = d.scan.eof()
+}
+
+// rescanLiteral is similar to scanWhile(scanContinue), but it specialises the
+// common case where we're decoding a literal. The decoder scans the input
+// twice, once for syntax errors and to check the length of the value, and the
+// second to perform the decoding.
+//
+// Only in the second step do we use decodeState to tokenize literals, so we
+// know there aren't any syntax errors. We can take advantage of that knowledge,
+// and scan a literal's bytes much more quickly.
+func (d *decodeState) rescanLiteral() {
+ data, i := d.data, d.off
+Switch:
+ switch data[i-1] {
+ case '"': // string
+ for ; i < len(data); i++ {
+ switch data[i] {
+ case '\\':
+ i++ // escaped char
+ case '"':
+ i++ // tokenize the closing quote too
+ break Switch
+ }
+ }
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-': // number
+ for ; i < len(data); i++ {
+ switch data[i] {
+ case '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
+ '.', 'e', 'E', '+', '-':
+ default:
+ break Switch
+ }
+ }
+ case 't': // true
+ i += len("rue")
+ case 'f': // false
+ i += len("alse")
+ case 'n': // null
+ i += len("ull")
+ }
+ if i < len(data) {
+ d.opcode = stateEndValue(&d.scan, data[i])
+ } else {
+ d.opcode = scanEnd
+ }
+ d.off = i + 1
+}
+
+// value consumes a JSON value from d.data[d.off-1:], decoding into v, and
+// reads the following byte ahead. If v is invalid, the value is discarded.
+// The first byte of the value has been read already.
+func (d *decodeState) value(v reflect.Value) error {
+ switch d.opcode {
+ default:
+ panic(phasePanicMsg)
+
+ case scanBeginArray:
+ if v.IsValid() {
+ if err := d.array(v); err != nil {
+ return err
+ }
+ } else {
+ d.skip()
+ }
+ d.scanNext()
+
+ case scanBeginObject:
+ if v.IsValid() {
+ if err := d.object(v); err != nil {
+ return err
+ }
+ } else {
+ d.skip()
+ }
+ d.scanNext()
+
+ case scanBeginLiteral:
+ // All bytes inside literal return scanContinue op code.
+ start := d.readIndex()
+ d.rescanLiteral()
+
+ if v.IsValid() {
+ if err := d.literalStore(d.data[start:d.readIndex()], v, false); err != nil {
+ return err
+ }
+ }
+ }
+ return nil
+}
+
+type unquotedValue struct{}
+
+// valueQuoted is like value but decodes a
+// quoted string literal or literal null into an interface value.
+// If it finds anything other than a quoted string literal or null,
+// valueQuoted returns unquotedValue{}.
+func (d *decodeState) valueQuoted() any {
+ switch d.opcode {
+ default:
+ panic(phasePanicMsg)
+
+ case scanBeginArray, scanBeginObject:
+ d.skip()
+ d.scanNext()
+
+ case scanBeginLiteral:
+ v := d.literalInterface()
+ switch v.(type) {
+ case nil, string:
+ return v
+ }
+ }
+ return unquotedValue{}
+}
+
+// indirect walks down v allocating pointers as needed,
+// until it gets to a non-pointer.
+// If it encounters an Unmarshaler, indirect stops and returns that.
+// If decodingNull is true, indirect stops at the first settable pointer so it
+// can be set to nil.
+func indirect(v reflect.Value, decodingNull bool) (Unmarshaler, encoding.TextUnmarshaler, reflect.Value) {
+ // Issue #24153 indicates that it is generally not a guaranteed property
+ // that you may round-trip a reflect.Value by calling Value.Addr().Elem()
+ // and expect the value to still be settable for values derived from
+ // unexported embedded struct fields.
+ //
+ // The logic below effectively does this when it first addresses the value
+ // (to satisfy possible pointer methods) and continues to dereference
+ // subsequent pointers as necessary.
+ //
+ // After the first round-trip, we set v back to the original value to
+ // preserve the original RW flags contained in reflect.Value.
+ v0 := v
+ haveAddr := false
+
+ // If v is a named type and is addressable,
+ // start with its address, so that if the type has pointer methods,
+ // we find them.
+ if v.Kind() != reflect.Pointer && v.Type().Name() != "" && v.CanAddr() {
+ haveAddr = true
+ v = v.Addr()
+ }
+ for {
+ // Load value from interface, but only if the result will be
+ // usefully addressable.
+ if v.Kind() == reflect.Interface && !v.IsNil() {
+ e := v.Elem()
+ if e.Kind() == reflect.Pointer && !e.IsNil() && (!decodingNull || e.Elem().Kind() == reflect.Pointer) {
+ haveAddr = false
+ v = e
+ continue
+ }
+ }
+
+ if v.Kind() != reflect.Pointer {
+ break
+ }
+
+ if decodingNull && v.CanSet() {
+ break
+ }
+
+ // Prevent infinite loop if v is an interface pointing to its own address:
+ // var v any
+ // v = &v
+ if v.Elem().Kind() == reflect.Interface && v.Elem().Elem().Equal(v) {
+ v = v.Elem()
+ break
+ }
+ if v.IsNil() {
+ v.Set(reflect.New(v.Type().Elem()))
+ }
+ if v.Type().NumMethod() > 0 && v.CanInterface() {
+ if u, ok := v.Interface().(Unmarshaler); ok {
+ return u, nil, reflect.Value{}
+ }
+ if !decodingNull {
+ if u, ok := v.Interface().(encoding.TextUnmarshaler); ok {
+ return nil, u, reflect.Value{}
+ }
+ }
+ }
+
+ if haveAddr {
+ v = v0 // restore original value after round-trip Value.Addr().Elem()
+ haveAddr = false
+ } else {
+ v = v.Elem()
+ }
+ }
+ return nil, nil, v
+}
+
+// array consumes an array from d.data[d.off-1:], decoding into v.
+// The first byte of the array ('[') has been read already.
+func (d *decodeState) array(v reflect.Value) error {
+ // Check for unmarshaler.
+ u, ut, pv := indirect(v, false)
+ if u != nil {
+ start := d.readIndex()
+ d.skip()
+ return u.UnmarshalJSON(d.data[start:d.off])
+ }
+ if ut != nil {
+ d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
+ d.skip()
+ return nil
+ }
+ v = pv
+
+ // Check type of target.
+ switch v.Kind() {
+ case reflect.Interface:
+ if v.NumMethod() == 0 {
+ // Decoding into nil interface? Switch to non-reflect code.
+ ai := d.arrayInterface()
+ v.Set(reflect.ValueOf(ai))
+ return nil
+ }
+ // Otherwise it's invalid.
+ fallthrough
+ default:
+ d.saveError(&UnmarshalTypeError{Value: "array", Type: v.Type(), Offset: int64(d.off)})
+ d.skip()
+ return nil
+ case reflect.Array, reflect.Slice:
+ break
+ }
+
+ i := 0
+ for {
+ // Look ahead for ] - can only happen on first iteration.
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndArray {
+ break
+ }
+
+ // Expand slice length, growing the slice if necessary.
+ if v.Kind() == reflect.Slice {
+ if i >= v.Cap() {
+ v.Grow(1)
+ }
+ if i >= v.Len() {
+ v.SetLen(i + 1)
+ }
+ }
+
+ if i < v.Len() {
+ // Decode into element.
+ if err := d.value(v.Index(i)); err != nil {
+ return err
+ }
+ } else {
+ // Ran out of fixed array: skip.
+ if err := d.value(reflect.Value{}); err != nil {
+ return err
+ }
+ }
+ i++
+
+ // Next token must be , or ].
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode == scanEndArray {
+ break
+ }
+ if d.opcode != scanArrayValue {
+ panic(phasePanicMsg)
+ }
+ }
+
+ if i < v.Len() {
+ if v.Kind() == reflect.Array {
+ for ; i < v.Len(); i++ {
+ v.Index(i).SetZero() // zero remainder of array
+ }
+ } else {
+ v.SetLen(i) // truncate the slice
+ }
+ }
+ if i == 0 && v.Kind() == reflect.Slice {
+ v.Set(reflect.MakeSlice(v.Type(), 0, 0))
+ }
+ return nil
+}
+
+var nullLiteral = []byte("null")
+
+// SHIM(reflect): reflect.TypeFor[T]() reflect.T
+var textUnmarshalerType = shims.TypeFor[encoding.TextUnmarshaler]()
+
+// object consumes an object from d.data[d.off-1:], decoding into v.
+// The first byte ('{') of the object has been read already.
+func (d *decodeState) object(v reflect.Value) error {
+ // Check for unmarshaler.
+ u, ut, pv := indirect(v, false)
+ if u != nil {
+ start := d.readIndex()
+ d.skip()
+ return u.UnmarshalJSON(d.data[start:d.off])
+ }
+ if ut != nil {
+ d.saveError(&UnmarshalTypeError{Value: "object", Type: v.Type(), Offset: int64(d.off)})
+ d.skip()
+ return nil
+ }
+ v = pv
+ t := v.Type()
+
+ // Decoding into nil interface? Switch to non-reflect code.
+ if v.Kind() == reflect.Interface && v.NumMethod() == 0 {
+ oi := d.objectInterface()
+ v.Set(reflect.ValueOf(oi))
+ return nil
+ }
+
+ var fields structFields
+
+ // Check type of target:
+ // struct or
+ // map[T1]T2 where T1 is string, an integer type,
+ // or an encoding.TextUnmarshaler
+ switch v.Kind() {
+ case reflect.Map:
+ // Map key must either have string kind, have an integer kind,
+ // or be an encoding.TextUnmarshaler.
+ switch t.Key().Kind() {
+ case reflect.String,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ default:
+ if !reflect.PointerTo(t.Key()).Implements(textUnmarshalerType) {
+ d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)})
+ d.skip()
+ return nil
+ }
+ }
+ if v.IsNil() {
+ v.Set(reflect.MakeMap(t))
+ }
+ case reflect.Struct:
+ fields = cachedTypeFields(t)
+ // ok
+ default:
+ d.saveError(&UnmarshalTypeError{Value: "object", Type: t, Offset: int64(d.off)})
+ d.skip()
+ return nil
+ }
+
+ var mapElem reflect.Value
+ var origErrorContext errorContext
+ if d.errorContext != nil {
+ origErrorContext = *d.errorContext
+ }
+
+ for {
+ // Read opening " of string key or closing }.
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndObject {
+ // closing } - can only happen on first iteration.
+ break
+ }
+ if d.opcode != scanBeginLiteral {
+ panic(phasePanicMsg)
+ }
+
+ // Read key.
+ start := d.readIndex()
+ d.rescanLiteral()
+ item := d.data[start:d.readIndex()]
+ key, ok := unquoteBytes(item)
+ if !ok {
+ panic(phasePanicMsg)
+ }
+
+ // Figure out field corresponding to key.
+ var subv reflect.Value
+ destring := false // whether the value is wrapped in a string to be decoded first
+
+ if v.Kind() == reflect.Map {
+ elemType := t.Elem()
+ if !mapElem.IsValid() {
+ mapElem = reflect.New(elemType).Elem()
+ } else {
+ mapElem.SetZero()
+ }
+ subv = mapElem
+ } else {
+ f := fields.byExactName[string(key)]
+ if f == nil {
+ f = fields.byFoldedName[string(foldName(key))]
+ }
+ if f != nil {
+ subv = v
+ destring = f.quoted
+ if d.errorContext == nil {
+ d.errorContext = new(errorContext)
+ }
+ for i, ind := range f.index {
+ if subv.Kind() == reflect.Pointer {
+ if subv.IsNil() {
+ // If a struct embeds a pointer to an unexported type,
+ // it is not possible to set a newly allocated value
+ // since the field is unexported.
+ //
+ // See https://golang.org/issue/21357
+ if !subv.CanSet() {
+ d.saveError(fmt.Errorf("json: cannot set embedded pointer to unexported struct: %v", subv.Type().Elem()))
+ // Invalidate subv to ensure d.value(subv) skips over
+ // the JSON value without assigning it to subv.
+ subv = reflect.Value{}
+ destring = false
+ break
+ }
+ subv.Set(reflect.New(subv.Type().Elem()))
+ }
+ subv = subv.Elem()
+ }
+ if i < len(f.index)-1 {
+ d.errorContext.FieldStack = append(
+ d.errorContext.FieldStack,
+ subv.Type().Field(ind).Name,
+ )
+ }
+ subv = subv.Field(ind)
+ }
+ d.errorContext.Struct = t
+ d.errorContext.FieldStack = append(d.errorContext.FieldStack, f.name)
+ } else if d.disallowUnknownFields {
+ d.saveError(fmt.Errorf("json: unknown field %q", key))
+ }
+ }
+
+ // Read : before value.
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode != scanObjectKey {
+ panic(phasePanicMsg)
+ }
+ d.scanWhile(scanSkipSpace)
+
+ if destring {
+ switch qv := d.valueQuoted().(type) {
+ case nil:
+ if err := d.literalStore(nullLiteral, subv, false); err != nil {
+ return err
+ }
+ case string:
+ if err := d.literalStore([]byte(qv), subv, true); err != nil {
+ return err
+ }
+ default:
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal unquoted value into %v", subv.Type()))
+ }
+ } else {
+ if err := d.value(subv); err != nil {
+ return err
+ }
+ }
+
+ // Write value back to map;
+ // if using struct, subv points into struct already.
+ if v.Kind() == reflect.Map {
+ kt := t.Key()
+ var kv reflect.Value
+ if reflect.PointerTo(kt).Implements(textUnmarshalerType) {
+ kv = reflect.New(kt)
+ if err := d.literalStore(item, kv, true); err != nil {
+ return err
+ }
+ kv = kv.Elem()
+ } else {
+ switch kt.Kind() {
+ case reflect.String:
+ kv = reflect.New(kt).Elem()
+ kv.SetString(string(key))
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ s := string(key)
+ n, err := strconv.ParseInt(s, 10, 64)
+ // SHIM(reflect): reflect.Type.OverflowInt(int64) bool
+ okt := shims.OverflowableType{Type: kt}
+ if err != nil || okt.OverflowInt(n) {
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
+ break
+ }
+ kv = reflect.New(kt).Elem()
+ kv.SetInt(n)
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ s := string(key)
+ n, err := strconv.ParseUint(s, 10, 64)
+ // SHIM(reflect): reflect.Type.OverflowUint(uint64) bool
+ okt := shims.OverflowableType{Type: kt}
+ if err != nil || okt.OverflowUint(n) {
+ d.saveError(&UnmarshalTypeError{Value: "number " + s, Type: kt, Offset: int64(start + 1)})
+ break
+ }
+ kv = reflect.New(kt).Elem()
+ kv.SetUint(n)
+ default:
+ panic("json: Unexpected key type") // should never occur
+ }
+ }
+ if kv.IsValid() {
+ v.SetMapIndex(kv, subv)
+ }
+ }
+
+ // Next token must be , or }.
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.errorContext != nil {
+ // Reset errorContext to its original state.
+ // Keep the same underlying array for FieldStack, to reuse the
+ // space and avoid unnecessary allocs.
+ d.errorContext.FieldStack = d.errorContext.FieldStack[:len(origErrorContext.FieldStack)]
+ d.errorContext.Struct = origErrorContext.Struct
+ }
+ if d.opcode == scanEndObject {
+ break
+ }
+ if d.opcode != scanObjectValue {
+ panic(phasePanicMsg)
+ }
+ }
+ return nil
+}
+
+// convertNumber converts the number literal s to a float64 or a Number
+// depending on the setting of d.useNumber.
+func (d *decodeState) convertNumber(s string) (any, error) {
+ if d.useNumber {
+ return Number(s), nil
+ }
+ f, err := strconv.ParseFloat(s, 64)
+ if err != nil {
+ // SHIM(reflect): reflect.TypeFor[T]() reflect.Type
+ return nil, &UnmarshalTypeError{Value: "number " + s, Type: shims.TypeFor[float64](), Offset: int64(d.off)}
+ }
+ return f, nil
+}
+
+// SHIM(reflect): TypeFor[T]() reflect.Type
+var numberType = shims.TypeFor[Number]()
+
+// literalStore decodes a literal stored in item into v.
+//
+// fromQuoted indicates whether this literal came from unwrapping a
+// string from the ",string" struct tag option. this is used only to
+// produce more helpful error messages.
+func (d *decodeState) literalStore(item []byte, v reflect.Value, fromQuoted bool) error {
+ // Check for unmarshaler.
+ if len(item) == 0 {
+ // Empty string given.
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ return nil
+ }
+ isNull := item[0] == 'n' // null
+ u, ut, pv := indirect(v, isNull)
+ if u != nil {
+ return u.UnmarshalJSON(item)
+ }
+ if ut != nil {
+ if item[0] != '"' {
+ if fromQuoted {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ return nil
+ }
+ val := "number"
+ switch item[0] {
+ case 'n':
+ val = "null"
+ case 't', 'f':
+ val = "bool"
+ }
+ d.saveError(&UnmarshalTypeError{Value: val, Type: v.Type(), Offset: int64(d.readIndex())})
+ return nil
+ }
+ s, ok := unquoteBytes(item)
+ if !ok {
+ if fromQuoted {
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
+ }
+ panic(phasePanicMsg)
+ }
+ return ut.UnmarshalText(s)
+ }
+
+ v = pv
+
+ switch c := item[0]; c {
+ case 'n': // null
+ // The main parser checks that only true and false can reach here,
+ // but if this was a quoted string input, it could be anything.
+ if fromQuoted && string(item) != "null" {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ break
+ }
+ switch v.Kind() {
+ case reflect.Interface, reflect.Pointer, reflect.Map, reflect.Slice:
+ v.SetZero()
+ // otherwise, ignore null for primitives/string
+ }
+ case 't', 'f': // true, false
+ value := item[0] == 't'
+ // The main parser checks that only true and false can reach here,
+ // but if this was a quoted string input, it could be anything.
+ if fromQuoted && string(item) != "true" && string(item) != "false" {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ break
+ }
+ switch v.Kind() {
+ default:
+ if fromQuoted {
+ d.saveError(fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type()))
+ } else {
+ d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())})
+ }
+ case reflect.Bool:
+ v.SetBool(value)
+ case reflect.Interface:
+ if v.NumMethod() == 0 {
+ v.Set(reflect.ValueOf(value))
+ } else {
+ d.saveError(&UnmarshalTypeError{Value: "bool", Type: v.Type(), Offset: int64(d.readIndex())})
+ }
+ }
+
+ case '"': // string
+ s, ok := unquoteBytes(item)
+ if !ok {
+ if fromQuoted {
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
+ }
+ panic(phasePanicMsg)
+ }
+ switch v.Kind() {
+ default:
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
+ case reflect.Slice:
+ if v.Type().Elem().Kind() != reflect.Uint8 {
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
+ break
+ }
+ b := make([]byte, base64.StdEncoding.DecodedLen(len(s)))
+ n, err := base64.StdEncoding.Decode(b, s)
+ if err != nil {
+ d.saveError(err)
+ break
+ }
+ v.SetBytes(b[:n])
+ case reflect.String:
+ t := string(s)
+ if v.Type() == numberType && !isValidNumber(t) {
+ return fmt.Errorf("json: invalid number literal, trying to unmarshal %q into Number", item)
+ }
+ v.SetString(t)
+ case reflect.Interface:
+ if v.NumMethod() == 0 {
+ v.Set(reflect.ValueOf(string(s)))
+ } else {
+ d.saveError(&UnmarshalTypeError{Value: "string", Type: v.Type(), Offset: int64(d.readIndex())})
+ }
+ }
+
+ default: // number
+ if c != '-' && (c < '0' || c > '9') {
+ if fromQuoted {
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
+ }
+ panic(phasePanicMsg)
+ }
+ switch v.Kind() {
+ default:
+ if v.Kind() == reflect.String && v.Type() == numberType {
+ // s must be a valid number, because it's
+ // already been tokenized.
+ v.SetString(string(item))
+ break
+ }
+ if fromQuoted {
+ return fmt.Errorf("json: invalid use of ,string struct tag, trying to unmarshal %q into %v", item, v.Type())
+ }
+ d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
+ case reflect.Interface:
+ n, err := d.convertNumber(string(item))
+ if err != nil {
+ d.saveError(err)
+ break
+ }
+ if v.NumMethod() != 0 {
+ d.saveError(&UnmarshalTypeError{Value: "number", Type: v.Type(), Offset: int64(d.readIndex())})
+ break
+ }
+ v.Set(reflect.ValueOf(n))
+
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ n, err := strconv.ParseInt(string(item), 10, 64)
+ if err != nil || v.OverflowInt(n) {
+ d.saveError(&UnmarshalTypeError{Value: "number " + string(item), Type: v.Type(), Offset: int64(d.readIndex())})
+ break
+ }
+ v.SetInt(n)
+
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ n, err := strconv.ParseUint(string(item), 10, 64)
+ if err != nil || v.OverflowUint(n) {
+ d.saveError(&UnmarshalTypeError{Value: "number " + string(item), Type: v.Type(), Offset: int64(d.readIndex())})
+ break
+ }
+ v.SetUint(n)
+
+ case reflect.Float32, reflect.Float64:
+ n, err := strconv.ParseFloat(string(item), v.Type().Bits())
+ if err != nil || v.OverflowFloat(n) {
+ d.saveError(&UnmarshalTypeError{Value: "number " + string(item), Type: v.Type(), Offset: int64(d.readIndex())})
+ break
+ }
+ v.SetFloat(n)
+ }
+ }
+ return nil
+}
+
+// The xxxInterface routines build up a value to be stored
+// in an empty interface. They are not strictly necessary,
+// but they avoid the weight of reflection in this common case.
+
+// valueInterface is like value but returns any.
+func (d *decodeState) valueInterface() (val any) {
+ switch d.opcode {
+ default:
+ panic(phasePanicMsg)
+ case scanBeginArray:
+ val = d.arrayInterface()
+ d.scanNext()
+ case scanBeginObject:
+ val = d.objectInterface()
+ d.scanNext()
+ case scanBeginLiteral:
+ val = d.literalInterface()
+ }
+ return
+}
+
+// arrayInterface is like array but returns []any.
+func (d *decodeState) arrayInterface() []any {
+ var v = make([]any, 0)
+ for {
+ // Look ahead for ] - can only happen on first iteration.
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndArray {
+ break
+ }
+
+ v = append(v, d.valueInterface())
+
+ // Next token must be , or ].
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode == scanEndArray {
+ break
+ }
+ if d.opcode != scanArrayValue {
+ panic(phasePanicMsg)
+ }
+ }
+ return v
+}
+
+// objectInterface is like object but returns map[string]any.
+func (d *decodeState) objectInterface() map[string]any {
+ m := make(map[string]any)
+ for {
+ // Read opening " of string key or closing }.
+ d.scanWhile(scanSkipSpace)
+ if d.opcode == scanEndObject {
+ // closing } - can only happen on first iteration.
+ break
+ }
+ if d.opcode != scanBeginLiteral {
+ panic(phasePanicMsg)
+ }
+
+ // Read string key.
+ start := d.readIndex()
+ d.rescanLiteral()
+ item := d.data[start:d.readIndex()]
+ key, ok := unquote(item)
+ if !ok {
+ panic(phasePanicMsg)
+ }
+
+ // Read : before value.
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode != scanObjectKey {
+ panic(phasePanicMsg)
+ }
+ d.scanWhile(scanSkipSpace)
+
+ // Read value.
+ m[key] = d.valueInterface()
+
+ // Next token must be , or }.
+ if d.opcode == scanSkipSpace {
+ d.scanWhile(scanSkipSpace)
+ }
+ if d.opcode == scanEndObject {
+ break
+ }
+ if d.opcode != scanObjectValue {
+ panic(phasePanicMsg)
+ }
+ }
+ return m
+}
+
+// literalInterface consumes and returns a literal from d.data[d.off-1:] and
+// it reads the following byte ahead. The first byte of the literal has been
+// read already (that's how the caller knows it's a literal).
+func (d *decodeState) literalInterface() any {
+ // All bytes inside literal return scanContinue op code.
+ start := d.readIndex()
+ d.rescanLiteral()
+
+ item := d.data[start:d.readIndex()]
+
+ switch c := item[0]; c {
+ case 'n': // null
+ return nil
+
+ case 't', 'f': // true, false
+ return c == 't'
+
+ case '"': // string
+ s, ok := unquote(item)
+ if !ok {
+ panic(phasePanicMsg)
+ }
+ return s
+
+ default: // number
+ if c != '-' && (c < '0' || c > '9') {
+ panic(phasePanicMsg)
+ }
+ n, err := d.convertNumber(string(item))
+ if err != nil {
+ d.saveError(err)
+ }
+ return n
+ }
+}
+
+// getu4 decodes \uXXXX from the beginning of s, returning the hex value,
+// or it returns -1.
+func getu4(s []byte) rune {
+ if len(s) < 6 || s[0] != '\\' || s[1] != 'u' {
+ return -1
+ }
+ var r rune
+ for _, c := range s[2:6] {
+ switch {
+ case '0' <= c && c <= '9':
+ c = c - '0'
+ case 'a' <= c && c <= 'f':
+ c = c - 'a' + 10
+ case 'A' <= c && c <= 'F':
+ c = c - 'A' + 10
+ default:
+ return -1
+ }
+ r = r*16 + rune(c)
+ }
+ return r
+}
+
+// unquote converts a quoted JSON string literal s into an actual string t.
+// The rules are different than for Go, so cannot use strconv.Unquote.
+func unquote(s []byte) (t string, ok bool) {
+ s, ok = unquoteBytes(s)
+ t = string(s)
+ return
+}
+
+// unquoteBytes should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/bytedance/sonic
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname unquoteBytes
+func unquoteBytes(s []byte) (t []byte, ok bool) {
+ if len(s) < 2 || s[0] != '"' || s[len(s)-1] != '"' {
+ return
+ }
+ s = s[1 : len(s)-1]
+
+ // Check for unusual characters. If there are none,
+ // then no unquoting is needed, so return a slice of the
+ // original bytes.
+ r := 0
+ for r < len(s) {
+ c := s[r]
+ if c == '\\' || c == '"' || c < ' ' {
+ break
+ }
+ if c < utf8.RuneSelf {
+ r++
+ continue
+ }
+ rr, size := utf8.DecodeRune(s[r:])
+ if rr == utf8.RuneError && size == 1 {
+ break
+ }
+ r += size
+ }
+ if r == len(s) {
+ return s, true
+ }
+
+ b := make([]byte, len(s)+2*utf8.UTFMax)
+ w := copy(b, s[0:r])
+ for r < len(s) {
+ // Out of room? Can only happen if s is full of
+ // malformed UTF-8 and we're replacing each
+ // byte with RuneError.
+ if w >= len(b)-2*utf8.UTFMax {
+ nb := make([]byte, (len(b)+utf8.UTFMax)*2)
+ copy(nb, b[0:w])
+ b = nb
+ }
+ switch c := s[r]; {
+ case c == '\\':
+ r++
+ if r >= len(s) {
+ return
+ }
+ switch s[r] {
+ default:
+ return
+ case '"', '\\', '/', '\'':
+ b[w] = s[r]
+ r++
+ w++
+ case 'b':
+ b[w] = '\b'
+ r++
+ w++
+ case 'f':
+ b[w] = '\f'
+ r++
+ w++
+ case 'n':
+ b[w] = '\n'
+ r++
+ w++
+ case 'r':
+ b[w] = '\r'
+ r++
+ w++
+ case 't':
+ b[w] = '\t'
+ r++
+ w++
+ case 'u':
+ r--
+ rr := getu4(s[r:])
+ if rr < 0 {
+ return
+ }
+ r += 6
+ if utf16.IsSurrogate(rr) {
+ rr1 := getu4(s[r:])
+ if dec := utf16.DecodeRune(rr, rr1); dec != unicode.ReplacementChar {
+ // A valid pair; consume.
+ r += 6
+ w += utf8.EncodeRune(b[w:], dec)
+ break
+ }
+ // Invalid surrogate; fall back to replacement rune.
+ rr = unicode.ReplacementChar
+ }
+ w += utf8.EncodeRune(b[w:], rr)
+ }
+
+ // Quote, control characters are invalid.
+ case c == '"', c < ' ':
+ return
+
+ // ASCII
+ case c < utf8.RuneSelf:
+ b[w] = c
+ r++
+ w++
+
+ // Coerce to well-formed UTF-8.
+ default:
+ rr, size := utf8.DecodeRune(s[r:])
+ r += size
+ w += utf8.EncodeRune(b[w:], rr)
+ }
+ }
+ return b[0:w], true
+}
diff --git a/internal/encoding/json/encode.go b/internal/encoding/json/encode.go
new file mode 100644
index 0000000..98b819d
--- /dev/null
+++ b/internal/encoding/json/encode.go
@@ -0,0 +1,1398 @@
+// Vendored from Go 1.24.0-pre-release
+// To find alterations, check package shims, and comments beginning in SHIM().
+//
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package json implements encoding and decoding of JSON as defined in
+// RFC 7159. The mapping between JSON and Go values is described
+// in the documentation for the Marshal and Unmarshal functions.
+//
+// See "JSON and Go" for an introduction to this package:
+// https://golang.org/doc/articles/json_and_go.html
+package json
+
+import (
+ "bytes"
+ "cmp"
+ "encoding"
+ "encoding/base64"
+ "fmt"
+ "github.com/anthropics/anthropic-sdk-go/internal/encoding/json/sentinel"
+ "github.com/anthropics/anthropic-sdk-go/internal/encoding/json/shims"
+ "math"
+ "reflect"
+ "slices"
+ "strconv"
+ "strings"
+ "sync"
+ "unicode"
+ "unicode/utf8"
+ _ "unsafe" // for linkname
+)
+
+// Marshal returns the JSON encoding of v.
+//
+// Marshal traverses the value v recursively.
+// If an encountered value implements [Marshaler]
+// and is not a nil pointer, Marshal calls [Marshaler.MarshalJSON]
+// to produce JSON. If no [Marshaler.MarshalJSON] method is present but the
+// value implements [encoding.TextMarshaler] instead, Marshal calls
+// [encoding.TextMarshaler.MarshalText] and encodes the result as a JSON string.
+// The nil pointer exception is not strictly necessary
+// but mimics a similar, necessary exception in the behavior of
+// [Unmarshaler.UnmarshalJSON].
+//
+// Otherwise, Marshal uses the following type-dependent default encodings:
+//
+// Boolean values encode as JSON booleans.
+//
+// Floating point, integer, and [Number] values encode as JSON numbers.
+// NaN and +/-Inf values will return an [UnsupportedValueError].
+//
+// String values encode as JSON strings coerced to valid UTF-8,
+// replacing invalid bytes with the Unicode replacement rune.
+// So that the JSON will be safe to embed inside HTML <script> tags,
+// the string is encoded using [HTMLEscape],
+// which replaces "<", ">", "&", U+2028, and U+2029 are escaped
+// to "\u003c","\u003e", "\u0026", "\u2028", and "\u2029".
+// This replacement can be disabled when using an [Encoder],
+// by calling [Encoder.SetEscapeHTML](false).
+//
+// Array and slice values encode as JSON arrays, except that
+// []byte encodes as a base64-encoded string, and a nil slice
+// encodes as the null JSON value.
+//
+// Struct values encode as JSON objects.
+// Each exported struct field becomes a member of the object, using the
+// field name as the object key, unless the field is omitted for one of the
+// reasons given below.
+//
+// The encoding of each struct field can be customized by the format string
+// stored under the "json" key in the struct field's tag.
+// The format string gives the name of the field, possibly followed by a
+// comma-separated list of options. The name may be empty in order to
+// specify options without overriding the default field name.
+//
+// The "omitempty" option specifies that the field should be omitted
+// from the encoding if the field has an empty value, defined as
+// false, 0, a nil pointer, a nil interface value, and any array,
+// slice, map, or string of length zero.
+//
+// As a special case, if the field tag is "-", the field is always omitted.
+// Note that a field with name "-" can still be generated using the tag "-,".
+//
+// Examples of struct field tags and their meanings:
+//
+// // Field appears in JSON as key "myName".
+// Field int `json:"myName"`
+//
+// // Field appears in JSON as key "myName" and
+// // the field is omitted from the object if its value is empty,
+// // as defined above.
+// Field int `json:"myName,omitempty"`
+//
+// // Field appears in JSON as key "Field" (the default), but
+// // the field is skipped if empty.
+// // Note the leading comma.
+// Field int `json:",omitempty"`
+//
+// // Field is ignored by this package.
+// Field int `json:"-"`
+//
+// // Field appears in JSON as key "-".
+// Field int `json:"-,"`
+//
+// The "omitzero" option specifies that the field should be omitted
+// from the encoding if the field has a zero value, according to rules:
+//
+// 1) If the field type has an "IsZero() bool" method, that will be used to
+// determine whether the value is zero.
+//
+// 2) Otherwise, the value is zero if it is the zero value for its type.
+//
+// If both "omitempty" and "omitzero" are specified, the field will be omitted
+// if the value is either empty or zero (or both).
+//
+// The "string" option signals that a field is stored as JSON inside a
+// JSON-encoded string. It applies only to fields of string, floating point,
+// integer, or boolean types. This extra level of encoding is sometimes used
+// when communicating with JavaScript programs:
+//
+// Int64String int64 `json:",string"`
+//
+// The key name will be used if it's a non-empty string consisting of
+// only Unicode letters, digits, and ASCII punctuation except quotation
+// marks, backslash, and comma.
+//
+// Embedded struct fields are usually marshaled as if their inner exported fields
+// were fields in the outer struct, subject to the usual Go visibility rules amended
+// as described in the next paragraph.
+// An anonymous struct field with a name given in its JSON tag is treated as
+// having that name, rather than being anonymous.
+// An anonymous struct field of interface type is treated the same as having
+// that type as its name, rather than being anonymous.
+//
+// The Go visibility rules for struct fields are amended for JSON when
+// deciding which field to marshal or unmarshal. If there are
+// multiple fields at the same level, and that level is the least
+// nested (and would therefore be the nesting level selected by the
+// usual Go rules), the following extra rules apply:
+//
+// 1) Of those fields, if any are JSON-tagged, only tagged fields are considered,
+// even if there are multiple untagged fields that would otherwise conflict.
+//
+// 2) If there is exactly one field (tagged or not according to the first rule), that is selected.
+//
+// 3) Otherwise there are multiple fields, and all are ignored; no error occurs.
+//
+// Handling of anonymous struct fields is new in Go 1.1.
+// Prior to Go 1.1, anonymous struct fields were ignored. To force ignoring of
+// an anonymous struct field in both current and earlier versions, give the field
+// a JSON tag of "-".
+//
+// Map values encode as JSON objects. The map's key type must either be a
+// string, an integer type, or implement [encoding.TextMarshaler]. The map keys
+// are sorted and used as JSON object keys by applying the following rules,
+// subject to the UTF-8 coercion described for string values above:
+// - keys of any string type are used directly
+// - keys that implement [encoding.TextMarshaler] are marshaled
+// - integer keys are converted to strings
+//
+// Pointer values encode as the value pointed to.
+// A nil pointer encodes as the null JSON value.
+//
+// Interface values encode as the value contained in the interface.
+// A nil interface value encodes as the null JSON value.
+//
+// Channel, complex, and function values cannot be encoded in JSON.
+// Attempting to encode such a value causes Marshal to return
+// an [UnsupportedTypeError].
+//
+// JSON cannot represent cyclic data structures and Marshal does not
+// handle them. Passing cyclic structures to Marshal will result in
+// an error.
+func Marshal(v any) ([]byte, error) {
+ e := newEncodeState()
+ defer encodeStatePool.Put(e)
+
+ err := e.marshal(v, encOpts{escapeHTML: true})
+ if err != nil {
+ return nil, err
+ }
+ buf := append([]byte(nil), e.Bytes()...)
+
+ return buf, nil
+}
+
+// MarshalIndent is like [Marshal] but applies [Indent] to format the output.
+// Each JSON element in the output will begin on a new line beginning with prefix
+// followed by one or more copies of indent according to the indentation nesting.
+func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
+ b, err := Marshal(v)
+ if err != nil {
+ return nil, err
+ }
+ b2 := make([]byte, 0, indentGrowthFactor*len(b))
+ b2, err = appendIndent(b2, b, prefix, indent)
+ if err != nil {
+ return nil, err
+ }
+ return b2, nil
+}
+
+// Marshaler is the interface implemented by types that
+// can marshal themselves into valid JSON.
+type Marshaler interface {
+ MarshalJSON() ([]byte, error)
+}
+
+// An UnsupportedTypeError is returned by [Marshal] when attempting
+// to encode an unsupported value type.
+type UnsupportedTypeError struct {
+ Type reflect.Type
+}
+
+func (e *UnsupportedTypeError) Error() string {
+ return "json: unsupported type: " + e.Type.String()
+}
+
+// An UnsupportedValueError is returned by [Marshal] when attempting
+// to encode an unsupported value.
+type UnsupportedValueError struct {
+ Value reflect.Value
+ Str string
+}
+
+func (e *UnsupportedValueError) Error() string {
+ return "json: unsupported value: " + e.Str
+}
+
+// Before Go 1.2, an InvalidUTF8Error was returned by [Marshal] when
+// attempting to encode a string value with invalid UTF-8 sequences.
+// As of Go 1.2, [Marshal] instead coerces the string to valid UTF-8 by
+// replacing invalid bytes with the Unicode replacement rune U+FFFD.
+//
+// Deprecated: No longer used; kept for compatibility.
+type InvalidUTF8Error struct {
+ S string // the whole string value that caused the error
+}
+
+func (e *InvalidUTF8Error) Error() string {
+ return "json: invalid UTF-8 in string: " + strconv.Quote(e.S)
+}
+
+// A MarshalerError represents an error from calling a
+// [Marshaler.MarshalJSON] or [encoding.TextMarshaler.MarshalText] method.
+type MarshalerError struct {
+ Type reflect.Type
+ Err error
+ sourceFunc string
+}
+
+func (e *MarshalerError) Error() string {
+ srcFunc := e.sourceFunc
+ if srcFunc == "" {
+ srcFunc = "MarshalJSON"
+ }
+ return "json: error calling " + srcFunc +
+ " for type " + e.Type.String() +
+ ": " + e.Err.Error()
+}
+
+// Unwrap returns the underlying error.
+func (e *MarshalerError) Unwrap() error { return e.Err }
+
+const hex = "0123456789abcdef"
+
+// An encodeState encodes JSON into a bytes.Buffer.
+type encodeState struct {
+ bytes.Buffer // accumulated output
+
+ // Keep track of what pointers we've seen in the current recursive call
+ // path, to avoid cycles that could lead to a stack overflow. Only do
+ // the relatively expensive map operations if ptrLevel is larger than
+ // startDetectingCyclesAfter, so that we skip the work if we're within a
+ // reasonable amount of nested pointers deep.
+ ptrLevel uint
+ ptrSeen map[any]struct{}
+}
+
+const startDetectingCyclesAfter = 1000
+
+var encodeStatePool sync.Pool
+
+func newEncodeState() *encodeState {
+ if v := encodeStatePool.Get(); v != nil {
+ e := v.(*encodeState)
+ e.Reset()
+ if len(e.ptrSeen) > 0 {
+ panic("ptrEncoder.encode should have emptied ptrSeen via defers")
+ }
+ e.ptrLevel = 0
+ return e
+ }
+ return &encodeState{ptrSeen: make(map[any]struct{})}
+}
+
+// jsonError is an error wrapper type for internal use only.
+// Panics with errors are wrapped in jsonError so that the top-level recover
+// can distinguish intentional panics from this package.
+type jsonError struct{ error }
+
+func (e *encodeState) marshal(v any, opts encOpts) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ if je, ok := r.(jsonError); ok {
+ err = je.error
+ } else {
+ panic(r)
+ }
+ }
+ }()
+ e.reflectValue(reflect.ValueOf(v), opts)
+ return nil
+}
+
+// error aborts the encoding by panicking with err wrapped in jsonError.
+func (e *encodeState) error(err error) {
+ panic(jsonError{err})
+}
+
+func isEmptyValue(v reflect.Value) bool {
+ switch v.Kind() {
+ case reflect.String:
+ return v.Len() == 0
+ case reflect.Array, reflect.Map, reflect.Slice:
+ return v.Len() == 0
+ case reflect.Bool,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
+ reflect.Float32, reflect.Float64,
+ reflect.Interface, reflect.Pointer:
+ return v.IsZero()
+ }
+ return false
+}
+
+func (e *encodeState) reflectValue(v reflect.Value, opts encOpts) {
+ valueEncoder(v)(e, v, opts)
+}
+
+type encOpts struct {
+ // quoted causes primitive fields to be encoded inside JSON strings.
+ quoted bool
+ // escapeHTML causes '<', '>', and '&' to be escaped in JSON strings.
+ escapeHTML bool
+ // EDIT(begin): save the timefmt
+ timefmt string
+ // EDIT(end)
+}
+
+type encoderFunc func(e *encodeState, v reflect.Value, opts encOpts)
+
+var encoderCache sync.Map // map[reflect.Type]encoderFunc
+
+func valueEncoder(v reflect.Value) encoderFunc {
+ if !v.IsValid() {
+ return invalidValueEncoder
+ }
+ return typeEncoder(v.Type())
+}
+
+func typeEncoder(t reflect.Type) encoderFunc {
+ if fi, ok := encoderCache.Load(t); ok {
+ return fi.(encoderFunc)
+ }
+
+ // To deal with recursive types, populate the map with an
+ // indirect func before we build it. This type waits on the
+ // real func (f) to be ready and then calls it. This indirect
+ // func is only used for recursive types.
+ var (
+ wg sync.WaitGroup
+ f encoderFunc
+ )
+ wg.Add(1)
+ fi, loaded := encoderCache.LoadOrStore(t, encoderFunc(func(e *encodeState, v reflect.Value, opts encOpts) {
+ wg.Wait()
+ f(e, v, opts)
+ }))
+ if loaded {
+ return fi.(encoderFunc)
+ }
+
+ // Compute the real encoder and replace the indirect func with it.
+ f = newTypeEncoder(t, true)
+ wg.Done()
+ encoderCache.Store(t, f)
+ return f
+}
+
+var (
+ // SHIM(begin): TypeFor[T]() reflect.Type
+ marshalerType = shims.TypeFor[Marshaler]()
+ textMarshalerType = shims.TypeFor[encoding.TextMarshaler]()
+ // SHIM(end)
+)
+
+// newTypeEncoder constructs an encoderFunc for a type.
+// The returned encoder only checks CanAddr when allowAddr is true.
+func newTypeEncoder(t reflect.Type, allowAddr bool) encoderFunc {
+ // EDIT(begin): add custom time encoder
+ if t == timeType {
+ return newTimeEncoder()
+ }
+ // EDIT(end)
+
+ // If we have a non-pointer value whose type implements
+ // Marshaler with a value receiver, then we're better off taking
+ // the address of the value - otherwise we end up with an
+ // allocation as we cast the value to an interface.
+ if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(marshalerType) {
+ return newCondAddrEncoder(addrMarshalerEncoder, newTypeEncoder(t, false))
+ }
+
+ if t.Implements(marshalerType) {
+ return marshalerEncoder
+ }
+ if t.Kind() != reflect.Pointer && allowAddr && reflect.PointerTo(t).Implements(textMarshalerType) {
+ return newCondAddrEncoder(addrTextMarshalerEncoder, newTypeEncoder(t, false))
+ }
+ if t.Implements(textMarshalerType) {
+ return textMarshalerEncoder
+ }
+
+ switch t.Kind() {
+ case reflect.Bool:
+ return boolEncoder
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return intEncoder
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return uintEncoder
+ case reflect.Float32:
+ return float32Encoder
+ case reflect.Float64:
+ return float64Encoder
+ case reflect.String:
+ return stringEncoder
+ case reflect.Interface:
+ return interfaceEncoder
+ case reflect.Struct:
+ return newStructEncoder(t)
+ case reflect.Map:
+ return newMapEncoder(t)
+ case reflect.Slice:
+ return newSliceEncoder(t)
+ case reflect.Array:
+ return newArrayEncoder(t)
+ case reflect.Pointer:
+ return newPtrEncoder(t)
+ default:
+ return unsupportedTypeEncoder
+ }
+}
+
+func invalidValueEncoder(e *encodeState, v reflect.Value, _ encOpts) {
+ e.WriteString("null")
+}
+
+func marshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ if v.Kind() == reflect.Pointer && v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ m, ok := v.Interface().(Marshaler)
+ if !ok {
+ e.WriteString("null")
+ return
+ }
+
+ // EDIT(begin): use custom time encoder
+ if timeMarshalEncoder(e, v, opts) {
+ return
+ }
+ // EDIT(end)
+
+ b, err := m.MarshalJSON()
+ if err == nil {
+ e.Grow(len(b))
+ out := e.AvailableBuffer()
+ out, err = appendCompact(out, b, opts.escapeHTML)
+ e.Buffer.Write(out)
+ }
+ if err != nil {
+ e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
+ }
+}
+
+func addrMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ va := v.Addr()
+ if va.IsNil() {
+ e.WriteString("null")
+ return
+ }
+
+ // EDIT(begin): use custom time encoder
+ if timeMarshalEncoder(e, v, opts) {
+ return
+ }
+ // EDIT(end)
+
+ m := va.Interface().(Marshaler)
+ b, err := m.MarshalJSON()
+ if err == nil {
+ e.Grow(len(b))
+ out := e.AvailableBuffer()
+ out, err = appendCompact(out, b, opts.escapeHTML)
+ e.Buffer.Write(out)
+ }
+ if err != nil {
+ e.error(&MarshalerError{v.Type(), err, "MarshalJSON"})
+ }
+}
+
+func textMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ if v.Kind() == reflect.Pointer && v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ m, ok := v.Interface().(encoding.TextMarshaler)
+ if !ok {
+ e.WriteString("null")
+ return
+ }
+ b, err := m.MarshalText()
+ if err != nil {
+ e.error(&MarshalerError{v.Type(), err, "MarshalText"})
+ }
+ e.Write(appendString(e.AvailableBuffer(), b, opts.escapeHTML))
+}
+
+func addrTextMarshalerEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ va := v.Addr()
+ if va.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ m := va.Interface().(encoding.TextMarshaler)
+ b, err := m.MarshalText()
+ if err != nil {
+ e.error(&MarshalerError{v.Type(), err, "MarshalText"})
+ }
+ e.Write(appendString(e.AvailableBuffer(), b, opts.escapeHTML))
+}
+
+func boolEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ b := e.AvailableBuffer()
+ b = mayAppendQuote(b, opts.quoted)
+ b = strconv.AppendBool(b, v.Bool())
+ b = mayAppendQuote(b, opts.quoted)
+ e.Write(b)
+}
+
+func intEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ b := e.AvailableBuffer()
+ b = mayAppendQuote(b, opts.quoted)
+ b = strconv.AppendInt(b, v.Int(), 10)
+ b = mayAppendQuote(b, opts.quoted)
+ e.Write(b)
+}
+
+func uintEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ b := e.AvailableBuffer()
+ b = mayAppendQuote(b, opts.quoted)
+ b = strconv.AppendUint(b, v.Uint(), 10)
+ b = mayAppendQuote(b, opts.quoted)
+ e.Write(b)
+}
+
+type floatEncoder int // number of bits
+
+func (bits floatEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
+ f := v.Float()
+ if math.IsInf(f, 0) || math.IsNaN(f) {
+ e.error(&UnsupportedValueError{v, strconv.FormatFloat(f, 'g', -1, int(bits))})
+ }
+
+ // Convert as if by ES6 number to string conversion.
+ // This matches most other JSON generators.
+ // See golang.org/issue/6384 and golang.org/issue/14135.
+ // Like fmt %g, but the exponent cutoffs are different
+ // and exponents themselves are not padded to two digits.
+ b := e.AvailableBuffer()
+ b = mayAppendQuote(b, opts.quoted)
+ abs := math.Abs(f)
+ fmt := byte('f')
+ // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right.
+ if abs != 0 {
+ if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) {
+ fmt = 'e'
+ }
+ }
+ b = strconv.AppendFloat(b, f, fmt, -1, int(bits))
+ if fmt == 'e' {
+ // clean up e-09 to e-9
+ n := len(b)
+ if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' {
+ b[n-2] = b[n-1]
+ b = b[:n-1]
+ }
+ }
+ b = mayAppendQuote(b, opts.quoted)
+ e.Write(b)
+}
+
+var (
+ float32Encoder = (floatEncoder(32)).encode
+ float64Encoder = (floatEncoder(64)).encode
+)
+
+func stringEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ if v.Type() == numberType {
+ numStr := v.String()
+ // In Go1.5 the empty string encodes to "0", while this is not a valid number literal
+ // we keep compatibility so check validity after this.
+ if numStr == "" {
+ numStr = "0" // Number's zero-val
+ }
+ if !isValidNumber(numStr) {
+ e.error(fmt.Errorf("json: invalid number literal %q", numStr))
+ }
+ b := e.AvailableBuffer()
+ b = mayAppendQuote(b, opts.quoted)
+ b = append(b, numStr...)
+ b = mayAppendQuote(b, opts.quoted)
+ e.Write(b)
+ return
+ }
+ if opts.quoted {
+ b := appendString(nil, v.String(), opts.escapeHTML)
+ e.Write(appendString(e.AvailableBuffer(), b, false)) // no need to escape again since it is already escaped
+ } else {
+ e.Write(appendString(e.AvailableBuffer(), v.String(), opts.escapeHTML))
+ }
+}
+
+// isValidNumber reports whether s is a valid JSON number literal.
+//
+// isValidNumber should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/bytedance/sonic
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname isValidNumber
+func isValidNumber(s string) bool {
+ // This function implements the JSON numbers grammar.
+ // See https://tools.ietf.org/html/rfc7159#section-6
+ // and https://www.json.org/img/number.png
+
+ if s == "" {
+ return false
+ }
+
+ // Optional -
+ if s[0] == '-' {
+ s = s[1:]
+ if s == "" {
+ return false
+ }
+ }
+
+ // Digits
+ switch {
+ default:
+ return false
+
+ case s[0] == '0':
+ s = s[1:]
+
+ case '1' <= s[0] && s[0] <= '9':
+ s = s[1:]
+ for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
+ s = s[1:]
+ }
+ }
+
+ // . followed by 1 or more digits.
+ if len(s) >= 2 && s[0] == '.' && '0' <= s[1] && s[1] <= '9' {
+ s = s[2:]
+ for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
+ s = s[1:]
+ }
+ }
+
+ // e or E followed by an optional - or + and
+ // 1 or more digits.
+ if len(s) >= 2 && (s[0] == 'e' || s[0] == 'E') {
+ s = s[1:]
+ if s[0] == '+' || s[0] == '-' {
+ s = s[1:]
+ if s == "" {
+ return false
+ }
+ }
+ for len(s) > 0 && '0' <= s[0] && s[0] <= '9' {
+ s = s[1:]
+ }
+ }
+
+ // Make sure we are at the end.
+ return s == ""
+}
+
+func interfaceEncoder(e *encodeState, v reflect.Value, opts encOpts) {
+ if v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ e.reflectValue(v.Elem(), opts)
+}
+
+func unsupportedTypeEncoder(e *encodeState, v reflect.Value, _ encOpts) {
+ e.error(&UnsupportedTypeError{v.Type()})
+}
+
+type structEncoder struct {
+ fields structFields
+}
+
+type structFields struct {
+ list []field
+ byExactName map[string]*field
+ byFoldedName map[string]*field
+}
+
+func (se structEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
+ next := byte('{')
+FieldLoop:
+ for i := range se.fields.list {
+ f := &se.fields.list[i]
+
+ // Find the nested struct field by following f.index.
+ fv := v
+ for _, i := range f.index {
+ if fv.Kind() == reflect.Pointer {
+ if fv.IsNil() {
+ continue FieldLoop
+ }
+ fv = fv.Elem()
+ }
+ fv = fv.Field(i)
+ }
+
+ if (f.omitEmpty && isEmptyValue(fv)) ||
+ (f.omitZero && (f.isZero == nil && fv.IsZero() || (f.isZero != nil && f.isZero(fv)))) {
+ continue
+ }
+ e.WriteByte(next)
+ next = ','
+ if opts.escapeHTML {
+ e.WriteString(f.nameEscHTML)
+ } else {
+ e.WriteString(f.nameNonEsc)
+ }
+ opts.quoted = f.quoted
+ f.encoder(e, fv, opts)
+ }
+ if next == '{' {
+ e.WriteString("{}")
+ } else {
+ e.WriteByte('}')
+ }
+}
+
+func newStructEncoder(t reflect.Type) encoderFunc {
+ se := structEncoder{fields: cachedTypeFields(t)}
+ return se.encode
+}
+
+type mapEncoder struct {
+ elemEnc encoderFunc
+}
+
+func (me mapEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
+ if v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
+ // We're a large number of nested ptrEncoder.encode calls deep;
+ // start checking if we've run into a pointer cycle.
+ ptr := v.UnsafePointer()
+ if _, ok := e.ptrSeen[ptr]; ok {
+ e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
+ }
+ e.ptrSeen[ptr] = struct{}{}
+ defer delete(e.ptrSeen, ptr)
+ }
+ e.WriteByte('{')
+
+ // Extract and sort the keys.
+ var (
+ sv = make([]reflectWithString, v.Len())
+ mi = v.MapRange()
+ err error
+ )
+ for i := 0; mi.Next(); i++ {
+ if sv[i].ks, err = resolveKeyName(mi.Key()); err != nil {
+ e.error(fmt.Errorf("json: encoding error for type %q: %q", v.Type().String(), err.Error()))
+ }
+ sv[i].v = mi.Value()
+ }
+ slices.SortFunc(sv, func(i, j reflectWithString) int {
+ return strings.Compare(i.ks, j.ks)
+ })
+
+ for i, kv := range sv {
+ if i > 0 {
+ e.WriteByte(',')
+ }
+ e.Write(appendString(e.AvailableBuffer(), kv.ks, opts.escapeHTML))
+ e.WriteByte(':')
+ me.elemEnc(e, kv.v, opts)
+ }
+ e.WriteByte('}')
+ e.ptrLevel--
+}
+
+func newMapEncoder(t reflect.Type) encoderFunc {
+ switch t.Key().Kind() {
+ case reflect.String,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ default:
+ if !t.Key().Implements(textMarshalerType) {
+ return unsupportedTypeEncoder
+ }
+ }
+ me := mapEncoder{typeEncoder(t.Elem())}
+ return me.encode
+}
+
+func encodeByteSlice(e *encodeState, v reflect.Value, _ encOpts) {
+ if v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+
+ s := v.Bytes()
+ b := e.AvailableBuffer()
+ b = append(b, '"')
+ // SHIM(base64): base64.StdEncoding.AppendEncode([]byte, []byte) []byte
+ b = (shims.AppendableStdEncoding{Encoding: base64.StdEncoding}).AppendEncode(b, s)
+ b = append(b, '"')
+ e.Write(b)
+}
+
+// sliceEncoder just wraps an arrayEncoder, checking to make sure the value isn't nil.
+type sliceEncoder struct {
+ arrayEnc encoderFunc
+}
+
+func (se sliceEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
+ if v.IsNil() {
+ e.WriteString("null")
+ return
+ }
+ if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
+ // We're a large number of nested ptrEncoder.encode calls deep;
+ // start checking if we've run into a pointer cycle.
+ // Here we use a struct to memorize the pointer to the first element of the slice
+ // and its length.
+ ptr := struct {
+ ptr any // always an unsafe.Pointer, but avoids a dependency on package unsafe
+ len int
+ }{v.UnsafePointer(), v.Len()}
+ if _, ok := e.ptrSeen[ptr]; ok {
+ e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
+ }
+ e.ptrSeen[ptr] = struct{}{}
+ defer delete(e.ptrSeen, ptr)
+ }
+ se.arrayEnc(e, v, opts)
+ e.ptrLevel--
+}
+
+func newSliceEncoder(t reflect.Type) encoderFunc {
+ // Byte slices get special treatment; arrays don't.
+ if t.Elem().Kind() == reflect.Uint8 {
+ p := reflect.PointerTo(t.Elem())
+ if !p.Implements(marshalerType) && !p.Implements(textMarshalerType) {
+ return encodeByteSlice
+ }
+ }
+ enc := sliceEncoder{newArrayEncoder(t)}
+ return enc.encode
+}
+
+type arrayEncoder struct {
+ elemEnc encoderFunc
+}
+
+func (ae arrayEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
+ e.WriteByte('[')
+ n := v.Len()
+ for i := 0; i < n; i++ {
+ if i > 0 {
+ e.WriteByte(',')
+ }
+ ae.elemEnc(e, v.Index(i), opts)
+ }
+ e.WriteByte(']')
+}
+
+func newArrayEncoder(t reflect.Type) encoderFunc {
+ enc := arrayEncoder{typeEncoder(t.Elem())}
+ return enc.encode
+}
+
+type ptrEncoder struct {
+ elemEnc encoderFunc
+}
+
+func (pe ptrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
+ // EDIT(begin)
+ //
+ // if v.IsNil() {
+ // e.WriteString("null")
+ // return
+ // }
+
+ if v.IsNil() || sentinel.IsValueNullPtr(v) || sentinel.IsValueNullSlice(v) {
+ e.WriteString("null")
+ return
+ }
+
+ // EDIT(end)
+ if e.ptrLevel++; e.ptrLevel > startDetectingCyclesAfter {
+ // We're a large number of nested ptrEncoder.encode calls deep;
+ // start checking if we've run into a pointer cycle.
+ ptr := v.Interface()
+ if _, ok := e.ptrSeen[ptr]; ok {
+ e.error(&UnsupportedValueError{v, fmt.Sprintf("encountered a cycle via %s", v.Type())})
+ }
+ e.ptrSeen[ptr] = struct{}{}
+ defer delete(e.ptrSeen, ptr)
+ }
+ pe.elemEnc(e, v.Elem(), opts)
+ e.ptrLevel--
+}
+
+func newPtrEncoder(t reflect.Type) encoderFunc {
+ enc := ptrEncoder{typeEncoder(t.Elem())}
+ return enc.encode
+}
+
+type condAddrEncoder struct {
+ canAddrEnc, elseEnc encoderFunc
+}
+
+func (ce condAddrEncoder) encode(e *encodeState, v reflect.Value, opts encOpts) {
+ if v.CanAddr() {
+ ce.canAddrEnc(e, v, opts)
+ } else {
+ ce.elseEnc(e, v, opts)
+ }
+}
+
+// newCondAddrEncoder returns an encoder that checks whether its value
+// CanAddr and delegates to canAddrEnc if so, else to elseEnc.
+func newCondAddrEncoder(canAddrEnc, elseEnc encoderFunc) encoderFunc {
+ enc := condAddrEncoder{canAddrEnc: canAddrEnc, elseEnc: elseEnc}
+ return enc.encode
+}
+
+func isValidTag(s string) bool {
+ if s == "" {
+ return false
+ }
+ for _, c := range s {
+ switch {
+ case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c):
+ // Backslash and quote chars are reserved, but
+ // otherwise any punctuation chars are allowed
+ // in a tag name.
+ case !unicode.IsLetter(c) && !unicode.IsDigit(c):
+ return false
+ }
+ }
+ return true
+}
+
+func typeByIndex(t reflect.Type, index []int) reflect.Type {
+ for _, i := range index {
+ if t.Kind() == reflect.Pointer {
+ t = t.Elem()
+ }
+ t = t.Field(i).Type
+ }
+ return t
+}
+
+type reflectWithString struct {
+ v reflect.Value
+ ks string
+}
+
+func resolveKeyName(k reflect.Value) (string, error) {
+ if k.Kind() == reflect.String {
+ return k.String(), nil
+ }
+ if tm, ok := k.Interface().(encoding.TextMarshaler); ok {
+ if k.Kind() == reflect.Pointer && k.IsNil() {
+ return "", nil
+ }
+ buf, err := tm.MarshalText()
+ return string(buf), err
+ }
+ switch k.Kind() {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ return strconv.FormatInt(k.Int(), 10), nil
+ case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
+ return strconv.FormatUint(k.Uint(), 10), nil
+ }
+ panic("unexpected map key type")
+}
+
+func appendString[Bytes []byte | string](dst []byte, src Bytes, escapeHTML bool) []byte {
+ dst = append(dst, '"')
+ start := 0
+ for i := 0; i < len(src); {
+ if b := src[i]; b < utf8.RuneSelf {
+ if htmlSafeSet[b] || (!escapeHTML && safeSet[b]) {
+ i++
+ continue
+ }
+ dst = append(dst, src[start:i]...)
+ switch b {
+ case '\\', '"':
+ dst = append(dst, '\\', b)
+ case '\b':
+ dst = append(dst, '\\', 'b')
+ case '\f':
+ dst = append(dst, '\\', 'f')
+ case '\n':
+ dst = append(dst, '\\', 'n')
+ case '\r':
+ dst = append(dst, '\\', 'r')
+ case '\t':
+ dst = append(dst, '\\', 't')
+ default:
+ // This encodes bytes < 0x20 except for \b, \f, \n, \r and \t.
+ // If escapeHTML is set, it also escapes <, >, and &
+ // because they can lead to security holes when
+ // user-controlled strings are rendered into JSON
+ // and served to some browsers.
+ dst = append(dst, '\\', 'u', '0', '0', hex[b>>4], hex[b&0xF])
+ }
+ i++
+ start = i
+ continue
+ }
+ // TODO(https://go.dev/issue/56948): Use generic utf8 functionality.
+ // For now, cast only a small portion of byte slices to a string
+ // so that it can be stack allocated. This slows down []byte slightly
+ // due to the extra copy, but keeps string performance roughly the same.
+ n := len(src) - i
+ if n > utf8.UTFMax {
+ n = utf8.UTFMax
+ }
+ c, size := utf8.DecodeRuneInString(string(src[i : i+n]))
+ if c == utf8.RuneError && size == 1 {
+ dst = append(dst, src[start:i]...)
+ dst = append(dst, `\ufffd`...)
+ i += size
+ start = i
+ continue
+ }
+ // U+2028 is LINE SEPARATOR.
+ // U+2029 is PARAGRAPH SEPARATOR.
+ // They are both technically valid characters in JSON strings,
+ // but don't work in JSONP, which has to be evaluated as JavaScript,
+ // and can lead to security holes there. It is valid JSON to
+ // escape them, so we do so unconditionally.
+ // See https://en.wikipedia.org/wiki/JSON#Safety.
+ if c == '\u2028' || c == '\u2029' {
+ dst = append(dst, src[start:i]...)
+ dst = append(dst, '\\', 'u', '2', '0', '2', hex[c&0xF])
+ i += size
+ start = i
+ continue
+ }
+ i += size
+ }
+ dst = append(dst, src[start:]...)
+ dst = append(dst, '"')
+ return dst
+}
+
+// A field represents a single field found in a struct.
+type field struct {
+ name string
+ nameBytes []byte // []byte(name)
+
+ nameNonEsc string // `"` + name + `":`
+ nameEscHTML string // `"` + HTMLEscape(name) + `":`
+
+ tag bool
+ index []int
+ typ reflect.Type
+ omitEmpty bool
+ omitZero bool
+ isZero func(reflect.Value) bool
+ quoted bool
+
+ encoder encoderFunc
+
+ // EDIT(begin): save the timefmt if present
+ timefmt string
+ // EDIT(end)
+}
+
+type isZeroer interface {
+ IsZero() bool
+}
+
+// SHIM(reflect): TypeFor[T]() reflect.Type
+var isZeroerType = shims.TypeFor[isZeroer]()
+
+// typeFields returns a list of fields that JSON should recognize for the given type.
+// The algorithm is breadth-first search over the set of structs to include - the top struct
+// and then any reachable anonymous structs.
+//
+// typeFields should be an internal detail,
+// but widely used packages access it using linkname.
+// Notable members of the hall of shame include:
+// - github.com/bytedance/sonic
+//
+// Do not remove or change the type signature.
+// See go.dev/issue/67401.
+//
+//go:linkname typeFields
+func typeFields(t reflect.Type) structFields {
+ // Anonymous fields to explore at the current level and the next.
+ current := []field{}
+ next := []field{{typ: t}}
+
+ // Count of queued names for current level and the next.
+ var count, nextCount map[reflect.Type]int
+
+ // Types already visited at an earlier level.
+ visited := map[reflect.Type]bool{}
+
+ // Fields found.
+ var fields []field
+
+ // Buffer to run appendHTMLEscape on field names.
+ var nameEscBuf []byte
+
+ for len(next) > 0 {
+ current, next = next, current[:0]
+ count, nextCount = nextCount, map[reflect.Type]int{}
+
+ for _, f := range current {
+ if visited[f.typ] {
+ continue
+ }
+ visited[f.typ] = true
+
+ // Scan f.typ for fields to include.
+ for i := 0; i < f.typ.NumField(); i++ {
+ sf := f.typ.Field(i)
+ if sf.Anonymous {
+ t := sf.Type
+ if t.Kind() == reflect.Pointer {
+ t = t.Elem()
+ }
+ if !sf.IsExported() && t.Kind() != reflect.Struct {
+ // Ignore embedded fields of unexported non-struct types.
+ continue
+ }
+ // Do not ignore embedded fields of unexported struct types
+ // since they may have exported fields.
+ } else if !sf.IsExported() {
+ // Ignore unexported non-embedded fields.
+ continue
+ }
+ tag := sf.Tag.Get("json")
+ if tag == "-" {
+ continue
+ }
+ name, opts := parseTag(tag)
+ if !isValidTag(name) {
+ name = ""
+ }
+ index := make([]int, len(f.index)+1)
+ copy(index, f.index)
+ index[len(f.index)] = i
+
+ ft := sf.Type
+ if ft.Name() == "" && ft.Kind() == reflect.Pointer {
+ // Follow pointer.
+ ft = ft.Elem()
+ }
+
+ // Only strings, floats, integers, and booleans can be quoted.
+ quoted := false
+ if opts.Contains("string") {
+ switch ft.Kind() {
+ case reflect.Bool,
+ reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
+ reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr,
+ reflect.Float32, reflect.Float64,
+ reflect.String:
+ quoted = true
+ }
+ }
+
+ // Record found field and index sequence.
+ if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
+ tagged := name != ""
+ if name == "" {
+ name = sf.Name
+ }
+ field := field{
+ name: name,
+ tag: tagged,
+ index: index,
+ typ: ft,
+ omitEmpty: opts.Contains("omitempty"),
+ omitZero: opts.Contains("omitzero"),
+ quoted: quoted,
+ // EDIT(begin): save the timefmt
+ timefmt: sf.Tag.Get("format"),
+ // EDIT(end)
+ }
+ field.nameBytes = []byte(field.name)
+
+ // Build nameEscHTML and nameNonEsc ahead of time.
+ nameEscBuf = appendHTMLEscape(nameEscBuf[:0], field.nameBytes)
+ field.nameEscHTML = `"` + string(nameEscBuf) + `":`
+ field.nameNonEsc = `"` + field.name + `":`
+
+ if field.omitZero {
+ t := sf.Type
+ // Provide a function that uses a type's IsZero method.
+ switch {
+ case t.Kind() == reflect.Interface && t.Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ // Avoid panics calling IsZero on a nil interface or
+ // non-nil interface with nil pointer.
+ return v.IsNil() ||
+ (v.Elem().Kind() == reflect.Pointer && v.Elem().IsNil()) ||
+ v.Interface().(isZeroer).IsZero()
+ }
+ case t.Kind() == reflect.Pointer && t.Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ // Avoid panics calling IsZero on nil pointer.
+ return v.IsNil() || v.Interface().(isZeroer).IsZero()
+ }
+ case t.Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ return v.Interface().(isZeroer).IsZero()
+ }
+ case reflect.PointerTo(t).Implements(isZeroerType):
+ field.isZero = func(v reflect.Value) bool {
+ if !v.CanAddr() {
+ // Temporarily box v so we can take the address.
+ v2 := reflect.New(v.Type()).Elem()
+ v2.Set(v)
+ v = v2
+ }
+ return v.Addr().Interface().(isZeroer).IsZero()
+ }
+ }
+ }
+
+ fields = append(fields, field)
+ if count[f.typ] > 1 {
+ // If there were multiple instances, add a second,
+ // so that the annihilation code will see a duplicate.
+ // It only cares about the distinction between 1 and 2,
+ // so don't bother generating any more copies.
+ fields = append(fields, fields[len(fields)-1])
+ }
+ continue
+ }
+
+ // Record new anonymous struct to explore in next round.
+ nextCount[ft]++
+ if nextCount[ft] == 1 {
+ next = append(next, field{name: ft.Name(), index: index, typ: ft})
+ }
+ }
+ }
+ }
+
+ slices.SortFunc(fields, func(a, b field) int {
+ // sort field by name, breaking ties with depth, then
+ // breaking ties with "name came from json tag", then
+ // breaking ties with index sequence.
+ if c := strings.Compare(a.name, b.name); c != 0 {
+ return c
+ }
+ if c := cmp.Compare(len(a.index), len(b.index)); c != 0 {
+ return c
+ }
+ if a.tag != b.tag {
+ if a.tag {
+ return -1
+ }
+ return +1
+ }
+ return slices.Compare(a.index, b.index)
+ })
+
+ // Delete all fields that are hidden by the Go rules for embedded fields,
+ // except that fields with JSON tags are promoted.
+
+ // The fields are sorted in primary order of name, secondary order
+ // of field index length. Loop over names; for each name, delete
+ // hidden fields by choosing the one dominant field that survives.
+ out := fields[:0]
+ for advance, i := 0, 0; i < len(fields); i += advance {
+ // One iteration per name.
+ // Find the sequence of fields with the name of this first field.
+ fi := fields[i]
+ name := fi.name
+ for advance = 1; i+advance < len(fields); advance++ {
+ fj := fields[i+advance]
+ if fj.name != name {
+ break
+ }
+ }
+ if advance == 1 { // Only one field with this name
+ out = append(out, fi)
+ continue
+ }
+ dominant, ok := dominantField(fields[i : i+advance])
+ if ok {
+ out = append(out, dominant)
+ }
+ }
+
+ fields = out
+ slices.SortFunc(fields, func(i, j field) int {
+ return slices.Compare(i.index, j.index)
+ })
+
+ for i := range fields {
+ f := &fields[i]
+ f.encoder = typeEncoder(typeByIndex(t, f.index))
+
+ // EDIT(begin): add custom timefmt if necessary
+ if f.timefmt != "" {
+ f.encoder = continueWithTimeFmt(f.timefmt, f.encoder)
+ }
+ // EDIT(end)
+ }
+ exactNameIndex := make(map[string]*field, len(fields))
+ foldedNameIndex := make(map[string]*field, len(fields))
+ for i, field := range fields {
+ exactNameIndex[field.name] = &fields[i]
+ // For historical reasons, first folded match takes precedence.
+ if _, ok := foldedNameIndex[string(foldName(field.nameBytes))]; !ok {
+ foldedNameIndex[string(foldName(field.nameBytes))] = &fields[i]
+ }
+ }
+ return structFields{fields, exactNameIndex, foldedNameIndex}
+}
+
+// dominantField looks through the fields, all of which are known to
+// have the same name, to find the single field that dominates the
+// others using Go's embedding rules, modified by the presence of
+// JSON tags. If there are multiple top-level fields, the boolean
+// will be false: This condition is an error in Go and we skip all
+// the fields.
+func dominantField(fields []field) (field, bool) {
+ // The fields are sorted in increasing index-length order, then by presence of tag.
+ // That means that the first field is the dominant one. We need only check
+ // for error cases: two fields at top level, either both tagged or neither tagged.
+ if len(fields) > 1 && len(fields[0].index) == len(fields[1].index) && fields[0].tag == fields[1].tag {
+ return field{}, false
+ }
+ return fields[0], true
+}
+
+var fieldCache sync.Map // map[reflect.Type]structFields
+
+// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
+func cachedTypeFields(t reflect.Type) structFields {
+ if f, ok := fieldCache.Load(t); ok {
+ return f.(structFields)
+ }
+ f, _ := fieldCache.LoadOrStore(t, typeFields(t))
+ return f.(structFields)
+}
+
+func mayAppendQuote(b []byte, quoted bool) []byte {
+ if quoted {
+ b = append(b, '"')
+ }
+ return b
+}
diff --git a/internal/encoding/json/fold.go b/internal/encoding/json/fold.go
new file mode 100644
index 0000000..c4c671b
--- /dev/null
+++ b/internal/encoding/json/fold.go
@@ -0,0 +1,48 @@
+// Copyright 2013 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+import (
+ "unicode"
+ "unicode/utf8"
+)
+
+// foldName returns a folded string such that foldName(x) == foldName(y)
+// is identical to bytes.EqualFold(x, y).
+func foldName(in []byte) []byte {
+ // This is inlinable to take advantage of "function outlining".
+ var arr [32]byte // large enough for most JSON names
+ return appendFoldedName(arr[:0], in)
+}
+
+func appendFoldedName(out, in []byte) []byte {
+ for i := 0; i < len(in); {
+ // Handle single-byte ASCII.
+ if c := in[i]; c < utf8.RuneSelf {
+ if 'a' <= c && c <= 'z' {
+ c -= 'a' - 'A'
+ }
+ out = append(out, c)
+ i++
+ continue
+ }
+ // Handle multi-byte Unicode.
+ r, n := utf8.DecodeRune(in[i:])
+ out = utf8.AppendRune(out, foldRune(r))
+ i += n
+ }
+ return out
+}
+
+// foldRune is returns the smallest rune for all runes in the same fold set.
+func foldRune(r rune) rune {
+ for {
+ r2 := unicode.SimpleFold(r)
+ if r2 <= r {
+ return r2
+ }
+ r = r2
+ }
+}
diff --git a/internal/encoding/json/indent.go b/internal/encoding/json/indent.go
new file mode 100644
index 0000000..01bfdf6
--- /dev/null
+++ b/internal/encoding/json/indent.go
@@ -0,0 +1,182 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+import "bytes"
+
+// HTMLEscape appends to dst the JSON-encoded src with <, >, &, U+2028 and U+2029
+// characters inside string literals changed to \u003c, \u003e, \u0026, \u2028, \u2029
+// so that the JSON will be safe to embed inside HTML <script> tags.
+// For historical reasons, web browsers don't honor standard HTML
+// escaping within <script> tags, so an alternative JSON encoding must be used.
+func HTMLEscape(dst *bytes.Buffer, src []byte) {
+ dst.Grow(len(src))
+ dst.Write(appendHTMLEscape(dst.AvailableBuffer(), src))
+}
+
+func appendHTMLEscape(dst, src []byte) []byte {
+ // The characters can only appear in string literals,
+ // so just scan the string one byte at a time.
+ start := 0
+ for i, c := range src {
+ if c == '<' || c == '>' || c == '&' {
+ dst = append(dst, src[start:i]...)
+ dst = append(dst, '\\', 'u', '0', '0', hex[c>>4], hex[c&0xF])
+ start = i + 1
+ }
+ // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
+ if c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
+ dst = append(dst, src[start:i]...)
+ dst = append(dst, '\\', 'u', '2', '0', '2', hex[src[i+2]&0xF])
+ start = i + len("\u2029")
+ }
+ }
+ return append(dst, src[start:]...)
+}
+
+// Compact appends to dst the JSON-encoded src with
+// insignificant space characters elided.
+func Compact(dst *bytes.Buffer, src []byte) error {
+ dst.Grow(len(src))
+ b := dst.AvailableBuffer()
+ b, err := appendCompact(b, src, false)
+ dst.Write(b)
+ return err
+}
+
+func appendCompact(dst, src []byte, escape bool) ([]byte, error) {
+ origLen := len(dst)
+ scan := newScanner()
+ defer freeScanner(scan)
+ start := 0
+ for i, c := range src {
+ if escape && (c == '<' || c == '>' || c == '&') {
+ if start < i {
+ dst = append(dst, src[start:i]...)
+ }
+ dst = append(dst, '\\', 'u', '0', '0', hex[c>>4], hex[c&0xF])
+ start = i + 1
+ }
+ // Convert U+2028 and U+2029 (E2 80 A8 and E2 80 A9).
+ if escape && c == 0xE2 && i+2 < len(src) && src[i+1] == 0x80 && src[i+2]&^1 == 0xA8 {
+ if start < i {
+ dst = append(dst, src[start:i]...)
+ }
+ dst = append(dst, '\\', 'u', '2', '0', '2', hex[src[i+2]&0xF])
+ start = i + 3
+ }
+ v := scan.step(scan, c)
+ if v >= scanSkipSpace {
+ if v == scanError {
+ break
+ }
+ if start < i {
+ dst = append(dst, src[start:i]...)
+ }
+ start = i + 1
+ }
+ }
+ if scan.eof() == scanError {
+ return dst[:origLen], scan.err
+ }
+ if start < len(src) {
+ dst = append(dst, src[start:]...)
+ }
+ return dst, nil
+}
+
+func appendNewline(dst []byte, prefix, indent string, depth int) []byte {
+ dst = append(dst, '\n')
+ dst = append(dst, prefix...)
+ for i := 0; i < depth; i++ {
+ dst = append(dst, indent...)
+ }
+ return dst
+}
+
+// indentGrowthFactor specifies the growth factor of indenting JSON input.
+// Empirically, the growth factor was measured to be between 1.4x to 1.8x
+// for some set of compacted JSON with the indent being a single tab.
+// Specify a growth factor slightly larger than what is observed
+// to reduce probability of allocation in appendIndent.
+// A factor no higher than 2 ensures that wasted space never exceeds 50%.
+const indentGrowthFactor = 2
+
+// Indent appends to dst an indented form of the JSON-encoded src.
+// Each element in a JSON object or array begins on a new,
+// indented line beginning with prefix followed by one or more
+// copies of indent according to the indentation nesting.
+// The data appended to dst does not begin with the prefix nor
+// any indentation, to make it easier to embed inside other formatted JSON data.
+// Although leading space characters (space, tab, carriage return, newline)
+// at the beginning of src are dropped, trailing space characters
+// at the end of src are preserved and copied to dst.
+// For example, if src has no trailing spaces, neither will dst;
+// if src ends in a trailing newline, so will dst.
+func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
+ dst.Grow(indentGrowthFactor * len(src))
+ b := dst.AvailableBuffer()
+ b, err := appendIndent(b, src, prefix, indent)
+ dst.Write(b)
+ return err
+}
+
+func appendIndent(dst, src []byte, prefix, indent string) ([]byte, error) {
+ origLen := len(dst)
+ scan := newScanner()
+ defer freeScanner(scan)
+ needIndent := false
+ depth := 0
+ for _, c := range src {
+ scan.bytes++
+ v := scan.step(scan, c)
+ if v == scanSkipSpace {
+ continue
+ }
+ if v == scanError {
+ break
+ }
+ if needIndent && v != scanEndObject && v != scanEndArray {
+ needIndent = false
+ depth++
+ dst = appendNewline(dst, prefix, indent, depth)
+ }
+
+ // Emit semantically uninteresting bytes
+ // (in particular, punctuation in strings) unmodified.
+ if v == scanContinue {
+ dst = append(dst, c)
+ continue
+ }
+
+ // Add spacing around real punctuation.
+ switch c {
+ case '{', '[':
+ // delay indent so that empty object and array are formatted as {} and [].
+ needIndent = true
+ dst = append(dst, c)
+ case ',':
+ dst = append(dst, c)
+ dst = appendNewline(dst, prefix, indent, depth)
+ case ':':
+ dst = append(dst, c, ' ')
+ case '}', ']':
+ if needIndent {
+ // suppress indent in empty object/array
+ needIndent = false
+ } else {
+ depth--
+ dst = appendNewline(dst, prefix, indent, depth)
+ }
+ dst = append(dst, c)
+ default:
+ dst = append(dst, c)
+ }
+ }
+ if scan.eof() == scanError {
+ return dst[:origLen], scan.err
+ }
+ return dst, nil
+}
diff --git a/internal/encoding/json/scanner.go b/internal/encoding/json/scanner.go
new file mode 100644
index 0000000..da6ea2a
--- /dev/null
+++ b/internal/encoding/json/scanner.go
@@ -0,0 +1,610 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+// JSON value parser state machine.
+// Just about at the limit of what is reasonable to write by hand.
+// Some parts are a bit tedious, but overall it nicely factors out the
+// otherwise common code from the multiple scanning functions
+// in this package (Compact, Indent, checkValid, etc).
+//
+// This file starts with two simple examples using the scanner
+// before diving into the scanner itself.
+
+import (
+ "strconv"
+ "sync"
+)
+
+// Valid reports whether data is a valid JSON encoding.
+func Valid(data []byte) bool {
+ scan := newScanner()
+ defer freeScanner(scan)
+ return checkValid(data, scan) == nil
+}
+
+// checkValid verifies that data is valid JSON-encoded data.
+// scan is passed in for use by checkValid to avoid an allocation.
+// checkValid returns nil or a SyntaxError.
+func checkValid(data []byte, scan *scanner) error {
+ scan.reset()
+ for _, c := range data {
+ scan.bytes++
+ if scan.step(scan, c) == scanError {
+ return scan.err
+ }
+ }
+ if scan.eof() == scanError {
+ return scan.err
+ }
+ return nil
+}
+
+// A SyntaxError is a description of a JSON syntax error.
+// [Unmarshal] will return a SyntaxError if the JSON can't be parsed.
+type SyntaxError struct {
+ msg string // description of error
+ Offset int64 // error occurred after reading Offset bytes
+}
+
+func (e *SyntaxError) Error() string { return e.msg }
+
+// A scanner is a JSON scanning state machine.
+// Callers call scan.reset and then pass bytes in one at a time
+// by calling scan.step(&scan, c) for each byte.
+// The return value, referred to as an opcode, tells the
+// caller about significant parsing events like beginning
+// and ending literals, objects, and arrays, so that the
+// caller can follow along if it wishes.
+// The return value scanEnd indicates that a single top-level
+// JSON value has been completed, *before* the byte that
+// just got passed in. (The indication must be delayed in order
+// to recognize the end of numbers: is 123 a whole value or
+// the beginning of 12345e+6?).
+type scanner struct {
+ // The step is a func to be called to execute the next transition.
+ // Also tried using an integer constant and a single func
+ // with a switch, but using the func directly was 10% faster
+ // on a 64-bit Mac Mini, and it's nicer to read.
+ step func(*scanner, byte) int
+
+ // Reached end of top-level value.
+ endTop bool
+
+ // Stack of what we're in the middle of - array values, object keys, object values.
+ parseState []int
+
+ // Error that happened, if any.
+ err error
+
+ // total bytes consumed, updated by decoder.Decode (and deliberately
+ // not set to zero by scan.reset)
+ bytes int64
+}
+
+var scannerPool = sync.Pool{
+ New: func() any {
+ return &scanner{}
+ },
+}
+
+func newScanner() *scanner {
+ scan := scannerPool.Get().(*scanner)
+ // scan.reset by design doesn't set bytes to zero
+ scan.bytes = 0
+ scan.reset()
+ return scan
+}
+
+func freeScanner(scan *scanner) {
+ // Avoid hanging on to too much memory in extreme cases.
+ if len(scan.parseState) > 1024 {
+ scan.parseState = nil
+ }
+ scannerPool.Put(scan)
+}
+
+// These values are returned by the state transition functions
+// assigned to scanner.state and the method scanner.eof.
+// They give details about the current state of the scan that
+// callers might be interested to know about.
+// It is okay to ignore the return value of any particular
+// call to scanner.state: if one call returns scanError,
+// every subsequent call will return scanError too.
+const (
+ // Continue.
+ scanContinue = iota // uninteresting byte
+ scanBeginLiteral // end implied by next result != scanContinue
+ scanBeginObject // begin object
+ scanObjectKey // just finished object key (string)
+ scanObjectValue // just finished non-last object value
+ scanEndObject // end object (implies scanObjectValue if possible)
+ scanBeginArray // begin array
+ scanArrayValue // just finished array value
+ scanEndArray // end array (implies scanArrayValue if possible)
+ scanSkipSpace // space byte; can skip; known to be last "continue" result
+
+ // Stop.
+ scanEnd // top-level value ended *before* this byte; known to be first "stop" result
+ scanError // hit an error, scanner.err.
+)
+
+// These values are stored in the parseState stack.
+// They give the current state of a composite value
+// being scanned. If the parser is inside a nested value
+// the parseState describes the nested state, outermost at entry 0.
+const (
+ parseObjectKey = iota // parsing object key (before colon)
+ parseObjectValue // parsing object value (after colon)
+ parseArrayValue // parsing array value
+)
+
+// This limits the max nesting depth to prevent stack overflow.
+// This is permitted by https://tools.ietf.org/html/rfc7159#section-9
+const maxNestingDepth = 10000
+
+// reset prepares the scanner for use.
+// It must be called before calling s.step.
+func (s *scanner) reset() {
+ s.step = stateBeginValue
+ s.parseState = s.parseState[0:0]
+ s.err = nil
+ s.endTop = false
+}
+
+// eof tells the scanner that the end of input has been reached.
+// It returns a scan status just as s.step does.
+func (s *scanner) eof() int {
+ if s.err != nil {
+ return scanError
+ }
+ if s.endTop {
+ return scanEnd
+ }
+ s.step(s, ' ')
+ if s.endTop {
+ return scanEnd
+ }
+ if s.err == nil {
+ s.err = &SyntaxError{"unexpected end of JSON input", s.bytes}
+ }
+ return scanError
+}
+
+// pushParseState pushes a new parse state p onto the parse stack.
+// an error state is returned if maxNestingDepth was exceeded, otherwise successState is returned.
+func (s *scanner) pushParseState(c byte, newParseState int, successState int) int {
+ s.parseState = append(s.parseState, newParseState)
+ if len(s.parseState) <= maxNestingDepth {
+ return successState
+ }
+ return s.error(c, "exceeded max depth")
+}
+
+// popParseState pops a parse state (already obtained) off the stack
+// and updates s.step accordingly.
+func (s *scanner) popParseState() {
+ n := len(s.parseState) - 1
+ s.parseState = s.parseState[0:n]
+ if n == 0 {
+ s.step = stateEndTop
+ s.endTop = true
+ } else {
+ s.step = stateEndValue
+ }
+}
+
+func isSpace(c byte) bool {
+ return c <= ' ' && (c == ' ' || c == '\t' || c == '\r' || c == '\n')
+}
+
+// stateBeginValueOrEmpty is the state after reading `[`.
+func stateBeginValueOrEmpty(s *scanner, c byte) int {
+ if isSpace(c) {
+ return scanSkipSpace
+ }
+ if c == ']' {
+ return stateEndValue(s, c)
+ }
+ return stateBeginValue(s, c)
+}
+
+// stateBeginValue is the state at the beginning of the input.
+func stateBeginValue(s *scanner, c byte) int {
+ if isSpace(c) {
+ return scanSkipSpace
+ }
+ switch c {
+ case '{':
+ s.step = stateBeginStringOrEmpty
+ return s.pushParseState(c, parseObjectKey, scanBeginObject)
+ case '[':
+ s.step = stateBeginValueOrEmpty
+ return s.pushParseState(c, parseArrayValue, scanBeginArray)
+ case '"':
+ s.step = stateInString
+ return scanBeginLiteral
+ case '-':
+ s.step = stateNeg
+ return scanBeginLiteral
+ case '0': // beginning of 0.123
+ s.step = state0
+ return scanBeginLiteral
+ case 't': // beginning of true
+ s.step = stateT
+ return scanBeginLiteral
+ case 'f': // beginning of false
+ s.step = stateF
+ return scanBeginLiteral
+ case 'n': // beginning of null
+ s.step = stateN
+ return scanBeginLiteral
+ }
+ if '1' <= c && c <= '9' { // beginning of 1234.5
+ s.step = state1
+ return scanBeginLiteral
+ }
+ return s.error(c, "looking for beginning of value")
+}
+
+// stateBeginStringOrEmpty is the state after reading `{`.
+func stateBeginStringOrEmpty(s *scanner, c byte) int {
+ if isSpace(c) {
+ return scanSkipSpace
+ }
+ if c == '}' {
+ n := len(s.parseState)
+ s.parseState[n-1] = parseObjectValue
+ return stateEndValue(s, c)
+ }
+ return stateBeginString(s, c)
+}
+
+// stateBeginString is the state after reading `{"key": value,`.
+func stateBeginString(s *scanner, c byte) int {
+ if isSpace(c) {
+ return scanSkipSpace
+ }
+ if c == '"' {
+ s.step = stateInString
+ return scanBeginLiteral
+ }
+ return s.error(c, "looking for beginning of object key string")
+}
+
+// stateEndValue is the state after completing a value,
+// such as after reading `{}` or `true` or `["x"`.
+func stateEndValue(s *scanner, c byte) int {
+ n := len(s.parseState)
+ if n == 0 {
+ // Completed top-level before the current byte.
+ s.step = stateEndTop
+ s.endTop = true
+ return stateEndTop(s, c)
+ }
+ if isSpace(c) {
+ s.step = stateEndValue
+ return scanSkipSpace
+ }
+ ps := s.parseState[n-1]
+ switch ps {
+ case parseObjectKey:
+ if c == ':' {
+ s.parseState[n-1] = parseObjectValue
+ s.step = stateBeginValue
+ return scanObjectKey
+ }
+ return s.error(c, "after object key")
+ case parseObjectValue:
+ if c == ',' {
+ s.parseState[n-1] = parseObjectKey
+ s.step = stateBeginString
+ return scanObjectValue
+ }
+ if c == '}' {
+ s.popParseState()
+ return scanEndObject
+ }
+ return s.error(c, "after object key:value pair")
+ case parseArrayValue:
+ if c == ',' {
+ s.step = stateBeginValue
+ return scanArrayValue
+ }
+ if c == ']' {
+ s.popParseState()
+ return scanEndArray
+ }
+ return s.error(c, "after array element")
+ }
+ return s.error(c, "")
+}
+
+// stateEndTop is the state after finishing the top-level value,
+// such as after reading `{}` or `[1,2,3]`.
+// Only space characters should be seen now.
+func stateEndTop(s *scanner, c byte) int {
+ if !isSpace(c) {
+ // Complain about non-space byte on next call.
+ s.error(c, "after top-level value")
+ }
+ return scanEnd
+}
+
+// stateInString is the state after reading `"`.
+func stateInString(s *scanner, c byte) int {
+ if c == '"' {
+ s.step = stateEndValue
+ return scanContinue
+ }
+ if c == '\\' {
+ s.step = stateInStringEsc
+ return scanContinue
+ }
+ if c < 0x20 {
+ return s.error(c, "in string literal")
+ }
+ return scanContinue
+}
+
+// stateInStringEsc is the state after reading `"\` during a quoted string.
+func stateInStringEsc(s *scanner, c byte) int {
+ switch c {
+ case 'b', 'f', 'n', 'r', 't', '\\', '/', '"':
+ s.step = stateInString
+ return scanContinue
+ case 'u':
+ s.step = stateInStringEscU
+ return scanContinue
+ }
+ return s.error(c, "in string escape code")
+}
+
+// stateInStringEscU is the state after reading `"\u` during a quoted string.
+func stateInStringEscU(s *scanner, c byte) int {
+ if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+ s.step = stateInStringEscU1
+ return scanContinue
+ }
+ // numbers
+ return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateInStringEscU1 is the state after reading `"\u1` during a quoted string.
+func stateInStringEscU1(s *scanner, c byte) int {
+ if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+ s.step = stateInStringEscU12
+ return scanContinue
+ }
+ // numbers
+ return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateInStringEscU12 is the state after reading `"\u12` during a quoted string.
+func stateInStringEscU12(s *scanner, c byte) int {
+ if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+ s.step = stateInStringEscU123
+ return scanContinue
+ }
+ // numbers
+ return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateInStringEscU123 is the state after reading `"\u123` during a quoted string.
+func stateInStringEscU123(s *scanner, c byte) int {
+ if '0' <= c && c <= '9' || 'a' <= c && c <= 'f' || 'A' <= c && c <= 'F' {
+ s.step = stateInString
+ return scanContinue
+ }
+ // numbers
+ return s.error(c, "in \\u hexadecimal character escape")
+}
+
+// stateNeg is the state after reading `-` during a number.
+func stateNeg(s *scanner, c byte) int {
+ if c == '0' {
+ s.step = state0
+ return scanContinue
+ }
+ if '1' <= c && c <= '9' {
+ s.step = state1
+ return scanContinue
+ }
+ return s.error(c, "in numeric literal")
+}
+
+// state1 is the state after reading a non-zero integer during a number,
+// such as after reading `1` or `100` but not `0`.
+func state1(s *scanner, c byte) int {
+ if '0' <= c && c <= '9' {
+ s.step = state1
+ return scanContinue
+ }
+ return state0(s, c)
+}
+
+// state0 is the state after reading `0` during a number.
+func state0(s *scanner, c byte) int {
+ if c == '.' {
+ s.step = stateDot
+ return scanContinue
+ }
+ if c == 'e' || c == 'E' {
+ s.step = stateE
+ return scanContinue
+ }
+ return stateEndValue(s, c)
+}
+
+// stateDot is the state after reading the integer and decimal point in a number,
+// such as after reading `1.`.
+func stateDot(s *scanner, c byte) int {
+ if '0' <= c && c <= '9' {
+ s.step = stateDot0
+ return scanContinue
+ }
+ return s.error(c, "after decimal point in numeric literal")
+}
+
+// stateDot0 is the state after reading the integer, decimal point, and subsequent
+// digits of a number, such as after reading `3.14`.
+func stateDot0(s *scanner, c byte) int {
+ if '0' <= c && c <= '9' {
+ return scanContinue
+ }
+ if c == 'e' || c == 'E' {
+ s.step = stateE
+ return scanContinue
+ }
+ return stateEndValue(s, c)
+}
+
+// stateE is the state after reading the mantissa and e in a number,
+// such as after reading `314e` or `0.314e`.
+func stateE(s *scanner, c byte) int {
+ if c == '+' || c == '-' {
+ s.step = stateESign
+ return scanContinue
+ }
+ return stateESign(s, c)
+}
+
+// stateESign is the state after reading the mantissa, e, and sign in a number,
+// such as after reading `314e-` or `0.314e+`.
+func stateESign(s *scanner, c byte) int {
+ if '0' <= c && c <= '9' {
+ s.step = stateE0
+ return scanContinue
+ }
+ return s.error(c, "in exponent of numeric literal")
+}
+
+// stateE0 is the state after reading the mantissa, e, optional sign,
+// and at least one digit of the exponent in a number,
+// such as after reading `314e-2` or `0.314e+1` or `3.14e0`.
+func stateE0(s *scanner, c byte) int {
+ if '0' <= c && c <= '9' {
+ return scanContinue
+ }
+ return stateEndValue(s, c)
+}
+
+// stateT is the state after reading `t`.
+func stateT(s *scanner, c byte) int {
+ if c == 'r' {
+ s.step = stateTr
+ return scanContinue
+ }
+ return s.error(c, "in literal true (expecting 'r')")
+}
+
+// stateTr is the state after reading `tr`.
+func stateTr(s *scanner, c byte) int {
+ if c == 'u' {
+ s.step = stateTru
+ return scanContinue
+ }
+ return s.error(c, "in literal true (expecting 'u')")
+}
+
+// stateTru is the state after reading `tru`.
+func stateTru(s *scanner, c byte) int {
+ if c == 'e' {
+ s.step = stateEndValue
+ return scanContinue
+ }
+ return s.error(c, "in literal true (expecting 'e')")
+}
+
+// stateF is the state after reading `f`.
+func stateF(s *scanner, c byte) int {
+ if c == 'a' {
+ s.step = stateFa
+ return scanContinue
+ }
+ return s.error(c, "in literal false (expecting 'a')")
+}
+
+// stateFa is the state after reading `fa`.
+func stateFa(s *scanner, c byte) int {
+ if c == 'l' {
+ s.step = stateFal
+ return scanContinue
+ }
+ return s.error(c, "in literal false (expecting 'l')")
+}
+
+// stateFal is the state after reading `fal`.
+func stateFal(s *scanner, c byte) int {
+ if c == 's' {
+ s.step = stateFals
+ return scanContinue
+ }
+ return s.error(c, "in literal false (expecting 's')")
+}
+
+// stateFals is the state after reading `fals`.
+func stateFals(s *scanner, c byte) int {
+ if c == 'e' {
+ s.step = stateEndValue
+ return scanContinue
+ }
+ return s.error(c, "in literal false (expecting 'e')")
+}
+
+// stateN is the state after reading `n`.
+func stateN(s *scanner, c byte) int {
+ if c == 'u' {
+ s.step = stateNu
+ return scanContinue
+ }
+ return s.error(c, "in literal null (expecting 'u')")
+}
+
+// stateNu is the state after reading `nu`.
+func stateNu(s *scanner, c byte) int {
+ if c == 'l' {
+ s.step = stateNul
+ return scanContinue
+ }
+ return s.error(c, "in literal null (expecting 'l')")
+}
+
+// stateNul is the state after reading `nul`.
+func stateNul(s *scanner, c byte) int {
+ if c == 'l' {
+ s.step = stateEndValue
+ return scanContinue
+ }
+ return s.error(c, "in literal null (expecting 'l')")
+}
+
+// stateError is the state after reaching a syntax error,
+// such as after reading `[1}` or `5.1.2`.
+func stateError(s *scanner, c byte) int {
+ return scanError
+}
+
+// error records an error and switches to the error state.
+func (s *scanner) error(c byte, context string) int {
+ s.step = stateError
+ s.err = &SyntaxError{"invalid character " + quoteChar(c) + " " + context, s.bytes}
+ return scanError
+}
+
+// quoteChar formats c as a quoted character literal.
+func quoteChar(c byte) string {
+ // special cases - different from quoted strings
+ if c == '\'' {
+ return `'\''`
+ }
+ if c == '"' {
+ return `'"'`
+ }
+
+ // use quoted string with different quotation marks
+ s := strconv.Quote(string(c))
+ return "'" + s[1:len(s)-1] + "'"
+}
diff --git a/internal/encoding/json/sentinel/null.go b/internal/encoding/json/sentinel/null.go
new file mode 100644
index 0000000..a811b14
--- /dev/null
+++ b/internal/encoding/json/sentinel/null.go
@@ -0,0 +1,57 @@
+package sentinel
+
+import (
+ "github.com/anthropics/anthropic-sdk-go/internal/encoding/json/shims"
+ "reflect"
+ "sync"
+)
+
+var nullPtrsCache sync.Map // map[reflect.Type]*T
+
+func NullPtr[T any]() *T {
+ t := shims.TypeFor[T]()
+ ptr, loaded := nullPtrsCache.Load(t) // avoid premature allocation
+ if !loaded {
+ ptr, _ = nullPtrsCache.LoadOrStore(t, new(T))
+ }
+ return (ptr.(*T))
+}
+
+var nullSlicesCache sync.Map // map[reflect.Type][]T
+
+func NullSlice[T any]() []T {
+ t := shims.TypeFor[T]()
+ slice, loaded := nullSlicesCache.Load(t) // avoid premature allocation
+ if !loaded {
+ slice, _ = nullSlicesCache.LoadOrStore(t, []T{})
+ }
+ return slice.([]T)
+}
+
+func IsNullPtr[T any](ptr *T) bool {
+ nullptr, ok := nullPtrsCache.Load(shims.TypeFor[T]())
+ return ok && ptr == nullptr.(*T)
+}
+
+func IsNullSlice[T any](slice []T) bool {
+ nullSlice, ok := nullSlicesCache.Load(shims.TypeFor[T]())
+ return ok && reflect.ValueOf(slice).Pointer() == reflect.ValueOf(nullSlice).Pointer()
+}
+
+// internal only
+func IsValueNullPtr(v reflect.Value) bool {
+ if v.Kind() != reflect.Ptr {
+ return false
+ }
+ nullptr, ok := nullPtrsCache.Load(v.Type().Elem())
+ return ok && v.Pointer() == reflect.ValueOf(nullptr).Pointer()
+}
+
+// internal only
+func IsValueNullSlice(v reflect.Value) bool {
+ if v.Kind() != reflect.Slice {
+ return false
+ }
+ nullSlice, ok := nullSlicesCache.Load(v.Type().Elem())
+ return ok && v.Pointer() == reflect.ValueOf(nullSlice).Pointer()
+}
diff --git a/internal/encoding/json/sentinel/sentinel_test.go b/internal/encoding/json/sentinel/sentinel_test.go
new file mode 100644
index 0000000..6d0b17b
--- /dev/null
+++ b/internal/encoding/json/sentinel/sentinel_test.go
@@ -0,0 +1,88 @@
+package sentinel_test
+
+import (
+ "github.com/anthropics/anthropic-sdk-go/internal/encoding/json/sentinel"
+ "reflect"
+ "slices"
+ "testing"
+)
+
+type Pair struct {
+ got bool
+ want bool
+}
+
+func TestNullSlice(t *testing.T) {
+ var nilSlice []int = nil
+ var nonNilSlice []int = []int{1, 2, 3}
+ var nullSlice []int = sentinel.NullSlice[int]()
+
+ cases := map[string]Pair{
+ "nilSlice": {sentinel.IsNullSlice(nilSlice), false},
+ "nullSlice": {sentinel.IsNullSlice(nullSlice), true},
+ "newNullSlice": {sentinel.IsNullSlice(sentinel.NullSlice[int]()), true},
+ "lenNullSlice": {len(nullSlice) == 0, true},
+ "nilSliceValue": {sentinel.IsValueNullSlice(reflect.ValueOf(nilSlice)), false},
+ "nullSliceValue": {sentinel.IsValueNullSlice(reflect.ValueOf(nullSlice)), true},
+ "compareSlices": {slices.Compare(nilSlice, nullSlice) == 0, true},
+ "compareNonNilSlices": {slices.Compare(nonNilSlice, nullSlice) == 0, false},
+ }
+
+ nilSlice = append(nullSlice, 12)
+ cases["append_result"] = Pair{sentinel.IsNullSlice(nilSlice), false}
+ cases["mutated_result"] = Pair{sentinel.IsNullSlice(nullSlice), true}
+ cases["append_result_len"] = Pair{len(nilSlice) == 1, true}
+ cases["append_null_slice_len"] = Pair{len(nullSlice) == 0, true}
+
+ for name, c := range cases {
+ t.Run(name, func(t *testing.T) {
+ got, want := c.got, c.want
+ if got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ })
+ }
+}
+
+func TestNullPtr(t *testing.T) {
+ var s *string = nil
+ var i *int = nil
+ var slice *[]int = nil
+
+ var nullptrStr *string = sentinel.NullPtr[string]()
+ var nullptrInt *int = sentinel.NullPtr[int]()
+ var nullptrSlice *[]int = sentinel.NullPtr[[]int]()
+
+ if *nullptrStr != "" {
+ t.Errorf("Failed to safely deref")
+ }
+ if *nullptrInt != 0 {
+ t.Errorf("Failed to safely deref")
+ }
+ if len(*nullptrSlice) != 0 {
+ t.Errorf("Failed to safely deref")
+ }
+
+ cases := map[string]Pair{
+ "nilStr": {sentinel.IsNullPtr(s), false},
+ "nullStr": {sentinel.IsNullPtr(nullptrStr), true},
+
+ "nilInt": {sentinel.IsNullPtr(i), false},
+ "nullInt": {sentinel.IsNullPtr(nullptrInt), true},
+
+ "nilSlice": {sentinel.IsNullPtr(slice), false},
+ "nullSlice": {sentinel.IsNullPtr(nullptrSlice), true},
+
+ "nilValuePtr": {sentinel.IsValueNullPtr(reflect.ValueOf(i)), false},
+ "nullValuePtr": {sentinel.IsValueNullPtr(reflect.ValueOf(nullptrInt)), true},
+ }
+
+ for name, test := range cases {
+ t.Run(name, func(t *testing.T) {
+ got, want := test.got, test.want
+ if got != want {
+ t.Errorf("got %v, want %v", got, want)
+ }
+ })
+ }
+}
diff --git a/internal/encoding/json/shims/shims.go b/internal/encoding/json/shims/shims.go
new file mode 100644
index 0000000..32316ef
--- /dev/null
+++ b/internal/encoding/json/shims/shims.go
@@ -0,0 +1,111 @@
+// This package provides shims over Go 1.2{2,3} APIs
+// which are missing from Go 1.21, and used by the Go 1.24 encoding/json package.
+//
+// Inside the vendored package, all shim code has comments that begin look like
+// // SHIM(...): ...
+package shims
+
+import (
+ "encoding/base64"
+ "reflect"
+ "slices"
+)
+
+type OverflowableType struct{ reflect.Type }
+
+func (t OverflowableType) OverflowInt(x int64) bool {
+ k := t.Kind()
+ switch k {
+ case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
+ bitSize := t.Size() * 8
+ trunc := (x << (64 - bitSize)) >> (64 - bitSize)
+ return x != trunc
+ }
+ panic("reflect: OverflowInt of non-int type " + t.String())
+}
+
+func (t OverflowableType) OverflowUint(x uint64) bool {
+ k := t.Kind()
+ switch k {
+ case reflect.Uint, reflect.Uintptr, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
+ bitSize := t.Size() * 8
+ trunc := (x << (64 - bitSize)) >> (64 - bitSize)
+ return x != trunc
+ }
+ panic("reflect: OverflowUint of non-uint type " + t.String())
+}
+
+// Original src code from Go 1.23 go/src/reflect/type.go (taken 1/9/25)
+/*
+
+func (t *rtype) OverflowInt(x int64) bool {
+ k := t.Kind()
+ switch k {
+ case Int, Int8, Int16, Int32, Int64:
+ bitSize := t.Size() * 8
+ trunc := (x << (64 - bitSize)) >> (64 - bitSize)
+ return x != trunc
+ }
+ panic("reflect: OverflowInt of non-int type " + t.String())
+}
+
+func (t *rtype) OverflowUint(x uint64) bool {
+ k := t.Kind()
+ switch k {
+ case Uint, Uintptr, Uint8, Uint16, Uint32, Uint64:
+ bitSize := t.Size() * 8
+ trunc := (x << (64 - bitSize)) >> (64 - bitSize)
+ return x != trunc
+ }
+ panic("reflect: OverflowUint of non-uint type " + t.String())
+}
+
+*/
+
+// TypeFor returns the [Type] that represents the type argument T.
+func TypeFor[T any]() reflect.Type {
+ var v T
+ if t := reflect.TypeOf(v); t != nil {
+ return t // optimize for T being a non-interface kind
+ }
+ return reflect.TypeOf((*T)(nil)).Elem() // only for an interface kind
+}
+
+// Original src code from Go 1.23 go/src/reflect/type.go (taken 1/9/25)
+/*
+
+// TypeFor returns the [Type] that represents the type argument T.
+func TypeFor[T any]() Type {
+ var v T
+ if t := TypeOf(v); t != nil {
+ return t // optimize for T being a non-interface kind
+ }
+ return TypeOf((*T)(nil)).Elem() // only for an interface kind
+}
+
+*/
+
+type AppendableStdEncoding struct{ *base64.Encoding }
+
+// AppendEncode appends the base64 encoded src to dst
+// and returns the extended buffer.
+func (enc AppendableStdEncoding) AppendEncode(dst, src []byte) []byte {
+ n := enc.EncodedLen(len(src))
+ dst = slices.Grow(dst, n)
+ enc.Encode(dst[len(dst):][:n], src)
+ return dst[:len(dst)+n]
+}
+
+// Original src code from Go 1.23.4 go/src/encoding/base64/base64.go (taken 1/9/25)
+/*
+
+// AppendEncode appends the base64 encoded src to dst
+// and returns the extended buffer.
+func (enc *Encoding) AppendEncode(dst, src []byte) []byte {
+ n := enc.EncodedLen(len(src))
+ dst = slices.Grow(dst, n)
+ enc.Encode(dst[len(dst):][:n], src)
+ return dst[:len(dst)+n]
+}
+
+*/
diff --git a/internal/encoding/json/stream.go b/internal/encoding/json/stream.go
new file mode 100644
index 0000000..e2d9470
--- /dev/null
+++ b/internal/encoding/json/stream.go
@@ -0,0 +1,512 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+import (
+ "bytes"
+ "errors"
+ "io"
+)
+
+// A Decoder reads and decodes JSON values from an input stream.
+type Decoder struct {
+ r io.Reader
+ buf []byte
+ d decodeState
+ scanp int // start of unread data in buf
+ scanned int64 // amount of data already scanned
+ scan scanner
+ err error
+
+ tokenState int
+ tokenStack []int
+}
+
+// NewDecoder returns a new decoder that reads from r.
+//
+// The decoder introduces its own buffering and may
+// read data from r beyond the JSON values requested.
+func NewDecoder(r io.Reader) *Decoder {
+ return &Decoder{r: r}
+}
+
+// UseNumber causes the Decoder to unmarshal a number into an
+// interface value as a [Number] instead of as a float64.
+func (dec *Decoder) UseNumber() { dec.d.useNumber = true }
+
+// DisallowUnknownFields causes the Decoder to return an error when the destination
+// is a struct and the input contains object keys which do not match any
+// non-ignored, exported fields in the destination.
+func (dec *Decoder) DisallowUnknownFields() { dec.d.disallowUnknownFields = true }
+
+// Decode reads the next JSON-encoded value from its
+// input and stores it in the value pointed to by v.
+//
+// See the documentation for [Unmarshal] for details about
+// the conversion of JSON into a Go value.
+func (dec *Decoder) Decode(v any) error {
+ if dec.err != nil {
+ return dec.err
+ }
+
+ if err := dec.tokenPrepareForDecode(); err != nil {
+ return err
+ }
+
+ if !dec.tokenValueAllowed() {
+ return &SyntaxError{msg: "not at beginning of value", Offset: dec.InputOffset()}
+ }
+
+ // Read whole value into buffer.
+ n, err := dec.readValue()
+ if err != nil {
+ return err
+ }
+ dec.d.init(dec.buf[dec.scanp : dec.scanp+n])
+ dec.scanp += n
+
+ // Don't save err from unmarshal into dec.err:
+ // the connection is still usable since we read a complete JSON
+ // object from it before the error happened.
+ err = dec.d.unmarshal(v)
+
+ // fixup token streaming state
+ dec.tokenValueEnd()
+
+ return err
+}
+
+// Buffered returns a reader of the data remaining in the Decoder's
+// buffer. The reader is valid until the next call to [Decoder.Decode].
+func (dec *Decoder) Buffered() io.Reader {
+ return bytes.NewReader(dec.buf[dec.scanp:])
+}
+
+// readValue reads a JSON value into dec.buf.
+// It returns the length of the encoding.
+func (dec *Decoder) readValue() (int, error) {
+ dec.scan.reset()
+
+ scanp := dec.scanp
+ var err error
+Input:
+ // help the compiler see that scanp is never negative, so it can remove
+ // some bounds checks below.
+ for scanp >= 0 {
+
+ // Look in the buffer for a new value.
+ for ; scanp < len(dec.buf); scanp++ {
+ c := dec.buf[scanp]
+ dec.scan.bytes++
+ switch dec.scan.step(&dec.scan, c) {
+ case scanEnd:
+ // scanEnd is delayed one byte so we decrement
+ // the scanner bytes count by 1 to ensure that
+ // this value is correct in the next call of Decode.
+ dec.scan.bytes--
+ break Input
+ case scanEndObject, scanEndArray:
+ // scanEnd is delayed one byte.
+ // We might block trying to get that byte from src,
+ // so instead invent a space byte.
+ if stateEndValue(&dec.scan, ' ') == scanEnd {
+ scanp++
+ break Input
+ }
+ case scanError:
+ dec.err = dec.scan.err
+ return 0, dec.scan.err
+ }
+ }
+
+ // Did the last read have an error?
+ // Delayed until now to allow buffer scan.
+ if err != nil {
+ if err == io.EOF {
+ if dec.scan.step(&dec.scan, ' ') == scanEnd {
+ break Input
+ }
+ if nonSpace(dec.buf) {
+ err = io.ErrUnexpectedEOF
+ }
+ }
+ dec.err = err
+ return 0, err
+ }
+
+ n := scanp - dec.scanp
+ err = dec.refill()
+ scanp = dec.scanp + n
+ }
+ return scanp - dec.scanp, nil
+}
+
+func (dec *Decoder) refill() error {
+ // Make room to read more into the buffer.
+ // First slide down data already consumed.
+ if dec.scanp > 0 {
+ dec.scanned += int64(dec.scanp)
+ n := copy(dec.buf, dec.buf[dec.scanp:])
+ dec.buf = dec.buf[:n]
+ dec.scanp = 0
+ }
+
+ // Grow buffer if not large enough.
+ const minRead = 512
+ if cap(dec.buf)-len(dec.buf) < minRead {
+ newBuf := make([]byte, len(dec.buf), 2*cap(dec.buf)+minRead)
+ copy(newBuf, dec.buf)
+ dec.buf = newBuf
+ }
+
+ // Read. Delay error for next iteration (after scan).
+ n, err := dec.r.Read(dec.buf[len(dec.buf):cap(dec.buf)])
+ dec.buf = dec.buf[0 : len(dec.buf)+n]
+
+ return err
+}
+
+func nonSpace(b []byte) bool {
+ for _, c := range b {
+ if !isSpace(c) {
+ return true
+ }
+ }
+ return false
+}
+
+// An Encoder writes JSON values to an output stream.
+type Encoder struct {
+ w io.Writer
+ err error
+ escapeHTML bool
+
+ indentBuf []byte
+ indentPrefix string
+ indentValue string
+}
+
+// NewEncoder returns a new encoder that writes to w.
+func NewEncoder(w io.Writer) *Encoder {
+ return &Encoder{w: w, escapeHTML: true}
+}
+
+// Encode writes the JSON encoding of v to the stream,
+// with insignificant space characters elided,
+// followed by a newline character.
+//
+// See the documentation for [Marshal] for details about the
+// conversion of Go values to JSON.
+func (enc *Encoder) Encode(v any) error {
+ if enc.err != nil {
+ return enc.err
+ }
+
+ e := newEncodeState()
+ defer encodeStatePool.Put(e)
+
+ err := e.marshal(v, encOpts{escapeHTML: enc.escapeHTML})
+ if err != nil {
+ return err
+ }
+
+ // Terminate each value with a newline.
+ // This makes the output look a little nicer
+ // when debugging, and some kind of space
+ // is required if the encoded value was a number,
+ // so that the reader knows there aren't more
+ // digits coming.
+ e.WriteByte('\n')
+
+ b := e.Bytes()
+ if enc.indentPrefix != "" || enc.indentValue != "" {
+ enc.indentBuf, err = appendIndent(enc.indentBuf[:0], b, enc.indentPrefix, enc.indentValue)
+ if err != nil {
+ return err
+ }
+ b = enc.indentBuf
+ }
+ if _, err = enc.w.Write(b); err != nil {
+ enc.err = err
+ }
+ return err
+}
+
+// SetIndent instructs the encoder to format each subsequent encoded
+// value as if indented by the package-level function Indent(dst, src, prefix, indent).
+// Calling SetIndent("", "") disables indentation.
+func (enc *Encoder) SetIndent(prefix, indent string) {
+ enc.indentPrefix = prefix
+ enc.indentValue = indent
+}
+
+// SetEscapeHTML specifies whether problematic HTML characters
+// should be escaped inside JSON quoted strings.
+// The default behavior is to escape &, <, and > to \u0026, \u003c, and \u003e
+// to avoid certain safety problems that can arise when embedding JSON in HTML.
+//
+// In non-HTML settings where the escaping interferes with the readability
+// of the output, SetEscapeHTML(false) disables this behavior.
+func (enc *Encoder) SetEscapeHTML(on bool) {
+ enc.escapeHTML = on
+}
+
+// RawMessage is a raw encoded JSON value.
+// It implements [Marshaler] and [Unmarshaler] and can
+// be used to delay JSON decoding or precompute a JSON encoding.
+type RawMessage []byte
+
+// MarshalJSON returns m as the JSON encoding of m.
+func (m RawMessage) MarshalJSON() ([]byte, error) {
+ if m == nil {
+ return []byte("null"), nil
+ }
+ return m, nil
+}
+
+// UnmarshalJSON sets *m to a copy of data.
+func (m *RawMessage) UnmarshalJSON(data []byte) error {
+ if m == nil {
+ return errors.New("json.RawMessage: UnmarshalJSON on nil pointer")
+ }
+ *m = append((*m)[0:0], data...)
+ return nil
+}
+
+var _ Marshaler = (*RawMessage)(nil)
+var _ Unmarshaler = (*RawMessage)(nil)
+
+// A Token holds a value of one of these types:
+//
+// - [Delim], for the four JSON delimiters [ ] { }
+// - bool, for JSON booleans
+// - float64, for JSON numbers
+// - [Number], for JSON numbers
+// - string, for JSON string literals
+// - nil, for JSON null
+type Token any
+
+const (
+ tokenTopValue = iota
+ tokenArrayStart
+ tokenArrayValue
+ tokenArrayComma
+ tokenObjectStart
+ tokenObjectKey
+ tokenObjectColon
+ tokenObjectValue
+ tokenObjectComma
+)
+
+// advance tokenstate from a separator state to a value state
+func (dec *Decoder) tokenPrepareForDecode() error {
+ // Note: Not calling peek before switch, to avoid
+ // putting peek into the standard Decode path.
+ // peek is only called when using the Token API.
+ switch dec.tokenState {
+ case tokenArrayComma:
+ c, err := dec.peek()
+ if err != nil {
+ return err
+ }
+ if c != ',' {
+ return &SyntaxError{"expected comma after array element", dec.InputOffset()}
+ }
+ dec.scanp++
+ dec.tokenState = tokenArrayValue
+ case tokenObjectColon:
+ c, err := dec.peek()
+ if err != nil {
+ return err
+ }
+ if c != ':' {
+ return &SyntaxError{"expected colon after object key", dec.InputOffset()}
+ }
+ dec.scanp++
+ dec.tokenState = tokenObjectValue
+ }
+ return nil
+}
+
+func (dec *Decoder) tokenValueAllowed() bool {
+ switch dec.tokenState {
+ case tokenTopValue, tokenArrayStart, tokenArrayValue, tokenObjectValue:
+ return true
+ }
+ return false
+}
+
+func (dec *Decoder) tokenValueEnd() {
+ switch dec.tokenState {
+ case tokenArrayStart, tokenArrayValue:
+ dec.tokenState = tokenArrayComma
+ case tokenObjectValue:
+ dec.tokenState = tokenObjectComma
+ }
+}
+
+// A Delim is a JSON array or object delimiter, one of [ ] { or }.
+type Delim rune
+
+func (d Delim) String() string {
+ return string(d)
+}
+
+// Token returns the next JSON token in the input stream.
+// At the end of the input stream, Token returns nil, [io.EOF].
+//
+// Token guarantees that the delimiters [ ] { } it returns are
+// properly nested and matched: if Token encounters an unexpected
+// delimiter in the input, it will return an error.
+//
+// The input stream consists of basic JSON values—bool, string,
+// number, and null—along with delimiters [ ] { } of type [Delim]
+// to mark the start and end of arrays and objects.
+// Commas and colons are elided.
+func (dec *Decoder) Token() (Token, error) {
+ for {
+ c, err := dec.peek()
+ if err != nil {
+ return nil, err
+ }
+ switch c {
+ case '[':
+ if !dec.tokenValueAllowed() {
+ return dec.tokenError(c)
+ }
+ dec.scanp++
+ dec.tokenStack = append(dec.tokenStack, dec.tokenState)
+ dec.tokenState = tokenArrayStart
+ return Delim('['), nil
+
+ case ']':
+ if dec.tokenState != tokenArrayStart && dec.tokenState != tokenArrayComma {
+ return dec.tokenError(c)
+ }
+ dec.scanp++
+ dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
+ dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
+ dec.tokenValueEnd()
+ return Delim(']'), nil
+
+ case '{':
+ if !dec.tokenValueAllowed() {
+ return dec.tokenError(c)
+ }
+ dec.scanp++
+ dec.tokenStack = append(dec.tokenStack, dec.tokenState)
+ dec.tokenState = tokenObjectStart
+ return Delim('{'), nil
+
+ case '}':
+ if dec.tokenState != tokenObjectStart && dec.tokenState != tokenObjectComma {
+ return dec.tokenError(c)
+ }
+ dec.scanp++
+ dec.tokenState = dec.tokenStack[len(dec.tokenStack)-1]
+ dec.tokenStack = dec.tokenStack[:len(dec.tokenStack)-1]
+ dec.tokenValueEnd()
+ return Delim('}'), nil
+
+ case ':':
+ if dec.tokenState != tokenObjectColon {
+ return dec.tokenError(c)
+ }
+ dec.scanp++
+ dec.tokenState = tokenObjectValue
+ continue
+
+ case ',':
+ if dec.tokenState == tokenArrayComma {
+ dec.scanp++
+ dec.tokenState = tokenArrayValue
+ continue
+ }
+ if dec.tokenState == tokenObjectComma {
+ dec.scanp++
+ dec.tokenState = tokenObjectKey
+ continue
+ }
+ return dec.tokenError(c)
+
+ case '"':
+ if dec.tokenState == tokenObjectStart || dec.tokenState == tokenObjectKey {
+ var x string
+ old := dec.tokenState
+ dec.tokenState = tokenTopValue
+ err := dec.Decode(&x)
+ dec.tokenState = old
+ if err != nil {
+ return nil, err
+ }
+ dec.tokenState = tokenObjectColon
+ return x, nil
+ }
+ fallthrough
+
+ default:
+ if !dec.tokenValueAllowed() {
+ return dec.tokenError(c)
+ }
+ var x any
+ if err := dec.Decode(&x); err != nil {
+ return nil, err
+ }
+ return x, nil
+ }
+ }
+}
+
+func (dec *Decoder) tokenError(c byte) (Token, error) {
+ var context string
+ switch dec.tokenState {
+ case tokenTopValue:
+ context = " looking for beginning of value"
+ case tokenArrayStart, tokenArrayValue, tokenObjectValue:
+ context = " looking for beginning of value"
+ case tokenArrayComma:
+ context = " after array element"
+ case tokenObjectKey:
+ context = " looking for beginning of object key string"
+ case tokenObjectColon:
+ context = " after object key"
+ case tokenObjectComma:
+ context = " after object key:value pair"
+ }
+ return nil, &SyntaxError{"invalid character " + quoteChar(c) + context, dec.InputOffset()}
+}
+
+// More reports whether there is another element in the
+// current array or object being parsed.
+func (dec *Decoder) More() bool {
+ c, err := dec.peek()
+ return err == nil && c != ']' && c != '}'
+}
+
+func (dec *Decoder) peek() (byte, error) {
+ var err error
+ for {
+ for i := dec.scanp; i < len(dec.buf); i++ {
+ c := dec.buf[i]
+ if isSpace(c) {
+ continue
+ }
+ dec.scanp = i
+ return c, nil
+ }
+ // buffer has been scanned, now report any error
+ if err != nil {
+ return 0, err
+ }
+ err = dec.refill()
+ }
+}
+
+// InputOffset returns the input stream byte offset of the current decoder position.
+// The offset gives the location of the end of the most recently returned token
+// and the beginning of the next token.
+func (dec *Decoder) InputOffset() int64 {
+ return dec.scanned + int64(dec.scanp)
+}
diff --git a/internal/encoding/json/tables.go b/internal/encoding/json/tables.go
new file mode 100644
index 0000000..10acdc1
--- /dev/null
+++ b/internal/encoding/json/tables.go
@@ -0,0 +1,218 @@
+// Copyright 2016 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+import "unicode/utf8"
+
+// safeSet holds the value true if the ASCII character with the given array
+// position can be represented inside a JSON string without any further
+// escaping.
+//
+// All values are true except for the ASCII control characters (0-31), the
+// double quote ("), and the backslash character ("\").
+var safeSet = [utf8.RuneSelf]bool{
+ ' ': true,
+ '!': true,
+ '"': false,
+ '#': true,
+ '$': true,
+ '%': true,
+ '&': true,
+ '\'': true,
+ '(': true,
+ ')': true,
+ '*': true,
+ '+': true,
+ ',': true,
+ '-': true,
+ '.': true,
+ '/': true,
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ ':': true,
+ ';': true,
+ '<': true,
+ '=': true,
+ '>': true,
+ '?': true,
+ '@': true,
+ 'A': true,
+ 'B': true,
+ 'C': true,
+ 'D': true,
+ 'E': true,
+ 'F': true,
+ 'G': true,
+ 'H': true,
+ 'I': true,
+ 'J': true,
+ 'K': true,
+ 'L': true,
+ 'M': true,
+ 'N': true,
+ 'O': true,
+ 'P': true,
+ 'Q': true,
+ 'R': true,
+ 'S': true,
+ 'T': true,
+ 'U': true,
+ 'V': true,
+ 'W': true,
+ 'X': true,
+ 'Y': true,
+ 'Z': true,
+ '[': true,
+ '\\': false,
+ ']': true,
+ '^': true,
+ '_': true,
+ '`': true,
+ 'a': true,
+ 'b': true,
+ 'c': true,
+ 'd': true,
+ 'e': true,
+ 'f': true,
+ 'g': true,
+ 'h': true,
+ 'i': true,
+ 'j': true,
+ 'k': true,
+ 'l': true,
+ 'm': true,
+ 'n': true,
+ 'o': true,
+ 'p': true,
+ 'q': true,
+ 'r': true,
+ 's': true,
+ 't': true,
+ 'u': true,
+ 'v': true,
+ 'w': true,
+ 'x': true,
+ 'y': true,
+ 'z': true,
+ '{': true,
+ '|': true,
+ '}': true,
+ '~': true,
+ '\u007f': true,
+}
+
+// htmlSafeSet holds the value true if the ASCII character with the given
+// array position can be safely represented inside a JSON string, embedded
+// inside of HTML <script> tags, without any additional escaping.
+//
+// All values are true except for the ASCII control characters (0-31), the
+// double quote ("), the backslash character ("\"), HTML opening and closing
+// tags ("<" and ">"), and the ampersand ("&").
+var htmlSafeSet = [utf8.RuneSelf]bool{
+ ' ': true,
+ '!': true,
+ '"': false,
+ '#': true,
+ '$': true,
+ '%': true,
+ '&': false,
+ '\'': true,
+ '(': true,
+ ')': true,
+ '*': true,
+ '+': true,
+ ',': true,
+ '-': true,
+ '.': true,
+ '/': true,
+ '0': true,
+ '1': true,
+ '2': true,
+ '3': true,
+ '4': true,
+ '5': true,
+ '6': true,
+ '7': true,
+ '8': true,
+ '9': true,
+ ':': true,
+ ';': true,
+ '<': false,
+ '=': true,
+ '>': false,
+ '?': true,
+ '@': true,
+ 'A': true,
+ 'B': true,
+ 'C': true,
+ 'D': true,
+ 'E': true,
+ 'F': true,
+ 'G': true,
+ 'H': true,
+ 'I': true,
+ 'J': true,
+ 'K': true,
+ 'L': true,
+ 'M': true,
+ 'N': true,
+ 'O': true,
+ 'P': true,
+ 'Q': true,
+ 'R': true,
+ 'S': true,
+ 'T': true,
+ 'U': true,
+ 'V': true,
+ 'W': true,
+ 'X': true,
+ 'Y': true,
+ 'Z': true,
+ '[': true,
+ '\\': false,
+ ']': true,
+ '^': true,
+ '_': true,
+ '`': true,
+ 'a': true,
+ 'b': true,
+ 'c': true,
+ 'd': true,
+ 'e': true,
+ 'f': true,
+ 'g': true,
+ 'h': true,
+ 'i': true,
+ 'j': true,
+ 'k': true,
+ 'l': true,
+ 'm': true,
+ 'n': true,
+ 'o': true,
+ 'p': true,
+ 'q': true,
+ 'r': true,
+ 's': true,
+ 't': true,
+ 'u': true,
+ 'v': true,
+ 'w': true,
+ 'x': true,
+ 'y': true,
+ 'z': true,
+ '{': true,
+ '|': true,
+ '}': true,
+ '~': true,
+ '\u007f': true,
+}
diff --git a/internal/encoding/json/tags.go b/internal/encoding/json/tags.go
new file mode 100644
index 0000000..b490328
--- /dev/null
+++ b/internal/encoding/json/tags.go
@@ -0,0 +1,38 @@
+// Copyright 2011 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package json
+
+import (
+ "strings"
+)
+
+// tagOptions is the string following a comma in a struct field's "json"
+// tag, or the empty string. It does not include the leading comma.
+type tagOptions string
+
+// parseTag splits a struct field's json tag into its name and
+// comma-separated options.
+func parseTag(tag string) (string, tagOptions) {
+ tag, opt, _ := strings.Cut(tag, ",")
+ return tag, tagOptions(opt)
+}
+
+// Contains reports whether a comma-separated list of options
+// contains a particular substr flag. substr must be surrounded by a
+// string boundary or commas.
+func (o tagOptions) Contains(optionName string) bool {
+ if len(o) == 0 {
+ return false
+ }
+ s := string(o)
+ for s != "" {
+ var name string
+ name, s, _ = strings.Cut(s, ",")
+ if name == optionName {
+ return true
+ }
+ }
+ return false
+}
diff --git a/internal/encoding/json/time.go b/internal/encoding/json/time.go
new file mode 100644
index 0000000..46e1a41
--- /dev/null
+++ b/internal/encoding/json/time.go
@@ -0,0 +1,59 @@
+// EDIT(begin): custom time marshaler
+package json
+
+import (
+ "github.com/anthropics/anthropic-sdk-go/internal/encoding/json/shims"
+ "reflect"
+ "time"
+)
+
+type TimeMarshaler interface {
+ MarshalJSONWithTimeLayout(string) []byte
+}
+
+var timeType = shims.TypeFor[time.Time]()
+
+const DateFmt = "2006-01-02"
+
+func newTimeEncoder() encoderFunc {
+ return func(e *encodeState, v reflect.Value, opts encOpts) {
+ t := v.Interface().(time.Time)
+ fmtted := t.Format(opts.timefmt)
+ if opts.timefmt == "date" {
+ fmtted = t.Format(DateFmt)
+ }
+ // Default to RFC3339 if format is invalid
+ if fmtted == "" {
+ fmtted = t.Format(time.RFC3339)
+ }
+ stringEncoder(e, reflect.ValueOf(fmtted), opts)
+ }
+}
+
+// Uses continuation passing style, to add the timefmt option to k
+func continueWithTimeFmt(timefmt string, k encoderFunc) encoderFunc {
+ return func(e *encodeState, v reflect.Value, opts encOpts) {
+ opts.timefmt = timefmt
+ k(e, v, opts)
+ }
+}
+
+func timeMarshalEncoder(e *encodeState, v reflect.Value, opts encOpts) bool {
+ tm, ok := v.Interface().(TimeMarshaler)
+ if !ok {
+ return false
+ }
+
+ b := tm.MarshalJSONWithTimeLayout(opts.timefmt)
+ if b != nil {
+ e.Grow(len(b))
+ out := e.AvailableBuffer()
+ out, _ = appendCompact(out, b, opts.escapeHTML)
+ e.Buffer.Write(out)
+ return true
+ }
+
+ return false
+}
+
+// EDIT(end)
diff --git a/internal/param/field.go b/internal/param/field.go
index 4d0fd9c..a665f70 100644
--- a/internal/param/field.go
+++ b/internal/param/field.go
@@ -1,8 +1,6 @@
package param
-import (
- "fmt"
-)
+import "fmt"
type FieldLike interface{ field() }
diff --git a/internal/requestconfig/requestconfig.go b/internal/requestconfig/requestconfig.go
index bba68f7..1560ad0 100644
--- a/internal/requestconfig/requestconfig.go
+++ b/internal/requestconfig/requestconfig.go
@@ -10,6 +10,7 @@ import (
"io"
"math"
"math/rand"
+ "mime"
"net/http"
"net/url"
"runtime"
@@ -76,7 +77,17 @@ func getPlatformProperties() map[string]string {
}
}
-func NewRequestConfig(ctx context.Context, method string, u string, body interface{}, dst interface{}, opts ...func(*RequestConfig) error) (*RequestConfig, error) {
+type RequestOption interface {
+ Apply(*RequestConfig) error
+}
+
+type RequestOptionFunc func(*RequestConfig) error
+type PreRequestOptionFunc func(*RequestConfig) error
+
+func (s RequestOptionFunc) Apply(r *RequestConfig) error { return s(r) }
+func (s PreRequestOptionFunc) Apply(r *RequestConfig) error { return s(r) }
+
+func NewRequestConfig(ctx context.Context, method string, u string, body interface{}, dst interface{}, opts ...RequestOption) (*RequestConfig, error) {
var reader io.Reader
contentType := "application/json"
@@ -176,7 +187,7 @@ func NewRequestConfig(ctx context.Context, method string, u string, body interfa
// RequestConfig represents all the state related to one request.
//
// Editing the variables inside RequestConfig directly is unstable api. Prefer
-// composing func(\*RequestConfig) error instead if possible.
+// composing the RequestOption instead if possible.
type RequestConfig struct {
MaxRetries int
RequestTimeout time.Duration
@@ -223,7 +234,7 @@ func shouldRetry(req *http.Request, res *http.Response) bool {
return true
}
- // If the header explictly wants a retry behavior, respect that over the
+ // If the header explicitly wants a retry behavior, respect that over the
// http status code.
if res.Header.Get("x-should-retry") == "true" {
return true
@@ -388,7 +399,6 @@ func (cfg *RequestConfig) Execute() (err error) {
// Don't send the current retry count in the headers if the caller modified the header defaults.
shouldSendRetryCount := cfg.Request.Header.Get("X-Stainless-Retry-Count") == "0"
- var req *http.Request
var res *http.Response
var cancel context.CancelFunc
for retryCount := 0; retryCount <= cfg.MaxRetries; retryCount += 1 {
@@ -403,7 +413,7 @@ func (cfg *RequestConfig) Execute() (err error) {
}()
}
- req = cfg.Request.Clone(ctx)
+ req := cfg.Request.Clone(ctx)
if shouldSendRetryCount {
req.Header.Set("X-Stainless-Retry-Count", strconv.Itoa(retryCount))
}
@@ -460,7 +470,7 @@ func (cfg *RequestConfig) Execute() (err error) {
res.Body = io.NopCloser(bytes.NewBuffer(contents))
// Load the contents into the error format if it is provided.
- aerr := apierror.Error{Request: req, Response: res, StatusCode: res.StatusCode}
+ aerr := apierror.Error{Request: cfg.Request, Response: res, StatusCode: res.StatusCode}
err = aerr.UnmarshalJSON(contents)
if err != nil {
return err
@@ -487,7 +497,8 @@ func (cfg *RequestConfig) Execute() (err error) {
// If we are not json, return plaintext
contentType := res.Header.Get("content-type")
- isJSON := strings.Contains(contentType, "application/json") || strings.Contains(contentType, "application/vnd.api+json")
+ mediaType, _, _ := mime.ParseMediaType(contentType)
+ isJSON := strings.Contains(mediaType, "application/json") || strings.HasSuffix(mediaType, "+json")
if !isJSON {
switch dst := cfg.ResponseBodyInto.(type) {
case *string:
@@ -498,7 +509,7 @@ func (cfg *RequestConfig) Execute() (err error) {
case *[]byte:
*dst = contents
default:
- return fmt.Errorf("expected destination type of 'string' or '[]byte' for responses with content-type that is not 'application/json'")
+ return fmt.Errorf("expected destination type of 'string' or '[]byte' for responses with content-type '%s' that is not 'application/json'", contentType)
}
return nil
}
@@ -511,13 +522,13 @@ func (cfg *RequestConfig) Execute() (err error) {
err = json.NewDecoder(bytes.NewReader(contents)).Decode(cfg.ResponseBodyInto)
if err != nil {
- err = fmt.Errorf("error parsing response json: %w", err)
+ return fmt.Errorf("error parsing response json: %w", err)
}
return nil
}
-func ExecuteNewRequest(ctx context.Context, method string, u string, body interface{}, dst interface{}, opts ...func(*RequestConfig) error) error {
+func ExecuteNewRequest(ctx context.Context, method string, u string, body interface{}, dst interface{}, opts ...RequestOption) error {
cfg, err := NewRequestConfig(ctx, method, u, body, dst, opts...)
if err != nil {
return err
@@ -552,12 +563,27 @@ func (cfg *RequestConfig) Clone(ctx context.Context) *RequestConfig {
return new
}
-func (cfg *RequestConfig) Apply(opts ...func(*RequestConfig) error) error {
+func (cfg *RequestConfig) Apply(opts ...RequestOption) error {
for _, opt := range opts {
- err := opt(cfg)
+ err := opt.Apply(cfg)
if err != nil {
return err
}
}
return nil
}
+
+func PreRequestOptions(opts ...RequestOption) (RequestConfig, error) {
+ cfg := RequestConfig{}
+ for _, opt := range opts {
+ if _, ok := opt.(PreRequestOptionFunc); !ok {
+ continue
+ }
+
+ err := opt.Apply(&cfg)
+ if err != nil {
+ return cfg, err
+ }
+ }
+ return cfg, nil
+}
diff --git a/internal/version.go b/internal/version.go
index 1e49ee4..7fd82e7 100644
--- a/internal/version.go
+++ b/internal/version.go
@@ -2,4 +2,4 @@
package internal
-const PackageVersion = "0.0.1-alpha.0"
+const PackageVersion = "0.2.0-beta.3" // x-release-please-version
diff --git a/message.go b/message.go
index 7ec0d60..ec639a9 100644
--- a/message.go
+++ b/message.go
@@ -8,13 +8,14 @@ import (
"fmt"
"net/http"
"reflect"
- "time"
"github.com/anthropics/anthropic-sdk-go/internal/apijson"
- "github.com/anthropics/anthropic-sdk-go/internal/param"
"github.com/anthropics/anthropic-sdk-go/internal/requestconfig"
"github.com/anthropics/anthropic-sdk-go/option"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
"github.com/anthropics/anthropic-sdk-go/packages/ssestream"
+ "github.com/anthropics/anthropic-sdk-go/shared/constant"
"github.com/tidwall/gjson"
)
@@ -26,14 +27,14 @@ import (
// the [NewMessageService] method instead.
type MessageService struct {
Options []option.RequestOption
- Batches *MessageBatchService
+ Batches MessageBatchService
}
// NewMessageService generates a new service that applies the given options to each
// request. These options are applied after the parent client's options (if there
// is one), and before any request-specific options.
-func NewMessageService(opts ...option.RequestOption) (r *MessageService) {
- r = &MessageService{}
+func NewMessageService(opts ...option.RequestOption) (r MessageService) {
+ r = MessageService{}
r.Options = opts
r.Batches = NewMessageBatchService(opts...)
return
@@ -51,38 +52,10 @@ func NewMessageService(opts ...option.RequestOption) (r *MessageService) {
func (r *MessageService) New(ctx context.Context, body MessageNewParams, opts ...option.RequestOption) (res *Message, err error) {
opts = append(r.Options[:], opts...)
path := "v1/messages"
-
- cfg, err := requestconfig.NewRequestConfig(ctx, http.MethodPost, path, body, &res, opts...)
- if err != nil {
- return
- }
-
- err = checkLongRequest(ctx, cfg, int(body.MaxTokens.Value))
- if err != nil {
- return
- }
-
- err = cfg.Execute()
+ err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &res, opts...)
return
}
-// Return an error early if the request is expected to take enough time that its likely to be dropped and the
-// user hasn't explicitly configured their own timeout.
-func checkLongRequest(ctx context.Context, cfg *requestconfig.RequestConfig, maxTokens int) error {
- _, hasDeadline := ctx.Deadline()
- if !hasDeadline && cfg.RequestTimeout == time.Duration(0) && maxTokens != 0 {
- maximumTime := 60 * 60
- defaultTime := 60 * 10
- expectedTime := maximumTime * int(maxTokens) / 128_000
- if expectedTime > defaultTime {
- return fmt.Errorf("Streaming is strongly recommended for operations that may take longer than 10 minutes. See https://github.com/anthropics/anthropic-sdk-go#long-requests")
- }
- }
-
- return nil
-
-}
-
// Send a structured list of input messages with text and/or image content, and the
// model will generate the next message in the conversation.
//
@@ -92,7 +65,7 @@ func checkLongRequest(ctx context.Context, cfg *requestconfig.RequestConfig, max
// Learn more about the Messages API in our [user guide](/en/docs/initial-setup)
//
// Note: If you choose to set a timeout for this request, we recommend 10 minutes.
-func (r *MessageService) NewStreaming(ctx context.Context, body MessageNewParams, opts ...option.RequestOption) (stream *ssestream.Stream[MessageStreamEvent]) {
+func (r *MessageService) NewStreaming(ctx context.Context, body MessageNewParams, opts ...option.RequestOption) (stream *ssestream.Stream[MessageStreamEventUnion]) {
var (
raw *http.Response
err error
@@ -101,7 +74,7 @@ func (r *MessageService) NewStreaming(ctx context.Context, body MessageNewParams
opts = append([]option.RequestOption{option.WithJSONSet("stream", true)}, opts...)
path := "v1/messages"
err = requestconfig.ExecuteNewRequest(ctx, http.MethodPost, path, body, &raw, opts...)
- return ssestream.NewStream[MessageStreamEvent](ssestream.NewDecoder(raw), err)
+ return ssestream.NewStream[MessageStreamEventUnion](ssestream.NewDecoder(raw), err)
}
// Count the number of tokens in a Message.
@@ -118,18 +91,24 @@ func (r *MessageService) CountTokens(ctx context.Context, body MessageCountToken
return
}
+// The properties Data, MediaType, Type are required.
type Base64ImageSourceParam struct {
- Data param.Field[string] `json:"data,required" format:"byte"`
- MediaType param.Field[Base64ImageSourceMediaType] `json:"media_type,required"`
- Type param.Field[Base64ImageSourceType] `json:"type,required"`
+ Data string `json:"data,required" format:"byte"`
+ // Any of "image/jpeg", "image/png", "image/gif", "image/webp".
+ MediaType Base64ImageSourceMediaType `json:"media_type,omitzero,required"`
+ // This field can be elided, and will marshal its zero value as "base64".
+ Type constant.Base64 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f Base64ImageSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r Base64ImageSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow Base64ImageSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r Base64ImageSourceParam) implementsImageBlockParamSourceUnion() {}
-
type Base64ImageSourceMediaType string
const (
@@ -139,955 +118,1128 @@ const (
Base64ImageSourceMediaTypeImageWebP Base64ImageSourceMediaType = "image/webp"
)
-func (r Base64ImageSourceMediaType) IsKnown() bool {
- switch r {
- case Base64ImageSourceMediaTypeImageJPEG, Base64ImageSourceMediaTypeImagePNG, Base64ImageSourceMediaTypeImageGIF, Base64ImageSourceMediaTypeImageWebP:
- return true
- }
- return false
-}
-
-type Base64ImageSourceType string
-
-const (
- Base64ImageSourceTypeBase64 Base64ImageSourceType = "base64"
-)
-
-func (r Base64ImageSourceType) IsKnown() bool {
- switch r {
- case Base64ImageSourceTypeBase64:
- return true
- }
- return false
-}
-
+// The properties Data, MediaType, Type are required.
type Base64PDFSourceParam struct {
- Data param.Field[string] `json:"data,required" format:"byte"`
- MediaType param.Field[Base64PDFSourceMediaType] `json:"media_type,required"`
- Type param.Field[Base64PDFSourceType] `json:"type,required"`
+ Data string `json:"data,required" format:"byte"`
+ // This field can be elided, and will marshal its zero value as "application/pdf".
+ MediaType constant.ApplicationPDF `json:"media_type,required"`
+ // This field can be elided, and will marshal its zero value as "base64".
+ Type constant.Base64 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f Base64PDFSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r Base64PDFSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow Base64PDFSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r Base64PDFSourceParam) implementsDocumentBlockParamSourceUnion() {}
-
-type Base64PDFSourceMediaType string
-
-const (
- Base64PDFSourceMediaTypeApplicationPDF Base64PDFSourceMediaType = "application/pdf"
-)
-
-func (r Base64PDFSourceMediaType) IsKnown() bool {
- switch r {
- case Base64PDFSourceMediaTypeApplicationPDF:
- return true
- }
- return false
+// The property Type is required.
+type CacheControlEphemeralParam struct {
+ // This field can be elided, and will marshal its zero value as "ephemeral".
+ Type constant.Ephemeral `json:"type,required"`
+ paramObj
}
-type Base64PDFSourceType string
-
-const (
- Base64PDFSourceTypeBase64 Base64PDFSourceType = "base64"
-)
-
-func (r Base64PDFSourceType) IsKnown() bool {
- switch r {
- case Base64PDFSourceTypeBase64:
- return true
- }
- return false
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f CacheControlEphemeralParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r CacheControlEphemeralParam) MarshalJSON() (data []byte, err error) {
+ type shadow CacheControlEphemeralParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-type CacheControlEphemeralParam struct {
- Type param.Field[CacheControlEphemeralType] `json:"type,required"`
+type CitationCharLocation struct {
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ DocumentTitle string `json:"document_title,required"`
+ EndCharIndex int64 `json:"end_char_index,required"`
+ StartCharIndex int64 `json:"start_char_index,required"`
+ Type constant.CharLocation `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ CitedText resp.Field
+ DocumentIndex resp.Field
+ DocumentTitle resp.Field
+ EndCharIndex resp.Field
+ StartCharIndex resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r CitationCharLocation) RawJSON() string { return r.JSON.raw }
+func (r *CitationCharLocation) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-func (r CacheControlEphemeralParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// The properties CitedText, DocumentIndex, DocumentTitle, EndCharIndex,
+// StartCharIndex, Type are required.
+type CitationCharLocationParam struct {
+ DocumentTitle param.Opt[string] `json:"document_title,omitzero,required"`
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ EndCharIndex int64 `json:"end_char_index,required"`
+ StartCharIndex int64 `json:"start_char_index,required"`
+ // This field can be elided, and will marshal its zero value as "char_location".
+ Type constant.CharLocation `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f CitationCharLocationParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r CitationCharLocationParam) MarshalJSON() (data []byte, err error) {
+ type shadow CitationCharLocationParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-type CacheControlEphemeralType string
-
-const (
- CacheControlEphemeralTypeEphemeral CacheControlEphemeralType = "ephemeral"
-)
+type CitationContentBlockLocation struct {
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ DocumentTitle string `json:"document_title,required"`
+ EndBlockIndex int64 `json:"end_block_index,required"`
+ StartBlockIndex int64 `json:"start_block_index,required"`
+ Type constant.ContentBlockLocation `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ CitedText resp.Field
+ DocumentIndex resp.Field
+ DocumentTitle resp.Field
+ EndBlockIndex resp.Field
+ StartBlockIndex resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r CitationContentBlockLocation) RawJSON() string { return r.JSON.raw }
+func (r *CitationContentBlockLocation) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-func (r CacheControlEphemeralType) IsKnown() bool {
- switch r {
- case CacheControlEphemeralTypeEphemeral:
- return true
- }
- return false
+// The properties CitedText, DocumentIndex, DocumentTitle, EndBlockIndex,
+// StartBlockIndex, Type are required.
+type CitationContentBlockLocationParam struct {
+ DocumentTitle param.Opt[string] `json:"document_title,omitzero,required"`
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ EndBlockIndex int64 `json:"end_block_index,required"`
+ StartBlockIndex int64 `json:"start_block_index,required"`
+ // This field can be elided, and will marshal its zero value as
+ // "content_block_location".
+ Type constant.ContentBlockLocation `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f CitationContentBlockLocationParam) IsPresent() bool {
+ return !param.IsOmitted(f) && !f.IsNull()
+}
+func (r CitationContentBlockLocationParam) MarshalJSON() (data []byte, err error) {
+ type shadow CitationContentBlockLocationParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-type CitationCharLocation struct {
- CitedText string `json:"cited_text,required"`
- DocumentIndex int64 `json:"document_index,required"`
- DocumentTitle string `json:"document_title,required,nullable"`
- EndCharIndex int64 `json:"end_char_index,required"`
- StartCharIndex int64 `json:"start_char_index,required"`
- Type CitationCharLocationType `json:"type,required"`
- JSON citationCharLocationJSON `json:"-"`
-}
-
-// citationCharLocationJSON contains the JSON metadata for the struct
-// [CitationCharLocation]
-type citationCharLocationJSON struct {
- CitedText apijson.Field
- DocumentIndex apijson.Field
- DocumentTitle apijson.Field
- EndCharIndex apijson.Field
- StartCharIndex apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *CitationCharLocation) UnmarshalJSON(data []byte) (err error) {
+type CitationPageLocation struct {
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ DocumentTitle string `json:"document_title,required"`
+ EndPageNumber int64 `json:"end_page_number,required"`
+ StartPageNumber int64 `json:"start_page_number,required"`
+ Type constant.PageLocation `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ CitedText resp.Field
+ DocumentIndex resp.Field
+ DocumentTitle resp.Field
+ EndPageNumber resp.Field
+ StartPageNumber resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r CitationPageLocation) RawJSON() string { return r.JSON.raw }
+func (r *CitationPageLocation) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r citationCharLocationJSON) RawJSON() string {
- return r.raw
+// The properties CitedText, DocumentIndex, DocumentTitle, EndPageNumber,
+// StartPageNumber, Type are required.
+type CitationPageLocationParam struct {
+ DocumentTitle param.Opt[string] `json:"document_title,omitzero,required"`
+ CitedText string `json:"cited_text,required"`
+ DocumentIndex int64 `json:"document_index,required"`
+ EndPageNumber int64 `json:"end_page_number,required"`
+ StartPageNumber int64 `json:"start_page_number,required"`
+ // This field can be elided, and will marshal its zero value as "page_location".
+ Type constant.PageLocation `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f CitationPageLocationParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r CitationPageLocationParam) MarshalJSON() (data []byte, err error) {
+ type shadow CitationPageLocationParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r CitationCharLocation) implementsCitationsDeltaCitation() {}
-
-func (r CitationCharLocation) implementsTextCitation() {}
+type CitationsConfigParam struct {
+ Enabled param.Opt[bool] `json:"enabled,omitzero"`
+ paramObj
+}
-type CitationCharLocationType string
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f CitationsConfigParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r CitationsConfigParam) MarshalJSON() (data []byte, err error) {
+ type shadow CitationsConfigParam
+ return param.MarshalObject(r, (*shadow)(&r))
+}
-const (
- CitationCharLocationTypeCharLocation CitationCharLocationType = "char_location"
-)
+type CitationsDelta struct {
+ Citation CitationsDeltaCitationUnion `json:"citation,required"`
+ Type constant.CitationsDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Citation resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r CitationsDelta) RawJSON() string { return r.JSON.raw }
+func (r *CitationsDelta) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-func (r CitationCharLocationType) IsKnown() bool {
- switch r {
- case CitationCharLocationTypeCharLocation:
- return true
+// CitationsDeltaCitationUnion contains all possible properties and values from
+// [CitationCharLocation], [CitationPageLocation], [CitationContentBlockLocation].
+//
+// Use the [CitationsDeltaCitationUnion.AsAny] method to switch on the variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type CitationsDeltaCitationUnion struct {
+ CitedText string `json:"cited_text"`
+ DocumentIndex int64 `json:"document_index"`
+ DocumentTitle string `json:"document_title"`
+ // This field is from variant [CitationCharLocation].
+ EndCharIndex int64 `json:"end_char_index"`
+ // This field is from variant [CitationCharLocation].
+ StartCharIndex int64 `json:"start_char_index"`
+ // Any of "char_location", "page_location", "content_block_location".
+ Type string `json:"type"`
+ // This field is from variant [CitationPageLocation].
+ EndPageNumber int64 `json:"end_page_number"`
+ // This field is from variant [CitationPageLocation].
+ StartPageNumber int64 `json:"start_page_number"`
+ // This field is from variant [CitationContentBlockLocation].
+ EndBlockIndex int64 `json:"end_block_index"`
+ // This field is from variant [CitationContentBlockLocation].
+ StartBlockIndex int64 `json:"start_block_index"`
+ JSON struct {
+ CitedText resp.Field
+ DocumentIndex resp.Field
+ DocumentTitle resp.Field
+ EndCharIndex resp.Field
+ StartCharIndex resp.Field
+ Type resp.Field
+ EndPageNumber resp.Field
+ StartPageNumber resp.Field
+ EndBlockIndex resp.Field
+ StartBlockIndex resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := CitationsDeltaCitationUnion.AsAny().(type) {
+// case CitationCharLocation:
+// case CitationPageLocation:
+// case CitationContentBlockLocation:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u CitationsDeltaCitationUnion) AsAny() any {
+ switch u.Type {
+ case "char_location":
+ return u.AsResponseCharLocationCitation()
+ case "page_location":
+ return u.AsResponsePageLocationCitation()
+ case "content_block_location":
+ return u.AsResponseContentBlockLocationCitation()
}
- return false
+ return nil
}
-type CitationCharLocationParam struct {
- CitedText param.Field[string] `json:"cited_text,required"`
- DocumentIndex param.Field[int64] `json:"document_index,required"`
- DocumentTitle param.Field[string] `json:"document_title,required"`
- EndCharIndex param.Field[int64] `json:"end_char_index,required"`
- StartCharIndex param.Field[int64] `json:"start_char_index,required"`
- Type param.Field[CitationCharLocationParamType] `json:"type,required"`
+func (u CitationsDeltaCitationUnion) AsResponseCharLocationCitation() (v CitationCharLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r CitationCharLocationParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+func (u CitationsDeltaCitationUnion) AsResponsePageLocationCitation() (v CitationPageLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r CitationCharLocationParam) implementsTextCitationParamUnion() {}
+func (u CitationsDeltaCitationUnion) AsResponseContentBlockLocationCitation() (v CitationContentBlockLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
+}
-type CitationCharLocationParamType string
+// Returns the unmodified JSON received from the API
+func (u CitationsDeltaCitationUnion) RawJSON() string { return u.JSON.raw }
-const (
- CitationCharLocationParamTypeCharLocation CitationCharLocationParamType = "char_location"
-)
+func (r *CitationsDeltaCitationUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-func (r CitationCharLocationParamType) IsKnown() bool {
- switch r {
- case CitationCharLocationParamTypeCharLocation:
- return true
+// ContentBlockUnion contains all possible properties and values from [TextBlock],
+// [ToolUseBlock], [ThinkingBlock], [RedactedThinkingBlock].
+//
+// Use the [ContentBlockUnion.AsAny] method to switch on the variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type ContentBlockUnion struct {
+ // This field is from variant [TextBlock].
+ Citations []TextCitationUnion `json:"citations"`
+ // This field is from variant [TextBlock].
+ Text string `json:"text"`
+ // Any of "text", "tool_use", "thinking", "redacted_thinking".
+ Type string `json:"type"`
+ // This field is from variant [ToolUseBlock].
+ ID string `json:"id"`
+ // This field is from variant [ToolUseBlock].
+ Input json.RawMessage `json:"input"`
+ // This field is from variant [ToolUseBlock].
+ Name string `json:"name"`
+ // This field is from variant [ThinkingBlock].
+ Signature string `json:"signature"`
+ // This field is from variant [ThinkingBlock].
+ Thinking string `json:"thinking"`
+ // This field is from variant [RedactedThinkingBlock].
+ Data string `json:"data"`
+ JSON struct {
+ Citations resp.Field
+ Text resp.Field
+ Type resp.Field
+ ID resp.Field
+ Input resp.Field
+ Name resp.Field
+ Signature resp.Field
+ Thinking resp.Field
+ Data resp.Field
+ raw string
+ } `json:"-"`
+}
+
+func (r ContentBlockUnion) ToParam() ContentBlockParamUnion {
+ switch variant := r.AsAny().(type) {
+ case TextBlock:
+ p := variant.ToParam()
+ return ContentBlockParamUnion{OfRequestTextBlock: &p}
+ case ToolUseBlock:
+ p := variant.ToParam()
+ return ContentBlockParamUnion{OfRequestToolUseBlock: &p}
+ case ThinkingBlock:
+ p := variant.ToParam()
+ return ContentBlockParamUnion{OfRequestThinkingBlock: &p}
+ case RedactedThinkingBlock:
+ p := variant.ToParam()
+ return ContentBlockParamUnion{OfRequestRedactedThinkingBlock: &p}
+ }
+ return ContentBlockParamUnion{}
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := ContentBlockUnion.AsAny().(type) {
+// case TextBlock:
+// case ToolUseBlock:
+// case ThinkingBlock:
+// case RedactedThinkingBlock:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u ContentBlockUnion) AsAny() any {
+ switch u.Type {
+ case "text":
+ return u.AsResponseTextBlock()
+ case "tool_use":
+ return u.AsResponseToolUseBlock()
+ case "thinking":
+ return u.AsResponseThinkingBlock()
+ case "redacted_thinking":
+ return u.AsResponseRedactedThinkingBlock()
}
- return false
+ return nil
}
-type CitationContentBlockLocation struct {
- CitedText string `json:"cited_text,required"`
- DocumentIndex int64 `json:"document_index,required"`
- DocumentTitle string `json:"document_title,required,nullable"`
- EndBlockIndex int64 `json:"end_block_index,required"`
- StartBlockIndex int64 `json:"start_block_index,required"`
- Type CitationContentBlockLocationType `json:"type,required"`
- JSON citationContentBlockLocationJSON `json:"-"`
-}
-
-// citationContentBlockLocationJSON contains the JSON metadata for the struct
-// [CitationContentBlockLocation]
-type citationContentBlockLocationJSON struct {
- CitedText apijson.Field
- DocumentIndex apijson.Field
- DocumentTitle apijson.Field
- EndBlockIndex apijson.Field
- StartBlockIndex apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *CitationContentBlockLocation) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+func (u ContentBlockUnion) AsResponseTextBlock() (v TextBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r citationContentBlockLocationJSON) RawJSON() string {
- return r.raw
+func (u ContentBlockUnion) AsResponseToolUseBlock() (v ToolUseBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r CitationContentBlockLocation) implementsCitationsDeltaCitation() {}
+func (u ContentBlockUnion) AsResponseThinkingBlock() (v ThinkingBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
+}
-func (r CitationContentBlockLocation) implementsTextCitation() {}
+func (u ContentBlockUnion) AsResponseRedactedThinkingBlock() (v RedactedThinkingBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
+}
-type CitationContentBlockLocationType string
+// Returns the unmodified JSON received from the API
+func (u ContentBlockUnion) RawJSON() string { return u.JSON.raw }
-const (
- CitationContentBlockLocationTypeContentBlockLocation CitationContentBlockLocationType = "content_block_location"
-)
+func (r *ContentBlockUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
+
+func ContentBlockParamOfRequestTextBlock(text string) ContentBlockParamUnion {
+ var variant TextBlockParam
+ variant.Text = text
+ return ContentBlockParamUnion{OfRequestTextBlock: &variant}
+}
-func (r CitationContentBlockLocationType) IsKnown() bool {
- switch r {
- case CitationContentBlockLocationTypeContentBlockLocation:
- return true
+func ContentBlockParamOfRequestImageBlock[T Base64ImageSourceParam | URLImageSourceParam](source T) ContentBlockParamUnion {
+ var variant ImageBlockParam
+ switch v := any(source).(type) {
+ case Base64ImageSourceParam:
+ variant.Source.OfBase64ImageSource = &v
+ case URLImageSourceParam:
+ variant.Source.OfURLImageSource = &v
}
- return false
+ return ContentBlockParamUnion{OfRequestImageBlock: &variant}
}
-type CitationContentBlockLocationParam struct {
- CitedText param.Field[string] `json:"cited_text,required"`
- DocumentIndex param.Field[int64] `json:"document_index,required"`
- DocumentTitle param.Field[string] `json:"document_title,required"`
- EndBlockIndex param.Field[int64] `json:"end_block_index,required"`
- StartBlockIndex param.Field[int64] `json:"start_block_index,required"`
- Type param.Field[CitationContentBlockLocationParamType] `json:"type,required"`
+func ContentBlockParamOfRequestToolUseBlock(id string, input interface{}, name string) ContentBlockParamUnion {
+ var variant ToolUseBlockParam
+ variant.ID = id
+ variant.Input = input
+ variant.Name = name
+ return ContentBlockParamUnion{OfRequestToolUseBlock: &variant}
}
-func (r CitationContentBlockLocationParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+func ContentBlockParamOfRequestToolResultBlock(toolUseID string) ContentBlockParamUnion {
+ var variant ToolResultBlockParam
+ variant.ToolUseID = toolUseID
+ return ContentBlockParamUnion{OfRequestToolResultBlock: &variant}
}
-func (r CitationContentBlockLocationParam) implementsTextCitationParamUnion() {}
+func ContentBlockParamOfRequestDocumentBlock[
+ T Base64PDFSourceParam | PlainTextSourceParam | ContentBlockSourceParam | URLPDFSourceParam,
+](source T) ContentBlockParamUnion {
+ var variant DocumentBlockParam
+ switch v := any(source).(type) {
+ case Base64PDFSourceParam:
+ variant.Source.OfBase64PDFSource = &v
+ case PlainTextSourceParam:
+ variant.Source.OfPlainTextSource = &v
+ case ContentBlockSourceParam:
+ variant.Source.OfContentBlockSource = &v
+ case URLPDFSourceParam:
+ variant.Source.OfUrlpdfSource = &v
+ }
+ return ContentBlockParamUnion{OfRequestDocumentBlock: &variant}
+}
-type CitationContentBlockLocationParamType string
+func ContentBlockParamOfRequestThinkingBlock(signature string, thinking string) ContentBlockParamUnion {
+ var variant ThinkingBlockParam
+ variant.Signature = signature
+ variant.Thinking = thinking
+ return ContentBlockParamUnion{OfRequestThinkingBlock: &variant}
+}
-const (
- CitationContentBlockLocationParamTypeContentBlockLocation CitationContentBlockLocationParamType = "content_block_location"
-)
+func ContentBlockParamOfRequestRedactedThinkingBlock(data string) ContentBlockParamUnion {
+ var variant RedactedThinkingBlockParam
+ variant.Data = data
+ return ContentBlockParamUnion{OfRequestRedactedThinkingBlock: &variant}
+}
-func (r CitationContentBlockLocationParamType) IsKnown() bool {
- switch r {
- case CitationContentBlockLocationParamTypeContentBlockLocation:
- return true
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type ContentBlockParamUnion struct {
+ OfRequestTextBlock *TextBlockParam `json:",omitzero,inline"`
+ OfRequestImageBlock *ImageBlockParam `json:",omitzero,inline"`
+ OfRequestToolUseBlock *ToolUseBlockParam `json:",omitzero,inline"`
+ OfRequestToolResultBlock *ToolResultBlockParam `json:",omitzero,inline"`
+ OfRequestDocumentBlock *DocumentBlockParam `json:",omitzero,inline"`
+ OfRequestThinkingBlock *ThinkingBlockParam `json:",omitzero,inline"`
+ OfRequestRedactedThinkingBlock *RedactedThinkingBlockParam `json:",omitzero,inline"`
+ paramUnion
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u ContentBlockParamUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u ContentBlockParamUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[ContentBlockParamUnion](u.OfRequestTextBlock,
+ u.OfRequestImageBlock,
+ u.OfRequestToolUseBlock,
+ u.OfRequestToolResultBlock,
+ u.OfRequestDocumentBlock,
+ u.OfRequestThinkingBlock,
+ u.OfRequestRedactedThinkingBlock)
+}
+
+func (u *ContentBlockParamUnion) asAny() any {
+ if !param.IsOmitted(u.OfRequestTextBlock) {
+ return u.OfRequestTextBlock
+ } else if !param.IsOmitted(u.OfRequestImageBlock) {
+ return u.OfRequestImageBlock
+ } else if !param.IsOmitted(u.OfRequestToolUseBlock) {
+ return u.OfRequestToolUseBlock
+ } else if !param.IsOmitted(u.OfRequestToolResultBlock) {
+ return u.OfRequestToolResultBlock
+ } else if !param.IsOmitted(u.OfRequestDocumentBlock) {
+ return u.OfRequestDocumentBlock
+ } else if !param.IsOmitted(u.OfRequestThinkingBlock) {
+ return u.OfRequestThinkingBlock
+ } else if !param.IsOmitted(u.OfRequestRedactedThinkingBlock) {
+ return u.OfRequestRedactedThinkingBlock
}
- return false
+ return nil
}
-type CitationPageLocation struct {
- CitedText string `json:"cited_text,required"`
- DocumentIndex int64 `json:"document_index,required"`
- DocumentTitle string `json:"document_title,required,nullable"`
- EndPageNumber int64 `json:"end_page_number,required"`
- StartPageNumber int64 `json:"start_page_number,required"`
- Type CitationPageLocationType `json:"type,required"`
- JSON citationPageLocationJSON `json:"-"`
-}
-
-// citationPageLocationJSON contains the JSON metadata for the struct
-// [CitationPageLocation]
-type citationPageLocationJSON struct {
- CitedText apijson.Field
- DocumentIndex apijson.Field
- DocumentTitle apijson.Field
- EndPageNumber apijson.Field
- StartPageNumber apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *CitationPageLocation) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetText() *string {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return &vt.Text
+ }
+ return nil
}
-func (r citationPageLocationJSON) RawJSON() string {
- return r.raw
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetID() *string {
+ if vt := u.OfRequestToolUseBlock; vt != nil {
+ return &vt.ID
+ }
+ return nil
}
-func (r CitationPageLocation) implementsCitationsDeltaCitation() {}
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetInput() *interface{} {
+ if vt := u.OfRequestToolUseBlock; vt != nil {
+ return &vt.Input
+ }
+ return nil
+}
-func (r CitationPageLocation) implementsTextCitation() {}
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetName() *string {
+ if vt := u.OfRequestToolUseBlock; vt != nil {
+ return &vt.Name
+ }
+ return nil
+}
-type CitationPageLocationType string
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetToolUseID() *string {
+ if vt := u.OfRequestToolResultBlock; vt != nil {
+ return &vt.ToolUseID
+ }
+ return nil
+}
-const (
- CitationPageLocationTypePageLocation CitationPageLocationType = "page_location"
-)
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetContent() *[]ToolResultBlockParamContentUnion {
+ if vt := u.OfRequestToolResultBlock; vt != nil {
+ return &vt.Content
+ }
+ return nil
+}
-func (r CitationPageLocationType) IsKnown() bool {
- switch r {
- case CitationPageLocationTypePageLocation:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetIsError() *bool {
+ if vt := u.OfRequestToolResultBlock; vt != nil && vt.IsError.IsPresent() {
+ return &vt.IsError.Value
}
- return false
+ return nil
}
-type CitationPageLocationParam struct {
- CitedText param.Field[string] `json:"cited_text,required"`
- DocumentIndex param.Field[int64] `json:"document_index,required"`
- DocumentTitle param.Field[string] `json:"document_title,required"`
- EndPageNumber param.Field[int64] `json:"end_page_number,required"`
- StartPageNumber param.Field[int64] `json:"start_page_number,required"`
- Type param.Field[CitationPageLocationParamType] `json:"type,required"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetContext() *string {
+ if vt := u.OfRequestDocumentBlock; vt != nil && vt.Context.IsPresent() {
+ return &vt.Context.Value
+ }
+ return nil
}
-func (r CitationPageLocationParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetTitle() *string {
+ if vt := u.OfRequestDocumentBlock; vt != nil && vt.Title.IsPresent() {
+ return &vt.Title.Value
+ }
+ return nil
}
-func (r CitationPageLocationParam) implementsTextCitationParamUnion() {}
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetSignature() *string {
+ if vt := u.OfRequestThinkingBlock; vt != nil {
+ return &vt.Signature
+ }
+ return nil
+}
-type CitationPageLocationParamType string
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetThinking() *string {
+ if vt := u.OfRequestThinkingBlock; vt != nil {
+ return &vt.Thinking
+ }
+ return nil
+}
-const (
- CitationPageLocationParamTypePageLocation CitationPageLocationParamType = "page_location"
-)
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetData() *string {
+ if vt := u.OfRequestRedactedThinkingBlock; vt != nil {
+ return &vt.Data
+ }
+ return nil
+}
-func (r CitationPageLocationParamType) IsKnown() bool {
- switch r {
- case CitationPageLocationParamTypePageLocation:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u ContentBlockParamUnion) GetType() *string {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestImageBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestToolUseBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestToolResultBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestDocumentBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestThinkingBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestRedactedThinkingBlock; vt != nil {
+ return (*string)(&vt.Type)
}
- return false
+ return nil
}
-type CitationsConfigParam struct {
- Enabled param.Field[bool] `json:"enabled"`
+// Returns a pointer to the underlying variant's CacheControl property, if present.
+func (u ContentBlockParamUnion) GetCacheControl() *CacheControlEphemeralParam {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfRequestImageBlock; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfRequestToolUseBlock; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfRequestToolResultBlock; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfRequestDocumentBlock; vt != nil {
+ return &vt.CacheControl
+ }
+ return nil
}
-func (r CitationsConfigParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a subunion which exports methods to access subproperties
+//
+// Or use AsAny() to get the underlying value
+func (u ContentBlockParamUnion) GetCitations() (res contentBlockParamUnionCitations) {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ res.ofTextBlockCitations = &vt.Citations
+ } else if vt := u.OfRequestDocumentBlock; vt != nil {
+ res.ofCitationsConfig = &vt.Citations
+ }
+ return
}
-type CitationsDelta struct {
- Citation CitationsDeltaCitation `json:"citation,required"`
- Type CitationsDeltaType `json:"type,required"`
- JSON citationsDeltaJSON `json:"-"`
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type contentBlockParamUnionCitations struct {
+ ofTextBlockCitations *[]TextCitationParamUnion
+ ofCitationsConfig *CitationsConfigParam
}
-// citationsDeltaJSON contains the JSON metadata for the struct [CitationsDelta]
-type citationsDeltaJSON struct {
- Citation apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+// Use the following switch statement to get the type of the union:
+//
+// switch u.AsAny().(type) {
+// case *[]anthropic.TextCitationParamUnion:
+// case *anthropic.CitationsConfigParam:
+// default:
+// fmt.Errorf("not present")
+// }
+func (u contentBlockParamUnionCitations) AsAny() any {
+ if !param.IsOmitted(u.ofTextBlockCitations) {
+ return u.ofTextBlockCitations
+ } else if !param.IsOmitted(u.ofCitationsConfig) {
+ return u.ofCitationsConfig
+ }
+ return nil
}
-func (r *CitationsDelta) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u contentBlockParamUnionCitations) GetEnabled() *bool {
+ if vt := u.ofCitationsConfig; vt != nil && vt.Enabled.IsPresent() {
+ return &vt.Enabled.Value
+ }
+ return nil
}
-func (r citationsDeltaJSON) RawJSON() string {
- return r.raw
+// Returns a subunion which exports methods to access subproperties
+//
+// Or use AsAny() to get the underlying value
+func (u ContentBlockParamUnion) GetSource() (res contentBlockParamUnionSource) {
+ if vt := u.OfRequestImageBlock; vt != nil {
+ res.ofImageBlockSource = &vt.Source
+ } else if vt := u.OfRequestDocumentBlock; vt != nil {
+ res.ofDocumentBlockSource = &vt.Source
+ }
+ return
}
-func (r CitationsDelta) implementsContentBlockDeltaEventDelta() {}
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type contentBlockParamUnionSource struct {
+ ofImageBlockSource *ImageBlockParamSourceUnion
+ ofDocumentBlockSource *DocumentBlockParamSourceUnion
+}
-type CitationsDeltaCitation struct {
- CitedText string `json:"cited_text,required"`
- DocumentIndex int64 `json:"document_index,required"`
- DocumentTitle string `json:"document_title,required,nullable"`
- Type CitationsDeltaCitationType `json:"type,required"`
- EndBlockIndex int64 `json:"end_block_index"`
- EndCharIndex int64 `json:"end_char_index"`
- EndPageNumber int64 `json:"end_page_number"`
- StartBlockIndex int64 `json:"start_block_index"`
- StartCharIndex int64 `json:"start_char_index"`
- StartPageNumber int64 `json:"start_page_number"`
- JSON citationsDeltaCitationJSON `json:"-"`
- union CitationsDeltaCitationUnion
+// Use the following switch statement to get the type of the union:
+//
+// switch u.AsAny().(type) {
+// case *anthropic.Base64ImageSourceParam:
+// case *anthropic.URLImageSourceParam:
+// case *anthropic.Base64PDFSourceParam:
+// case *anthropic.PlainTextSourceParam:
+// case *anthropic.ContentBlockSourceParam:
+// case *anthropic.URLPDFSourceParam:
+// default:
+// fmt.Errorf("not present")
+// }
+func (u contentBlockParamUnionSource) AsAny() any {
+ if !param.IsOmitted(u.ofImageBlockSource) {
+ return u.ofImageBlockSource.asAny()
+ } else if !param.IsOmitted(u.ofDocumentBlockSource) {
+ return u.ofDocumentBlockSource.asAny()
+ }
+ return nil
}
-// citationsDeltaCitationJSON contains the JSON metadata for the struct
-// [CitationsDeltaCitation]
-type citationsDeltaCitationJSON struct {
- CitedText apijson.Field
- DocumentIndex apijson.Field
- DocumentTitle apijson.Field
- Type apijson.Field
- EndBlockIndex apijson.Field
- EndCharIndex apijson.Field
- EndPageNumber apijson.Field
- StartBlockIndex apijson.Field
- StartCharIndex apijson.Field
- StartPageNumber apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+// Returns a pointer to the underlying variant's property, if present.
+func (u contentBlockParamUnionSource) GetContent() *ContentBlockSourceContentUnionParam {
+ if u.ofDocumentBlockSource != nil {
+ return u.ofDocumentBlockSource.GetContent()
+ }
+ return nil
}
-func (r citationsDeltaCitationJSON) RawJSON() string {
- return r.raw
+// Returns a pointer to the underlying variant's property, if present.
+func (u contentBlockParamUnionSource) GetData() *string {
+ if u.ofImageBlockSource != nil {
+ return u.ofImageBlockSource.GetData()
+ } else if u.ofDocumentBlockSource != nil {
+ return u.ofDocumentBlockSource.GetData()
+ } else if u.ofDocumentBlockSource != nil {
+ return u.ofDocumentBlockSource.GetData()
+ }
+ return nil
}
-func (r *CitationsDeltaCitation) UnmarshalJSON(data []byte) (err error) {
- *r = CitationsDeltaCitation{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
+// Returns a pointer to the underlying variant's property, if present.
+func (u contentBlockParamUnionSource) GetMediaType() *string {
+ if u.ofImageBlockSource != nil {
+ return u.ofImageBlockSource.GetMediaType()
+ } else if u.ofDocumentBlockSource != nil {
+ return u.ofDocumentBlockSource.GetMediaType()
+ } else if u.ofDocumentBlockSource != nil {
+ return u.ofDocumentBlockSource.GetMediaType()
}
- return apijson.Port(r.union, &r)
+ return nil
}
-// AsUnion returns a [CitationsDeltaCitationUnion] interface which you can cast to
-// the specific types for more type safety.
-//
-// Possible runtime types of the union are [CitationCharLocation],
-// [CitationPageLocation], [CitationContentBlockLocation].
-func (r CitationsDeltaCitation) AsUnion() CitationsDeltaCitationUnion {
- return r.union
+// Returns a pointer to the underlying variant's property, if present.
+func (u contentBlockParamUnionSource) GetType() *string {
+ if u.ofImageBlockSource != nil {
+ return u.ofImageBlockSource.GetType()
+ } else if u.ofImageBlockSource != nil {
+ return u.ofImageBlockSource.GetType()
+ } else if u.ofDocumentBlockSource != nil {
+ return u.ofDocumentBlockSource.GetType()
+ } else if u.ofDocumentBlockSource != nil {
+ return u.ofDocumentBlockSource.GetType()
+ } else if u.ofDocumentBlockSource != nil {
+ return u.ofDocumentBlockSource.GetType()
+ } else if u.ofDocumentBlockSource != nil {
+ return u.ofDocumentBlockSource.GetType()
+ }
+ return nil
}
-// Union satisfied by [CitationCharLocation], [CitationPageLocation] or
-// [CitationContentBlockLocation].
-type CitationsDeltaCitationUnion interface {
- implementsCitationsDeltaCitation()
+// Returns a pointer to the underlying variant's property, if present.
+func (u contentBlockParamUnionSource) GetURL() *string {
+ if u.ofImageBlockSource != nil {
+ return u.ofImageBlockSource.GetURL()
+ } else if u.ofDocumentBlockSource != nil {
+ return u.ofDocumentBlockSource.GetURL()
+ }
+ return nil
}
func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*CitationsDeltaCitationUnion)(nil)).Elem(),
+ apijson.RegisterUnion[ContentBlockParamUnion](
"type",
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(CitationCharLocation{}),
- DiscriminatorValue: "char_location",
+ Type: reflect.TypeOf(TextBlockParam{}),
+ DiscriminatorValue: "text",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(CitationPageLocation{}),
- DiscriminatorValue: "page_location",
+ Type: reflect.TypeOf(ImageBlockParam{}),
+ DiscriminatorValue: "image",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(CitationContentBlockLocation{}),
- DiscriminatorValue: "content_block_location",
+ Type: reflect.TypeOf(ToolUseBlockParam{}),
+ DiscriminatorValue: "tool_use",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ToolResultBlockParam{}),
+ DiscriminatorValue: "tool_result",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(DocumentBlockParam{}),
+ DiscriminatorValue: "document",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ThinkingBlockParam{}),
+ DiscriminatorValue: "thinking",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(RedactedThinkingBlockParam{}),
+ DiscriminatorValue: "redacted_thinking",
},
)
}
-type CitationsDeltaCitationType string
-
-const (
- CitationsDeltaCitationTypeCharLocation CitationsDeltaCitationType = "char_location"
- CitationsDeltaCitationTypePageLocation CitationsDeltaCitationType = "page_location"
- CitationsDeltaCitationTypeContentBlockLocation CitationsDeltaCitationType = "content_block_location"
-)
+// The properties Content, Type are required.
+type ContentBlockSourceParam struct {
+ Content ContentBlockSourceContentUnionParam `json:"content,omitzero,required"`
+ // This field can be elided, and will marshal its zero value as "content".
+ Type constant.Content `json:"type,required"`
+ paramObj
+}
-func (r CitationsDeltaCitationType) IsKnown() bool {
- switch r {
- case CitationsDeltaCitationTypeCharLocation, CitationsDeltaCitationTypePageLocation, CitationsDeltaCitationTypeContentBlockLocation:
- return true
- }
- return false
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ContentBlockSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r ContentBlockSourceParam) MarshalJSON() (data []byte, err error) {
+ type shadow ContentBlockSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-type CitationsDeltaType string
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type ContentBlockSourceContentUnionParam struct {
+ OfString param.Opt[string] `json:",omitzero,inline"`
+ OfContentBlockSourceContent []ContentBlockSourceContentUnionParam `json:",omitzero,inline"`
+ paramUnion
+}
-const (
- CitationsDeltaTypeCitationsDelta CitationsDeltaType = "citations_delta"
-)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u ContentBlockSourceContentUnionParam) IsPresent() bool {
+ return !param.IsOmitted(u) && !u.IsNull()
+}
+func (u ContentBlockSourceContentUnionParam) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[ContentBlockSourceContentUnionParam](u.OfString, u.OfContentBlockSourceContent)
+}
-func (r CitationsDeltaType) IsKnown() bool {
- switch r {
- case CitationsDeltaTypeCitationsDelta:
- return true
+func (u *ContentBlockSourceContentUnionParam) asAny() any {
+ if !param.IsOmitted(u.OfString) {
+ return &u.OfString.Value
+ } else if !param.IsOmitted(u.OfContentBlockSourceContent) {
+ return &u.OfContentBlockSourceContent
}
- return false
+ return nil
+}
+
+// The properties Source, Type are required.
+type DocumentBlockParam struct {
+ Source DocumentBlockParamSourceUnion `json:"source,omitzero,required"`
+ Context param.Opt[string] `json:"context,omitzero"`
+ Title param.Opt[string] `json:"title,omitzero"`
+ CacheControl CacheControlEphemeralParam `json:"cache_control,omitzero"`
+ Citations CitationsConfigParam `json:"citations,omitzero"`
+ // This field can be elided, and will marshal its zero value as "document".
+ Type constant.Document `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f DocumentBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r DocumentBlockParam) MarshalJSON() (data []byte, err error) {
+ type shadow DocumentBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-type ContentBlock struct {
- Type ContentBlockType `json:"type,required"`
- ID string `json:"id"`
- // This field can have the runtime type of [[]TextCitation].
- Citations interface{} `json:"citations"`
- Data string `json:"data"`
- // This field can have the runtime type of [interface{}].
- Input json.RawMessage `json:"input"`
- Name string `json:"name"`
- Signature string `json:"signature"`
- Text string `json:"text"`
- Thinking string `json:"thinking"`
- JSON contentBlockJSON `json:"-"`
- union ContentBlockUnion
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type DocumentBlockParamSourceUnion struct {
+ OfBase64PDFSource *Base64PDFSourceParam `json:",omitzero,inline"`
+ OfPlainTextSource *PlainTextSourceParam `json:",omitzero,inline"`
+ OfContentBlockSource *ContentBlockSourceParam `json:",omitzero,inline"`
+ OfUrlpdfSource *URLPDFSourceParam `json:",omitzero,inline"`
+ paramUnion
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u DocumentBlockParamSourceUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u DocumentBlockParamSourceUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[DocumentBlockParamSourceUnion](u.OfBase64PDFSource, u.OfPlainTextSource, u.OfContentBlockSource, u.OfUrlpdfSource)
+}
+
+func (u *DocumentBlockParamSourceUnion) asAny() any {
+ if !param.IsOmitted(u.OfBase64PDFSource) {
+ return u.OfBase64PDFSource
+ } else if !param.IsOmitted(u.OfPlainTextSource) {
+ return u.OfPlainTextSource
+ } else if !param.IsOmitted(u.OfContentBlockSource) {
+ return u.OfContentBlockSource
+ } else if !param.IsOmitted(u.OfUrlpdfSource) {
+ return u.OfUrlpdfSource
+ }
+ return nil
}
-// contentBlockJSON contains the JSON metadata for the struct [ContentBlock]
-type contentBlockJSON struct {
- Type apijson.Field
- ID apijson.Field
- Citations apijson.Field
- Data apijson.Field
- Input apijson.Field
- Name apijson.Field
- Signature apijson.Field
- Text apijson.Field
- Thinking apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+// Returns a pointer to the underlying variant's property, if present.
+func (u DocumentBlockParamSourceUnion) GetContent() *ContentBlockSourceContentUnionParam {
+ if vt := u.OfContentBlockSource; vt != nil {
+ return &vt.Content
+ }
+ return nil
}
-func (r contentBlockJSON) RawJSON() string {
- return r.raw
+// Returns a pointer to the underlying variant's property, if present.
+func (u DocumentBlockParamSourceUnion) GetURL() *string {
+ if vt := u.OfUrlpdfSource; vt != nil {
+ return &vt.URL
+ }
+ return nil
}
-func (r *ContentBlock) UnmarshalJSON(data []byte) (err error) {
- *r = ContentBlock{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
+// Returns a pointer to the underlying variant's property, if present.
+func (u DocumentBlockParamSourceUnion) GetData() *string {
+ if vt := u.OfBase64PDFSource; vt != nil {
+ return (*string)(&vt.Data)
+ } else if vt := u.OfPlainTextSource; vt != nil {
+ return (*string)(&vt.Data)
}
- return apijson.Port(r.union, &r)
+ return nil
}
-// AsUnion returns a [ContentBlockUnion] interface which you can cast to the
-// specific types for more type safety.
-//
-// Possible runtime types of the union are [TextBlock], [ToolUseBlock],
-// [ThinkingBlock], [RedactedThinkingBlock].
-func (r ContentBlock) AsUnion() ContentBlockUnion {
- return r.union
+// Returns a pointer to the underlying variant's property, if present.
+func (u DocumentBlockParamSourceUnion) GetMediaType() *string {
+ if vt := u.OfBase64PDFSource; vt != nil {
+ return (*string)(&vt.MediaType)
+ } else if vt := u.OfPlainTextSource; vt != nil {
+ return (*string)(&vt.MediaType)
+ }
+ return nil
}
-// Union satisfied by [TextBlock], [ToolUseBlock], [ThinkingBlock] or
-// [RedactedThinkingBlock].
-type ContentBlockUnion interface {
- implementsContentBlock()
+// Returns a pointer to the underlying variant's property, if present.
+func (u DocumentBlockParamSourceUnion) GetType() *string {
+ if vt := u.OfBase64PDFSource; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfPlainTextSource; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfContentBlockSource; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfUrlpdfSource; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
}
func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*ContentBlockUnion)(nil)).Elem(),
+ apijson.RegisterUnion[DocumentBlockParamSourceUnion](
"type",
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(TextBlock{}),
- DiscriminatorValue: "text",
+ Type: reflect.TypeOf(Base64PDFSourceParam{}),
+ DiscriminatorValue: "base64",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(ToolUseBlock{}),
- DiscriminatorValue: "tool_use",
+ Type: reflect.TypeOf(PlainTextSourceParam{}),
+ DiscriminatorValue: "text",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(ThinkingBlock{}),
- DiscriminatorValue: "thinking",
+ Type: reflect.TypeOf(ContentBlockSourceParam{}),
+ DiscriminatorValue: "content",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(RedactedThinkingBlock{}),
- DiscriminatorValue: "redacted_thinking",
+ Type: reflect.TypeOf(URLPDFSourceParam{}),
+ DiscriminatorValue: "url",
},
)
}
-type ContentBlockType string
-
-const (
- ContentBlockTypeText ContentBlockType = "text"
- ContentBlockTypeToolUse ContentBlockType = "tool_use"
- ContentBlockTypeThinking ContentBlockType = "thinking"
- ContentBlockTypeRedactedThinking ContentBlockType = "redacted_thinking"
-)
-
-func (r ContentBlockType) IsKnown() bool {
- switch r {
- case ContentBlockTypeText, ContentBlockTypeToolUse, ContentBlockTypeThinking, ContentBlockTypeRedactedThinking:
- return true
+// The properties Source, Type are required.
+type ImageBlockParam struct {
+ Source ImageBlockParamSourceUnion `json:"source,omitzero,required"`
+ CacheControl CacheControlEphemeralParam `json:"cache_control,omitzero"`
+ // This field can be elided, and will marshal its zero value as "image".
+ Type constant.Image `json:"type,required"`
+ paramObj
+}
+
+func NewImageBlockBase64(mediaType string, encodedData string) ContentBlockParamUnion {
+ return ContentBlockParamUnion{
+ OfRequestImageBlock: &ImageBlockParam{
+ Source: ImageBlockParamSourceUnion{
+ OfBase64ImageSource: &Base64ImageSourceParam{
+ Data: encodedData,
+ MediaType: Base64ImageSourceMediaType(mediaType),
+ },
+ },
+ },
}
- return false
}
-type ContentBlockParam struct {
- Type param.Field[ContentBlockParamType] `json:"type,required"`
- ID param.Field[string] `json:"id"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
- Citations param.Field[interface{}] `json:"citations"`
- Content param.Field[interface{}] `json:"content"`
- Context param.Field[string] `json:"context"`
- Data param.Field[string] `json:"data"`
- Input param.Field[interface{}] `json:"input"`
- IsError param.Field[bool] `json:"is_error"`
- Name param.Field[string] `json:"name"`
- Signature param.Field[string] `json:"signature"`
- Source param.Field[interface{}] `json:"source"`
- Text param.Field[string] `json:"text"`
- Thinking param.Field[string] `json:"thinking"`
- Title param.Field[string] `json:"title"`
- ToolUseID param.Field[string] `json:"tool_use_id"`
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ImageBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r ImageBlockParam) MarshalJSON() (data []byte, err error) {
+ type shadow ImageBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r ContentBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type ImageBlockParamSourceUnion struct {
+ OfBase64ImageSource *Base64ImageSourceParam `json:",omitzero,inline"`
+ OfURLImageSource *URLImageSourceParam `json:",omitzero,inline"`
+ paramUnion
}
-func (r ContentBlockParam) implementsContentBlockParamUnion() {}
-
-// Satisfied by [TextBlockParam], [ImageBlockParam], [ToolUseBlockParam],
-// [ToolResultBlockParam], [DocumentBlockParam], [ThinkingBlockParam],
-// [RedactedThinkingBlockParam], [ContentBlockParam].
-type ContentBlockParamUnion interface {
- implementsContentBlockParamUnion()
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u ImageBlockParamSourceUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u ImageBlockParamSourceUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[ImageBlockParamSourceUnion](u.OfBase64ImageSource, u.OfURLImageSource)
}
-type ContentBlockParamType string
-
-const (
- ContentBlockParamTypeText ContentBlockParamType = "text"
- ContentBlockParamTypeImage ContentBlockParamType = "image"
- ContentBlockParamTypeToolUse ContentBlockParamType = "tool_use"
- ContentBlockParamTypeToolResult ContentBlockParamType = "tool_result"
- ContentBlockParamTypeDocument ContentBlockParamType = "document"
- ContentBlockParamTypeThinking ContentBlockParamType = "thinking"
- ContentBlockParamTypeRedactedThinking ContentBlockParamType = "redacted_thinking"
-)
-
-func (r ContentBlockParamType) IsKnown() bool {
- switch r {
- case ContentBlockParamTypeText, ContentBlockParamTypeImage, ContentBlockParamTypeToolUse, ContentBlockParamTypeToolResult, ContentBlockParamTypeDocument, ContentBlockParamTypeThinking, ContentBlockParamTypeRedactedThinking:
- return true
+func (u *ImageBlockParamSourceUnion) asAny() any {
+ if !param.IsOmitted(u.OfBase64ImageSource) {
+ return u.OfBase64ImageSource
+ } else if !param.IsOmitted(u.OfURLImageSource) {
+ return u.OfURLImageSource
}
- return false
+ return nil
}
-type ContentBlockSourceParam struct {
- Content param.Field[ContentBlockSourceContentUnionParam] `json:"content,required"`
- Type param.Field[ContentBlockSourceType] `json:"type,required"`
-}
-
-func (r ContentBlockSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r ContentBlockSourceParam) implementsDocumentBlockParamSourceUnion() {}
-
-// Satisfied by [shared.UnionString],
-// [ContentBlockSourceContentContentBlockSourceContentParam].
-type ContentBlockSourceContentUnionParam interface {
- ImplementsContentBlockSourceContentUnionParam()
-}
-
-type ContentBlockSourceContentContentBlockSourceContentParam []ContentBlockSourceContentUnionParam
-
-func (r ContentBlockSourceContentContentBlockSourceContentParam) ImplementsContentBlockSourceContentUnionParam() {
-}
-
-type ContentBlockSourceType string
-
-const (
- ContentBlockSourceTypeContent ContentBlockSourceType = "content"
-)
-
-func (r ContentBlockSourceType) IsKnown() bool {
- switch r {
- case ContentBlockSourceTypeContent:
- return true
- }
- return false
-}
-
-type DocumentBlockParam struct {
- Source param.Field[DocumentBlockParamSourceUnion] `json:"source,required"`
- Type param.Field[DocumentBlockParamType] `json:"type,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
- Citations param.Field[CitationsConfigParam] `json:"citations"`
- Context param.Field[string] `json:"context"`
- Title param.Field[string] `json:"title"`
-}
-
-func (r DocumentBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r DocumentBlockParam) implementsContentBlockParamUnion() {}
-
-type DocumentBlockParamSource struct {
- Type param.Field[DocumentBlockParamSourceType] `json:"type,required"`
- Content param.Field[interface{}] `json:"content"`
- Data param.Field[string] `json:"data" format:"byte"`
- MediaType param.Field[DocumentBlockParamSourceMediaType] `json:"media_type"`
- URL param.Field[string] `json:"url"`
-}
-
-func (r DocumentBlockParamSource) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r DocumentBlockParamSource) implementsDocumentBlockParamSourceUnion() {}
-
-// Satisfied by [Base64PDFSourceParam], [PlainTextSourceParam],
-// [ContentBlockSourceParam], [URLPDFSourceParam], [DocumentBlockParamSource].
-type DocumentBlockParamSourceUnion interface {
- implementsDocumentBlockParamSourceUnion()
-}
-
-type DocumentBlockParamSourceType string
-
-const (
- DocumentBlockParamSourceTypeBase64 DocumentBlockParamSourceType = "base64"
- DocumentBlockParamSourceTypeText DocumentBlockParamSourceType = "text"
- DocumentBlockParamSourceTypeContent DocumentBlockParamSourceType = "content"
- DocumentBlockParamSourceTypeURL DocumentBlockParamSourceType = "url"
-)
-
-func (r DocumentBlockParamSourceType) IsKnown() bool {
- switch r {
- case DocumentBlockParamSourceTypeBase64, DocumentBlockParamSourceTypeText, DocumentBlockParamSourceTypeContent, DocumentBlockParamSourceTypeURL:
- return true
- }
- return false
-}
-
-type DocumentBlockParamSourceMediaType string
-
-const (
- DocumentBlockParamSourceMediaTypeApplicationPDF DocumentBlockParamSourceMediaType = "application/pdf"
- DocumentBlockParamSourceMediaTypeTextPlain DocumentBlockParamSourceMediaType = "text/plain"
-)
-
-func (r DocumentBlockParamSourceMediaType) IsKnown() bool {
- switch r {
- case DocumentBlockParamSourceMediaTypeApplicationPDF, DocumentBlockParamSourceMediaTypeTextPlain:
- return true
- }
- return false
-}
-
-type DocumentBlockParamType string
-
-const (
- DocumentBlockParamTypeDocument DocumentBlockParamType = "document"
-)
-
-func (r DocumentBlockParamType) IsKnown() bool {
- switch r {
- case DocumentBlockParamTypeDocument:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u ImageBlockParamSourceUnion) GetData() *string {
+ if vt := u.OfBase64ImageSource; vt != nil {
+ return &vt.Data
}
- return false
-}
-
-type ImageBlockParam struct {
- Source param.Field[ImageBlockParamSourceUnion] `json:"source,required"`
- Type param.Field[ImageBlockParamType] `json:"type,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
+ return nil
}
-func NewImageBlockBase64(mediaType string, encodedData string) ImageBlockParam {
- return ImageBlockParam{
- Type: F(ImageBlockParamTypeImage),
- Source: F(ImageBlockParamSourceUnion(ImageBlockParamSource{
- Type: F(ImageBlockParamSourceTypeBase64),
- Data: F(encodedData),
- MediaType: F(ImageBlockParamSourceMediaType(mediaType)),
- })),
+// Returns a pointer to the underlying variant's property, if present.
+func (u ImageBlockParamSourceUnion) GetMediaType() *string {
+ if vt := u.OfBase64ImageSource; vt != nil {
+ return (*string)(&vt.MediaType)
}
+ return nil
}
-func (r ImageBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r ImageBlockParam) implementsContentBlockParamUnion() {}
-
-func (r ImageBlockParam) implementsContentBlockSourceContentUnionParam() {}
-
-func (r ImageBlockParam) implementsToolResultBlockParamContentUnion() {}
-
-type ImageBlockParamSource struct {
- Type param.Field[ImageBlockParamSourceType] `json:"type,required"`
- Data param.Field[string] `json:"data" format:"byte"`
- MediaType param.Field[ImageBlockParamSourceMediaType] `json:"media_type"`
- URL param.Field[string] `json:"url"`
-}
-
-func (r ImageBlockParamSource) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r ImageBlockParamSource) implementsImageBlockParamSourceUnion() {}
-
-// Satisfied by [Base64ImageSourceParam], [URLImageSourceParam],
-// [ImageBlockParamSource].
-type ImageBlockParamSourceUnion interface {
- implementsImageBlockParamSourceUnion()
-}
-
-type ImageBlockParamSourceType string
-
-const (
- ImageBlockParamSourceTypeBase64 ImageBlockParamSourceType = "base64"
- ImageBlockParamSourceTypeURL ImageBlockParamSourceType = "url"
-)
-
-func (r ImageBlockParamSourceType) IsKnown() bool {
- switch r {
- case ImageBlockParamSourceTypeBase64, ImageBlockParamSourceTypeURL:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u ImageBlockParamSourceUnion) GetURL() *string {
+ if vt := u.OfURLImageSource; vt != nil {
+ return &vt.URL
}
- return false
+ return nil
}
-type ImageBlockParamSourceMediaType string
-
-const (
- ImageBlockParamSourceMediaTypeImageJPEG ImageBlockParamSourceMediaType = "image/jpeg"
- ImageBlockParamSourceMediaTypeImagePNG ImageBlockParamSourceMediaType = "image/png"
- ImageBlockParamSourceMediaTypeImageGIF ImageBlockParamSourceMediaType = "image/gif"
- ImageBlockParamSourceMediaTypeImageWebP ImageBlockParamSourceMediaType = "image/webp"
-)
-
-func (r ImageBlockParamSourceMediaType) IsKnown() bool {
- switch r {
- case ImageBlockParamSourceMediaTypeImageJPEG, ImageBlockParamSourceMediaTypeImagePNG, ImageBlockParamSourceMediaTypeImageGIF, ImageBlockParamSourceMediaTypeImageWebP:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u ImageBlockParamSourceUnion) GetType() *string {
+ if vt := u.OfBase64ImageSource; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfURLImageSource; vt != nil {
+ return (*string)(&vt.Type)
}
- return false
+ return nil
}
-type ImageBlockParamType string
-
-const (
- ImageBlockParamTypeImage ImageBlockParamType = "image"
-)
-
-func (r ImageBlockParamType) IsKnown() bool {
- switch r {
- case ImageBlockParamTypeImage:
- return true
- }
- return false
+func init() {
+ apijson.RegisterUnion[ImageBlockParamSourceUnion](
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(Base64ImageSourceParam{}),
+ DiscriminatorValue: "base64",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(URLImageSourceParam{}),
+ DiscriminatorValue: "url",
+ },
+ )
}
type InputJSONDelta struct {
- PartialJSON string `json:"partial_json,required"`
- Type InputJSONDeltaType `json:"type,required"`
- JSON inputJSONDeltaJSON `json:"-"`
-}
-
-// inputJSONDeltaJSON contains the JSON metadata for the struct [InputJSONDelta]
-type inputJSONDeltaJSON struct {
- PartialJSON apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *InputJSONDelta) UnmarshalJSON(data []byte) (err error) {
+ PartialJSON string `json:"partial_json,required"`
+ Type constant.InputJSONDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ PartialJSON resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r InputJSONDelta) RawJSON() string { return r.JSON.raw }
+func (r *InputJSONDelta) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r inputJSONDeltaJSON) RawJSON() string {
- return r.raw
-}
-
-func (r InputJSONDelta) implementsContentBlockDeltaEventDelta() {}
-
-type InputJSONDeltaType string
-
-const (
- InputJSONDeltaTypeInputJSONDelta InputJSONDeltaType = "input_json_delta"
-)
-
-func (r InputJSONDeltaType) IsKnown() bool {
- switch r {
- case InputJSONDeltaTypeInputJSONDelta:
- return true
- }
- return false
-}
-
-// Accumulate builds up the Message incrementally from a MessageStreamEvent. The Message then can be used as
-// any other Message, except with the caveat that the Message.JSON field which normally can be used to inspect
-// the JSON sent over the network may not be populated fully.
-//
-// message := anthropic.Message{}
-// for stream.Next() {
-// event := stream.Current()
-// message.Accumulate(event)
-// }
-func (a *Message) Accumulate(event MessageStreamEvent) error {
- if a == nil {
- *a = Message{}
- }
-
- switch event := event.AsUnion().(type) {
- case MessageStartEvent:
- *a = event.Message
-
- case MessageDeltaEvent:
- a.StopReason = MessageStopReason(event.Delta.StopReason)
- a.JSON.StopReason = event.Delta.JSON.StopReason
- a.StopSequence = event.Delta.StopSequence
- a.JSON.StopSequence = event.Delta.JSON.StopSequence
- a.Usage.OutputTokens = event.Usage.OutputTokens
- a.Usage.JSON.OutputTokens = event.Usage.JSON.OutputTokens
-
- case MessageStopEvent:
-
- case ContentBlockStartEvent:
- a.Content = append(a.Content, ContentBlock{})
- err := a.Content[len(a.Content)-1].UnmarshalJSON([]byte(event.ContentBlock.JSON.RawJSON()))
- if err != nil {
- return err
- }
-
- case ContentBlockDeltaEvent:
- if len(a.Content) == 0 {
- return fmt.Errorf("received event of type %s but there was no content block", event.Type)
- }
- switch delta := event.Delta.AsUnion().(type) {
- case TextDelta:
- cb := &a.Content[len(a.Content)-1]
- cb.Text += delta.Text
- if tb, ok := cb.union.(TextBlock); ok {
- tb.Text = cb.Text
- cb.union = tb
- }
-
- case InputJSONDelta:
- cb := &a.Content[len(a.Content)-1]
- if string(cb.Input) == "{}" {
- cb.Input = json.RawMessage{}
- }
- cb.Input = append(cb.Input, []byte(delta.PartialJSON)...)
- if tb, ok := cb.union.(ToolUseBlock); ok {
- tb.Input = cb.Input
- cb.union = tb
- }
- case ThinkingDelta:
- cb := &a.Content[len(a.Content)-1]
- cb.Thinking += delta.Thinking
- if tb, ok := cb.union.(ThinkingBlock); ok {
- tb.Thinking = cb.Thinking
- cb.union = tb
- }
- case SignatureDelta:
- cb := &a.Content[len(a.Content)-1]
- cb.Signature += delta.Signature
- if tb, ok := cb.union.(ThinkingBlock); ok {
- tb.Signature = cb.Signature
- cb.union = tb
- }
- }
-
- case ContentBlockStopEvent:
- if len(a.Content) == 0 {
- return fmt.Errorf("received event of type %s but there was no content block", event.Type)
- }
- }
-
- return nil
-}
-
-// ToParam converts a Message to a MessageParam, which can be used when constructing a new
-// Create
type Message struct {
// Unique object identifier.
//
@@ -1127,7 +1279,7 @@ type Message struct {
// ```json
// [{ "type": "text", "text": "B)" }]
// ```
- Content []ContentBlock `json:"content,required"`
+ Content []ContentBlockUnion `json:"content,required"`
// The model that will complete your prompt.\n\nSee
// [models](https://docs.anthropic.com/en/docs/models-overview) for additional
// details and options.
@@ -1135,7 +1287,7 @@ type Message struct {
// Conversational role of the generated message.
//
// This will always be `"assistant"`.
- Role MessageRole `json:"role,required"`
+ Role constant.Assistant `json:"role,required"`
// The reason that we stopped.
//
// This may be one the following values:
@@ -1147,16 +1299,18 @@ type Message struct {
//
// In non-streaming mode this value is always non-null. In streaming mode, it is
// null in the `message_start` event and non-null otherwise.
- StopReason MessageStopReason `json:"stop_reason,required,nullable"`
+ //
+ // Any of "end_turn", "max_tokens", "stop_sequence", "tool_use".
+ StopReason MessageStopReason `json:"stop_reason,required"`
// Which custom stop sequence was generated, if any.
//
// This value will be a non-null string if one of your custom stop sequences was
// generated.
- StopSequence string `json:"stop_sequence,required,nullable"`
+ StopSequence string `json:"stop_sequence,required"`
// Object type.
//
// For Messages, this is always `"message"`.
- Type MessageType `json:"type,required"`
+ Type constant.Message `json:"type,required"`
// Billing and rate-limit usage.
//
// Anthropic's API bills and rate-limits by token counts, as tokens represent the
@@ -1172,111 +1326,37 @@ type Message struct {
//
// Total input tokens in a request is the summation of `input_tokens`,
// `cache_creation_input_tokens`, and `cache_read_input_tokens`.
- Usage Usage `json:"usage,required"`
- JSON messageJSON `json:"-"`
-}
-
-// messageJSON contains the JSON metadata for the struct [Message]
-type messageJSON struct {
- ID apijson.Field
- Content apijson.Field
- Model apijson.Field
- Role apijson.Field
- StopReason apijson.Field
- StopSequence apijson.Field
- Type apijson.Field
- Usage apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-// ToParam converts a Message to a MessageParam which can be used when making another network
-// request. This is useful when interacting with Claude conversationally or when tool calling.
-//
-// messages := []anthropic.MessageParam{
-// anthropic.NewUserMessage(anthropic.NewTextBlock("What is my first name?")),
-// }
-//
-// message, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
-// MaxTokens: anthropic.F(int64(1024)),
-// Messages: anthropic.F(messages),
-// Model: anthropic.F(anthropic.ModelClaude_3_5_Sonnet_20240620),
-// })
-//
-// messages = append(messages, message.ToParam())
-// messages = append(messages, anthropic.NewUserMessage(
-// anthropic.NewTextBlock("My full name is John Doe"),
-// ))
-//
-// message, err = client.Messages.New(context.TODO(), anthropic.MessageNewParams{
-// MaxTokens: anthropic.F(int64(1024)),
-// Messages: anthropic.F(messages),
-// Model: anthropic.F(anthropic.ModelClaude_3_5_Sonnet_20240620),
-// })
-func (r *Message) ToParam() MessageParam {
- content := []ContentBlockParamUnion{}
-
- for _, block := range r.Content {
- content = append(content, ContentBlockParam{
- Type: F(ContentBlockParamType(block.Type)),
- ID: param.Field[string]{
- Value: block.ID,
- Present: !block.JSON.ID.IsNull(),
- },
- Text: param.Field[string]{
- Value: block.Text,
- Present: !block.JSON.Text.IsNull(),
- },
- Name: param.Field[string]{
- Value: block.Name,
- Present: !block.JSON.Name.IsNull(),
- },
- Input: param.Field[interface{}]{
- Value: block.Input,
- Present: len(block.Input) > 0 && !block.JSON.Input.IsNull(),
- },
- Thinking: param.Field[string]{
- Value: block.Thinking,
- Present: !block.JSON.Thinking.IsNull(),
- },
- Signature: param.Field[string]{
- Value: block.Signature,
- Present: !block.JSON.Signature.IsNull(),
- },
- })
- }
-
- message := MessageParam{
- Role: F(MessageParamRole(r.Role)),
- Content: F(content),
- }
-
- return message
-}
-
-func (r *Message) UnmarshalJSON(data []byte) (err error) {
+ Usage Usage `json:"usage,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ Content resp.Field
+ Model resp.Field
+ Role resp.Field
+ StopReason resp.Field
+ StopSequence resp.Field
+ Type resp.Field
+ Usage resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r Message) RawJSON() string { return r.JSON.raw }
+func (r *Message) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageJSON) RawJSON() string {
- return r.raw
-}
-
-// Conversational role of the generated message.
-//
-// This will always be `"assistant"`.
-type MessageRole string
-
-const (
- MessageRoleAssistant MessageRole = "assistant"
-)
-
-func (r MessageRole) IsKnown() bool {
- switch r {
- case MessageRoleAssistant:
- return true
+func (r Message) ToParam() MessageParam {
+ var p MessageParam
+ p.Role = MessageParamRole(r.Role)
+ p.Content = make([]ContentBlockParamUnion, len(r.Content))
+ for i, c := range r.Content {
+ p.Content[i] = c.ToParam()
}
- return false
+ return p
}
// The reason that we stopped.
@@ -1299,118 +1379,137 @@ const (
MessageStopReasonToolUse MessageStopReason = "tool_use"
)
-func (r MessageStopReason) IsKnown() bool {
- switch r {
- case MessageStopReasonEndTurn, MessageStopReasonMaxTokens, MessageStopReasonStopSequence, MessageStopReasonToolUse:
- return true
- }
- return false
+func MessageCountTokensToolParamOfTool(inputSchema ToolInputSchemaParam, name string) MessageCountTokensToolUnionParam {
+ var variant ToolParam
+ variant.InputSchema = inputSchema
+ variant.Name = name
+ return MessageCountTokensToolUnionParam{OfTool: &variant}
}
-// Object type.
+// Only one field can be non-zero.
//
-// For Messages, this is always `"message"`.
-type MessageType string
+// Use [param.IsOmitted] to confirm if a field is set.
+type MessageCountTokensToolUnionParam struct {
+ OfTool *ToolParam `json:",omitzero,inline"`
+ OfBashTool20250124 *ToolBash20250124Param `json:",omitzero,inline"`
+ OfTextEditor20250124 *ToolTextEditor20250124Param `json:",omitzero,inline"`
+ paramUnion
+}
-const (
- MessageTypeMessage MessageType = "message"
-)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u MessageCountTokensToolUnionParam) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u MessageCountTokensToolUnionParam) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[MessageCountTokensToolUnionParam](u.OfTool, u.OfBashTool20250124, u.OfTextEditor20250124)
+}
-func (r MessageType) IsKnown() bool {
- switch r {
- case MessageTypeMessage:
- return true
+func (u *MessageCountTokensToolUnionParam) asAny() any {
+ if !param.IsOmitted(u.OfTool) {
+ return u.OfTool
+ } else if !param.IsOmitted(u.OfBashTool20250124) {
+ return u.OfBashTool20250124
+ } else if !param.IsOmitted(u.OfTextEditor20250124) {
+ return u.OfTextEditor20250124
}
- return false
+ return nil
}
-type MessageCountTokensToolParam struct {
- // Name of the tool.
- //
- // This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[string] `json:"name,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
- // Description of what this tool does.
- //
- // Tool descriptions should be as detailed as possible. The more information that
- // the model has about what the tool is and how to use it, the better it will
- // perform. You can use natural language descriptions to reinforce important
- // aspects of the tool input JSON schema.
- Description param.Field[string] `json:"description"`
- InputSchema param.Field[interface{}] `json:"input_schema"`
- Type param.Field[MessageCountTokensToolType] `json:"type"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u MessageCountTokensToolUnionParam) GetInputSchema() *ToolInputSchemaParam {
+ if vt := u.OfTool; vt != nil {
+ return &vt.InputSchema
+ }
+ return nil
}
-func (r MessageCountTokensToolParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u MessageCountTokensToolUnionParam) GetDescription() *string {
+ if vt := u.OfTool; vt != nil && vt.Description.IsPresent() {
+ return &vt.Description.Value
+ }
+ return nil
}
-func (r MessageCountTokensToolParam) implementsMessageCountTokensToolUnionParam() {}
-
-// Satisfied by [ToolParam], [ToolBash20250124Param],
-// [ToolTextEditor20250124Param], [MessageCountTokensToolParam].
-type MessageCountTokensToolUnionParam interface {
- implementsMessageCountTokensToolUnionParam()
+// Returns a pointer to the underlying variant's property, if present.
+func (u MessageCountTokensToolUnionParam) GetName() *string {
+ if vt := u.OfTool; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfBashTool20250124; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return (*string)(&vt.Name)
+ }
+ return nil
}
-type MessageCountTokensToolType string
-
-const (
- MessageCountTokensToolTypeBash20250124 MessageCountTokensToolType = "bash_20250124"
- MessageCountTokensToolTypeTextEditor20250124 MessageCountTokensToolType = "text_editor_20250124"
-)
+// Returns a pointer to the underlying variant's property, if present.
+func (u MessageCountTokensToolUnionParam) GetType() *string {
+ if vt := u.OfBashTool20250124; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
+}
-func (r MessageCountTokensToolType) IsKnown() bool {
- switch r {
- case MessageCountTokensToolTypeBash20250124, MessageCountTokensToolTypeTextEditor20250124:
- return true
+// Returns a pointer to the underlying variant's CacheControl property, if present.
+func (u MessageCountTokensToolUnionParam) GetCacheControl() *CacheControlEphemeralParam {
+ if vt := u.OfTool; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfBashTool20250124; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return &vt.CacheControl
}
- return false
+ return nil
}
type MessageDeltaUsage struct {
// The cumulative number of output tokens which were used.
- OutputTokens int64 `json:"output_tokens,required"`
- JSON messageDeltaUsageJSON `json:"-"`
-}
-
-// messageDeltaUsageJSON contains the JSON metadata for the struct
-// [MessageDeltaUsage]
-type messageDeltaUsageJSON struct {
- OutputTokens apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageDeltaUsage) UnmarshalJSON(data []byte) (err error) {
+ OutputTokens int64 `json:"output_tokens,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ OutputTokens resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageDeltaUsage) RawJSON() string { return r.JSON.raw }
+func (r *MessageDeltaUsage) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageDeltaUsageJSON) RawJSON() string {
- return r.raw
-}
-
+// The properties Content, Role are required.
type MessageParam struct {
- Content param.Field[[]ContentBlockParamUnion] `json:"content,required"`
- Role param.Field[MessageParamRole] `json:"role,required"`
+ Content []ContentBlockParamUnion `json:"content,omitzero,required"`
+ // Any of "user", "assistant".
+ Role MessageParamRole `json:"role,omitzero,required"`
+ paramObj
}
func NewUserMessage(blocks ...ContentBlockParamUnion) MessageParam {
return MessageParam{
- Role: F(MessageParamRoleUser),
- Content: F(blocks),
+ Role: MessageParamRoleUser,
+ Content: blocks,
}
}
func NewAssistantMessage(blocks ...ContentBlockParamUnion) MessageParam {
return MessageParam{
- Role: F(MessageParamRoleAssistant),
- Content: F(blocks),
+ Role: MessageParamRoleAssistant,
+ Content: blocks,
}
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f MessageParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r MessageParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow MessageParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
type MessageParamRole string
@@ -1420,48 +1519,41 @@ const (
MessageParamRoleAssistant MessageParamRole = "assistant"
)
-func (r MessageParamRole) IsKnown() bool {
- switch r {
- case MessageParamRoleUser, MessageParamRoleAssistant:
- return true
- }
- return false
-}
-
type MessageTokensCount struct {
// The total number of tokens across the provided list of messages, system prompt,
// and tools.
- InputTokens int64 `json:"input_tokens,required"`
- JSON messageTokensCountJSON `json:"-"`
-}
-
-// messageTokensCountJSON contains the JSON metadata for the struct
-// [MessageTokensCount]
-type messageTokensCountJSON struct {
- InputTokens apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageTokensCount) UnmarshalJSON(data []byte) (err error) {
+ InputTokens int64 `json:"input_tokens,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ InputTokens resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageTokensCount) RawJSON() string { return r.JSON.raw }
+func (r *MessageTokensCount) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageTokensCountJSON) RawJSON() string {
- return r.raw
-}
-
type MetadataParam struct {
// An external identifier for the user who is associated with the request.
//
// This should be a uuid, hash value, or other opaque identifier. Anthropic may use
// this id to help detect abuse. Do not include any identifying information such as
// name, email address, or phone number.
- UserID param.Field[string] `json:"user_id"`
+ UserID param.Opt[string] `json:"user_id,omitzero"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f MetadataParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r MetadataParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow MetadataParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
// The model that will complete your prompt.\n\nSee
@@ -1494,377 +1586,272 @@ const (
ModelClaude_2_0 Model = "claude-2.0"
)
+// The properties Data, MediaType, Type are required.
type PlainTextSourceParam struct {
- Data param.Field[string] `json:"data,required"`
- MediaType param.Field[PlainTextSourceMediaType] `json:"media_type,required"`
- Type param.Field[PlainTextSourceType] `json:"type,required"`
+ Data string `json:"data,required"`
+ // This field can be elided, and will marshal its zero value as "text/plain".
+ MediaType constant.TextPlain `json:"media_type,required"`
+ // This field can be elided, and will marshal its zero value as "text".
+ Type constant.Text `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f PlainTextSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r PlainTextSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow PlainTextSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r PlainTextSourceParam) implementsDocumentBlockParamSourceUnion() {}
-
-type PlainTextSourceMediaType string
-
-const (
- PlainTextSourceMediaTypeTextPlain PlainTextSourceMediaType = "text/plain"
-)
+type ContentBlockDeltaEvent struct {
+ Delta ContentBlockDeltaEventDeltaUnion `json:"delta,required"`
+ Index int64 `json:"index,required"`
+ Type constant.ContentBlockDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Delta resp.Field
+ Index resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r ContentBlockDeltaEvent) RawJSON() string { return r.JSON.raw }
+func (r *ContentBlockDeltaEvent) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-func (r PlainTextSourceMediaType) IsKnown() bool {
- switch r {
- case PlainTextSourceMediaTypeTextPlain:
- return true
+// ContentBlockDeltaEventDeltaUnion contains all possible properties and values
+// from [TextDelta], [InputJSONDelta], [CitationsDelta], [ThinkingDelta],
+// [SignatureDelta].
+//
+// Use the [ContentBlockDeltaEventDeltaUnion.AsAny] method to switch on the
+// variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type ContentBlockDeltaEventDeltaUnion struct {
+ // This field is from variant [TextDelta].
+ Text string `json:"text"`
+ // Any of "text_delta", "input_json_delta", "citations_delta", "thinking_delta",
+ // "signature_delta".
+ Type string `json:"type"`
+ // This field is from variant [InputJSONDelta].
+ PartialJSON string `json:"partial_json"`
+ // This field is from variant [CitationsDelta].
+ Citation CitationsDeltaCitationUnion `json:"citation"`
+ // This field is from variant [ThinkingDelta].
+ Thinking string `json:"thinking"`
+ // This field is from variant [SignatureDelta].
+ Signature string `json:"signature"`
+ JSON struct {
+ Text resp.Field
+ Type resp.Field
+ PartialJSON resp.Field
+ Citation resp.Field
+ Thinking resp.Field
+ Signature resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := ContentBlockDeltaEventDeltaUnion.AsAny().(type) {
+// case TextDelta:
+// case InputJSONDelta:
+// case CitationsDelta:
+// case ThinkingDelta:
+// case SignatureDelta:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u ContentBlockDeltaEventDeltaUnion) AsAny() any {
+ switch u.Type {
+ case "text_delta":
+ return u.AsTextContentBlockDelta()
+ case "input_json_delta":
+ return u.AsInputJSONContentBlockDelta()
+ case "citations_delta":
+ return u.AsCitationsDelta()
+ case "thinking_delta":
+ return u.AsThinkingContentBlockDelta()
+ case "signature_delta":
+ return u.AsSignatureContentBlockDelta()
}
- return false
+ return nil
}
-type PlainTextSourceType string
-
-const (
- PlainTextSourceTypeText PlainTextSourceType = "text"
-)
-
-func (r PlainTextSourceType) IsKnown() bool {
- switch r {
- case PlainTextSourceTypeText:
- return true
- }
- return false
+func (u ContentBlockDeltaEventDeltaUnion) AsTextContentBlockDelta() (v TextDelta) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type ContentBlockDeltaEvent struct {
- Delta ContentBlockDeltaEventDelta `json:"delta,required"`
- Index int64 `json:"index,required"`
- Type ContentBlockDeltaEventType `json:"type,required"`
- JSON contentBlockDeltaEventJSON `json:"-"`
+func (u ContentBlockDeltaEventDeltaUnion) AsInputJSONContentBlockDelta() (v InputJSONDelta) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// contentBlockDeltaEventJSON contains the JSON metadata for the struct
-// [ContentBlockDeltaEvent]
-type contentBlockDeltaEventJSON struct {
- Delta apijson.Field
- Index apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func (u ContentBlockDeltaEventDeltaUnion) AsCitationsDelta() (v CitationsDelta) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r *ContentBlockDeltaEvent) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+func (u ContentBlockDeltaEventDeltaUnion) AsThinkingContentBlockDelta() (v ThinkingDelta) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r contentBlockDeltaEventJSON) RawJSON() string {
- return r.raw
+func (u ContentBlockDeltaEventDeltaUnion) AsSignatureContentBlockDelta() (v SignatureDelta) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r ContentBlockDeltaEvent) implementsMessageStreamEvent() {}
+// Returns the unmodified JSON received from the API
+func (u ContentBlockDeltaEventDeltaUnion) RawJSON() string { return u.JSON.raw }
-type ContentBlockDeltaEventDelta struct {
- Type ContentBlockDeltaEventDeltaType `json:"type,required"`
- // This field can have the runtime type of [CitationsDeltaCitation].
- Citation interface{} `json:"citation"`
- PartialJSON string `json:"partial_json"`
- Signature string `json:"signature"`
- Text string `json:"text"`
- Thinking string `json:"thinking"`
- JSON contentBlockDeltaEventDeltaJSON `json:"-"`
- union ContentBlockDeltaEventDeltaUnion
+func (r *ContentBlockDeltaEventDeltaUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-// contentBlockDeltaEventDeltaJSON contains the JSON metadata for the struct
-// [ContentBlockDeltaEventDelta]
-type contentBlockDeltaEventDeltaJSON struct {
- Type apijson.Field
- Citation apijson.Field
- PartialJSON apijson.Field
- Signature apijson.Field
- Text apijson.Field
- Thinking apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+type ContentBlockStartEvent struct {
+ ContentBlock ContentBlockStartEventContentBlockUnion `json:"content_block,required"`
+ Index int64 `json:"index,required"`
+ Type constant.ContentBlockStart `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ContentBlock resp.Field
+ Index resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r ContentBlockStartEvent) RawJSON() string { return r.JSON.raw }
+func (r *ContentBlockStartEvent) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-func (r contentBlockDeltaEventDeltaJSON) RawJSON() string {
- return r.raw
-}
-
-func (r *ContentBlockDeltaEventDelta) UnmarshalJSON(data []byte) (err error) {
- *r = ContentBlockDeltaEventDelta{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
- }
- return apijson.Port(r.union, &r)
-}
-
-// AsUnion returns a [ContentBlockDeltaEventDeltaUnion] interface which you can
-// cast to the specific types for more type safety.
+// ContentBlockStartEventContentBlockUnion contains all possible properties and
+// values from [TextBlock], [ToolUseBlock], [ThinkingBlock],
+// [RedactedThinkingBlock].
//
-// Possible runtime types of the union are [TextDelta], [InputJSONDelta],
-// [CitationsDelta], [ThinkingDelta], [SignatureDelta].
-func (r ContentBlockDeltaEventDelta) AsUnion() ContentBlockDeltaEventDeltaUnion {
- return r.union
-}
-
-// Union satisfied by [TextDelta], [InputJSONDelta], [CitationsDelta],
-// [ThinkingDelta] or [SignatureDelta].
-type ContentBlockDeltaEventDeltaUnion interface {
- implementsContentBlockDeltaEventDelta()
-}
-
-func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*ContentBlockDeltaEventDeltaUnion)(nil)).Elem(),
- "type",
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(TextDelta{}),
- DiscriminatorValue: "text_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(InputJSONDelta{}),
- DiscriminatorValue: "input_json_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(CitationsDelta{}),
- DiscriminatorValue: "citations_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(ThinkingDelta{}),
- DiscriminatorValue: "thinking_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(SignatureDelta{}),
- DiscriminatorValue: "signature_delta",
- },
- )
-}
-
-type ContentBlockDeltaEventDeltaType string
-
-const (
- ContentBlockDeltaEventDeltaTypeTextDelta ContentBlockDeltaEventDeltaType = "text_delta"
- ContentBlockDeltaEventDeltaTypeInputJSONDelta ContentBlockDeltaEventDeltaType = "input_json_delta"
- ContentBlockDeltaEventDeltaTypeCitationsDelta ContentBlockDeltaEventDeltaType = "citations_delta"
- ContentBlockDeltaEventDeltaTypeThinkingDelta ContentBlockDeltaEventDeltaType = "thinking_delta"
- ContentBlockDeltaEventDeltaTypeSignatureDelta ContentBlockDeltaEventDeltaType = "signature_delta"
-)
-
-func (r ContentBlockDeltaEventDeltaType) IsKnown() bool {
- switch r {
- case ContentBlockDeltaEventDeltaTypeTextDelta, ContentBlockDeltaEventDeltaTypeInputJSONDelta, ContentBlockDeltaEventDeltaTypeCitationsDelta, ContentBlockDeltaEventDeltaTypeThinkingDelta, ContentBlockDeltaEventDeltaTypeSignatureDelta:
- return true
- }
- return false
-}
-
-type ContentBlockDeltaEventType string
-
-const (
- ContentBlockDeltaEventTypeContentBlockDelta ContentBlockDeltaEventType = "content_block_delta"
-)
-
-func (r ContentBlockDeltaEventType) IsKnown() bool {
- switch r {
- case ContentBlockDeltaEventTypeContentBlockDelta:
- return true
- }
- return false
-}
-
-type ContentBlockStartEvent struct {
- ContentBlock ContentBlockStartEventContentBlock `json:"content_block,required"`
- Index int64 `json:"index,required"`
- Type ContentBlockStartEventType `json:"type,required"`
- JSON contentBlockStartEventJSON `json:"-"`
-}
-
-// contentBlockStartEventJSON contains the JSON metadata for the struct
-// [ContentBlockStartEvent]
-type contentBlockStartEventJSON struct {
- ContentBlock apijson.Field
- Index apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *ContentBlockStartEvent) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
-}
-
-func (r contentBlockStartEventJSON) RawJSON() string {
- return r.raw
-}
-
-func (r ContentBlockStartEvent) implementsMessageStreamEvent() {}
-
-type ContentBlockStartEventContentBlock struct {
- Type ContentBlockStartEventContentBlockType `json:"type,required"`
- ID string `json:"id"`
- // This field can have the runtime type of [[]TextCitation].
- Citations interface{} `json:"citations"`
- Data string `json:"data"`
- // This field can have the runtime type of [interface{}].
- Input json.RawMessage `json:"input"`
- Name string `json:"name"`
- Signature string `json:"signature"`
- Text string `json:"text"`
- Thinking string `json:"thinking"`
- JSON contentBlockStartEventContentBlockJSON `json:"-"`
- union ContentBlockStartEventContentBlockUnion
-}
-
-// contentBlockStartEventContentBlockJSON contains the JSON metadata for the struct
-// [ContentBlockStartEventContentBlock]
-type contentBlockStartEventContentBlockJSON struct {
- Type apijson.Field
- ID apijson.Field
- Citations apijson.Field
- Data apijson.Field
- Input apijson.Field
- Name apijson.Field
- Signature apijson.Field
- Text apijson.Field
- Thinking apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r contentBlockStartEventContentBlockJSON) RawJSON() string {
- return r.raw
-}
-
-func (r *ContentBlockStartEventContentBlock) UnmarshalJSON(data []byte) (err error) {
- *r = ContentBlockStartEventContentBlock{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
+// Use the [ContentBlockStartEventContentBlockUnion.AsAny] method to switch on the
+// variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type ContentBlockStartEventContentBlockUnion struct {
+ // This field is from variant [TextBlock].
+ Citations []TextCitationUnion `json:"citations"`
+ // This field is from variant [TextBlock].
+ Text string `json:"text"`
+ // Any of "text", "tool_use", "thinking", "redacted_thinking".
+ Type string `json:"type"`
+ // This field is from variant [ToolUseBlock].
+ ID string `json:"id"`
+ // This field is from variant [ToolUseBlock].
+ Input interface{} `json:"input"`
+ // This field is from variant [ToolUseBlock].
+ Name string `json:"name"`
+ // This field is from variant [ThinkingBlock].
+ Signature string `json:"signature"`
+ // This field is from variant [ThinkingBlock].
+ Thinking string `json:"thinking"`
+ // This field is from variant [RedactedThinkingBlock].
+ Data string `json:"data"`
+ JSON struct {
+ Citations resp.Field
+ Text resp.Field
+ Type resp.Field
+ ID resp.Field
+ Input resp.Field
+ Name resp.Field
+ Signature resp.Field
+ Thinking resp.Field
+ Data resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := ContentBlockStartEventContentBlockUnion.AsAny().(type) {
+// case TextBlock:
+// case ToolUseBlock:
+// case ThinkingBlock:
+// case RedactedThinkingBlock:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u ContentBlockStartEventContentBlockUnion) AsAny() any {
+ switch u.Type {
+ case "text":
+ return u.AsResponseTextBlock()
+ case "tool_use":
+ return u.AsResponseToolUseBlock()
+ case "thinking":
+ return u.AsResponseThinkingBlock()
+ case "redacted_thinking":
+ return u.AsResponseRedactedThinkingBlock()
}
- return apijson.Port(r.union, &r)
+ return nil
}
-// AsUnion returns a [ContentBlockStartEventContentBlockUnion] interface which you
-// can cast to the specific types for more type safety.
-//
-// Possible runtime types of the union are [TextBlock], [ToolUseBlock],
-// [ThinkingBlock], [RedactedThinkingBlock].
-func (r ContentBlockStartEventContentBlock) AsUnion() ContentBlockStartEventContentBlockUnion {
- return r.union
+func (u ContentBlockStartEventContentBlockUnion) AsResponseTextBlock() (v TextBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// Union satisfied by [TextBlock], [ToolUseBlock], [ThinkingBlock] or
-// [RedactedThinkingBlock].
-type ContentBlockStartEventContentBlockUnion interface {
- implementsContentBlockStartEventContentBlock()
+func (u ContentBlockStartEventContentBlockUnion) AsResponseToolUseBlock() (v ToolUseBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*ContentBlockStartEventContentBlockUnion)(nil)).Elem(),
- "type",
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(TextBlock{}),
- DiscriminatorValue: "text",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(ToolUseBlock{}),
- DiscriminatorValue: "tool_use",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(ThinkingBlock{}),
- DiscriminatorValue: "thinking",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(RedactedThinkingBlock{}),
- DiscriminatorValue: "redacted_thinking",
- },
- )
+func (u ContentBlockStartEventContentBlockUnion) AsResponseThinkingBlock() (v ThinkingBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type ContentBlockStartEventContentBlockType string
-
-const (
- ContentBlockStartEventContentBlockTypeText ContentBlockStartEventContentBlockType = "text"
- ContentBlockStartEventContentBlockTypeToolUse ContentBlockStartEventContentBlockType = "tool_use"
- ContentBlockStartEventContentBlockTypeThinking ContentBlockStartEventContentBlockType = "thinking"
- ContentBlockStartEventContentBlockTypeRedactedThinking ContentBlockStartEventContentBlockType = "redacted_thinking"
-)
-
-func (r ContentBlockStartEventContentBlockType) IsKnown() bool {
- switch r {
- case ContentBlockStartEventContentBlockTypeText, ContentBlockStartEventContentBlockTypeToolUse, ContentBlockStartEventContentBlockTypeThinking, ContentBlockStartEventContentBlockTypeRedactedThinking:
- return true
- }
- return false
+func (u ContentBlockStartEventContentBlockUnion) AsResponseRedactedThinkingBlock() (v RedactedThinkingBlock) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type ContentBlockStartEventType string
+// Returns the unmodified JSON received from the API
+func (u ContentBlockStartEventContentBlockUnion) RawJSON() string { return u.JSON.raw }
-const (
- ContentBlockStartEventTypeContentBlockStart ContentBlockStartEventType = "content_block_start"
-)
-
-func (r ContentBlockStartEventType) IsKnown() bool {
- switch r {
- case ContentBlockStartEventTypeContentBlockStart:
- return true
- }
- return false
+func (r *ContentBlockStartEventContentBlockUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
type ContentBlockStopEvent struct {
Index int64 `json:"index,required"`
- Type ContentBlockStopEventType `json:"type,required"`
- JSON contentBlockStopEventJSON `json:"-"`
-}
-
-// contentBlockStopEventJSON contains the JSON metadata for the struct
-// [ContentBlockStopEvent]
-type contentBlockStopEventJSON struct {
- Index apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *ContentBlockStopEvent) UnmarshalJSON(data []byte) (err error) {
+ Type constant.ContentBlockStop `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Index resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r ContentBlockStopEvent) RawJSON() string { return r.JSON.raw }
+func (r *ContentBlockStopEvent) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r contentBlockStopEventJSON) RawJSON() string {
- return r.raw
-}
-
-func (r ContentBlockStopEvent) implementsMessageStreamEvent() {}
-
-type ContentBlockStopEventType string
-
-const (
- ContentBlockStopEventTypeContentBlockStop ContentBlockStopEventType = "content_block_stop"
-)
-
-func (r ContentBlockStopEventType) IsKnown() bool {
- switch r {
- case ContentBlockStopEventTypeContentBlockStop:
- return true
- }
- return false
-}
-
type MessageDeltaEvent struct {
Delta MessageDeltaEventDelta `json:"delta,required"`
- Type MessageDeltaEventType `json:"type,required"`
+ Type constant.MessageDelta `json:"type,required"`
// Billing and rate-limit usage.
//
// Anthropic's API bills and rate-limits by token counts, as tokens represent the
@@ -1880,744 +1867,748 @@ type MessageDeltaEvent struct {
//
// Total input tokens in a request is the summation of `input_tokens`,
// `cache_creation_input_tokens`, and `cache_read_input_tokens`.
- Usage MessageDeltaUsage `json:"usage,required"`
- JSON messageDeltaEventJSON `json:"-"`
-}
-
-// messageDeltaEventJSON contains the JSON metadata for the struct
-// [MessageDeltaEvent]
-type messageDeltaEventJSON struct {
- Delta apijson.Field
- Type apijson.Field
- Usage apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageDeltaEvent) UnmarshalJSON(data []byte) (err error) {
+ Usage MessageDeltaUsage `json:"usage,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Delta resp.Field
+ Type resp.Field
+ Usage resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageDeltaEvent) RawJSON() string { return r.JSON.raw }
+func (r *MessageDeltaEvent) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageDeltaEventJSON) RawJSON() string {
- return r.raw
-}
-
-func (r MessageDeltaEvent) implementsMessageStreamEvent() {}
-
type MessageDeltaEventDelta struct {
- StopReason MessageDeltaEventDeltaStopReason `json:"stop_reason,required,nullable"`
- StopSequence string `json:"stop_sequence,required,nullable"`
- JSON messageDeltaEventDeltaJSON `json:"-"`
-}
-
-// messageDeltaEventDeltaJSON contains the JSON metadata for the struct
-// [MessageDeltaEventDelta]
-type messageDeltaEventDeltaJSON struct {
- StopReason apijson.Field
- StopSequence apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageDeltaEventDelta) UnmarshalJSON(data []byte) (err error) {
+ // Any of "end_turn", "max_tokens", "stop_sequence", "tool_use".
+ StopReason string `json:"stop_reason,required"`
+ StopSequence string `json:"stop_sequence,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ StopReason resp.Field
+ StopSequence resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageDeltaEventDelta) RawJSON() string { return r.JSON.raw }
+func (r *MessageDeltaEventDelta) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageDeltaEventDeltaJSON) RawJSON() string {
- return r.raw
-}
-
-type MessageDeltaEventDeltaStopReason string
-
-const (
- MessageDeltaEventDeltaStopReasonEndTurn MessageDeltaEventDeltaStopReason = "end_turn"
- MessageDeltaEventDeltaStopReasonMaxTokens MessageDeltaEventDeltaStopReason = "max_tokens"
- MessageDeltaEventDeltaStopReasonStopSequence MessageDeltaEventDeltaStopReason = "stop_sequence"
- MessageDeltaEventDeltaStopReasonToolUse MessageDeltaEventDeltaStopReason = "tool_use"
-)
-
-func (r MessageDeltaEventDeltaStopReason) IsKnown() bool {
- switch r {
- case MessageDeltaEventDeltaStopReasonEndTurn, MessageDeltaEventDeltaStopReasonMaxTokens, MessageDeltaEventDeltaStopReasonStopSequence, MessageDeltaEventDeltaStopReasonToolUse:
- return true
- }
- return false
-}
-
-type MessageDeltaEventType string
-
-const (
- MessageDeltaEventTypeMessageDelta MessageDeltaEventType = "message_delta"
-)
-
-func (r MessageDeltaEventType) IsKnown() bool {
- switch r {
- case MessageDeltaEventTypeMessageDelta:
- return true
- }
- return false
-}
-
type MessageStartEvent struct {
Message Message `json:"message,required"`
- Type MessageStartEventType `json:"type,required"`
- JSON messageStartEventJSON `json:"-"`
-}
-
-// messageStartEventJSON contains the JSON metadata for the struct
-// [MessageStartEvent]
-type messageStartEventJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageStartEvent) UnmarshalJSON(data []byte) (err error) {
+ Type constant.MessageStart `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageStartEvent) RawJSON() string { return r.JSON.raw }
+func (r *MessageStartEvent) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageStartEventJSON) RawJSON() string {
- return r.raw
+type MessageStopEvent struct {
+ Type constant.MessageStop `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageStopEvent) RawJSON() string { return r.JSON.raw }
+func (r *MessageStopEvent) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-func (r MessageStartEvent) implementsMessageStreamEvent() {}
-
-type MessageStartEventType string
-
-const (
- MessageStartEventTypeMessageStart MessageStartEventType = "message_start"
-)
-
-func (r MessageStartEventType) IsKnown() bool {
- switch r {
- case MessageStartEventTypeMessageStart:
- return true
+// MessageStreamEventUnion contains all possible properties and values from
+// [MessageStartEvent], [MessageDeltaEvent], [MessageStopEvent],
+// [ContentBlockStartEvent], [ContentBlockDeltaEvent], [ContentBlockStopEvent].
+//
+// Use the [MessageStreamEventUnion.AsAny] method to switch on the variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type MessageStreamEventUnion struct {
+ // This field is from variant [MessageStartEvent].
+ Message Message `json:"message"`
+ // Any of "message_start", "message_delta", "message_stop", "content_block_start",
+ // "content_block_delta", "content_block_stop".
+ Type string `json:"type"`
+ // This field is a union of [MessageDeltaEventDelta],
+ // [ContentBlockDeltaEventDeltaUnion]
+ Delta MessageStreamEventUnionDelta `json:"delta"`
+ // This field is from variant [MessageDeltaEvent].
+ Usage MessageDeltaUsage `json:"usage"`
+ // This field is from variant [ContentBlockStartEvent].
+ ContentBlock ContentBlockStartEventContentBlockUnion `json:"content_block"`
+ Index int64 `json:"index"`
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ Delta resp.Field
+ Usage resp.Field
+ ContentBlock resp.Field
+ Index resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := MessageStreamEventUnion.AsAny().(type) {
+// case MessageStartEvent:
+// case MessageDeltaEvent:
+// case MessageStopEvent:
+// case ContentBlockStartEvent:
+// case ContentBlockDeltaEvent:
+// case ContentBlockStopEvent:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u MessageStreamEventUnion) AsAny() any {
+ switch u.Type {
+ case "message_start":
+ return u.AsMessageStartEvent()
+ case "message_delta":
+ return u.AsMessageDeltaEvent()
+ case "message_stop":
+ return u.AsMessageStopEvent()
+ case "content_block_start":
+ return u.AsContentBlockStartEvent()
+ case "content_block_delta":
+ return u.AsContentBlockDeltaEvent()
+ case "content_block_stop":
+ return u.AsContentBlockStopEvent()
}
- return false
-}
-
-type MessageStopEvent struct {
- Type MessageStopEventType `json:"type,required"`
- JSON messageStopEventJSON `json:"-"`
+ return nil
}
-// messageStopEventJSON contains the JSON metadata for the struct
-// [MessageStopEvent]
-type messageStopEventJSON struct {
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func (u MessageStreamEventUnion) AsMessageStartEvent() (v MessageStartEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r *MessageStopEvent) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+func (u MessageStreamEventUnion) AsMessageDeltaEvent() (v MessageDeltaEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r messageStopEventJSON) RawJSON() string {
- return r.raw
+func (u MessageStreamEventUnion) AsMessageStopEvent() (v MessageStopEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r MessageStopEvent) implementsMessageStreamEvent() {}
-
-type MessageStopEventType string
-
-const (
- MessageStopEventTypeMessageStop MessageStopEventType = "message_stop"
-)
-
-func (r MessageStopEventType) IsKnown() bool {
- switch r {
- case MessageStopEventTypeMessageStop:
- return true
- }
- return false
+func (u MessageStreamEventUnion) AsContentBlockStartEvent() (v ContentBlockStartEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type MessageStreamEvent struct {
- Type MessageStreamEventType `json:"type,required"`
- // This field can have the runtime type of [ContentBlockStartEventContentBlock].
- ContentBlock interface{} `json:"content_block"`
- // This field can have the runtime type of [MessageDeltaEventDelta],
- // [ContentBlockDeltaEventDelta].
- Delta interface{} `json:"delta"`
- Index int64 `json:"index"`
- Message Message `json:"message"`
- // Billing and rate-limit usage.
- //
- // Anthropic's API bills and rate-limits by token counts, as tokens represent the
- // underlying cost to our systems.
- //
- // Under the hood, the API transforms requests into a format suitable for the
- // model. The model's output then goes through a parsing stage before becoming an
- // API response. As a result, the token counts in `usage` will not match one-to-one
- // with the exact visible content of an API request or response.
- //
- // For example, `output_tokens` will be non-zero, even for an empty string response
- // from Claude.
- //
- // Total input tokens in a request is the summation of `input_tokens`,
- // `cache_creation_input_tokens`, and `cache_read_input_tokens`.
- Usage MessageDeltaUsage `json:"usage"`
- JSON messageStreamEventJSON `json:"-"`
- union MessageStreamEventUnion
+func (u MessageStreamEventUnion) AsContentBlockDeltaEvent() (v ContentBlockDeltaEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// messageStreamEventJSON contains the JSON metadata for the struct
-// [MessageStreamEvent]
-type messageStreamEventJSON struct {
- Type apijson.Field
- ContentBlock apijson.Field
- Delta apijson.Field
- Index apijson.Field
- Message apijson.Field
- Usage apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func (u MessageStreamEventUnion) AsContentBlockStopEvent() (v ContentBlockStopEvent) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r messageStreamEventJSON) RawJSON() string {
- return r.raw
-}
+// Returns the unmodified JSON received from the API
+func (u MessageStreamEventUnion) RawJSON() string { return u.JSON.raw }
-func (r *MessageStreamEvent) UnmarshalJSON(data []byte) (err error) {
- *r = MessageStreamEvent{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
- }
- return apijson.Port(r.union, &r)
+func (r *MessageStreamEventUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-// AsUnion returns a [MessageStreamEventUnion] interface which you can cast to the
-// specific types for more type safety.
+// MessageStreamEventUnionDelta is an implicit subunion of
+// [MessageStreamEventUnion]. MessageStreamEventUnionDelta provides convenient
+// access to the sub-properties of the union.
//
-// Possible runtime types of the union are [MessageStartEvent],
-// [MessageDeltaEvent], [MessageStopEvent], [ContentBlockStartEvent],
-// [ContentBlockDeltaEvent], [ContentBlockStopEvent].
-func (r MessageStreamEvent) AsUnion() MessageStreamEventUnion {
- return r.union
-}
-
-// Union satisfied by [MessageStartEvent], [MessageDeltaEvent], [MessageStopEvent],
-// [ContentBlockStartEvent], [ContentBlockDeltaEvent] or [ContentBlockStopEvent].
-type MessageStreamEventUnion interface {
- implementsMessageStreamEvent()
-}
-
-func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*MessageStreamEventUnion)(nil)).Elem(),
- "type",
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(MessageStartEvent{}),
- DiscriminatorValue: "message_start",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(MessageDeltaEvent{}),
- DiscriminatorValue: "message_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(MessageStopEvent{}),
- DiscriminatorValue: "message_stop",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(ContentBlockStartEvent{}),
- DiscriminatorValue: "content_block_start",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(ContentBlockDeltaEvent{}),
- DiscriminatorValue: "content_block_delta",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(ContentBlockStopEvent{}),
- DiscriminatorValue: "content_block_stop",
- },
- )
+// For type safety it is recommended to directly use a variant of the
+// [MessageStreamEventUnion].
+type MessageStreamEventUnionDelta struct {
+ // This field is from variant [MessageDeltaEventDelta].
+ StopReason string `json:"stop_reason"`
+ // This field is from variant [MessageDeltaEventDelta].
+ StopSequence string `json:"stop_sequence"`
+ // This field is from variant [ContentBlockDeltaEventDeltaUnion].
+ Text string `json:"text"`
+ Type string `json:"type"`
+ // This field is from variant [ContentBlockDeltaEventDeltaUnion].
+ PartialJSON string `json:"partial_json"`
+ // This field is from variant [ContentBlockDeltaEventDeltaUnion].
+ Citation CitationsDeltaCitationUnion `json:"citation"`
+ // This field is from variant [ContentBlockDeltaEventDeltaUnion].
+ Thinking string `json:"thinking"`
+ // This field is from variant [ContentBlockDeltaEventDeltaUnion].
+ Signature string `json:"signature"`
+ JSON struct {
+ StopReason resp.Field
+ StopSequence resp.Field
+ Text resp.Field
+ Type resp.Field
+ PartialJSON resp.Field
+ Citation resp.Field
+ Thinking resp.Field
+ Signature resp.Field
+ raw string
+ } `json:"-"`
+}
+
+func (r *MessageStreamEventUnionDelta) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
-type MessageStreamEventType string
+// Accumulate builds up the Message incrementally from a MessageStreamEvent. The Message then can be used as
+// any other Message, except with the caveat that the Message.JSON field which normally can be used to inspect
+// the JSON sent over the network may not be populated fully.
+//
+// message := anthropic.Message{}
+// for stream.Next() {
+// event := stream.Current()
+// message.Accumulate(event)
+// }
+func (acc *Message) Accumulate(event MessageStreamEventUnion) error {
+ if acc == nil {
+ return fmt.Errorf("accumulate: cannot accumlate into nil Message")
+ }
-const (
- MessageStreamEventTypeMessageStart MessageStreamEventType = "message_start"
- MessageStreamEventTypeMessageDelta MessageStreamEventType = "message_delta"
- MessageStreamEventTypeMessageStop MessageStreamEventType = "message_stop"
- MessageStreamEventTypeContentBlockStart MessageStreamEventType = "content_block_start"
- MessageStreamEventTypeContentBlockDelta MessageStreamEventType = "content_block_delta"
- MessageStreamEventTypeContentBlockStop MessageStreamEventType = "content_block_stop"
-)
+ switch event := event.AsAny().(type) {
+ case MessageStartEvent:
+ *acc = event.Message
+ case MessageDeltaEvent:
+ acc.StopReason = MessageStopReason(event.Delta.StopReason)
+ acc.StopSequence = event.Delta.StopSequence
+ acc.Usage.OutputTokens = event.Usage.OutputTokens
-func (r MessageStreamEventType) IsKnown() bool {
- switch r {
- case MessageStreamEventTypeMessageStart, MessageStreamEventTypeMessageDelta, MessageStreamEventTypeMessageStop, MessageStreamEventTypeContentBlockStart, MessageStreamEventTypeContentBlockDelta, MessageStreamEventTypeContentBlockStop:
- return true
+ // acc.JSON.StopReason = event.Delta.JSON.StopReason
+ // acc.JSON.StopSequence = event.Delta.JSON.StopSequence
+ // acc.Usage.JSON.OutputTokens = event.Usage.JSON.OutputTokens
+ case MessageStopEvent:
+ accJson, err := json.Marshal(acc)
+ if err != nil {
+ return fmt.Errorf("error converting content block to JSON: %w", err)
+ }
+ acc.JSON.raw = string(accJson)
+ case ContentBlockStartEvent:
+ acc.Content = append(acc.Content, ContentBlockUnion{})
+ err := acc.Content[len(acc.Content)-1].UnmarshalJSON([]byte(event.ContentBlock.RawJSON()))
+ if err != nil {
+ return err
+ }
+ case ContentBlockDeltaEvent:
+ if len(acc.Content) == 0 {
+ return fmt.Errorf("received event of type %s but there was no content block", event.Type)
+ }
+ cb := &acc.Content[len(acc.Content)-1]
+ switch delta := event.Delta.AsAny().(type) {
+ case TextDelta:
+ cb.Text += delta.Text
+ case InputJSONDelta:
+ if string(cb.Input) == "{}" {
+ cb.Input = json.RawMessage{}
+ }
+ cb.Input = append(cb.Input, []byte(delta.PartialJSON)...)
+ case ThinkingDelta:
+ cb.Thinking += delta.Thinking
+ case SignatureDelta:
+ cb.Signature += delta.Signature
+ }
+ case ContentBlockStopEvent:
+ if len(acc.Content) == 0 {
+ return fmt.Errorf("received event of type %s but there was no content block", event.Type)
+ }
+ contentBlock := &acc.Content[len(acc.Content)-1]
+ cbJson, err := json.Marshal(contentBlock)
+ if err != nil {
+ return fmt.Errorf("error converting content block to JSON: %w", err)
+ }
+ contentBlock.JSON.raw = string(cbJson)
}
- return false
+
+ return nil
}
type RedactedThinkingBlock struct {
Data string `json:"data,required"`
- Type RedactedThinkingBlockType `json:"type,required"`
- JSON redactedThinkingBlockJSON `json:"-"`
-}
-
-// redactedThinkingBlockJSON contains the JSON metadata for the struct
-// [RedactedThinkingBlock]
-type redactedThinkingBlockJSON struct {
- Data apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *RedactedThinkingBlock) UnmarshalJSON(data []byte) (err error) {
+ Type constant.RedactedThinking `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Data resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r RedactedThinkingBlock) RawJSON() string { return r.JSON.raw }
+func (r *RedactedThinkingBlock) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r redactedThinkingBlockJSON) RawJSON() string {
- return r.raw
-}
-
-func (r RedactedThinkingBlock) implementsContentBlock() {}
-
-func (r RedactedThinkingBlock) implementsContentBlockStartEventContentBlock() {}
-
-type RedactedThinkingBlockType string
-
-const (
- RedactedThinkingBlockTypeRedactedThinking RedactedThinkingBlockType = "redacted_thinking"
-)
-
-func (r RedactedThinkingBlockType) IsKnown() bool {
- switch r {
- case RedactedThinkingBlockTypeRedactedThinking:
- return true
- }
- return false
+func (r RedactedThinkingBlock) ToParam() RedactedThinkingBlockParam {
+ var p RedactedThinkingBlockParam
+ p.Type = r.Type
+ p.Data = r.Data
+ return p
}
+// The properties Data, Type are required.
type RedactedThinkingBlockParam struct {
- Data param.Field[string] `json:"data,required"`
- Type param.Field[RedactedThinkingBlockParamType] `json:"type,required"`
+ Data string `json:"data,required"`
+ // This field can be elided, and will marshal its zero value as
+ // "redacted_thinking".
+ Type constant.RedactedThinking `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f RedactedThinkingBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r RedactedThinkingBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow RedactedThinkingBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r RedactedThinkingBlockParam) implementsContentBlockParamUnion() {}
-
-type RedactedThinkingBlockParamType string
+type SignatureDelta struct {
+ Signature string `json:"signature,required"`
+ Type constant.SignatureDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Signature resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r SignatureDelta) RawJSON() string { return r.JSON.raw }
+func (r *SignatureDelta) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-const (
- RedactedThinkingBlockParamTypeRedactedThinking RedactedThinkingBlockParamType = "redacted_thinking"
-)
+type TextBlock struct {
+ // Citations supporting the text block.
+ //
+ // The type of citation returned will depend on the type of document being cited.
+ // Citing a PDF results in `page_location`, plain text results in `char_location`,
+ // and content document results in `content_block_location`.
+ Citations []TextCitationUnion `json:"citations,required"`
+ Text string `json:"text,required"`
+ Type constant.Text `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Citations resp.Field
+ Text resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r TextBlock) RawJSON() string { return r.JSON.raw }
+func (r *TextBlock) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-func (r RedactedThinkingBlockParamType) IsKnown() bool {
- switch r {
- case RedactedThinkingBlockParamTypeRedactedThinking:
- return true
+func (r TextBlock) ToParam() TextBlockParam {
+ var p TextBlockParam
+ p.Type = r.Type
+ p.Text = r.Text
+ p.Citations = make([]TextCitationParamUnion, len(r.Citations))
+ for i, citation := range r.Citations {
+ switch citationVariant := citation.AsAny().(type) {
+ case CitationCharLocation:
+ var citationParam CitationCharLocationParam
+ citationParam.Type = citationVariant.Type
+ citationParam.DocumentTitle = toParam(citationVariant.DocumentTitle, citationVariant.JSON.DocumentTitle)
+ citationParam.CitedText = citationVariant.CitedText
+ citationParam.DocumentIndex = citationVariant.DocumentIndex
+ citationParam.EndCharIndex = citationVariant.EndCharIndex
+ citationParam.StartCharIndex = citationVariant.StartCharIndex
+ p.Citations[i] = TextCitationParamUnion{OfRequestCharLocationCitation: &citationParam}
+ case CitationPageLocation:
+ var citationParam CitationPageLocationParam
+ citationParam.Type = citationVariant.Type
+ citationParam.DocumentTitle = toParam(citationVariant.DocumentTitle, citationVariant.JSON.DocumentTitle)
+ citationParam.DocumentIndex = citationVariant.DocumentIndex
+ citationParam.EndPageNumber = citationVariant.EndPageNumber
+ citationParam.StartPageNumber = citationVariant.StartPageNumber
+ p.Citations[i] = TextCitationParamUnion{OfRequestPageLocationCitation: &citationParam}
+ case CitationContentBlockLocation:
+ var citationParam CitationContentBlockLocationParam
+ citationParam.Type = citationVariant.Type
+ citationParam.DocumentTitle = toParam(citationVariant.DocumentTitle, citationVariant.JSON.DocumentTitle)
+ citationParam.CitedText = citationVariant.CitedText
+ citationParam.DocumentIndex = citationVariant.DocumentIndex
+ citationParam.EndBlockIndex = citationVariant.EndBlockIndex
+ citationParam.StartBlockIndex = citationVariant.StartBlockIndex
+ p.Citations[i] = TextCitationParamUnion{OfRequestContentBlockLocationCitation: &citationParam}
+ }
}
- return false
+ return p
}
-type SignatureDelta struct {
- Signature string `json:"signature,required"`
- Type SignatureDeltaType `json:"type,required"`
- JSON signatureDeltaJSON `json:"-"`
+// The properties Text, Type are required.
+type TextBlockParam struct {
+ Text string `json:"text,required"`
+ Citations []TextCitationParamUnion `json:"citations,omitzero"`
+ CacheControl CacheControlEphemeralParam `json:"cache_control,omitzero"`
+ // This field can be elided, and will marshal its zero value as "text".
+ Type constant.Text `json:"type,required"`
+ paramObj
+}
+
+func NewTextBlock(text string) ContentBlockParamUnion {
+ return ContentBlockParamUnion{
+ OfRequestTextBlock: &TextBlockParam{
+ Text: text,
+ },
+ }
}
-// signatureDeltaJSON contains the JSON metadata for the struct [SignatureDelta]
-type signatureDeltaJSON struct {
- Signature apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f TextBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r TextBlockParam) MarshalJSON() (data []byte, err error) {
+ type shadow TextBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r *SignatureDelta) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+// TextCitationUnion contains all possible properties and values from
+// [CitationCharLocation], [CitationPageLocation], [CitationContentBlockLocation].
+//
+// Use the [TextCitationUnion.AsAny] method to switch on the variant.
+//
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type TextCitationUnion struct {
+ CitedText string `json:"cited_text"`
+ DocumentIndex int64 `json:"document_index"`
+ DocumentTitle string `json:"document_title"`
+ // This field is from variant [CitationCharLocation].
+ EndCharIndex int64 `json:"end_char_index"`
+ // This field is from variant [CitationCharLocation].
+ StartCharIndex int64 `json:"start_char_index"`
+ // Any of "char_location", "page_location", "content_block_location".
+ Type string `json:"type"`
+ // This field is from variant [CitationPageLocation].
+ EndPageNumber int64 `json:"end_page_number"`
+ // This field is from variant [CitationPageLocation].
+ StartPageNumber int64 `json:"start_page_number"`
+ // This field is from variant [CitationContentBlockLocation].
+ EndBlockIndex int64 `json:"end_block_index"`
+ // This field is from variant [CitationContentBlockLocation].
+ StartBlockIndex int64 `json:"start_block_index"`
+ JSON struct {
+ CitedText resp.Field
+ DocumentIndex resp.Field
+ DocumentTitle resp.Field
+ EndCharIndex resp.Field
+ StartCharIndex resp.Field
+ Type resp.Field
+ EndPageNumber resp.Field
+ StartPageNumber resp.Field
+ EndBlockIndex resp.Field
+ StartBlockIndex resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
+//
+// switch variant := TextCitationUnion.AsAny().(type) {
+// case CitationCharLocation:
+// case CitationPageLocation:
+// case CitationContentBlockLocation:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u TextCitationUnion) AsAny() any {
+ switch u.Type {
+ case "char_location":
+ return u.AsResponseCharLocationCitation()
+ case "page_location":
+ return u.AsResponsePageLocationCitation()
+ case "content_block_location":
+ return u.AsResponseContentBlockLocationCitation()
+ }
+ return nil
}
-func (r signatureDeltaJSON) RawJSON() string {
- return r.raw
+func (u TextCitationUnion) AsResponseCharLocationCitation() (v CitationCharLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r SignatureDelta) implementsContentBlockDeltaEventDelta() {}
-
-type SignatureDeltaType string
-
-const (
- SignatureDeltaTypeSignatureDelta SignatureDeltaType = "signature_delta"
-)
-
-func (r SignatureDeltaType) IsKnown() bool {
- switch r {
- case SignatureDeltaTypeSignatureDelta:
- return true
- }
- return false
+func (u TextCitationUnion) AsResponsePageLocationCitation() (v CitationPageLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-type TextBlock struct {
- // Citations supporting the text block.
- //
- // The type of citation returned will depend on the type of document being cited.
- // Citing a PDF results in `page_location`, plain text results in `char_location`,
- // and content document results in `content_block_location`.
- Citations []TextCitation `json:"citations,required,nullable"`
- Text string `json:"text,required"`
- Type TextBlockType `json:"type,required"`
- JSON textBlockJSON `json:"-"`
+func (u TextCitationUnion) AsResponseContentBlockLocationCitation() (v CitationContentBlockLocation) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// textBlockJSON contains the JSON metadata for the struct [TextBlock]
-type textBlockJSON struct {
- Citations apijson.Field
- Text apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
+// Returns the unmodified JSON received from the API
+func (u TextCitationUnion) RawJSON() string { return u.JSON.raw }
-func (r *TextBlock) UnmarshalJSON(data []byte) (err error) {
+func (r *TextCitationUnion) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r textBlockJSON) RawJSON() string {
- return r.raw
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type TextCitationParamUnion struct {
+ OfRequestCharLocationCitation *CitationCharLocationParam `json:",omitzero,inline"`
+ OfRequestPageLocationCitation *CitationPageLocationParam `json:",omitzero,inline"`
+ OfRequestContentBlockLocationCitation *CitationContentBlockLocationParam `json:",omitzero,inline"`
+ paramUnion
}
-func (r TextBlock) implementsContentBlock() {}
-
-func (r TextBlock) implementsContentBlockStartEventContentBlock() {}
-
-type TextBlockType string
-
-const (
- TextBlockTypeText TextBlockType = "text"
-)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u TextCitationParamUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u TextCitationParamUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[TextCitationParamUnion](u.OfRequestCharLocationCitation, u.OfRequestPageLocationCitation, u.OfRequestContentBlockLocationCitation)
+}
-func (r TextBlockType) IsKnown() bool {
- switch r {
- case TextBlockTypeText:
- return true
+func (u *TextCitationParamUnion) asAny() any {
+ if !param.IsOmitted(u.OfRequestCharLocationCitation) {
+ return u.OfRequestCharLocationCitation
+ } else if !param.IsOmitted(u.OfRequestPageLocationCitation) {
+ return u.OfRequestPageLocationCitation
+ } else if !param.IsOmitted(u.OfRequestContentBlockLocationCitation) {
+ return u.OfRequestContentBlockLocationCitation
}
- return false
+ return nil
}
-type TextBlockParam struct {
- Text param.Field[string] `json:"text,required"`
- Type param.Field[TextBlockParamType] `json:"type,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
- Citations param.Field[[]TextCitationParamUnion] `json:"citations"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u TextCitationParamUnion) GetEndCharIndex() *int64 {
+ if vt := u.OfRequestCharLocationCitation; vt != nil {
+ return &vt.EndCharIndex
+ }
+ return nil
}
-func NewTextBlock(text string) TextBlockParam {
- return TextBlockParam{
- Text: F(text),
- Type: F(TextBlockParamTypeText),
+// Returns a pointer to the underlying variant's property, if present.
+func (u TextCitationParamUnion) GetStartCharIndex() *int64 {
+ if vt := u.OfRequestCharLocationCitation; vt != nil {
+ return &vt.StartCharIndex
}
+ return nil
}
-func (r TextBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u TextCitationParamUnion) GetEndPageNumber() *int64 {
+ if vt := u.OfRequestPageLocationCitation; vt != nil {
+ return &vt.EndPageNumber
+ }
+ return nil
}
-func (r TextBlockParam) implementsContentBlockParamUnion() {}
-
-func (r TextBlockParam) implementsContentBlockSourceContentUnionParam() {}
-
-func (r TextBlockParam) implementsToolResultBlockParamContentUnion() {}
-
-type TextBlockParamType string
-
-const (
- TextBlockParamTypeText TextBlockParamType = "text"
-)
-
-func (r TextBlockParamType) IsKnown() bool {
- switch r {
- case TextBlockParamTypeText:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u TextCitationParamUnion) GetStartPageNumber() *int64 {
+ if vt := u.OfRequestPageLocationCitation; vt != nil {
+ return &vt.StartPageNumber
}
- return false
+ return nil
}
-type TextCitation struct {
- CitedText string `json:"cited_text,required"`
- DocumentIndex int64 `json:"document_index,required"`
- DocumentTitle string `json:"document_title,required,nullable"`
- Type TextCitationType `json:"type,required"`
- EndBlockIndex int64 `json:"end_block_index"`
- EndCharIndex int64 `json:"end_char_index"`
- EndPageNumber int64 `json:"end_page_number"`
- StartBlockIndex int64 `json:"start_block_index"`
- StartCharIndex int64 `json:"start_char_index"`
- StartPageNumber int64 `json:"start_page_number"`
- JSON textCitationJSON `json:"-"`
- union TextCitationUnion
+// Returns a pointer to the underlying variant's property, if present.
+func (u TextCitationParamUnion) GetEndBlockIndex() *int64 {
+ if vt := u.OfRequestContentBlockLocationCitation; vt != nil {
+ return &vt.EndBlockIndex
+ }
+ return nil
}
-// textCitationJSON contains the JSON metadata for the struct [TextCitation]
-type textCitationJSON struct {
- CitedText apijson.Field
- DocumentIndex apijson.Field
- DocumentTitle apijson.Field
- Type apijson.Field
- EndBlockIndex apijson.Field
- EndCharIndex apijson.Field
- EndPageNumber apijson.Field
- StartBlockIndex apijson.Field
- StartCharIndex apijson.Field
- StartPageNumber apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+// Returns a pointer to the underlying variant's property, if present.
+func (u TextCitationParamUnion) GetStartBlockIndex() *int64 {
+ if vt := u.OfRequestContentBlockLocationCitation; vt != nil {
+ return &vt.StartBlockIndex
+ }
+ return nil
}
-func (r textCitationJSON) RawJSON() string {
- return r.raw
+// Returns a pointer to the underlying variant's property, if present.
+func (u TextCitationParamUnion) GetCitedText() *string {
+ if vt := u.OfRequestCharLocationCitation; vt != nil {
+ return (*string)(&vt.CitedText)
+ } else if vt := u.OfRequestPageLocationCitation; vt != nil {
+ return (*string)(&vt.CitedText)
+ } else if vt := u.OfRequestContentBlockLocationCitation; vt != nil {
+ return (*string)(&vt.CitedText)
+ }
+ return nil
}
-func (r *TextCitation) UnmarshalJSON(data []byte) (err error) {
- *r = TextCitation{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
+// Returns a pointer to the underlying variant's property, if present.
+func (u TextCitationParamUnion) GetDocumentIndex() *int64 {
+ if vt := u.OfRequestCharLocationCitation; vt != nil {
+ return (*int64)(&vt.DocumentIndex)
+ } else if vt := u.OfRequestPageLocationCitation; vt != nil {
+ return (*int64)(&vt.DocumentIndex)
+ } else if vt := u.OfRequestContentBlockLocationCitation; vt != nil {
+ return (*int64)(&vt.DocumentIndex)
}
- return apijson.Port(r.union, &r)
+ return nil
}
-// AsUnion returns a [TextCitationUnion] interface which you can cast to the
-// specific types for more type safety.
-//
-// Possible runtime types of the union are [CitationCharLocation],
-// [CitationPageLocation], [CitationContentBlockLocation].
-func (r TextCitation) AsUnion() TextCitationUnion {
- return r.union
+// Returns a pointer to the underlying variant's property, if present.
+func (u TextCitationParamUnion) GetDocumentTitle() *string {
+ if vt := u.OfRequestCharLocationCitation; vt != nil && vt.DocumentTitle.IsPresent() {
+ return &vt.DocumentTitle.Value
+ } else if vt := u.OfRequestPageLocationCitation; vt != nil && vt.DocumentTitle.IsPresent() {
+ return &vt.DocumentTitle.Value
+ } else if vt := u.OfRequestContentBlockLocationCitation; vt != nil && vt.DocumentTitle.IsPresent() {
+ return &vt.DocumentTitle.Value
+ }
+ return nil
}
-// Union satisfied by [CitationCharLocation], [CitationPageLocation] or
-// [CitationContentBlockLocation].
-type TextCitationUnion interface {
- implementsTextCitation()
+// Returns a pointer to the underlying variant's property, if present.
+func (u TextCitationParamUnion) GetType() *string {
+ if vt := u.OfRequestCharLocationCitation; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestPageLocationCitation; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestContentBlockLocationCitation; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
}
func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*TextCitationUnion)(nil)).Elem(),
+ apijson.RegisterUnion[TextCitationParamUnion](
"type",
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(CitationCharLocation{}),
+ Type: reflect.TypeOf(CitationCharLocationParam{}),
DiscriminatorValue: "char_location",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(CitationPageLocation{}),
+ Type: reflect.TypeOf(CitationPageLocationParam{}),
DiscriminatorValue: "page_location",
},
apijson.UnionVariant{
TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(CitationContentBlockLocation{}),
+ Type: reflect.TypeOf(CitationContentBlockLocationParam{}),
DiscriminatorValue: "content_block_location",
},
)
}
-type TextCitationType string
-
-const (
- TextCitationTypeCharLocation TextCitationType = "char_location"
- TextCitationTypePageLocation TextCitationType = "page_location"
- TextCitationTypeContentBlockLocation TextCitationType = "content_block_location"
-)
-
-func (r TextCitationType) IsKnown() bool {
- switch r {
- case TextCitationTypeCharLocation, TextCitationTypePageLocation, TextCitationTypeContentBlockLocation:
- return true
- }
- return false
-}
-
-type TextCitationParam struct {
- CitedText param.Field[string] `json:"cited_text,required"`
- DocumentIndex param.Field[int64] `json:"document_index,required"`
- DocumentTitle param.Field[string] `json:"document_title,required"`
- Type param.Field[TextCitationParamType] `json:"type,required"`
- EndBlockIndex param.Field[int64] `json:"end_block_index"`
- EndCharIndex param.Field[int64] `json:"end_char_index"`
- EndPageNumber param.Field[int64] `json:"end_page_number"`
- StartBlockIndex param.Field[int64] `json:"start_block_index"`
- StartCharIndex param.Field[int64] `json:"start_char_index"`
- StartPageNumber param.Field[int64] `json:"start_page_number"`
-}
-
-func (r TextCitationParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r TextCitationParam) implementsTextCitationParamUnion() {}
-
-// Satisfied by [CitationCharLocationParam], [CitationPageLocationParam],
-// [CitationContentBlockLocationParam], [TextCitationParam].
-type TextCitationParamUnion interface {
- implementsTextCitationParamUnion()
-}
-
-type TextCitationParamType string
-
-const (
- TextCitationParamTypeCharLocation TextCitationParamType = "char_location"
- TextCitationParamTypePageLocation TextCitationParamType = "page_location"
- TextCitationParamTypeContentBlockLocation TextCitationParamType = "content_block_location"
-)
-
-func (r TextCitationParamType) IsKnown() bool {
- switch r {
- case TextCitationParamTypeCharLocation, TextCitationParamTypePageLocation, TextCitationParamTypeContentBlockLocation:
- return true
- }
- return false
-}
-
type TextDelta struct {
- Text string `json:"text,required"`
- Type TextDeltaType `json:"type,required"`
- JSON textDeltaJSON `json:"-"`
-}
-
-// textDeltaJSON contains the JSON metadata for the struct [TextDelta]
-type textDeltaJSON struct {
- Text apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *TextDelta) UnmarshalJSON(data []byte) (err error) {
+ Text string `json:"text,required"`
+ Type constant.TextDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Text resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r TextDelta) RawJSON() string { return r.JSON.raw }
+func (r *TextDelta) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r textDeltaJSON) RawJSON() string {
- return r.raw
-}
-
-func (r TextDelta) implementsContentBlockDeltaEventDelta() {}
-
-type TextDeltaType string
-
-const (
- TextDeltaTypeTextDelta TextDeltaType = "text_delta"
-)
-
-func (r TextDeltaType) IsKnown() bool {
- switch r {
- case TextDeltaTypeTextDelta:
- return true
- }
- return false
-}
-
type ThinkingBlock struct {
Signature string `json:"signature,required"`
Thinking string `json:"thinking,required"`
- Type ThinkingBlockType `json:"type,required"`
- JSON thinkingBlockJSON `json:"-"`
-}
-
-// thinkingBlockJSON contains the JSON metadata for the struct [ThinkingBlock]
-type thinkingBlockJSON struct {
- Signature apijson.Field
- Thinking apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *ThinkingBlock) UnmarshalJSON(data []byte) (err error) {
+ Type constant.Thinking `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Signature resp.Field
+ Thinking resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r ThinkingBlock) RawJSON() string { return r.JSON.raw }
+func (r *ThinkingBlock) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r thinkingBlockJSON) RawJSON() string {
- return r.raw
-}
-
-func (r ThinkingBlock) implementsContentBlock() {}
-
-func (r ThinkingBlock) implementsContentBlockStartEventContentBlock() {}
-
-type ThinkingBlockType string
-
-const (
- ThinkingBlockTypeThinking ThinkingBlockType = "thinking"
-)
-
-func (r ThinkingBlockType) IsKnown() bool {
- switch r {
- case ThinkingBlockTypeThinking:
- return true
- }
- return false
+func (r ThinkingBlock) ToParam() ThinkingBlockParam {
+ var p ThinkingBlockParam
+ p.Type = r.Type
+ p.Signature = r.Signature
+ p.Thinking = r.Thinking
+ return p
}
+// The properties Signature, Thinking, Type are required.
type ThinkingBlockParam struct {
- Signature param.Field[string] `json:"signature,required"`
- Thinking param.Field[string] `json:"thinking,required"`
- Type param.Field[ThinkingBlockParamType] `json:"type,required"`
+ Signature string `json:"signature,required"`
+ Thinking string `json:"thinking,required"`
+ // This field can be elided, and will marshal its zero value as "thinking".
+ Type constant.Thinking `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ThinkingBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ThinkingBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r ThinkingBlockParam) implementsContentBlockParamUnion() {}
-
-type ThinkingBlockParamType string
-
-const (
- ThinkingBlockParamTypeThinking ThinkingBlockParamType = "thinking"
-)
-
-func (r ThinkingBlockParamType) IsKnown() bool {
- switch r {
- case ThinkingBlockParamTypeThinking:
- return true
- }
- return false
+ type shadow ThinkingBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The property Type is required.
type ThinkingConfigDisabledParam struct {
- Type param.Field[ThinkingConfigDisabledType] `json:"type,required"`
+ // This field can be elided, and will marshal its zero value as "disabled".
+ Type constant.Disabled `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ThinkingConfigDisabledParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ThinkingConfigDisabledParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r ThinkingConfigDisabledParam) implementsThinkingConfigParamUnion() {}
-
-type ThinkingConfigDisabledType string
-
-const (
- ThinkingConfigDisabledTypeDisabled ThinkingConfigDisabledType = "disabled"
-)
-
-func (r ThinkingConfigDisabledType) IsKnown() bool {
- switch r {
- case ThinkingConfigDisabledTypeDisabled:
- return true
- }
- return false
+ type shadow ThinkingConfigDisabledParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties BudgetTokens, Type are required.
type ThinkingConfigEnabledParam struct {
// Determines how many tokens Claude can use for its internal reasoning process.
// Larger budgets can enable more thorough analysis for complex problems, improving
@@ -2628,718 +2619,694 @@ type ThinkingConfigEnabledParam struct {
// See
// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
// for details.
- BudgetTokens param.Field[int64] `json:"budget_tokens,required"`
- Type param.Field[ThinkingConfigEnabledType] `json:"type,required"`
+ BudgetTokens int64 `json:"budget_tokens,required"`
+ // This field can be elided, and will marshal its zero value as "enabled".
+ Type constant.Enabled `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ThinkingConfigEnabledParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ThinkingConfigEnabledParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow ThinkingConfigEnabledParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r ThinkingConfigEnabledParam) implementsThinkingConfigParamUnion() {}
-
-type ThinkingConfigEnabledType string
-
-const (
- ThinkingConfigEnabledTypeEnabled ThinkingConfigEnabledType = "enabled"
-)
-
-func (r ThinkingConfigEnabledType) IsKnown() bool {
- switch r {
- case ThinkingConfigEnabledTypeEnabled:
- return true
- }
- return false
+func ThinkingConfigParamOfThinkingConfigEnabled(budgetTokens int64) ThinkingConfigParamUnion {
+ var variant ThinkingConfigEnabledParam
+ variant.BudgetTokens = budgetTokens
+ return ThinkingConfigParamUnion{OfThinkingConfigEnabled: &variant}
}
-// Configuration for enabling Claude's extended thinking.
+// Only one field can be non-zero.
//
-// When enabled, responses include `thinking` content blocks showing Claude's
-// thinking process before the final answer. Requires a minimum budget of 1,024
-// tokens and counts towards your `max_tokens` limit.
-//
-// See
-// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
-// for details.
-type ThinkingConfigParam struct {
- Type param.Field[ThinkingConfigParamType] `json:"type,required"`
- // Determines how many tokens Claude can use for its internal reasoning process.
- // Larger budgets can enable more thorough analysis for complex problems, improving
- // response quality.
- //
- // Must be ≥1024 and less than `max_tokens`.
- //
- // See
- // [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
- // for details.
- BudgetTokens param.Field[int64] `json:"budget_tokens"`
+// Use [param.IsOmitted] to confirm if a field is set.
+type ThinkingConfigParamUnion struct {
+ OfThinkingConfigEnabled *ThinkingConfigEnabledParam `json:",omitzero,inline"`
+ OfThinkingConfigDisabled *ThinkingConfigDisabledParam `json:",omitzero,inline"`
+ paramUnion
}
-func (r ThinkingConfigParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u ThinkingConfigParamUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u ThinkingConfigParamUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[ThinkingConfigParamUnion](u.OfThinkingConfigEnabled, u.OfThinkingConfigDisabled)
}
-func (r ThinkingConfigParam) implementsThinkingConfigParamUnion() {}
-
-// Configuration for enabling Claude's extended thinking.
-//
-// When enabled, responses include `thinking` content blocks showing Claude's
-// thinking process before the final answer. Requires a minimum budget of 1,024
-// tokens and counts towards your `max_tokens` limit.
-//
-// See
-// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
-// for details.
-//
-// Satisfied by [ThinkingConfigEnabledParam], [ThinkingConfigDisabledParam],
-// [ThinkingConfigParam].
-type ThinkingConfigParamUnion interface {
- implementsThinkingConfigParamUnion()
+func (u *ThinkingConfigParamUnion) asAny() any {
+ if !param.IsOmitted(u.OfThinkingConfigEnabled) {
+ return u.OfThinkingConfigEnabled
+ } else if !param.IsOmitted(u.OfThinkingConfigDisabled) {
+ return u.OfThinkingConfigDisabled
+ }
+ return nil
}
-type ThinkingConfigParamType string
-
-const (
- ThinkingConfigParamTypeEnabled ThinkingConfigParamType = "enabled"
- ThinkingConfigParamTypeDisabled ThinkingConfigParamType = "disabled"
-)
-
-func (r ThinkingConfigParamType) IsKnown() bool {
- switch r {
- case ThinkingConfigParamTypeEnabled, ThinkingConfigParamTypeDisabled:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u ThinkingConfigParamUnion) GetBudgetTokens() *int64 {
+ if vt := u.OfThinkingConfigEnabled; vt != nil {
+ return &vt.BudgetTokens
}
- return false
+ return nil
}
-type ThinkingDelta struct {
- Thinking string `json:"thinking,required"`
- Type ThinkingDeltaType `json:"type,required"`
- JSON thinkingDeltaJSON `json:"-"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u ThinkingConfigParamUnion) GetType() *string {
+ if vt := u.OfThinkingConfigEnabled; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfThinkingConfigDisabled; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
}
-// thinkingDeltaJSON contains the JSON metadata for the struct [ThinkingDelta]
-type thinkingDeltaJSON struct {
- Thinking apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func init() {
+ apijson.RegisterUnion[ThinkingConfigParamUnion](
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ThinkingConfigEnabledParam{}),
+ DiscriminatorValue: "enabled",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ThinkingConfigDisabledParam{}),
+ DiscriminatorValue: "disabled",
+ },
+ )
}
-func (r *ThinkingDelta) UnmarshalJSON(data []byte) (err error) {
+type ThinkingDelta struct {
+ Thinking string `json:"thinking,required"`
+ Type constant.ThinkingDelta `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Thinking resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r ThinkingDelta) RawJSON() string { return r.JSON.raw }
+func (r *ThinkingDelta) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r thinkingDeltaJSON) RawJSON() string {
- return r.raw
-}
-
-func (r ThinkingDelta) implementsContentBlockDeltaEventDelta() {}
-
-type ThinkingDeltaType string
-
-const (
- ThinkingDeltaTypeThinkingDelta ThinkingDeltaType = "thinking_delta"
-)
-
-func (r ThinkingDeltaType) IsKnown() bool {
- switch r {
- case ThinkingDeltaTypeThinkingDelta:
- return true
- }
- return false
-}
-
+// The properties InputSchema, Name are required.
type ToolParam struct {
// [JSON schema](https://json-schema.org/draft/2020-12) for this tool's input.
//
// This defines the shape of the `input` that your tool accepts and that the model
// will produce.
- InputSchema param.Field[interface{}] `json:"input_schema,required"`
+ InputSchema ToolInputSchemaParam `json:"input_schema,omitzero,required"`
// Name of the tool.
//
// This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[string] `json:"name,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
+ Name string `json:"name,required"`
// Description of what this tool does.
//
// Tool descriptions should be as detailed as possible. The more information that
// the model has about what the tool is and how to use it, the better it will
// perform. You can use natural language descriptions to reinforce important
// aspects of the tool input JSON schema.
- Description param.Field[string] `json:"description"`
+ Description param.Opt[string] `json:"description,omitzero"`
+ CacheControl CacheControlEphemeralParam `json:"cache_control,omitzero"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ToolParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow ToolParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r ToolParam) implementsMessageCountTokensToolUnionParam() {}
-
-func (r ToolParam) implementsToolUnionUnionParam() {}
-
// [JSON schema](https://json-schema.org/draft/2020-12) for this tool's input.
//
// This defines the shape of the `input` that your tool accepts and that the model
// will produce.
+//
+// The property Type is required.
type ToolInputSchemaParam struct {
- Type param.Field[ToolInputSchemaType] `json:"type,required"`
- Properties param.Field[interface{}] `json:"properties"`
- ExtraFields map[string]interface{} `json:"-,extras"`
-}
-
-func (r ToolInputSchemaParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ Properties interface{} `json:"properties,omitzero"`
+ // This field can be elided, and will marshal its zero value as "object".
+ Type constant.Object `json:"type,required"`
+ ExtraFields map[string]interface{} `json:"-,extras"`
+ paramObj
}
-type ToolInputSchemaType string
-
-const (
- ToolInputSchemaTypeObject ToolInputSchemaType = "object"
-)
-
-func (r ToolInputSchemaType) IsKnown() bool {
- switch r {
- case ToolInputSchemaTypeObject:
- return true
- }
- return false
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ToolInputSchemaParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+func (r ToolInputSchemaParam) MarshalJSON() (data []byte, err error) {
+ type shadow ToolInputSchemaParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties Name, Type are required.
type ToolBash20250124Param struct {
+ CacheControl CacheControlEphemeralParam `json:"cache_control,omitzero"`
// Name of the tool.
//
// This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[ToolBash20250124Name] `json:"name,required"`
- Type param.Field[ToolBash20250124Type] `json:"type,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
+ //
+ // This field can be elided, and will marshal its zero value as "bash".
+ Name constant.Bash `json:"name,required"`
+ // This field can be elided, and will marshal its zero value as "bash_20250124".
+ Type constant.Bash20250124 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ToolBash20250124Param) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ToolBash20250124Param) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow ToolBash20250124Param
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r ToolBash20250124Param) implementsMessageCountTokensToolUnionParam() {}
-
-func (r ToolBash20250124Param) implementsToolUnionUnionParam() {}
+func ToolChoiceParamOfToolChoiceTool(name string) ToolChoiceUnionParam {
+ var variant ToolChoiceToolParam
+ variant.Name = name
+ return ToolChoiceUnionParam{OfToolChoiceTool: &variant}
+}
-// Name of the tool.
+// Only one field can be non-zero.
//
-// This is how the tool will be called by the model and in tool_use blocks.
-type ToolBash20250124Name string
-
-const (
- ToolBash20250124NameBash ToolBash20250124Name = "bash"
-)
-
-func (r ToolBash20250124Name) IsKnown() bool {
- switch r {
- case ToolBash20250124NameBash:
- return true
+// Use [param.IsOmitted] to confirm if a field is set.
+type ToolChoiceUnionParam struct {
+ OfToolChoiceAuto *ToolChoiceAutoParam `json:",omitzero,inline"`
+ OfToolChoiceAny *ToolChoiceAnyParam `json:",omitzero,inline"`
+ OfToolChoiceTool *ToolChoiceToolParam `json:",omitzero,inline"`
+ OfToolChoiceNone *ToolChoiceNoneParam `json:",omitzero,inline"`
+ paramUnion
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u ToolChoiceUnionParam) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u ToolChoiceUnionParam) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[ToolChoiceUnionParam](u.OfToolChoiceAuto, u.OfToolChoiceAny, u.OfToolChoiceTool, u.OfToolChoiceNone)
+}
+
+func (u *ToolChoiceUnionParam) asAny() any {
+ if !param.IsOmitted(u.OfToolChoiceAuto) {
+ return u.OfToolChoiceAuto
+ } else if !param.IsOmitted(u.OfToolChoiceAny) {
+ return u.OfToolChoiceAny
+ } else if !param.IsOmitted(u.OfToolChoiceTool) {
+ return u.OfToolChoiceTool
+ } else if !param.IsOmitted(u.OfToolChoiceNone) {
+ return u.OfToolChoiceNone
}
- return false
+ return nil
}
-type ToolBash20250124Type string
-
-const (
- ToolBash20250124TypeBash20250124 ToolBash20250124Type = "bash_20250124"
-)
-
-func (r ToolBash20250124Type) IsKnown() bool {
- switch r {
- case ToolBash20250124TypeBash20250124:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolChoiceUnionParam) GetName() *string {
+ if vt := u.OfToolChoiceTool; vt != nil {
+ return &vt.Name
}
- return false
-}
-
-// How the model should use the provided tools. The model can use a specific tool,
-// any available tool, decide by itself, or not use tools at all.
-type ToolChoiceParam struct {
- Type param.Field[ToolChoiceType] `json:"type,required"`
- // Whether to disable parallel tool use.
- //
- // Defaults to `false`. If set to `true`, the model will output at most one tool
- // use.
- DisableParallelToolUse param.Field[bool] `json:"disable_parallel_tool_use"`
- // The name of the tool to use.
- Name param.Field[string] `json:"name"`
+ return nil
}
-func (r ToolChoiceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolChoiceUnionParam) GetType() *string {
+ if vt := u.OfToolChoiceAuto; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfToolChoiceAny; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfToolChoiceTool; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfToolChoiceNone; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
}
-func (r ToolChoiceParam) implementsToolChoiceUnionParam() {}
-
-// How the model should use the provided tools. The model can use a specific tool,
-// any available tool, decide by itself, or not use tools at all.
-//
-// Satisfied by [ToolChoiceAutoParam], [ToolChoiceAnyParam], [ToolChoiceToolParam],
-// [ToolChoiceNoneParam], [ToolChoiceParam].
-type ToolChoiceUnionParam interface {
- implementsToolChoiceUnionParam()
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolChoiceUnionParam) GetDisableParallelToolUse() *bool {
+ if vt := u.OfToolChoiceAuto; vt != nil && vt.DisableParallelToolUse.IsPresent() {
+ return &vt.DisableParallelToolUse.Value
+ } else if vt := u.OfToolChoiceAny; vt != nil && vt.DisableParallelToolUse.IsPresent() {
+ return &vt.DisableParallelToolUse.Value
+ } else if vt := u.OfToolChoiceTool; vt != nil && vt.DisableParallelToolUse.IsPresent() {
+ return &vt.DisableParallelToolUse.Value
+ }
+ return nil
}
-type ToolChoiceType string
-
-const (
- ToolChoiceTypeAuto ToolChoiceType = "auto"
- ToolChoiceTypeAny ToolChoiceType = "any"
- ToolChoiceTypeTool ToolChoiceType = "tool"
- ToolChoiceTypeNone ToolChoiceType = "none"
-)
-
-func (r ToolChoiceType) IsKnown() bool {
- switch r {
- case ToolChoiceTypeAuto, ToolChoiceTypeAny, ToolChoiceTypeTool, ToolChoiceTypeNone:
- return true
- }
- return false
+func init() {
+ apijson.RegisterUnion[ToolChoiceUnionParam](
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ToolChoiceAutoParam{}),
+ DiscriminatorValue: "auto",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ToolChoiceAnyParam{}),
+ DiscriminatorValue: "any",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ToolChoiceToolParam{}),
+ DiscriminatorValue: "tool",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ToolChoiceNoneParam{}),
+ DiscriminatorValue: "none",
+ },
+ )
}
// The model will use any available tools.
+//
+// The property Type is required.
type ToolChoiceAnyParam struct {
- Type param.Field[ToolChoiceAnyType] `json:"type,required"`
// Whether to disable parallel tool use.
//
// Defaults to `false`. If set to `true`, the model will output exactly one tool
// use.
- DisableParallelToolUse param.Field[bool] `json:"disable_parallel_tool_use"`
+ DisableParallelToolUse param.Opt[bool] `json:"disable_parallel_tool_use,omitzero"`
+ // This field can be elided, and will marshal its zero value as "any".
+ Type constant.Any `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ToolChoiceAnyParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ToolChoiceAnyParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r ToolChoiceAnyParam) implementsToolChoiceUnionParam() {}
-
-type ToolChoiceAnyType string
-
-const (
- ToolChoiceAnyTypeAny ToolChoiceAnyType = "any"
-)
-
-func (r ToolChoiceAnyType) IsKnown() bool {
- switch r {
- case ToolChoiceAnyTypeAny:
- return true
- }
- return false
+ type shadow ToolChoiceAnyParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
// The model will automatically decide whether to use tools.
+//
+// The property Type is required.
type ToolChoiceAutoParam struct {
- Type param.Field[ToolChoiceAutoType] `json:"type,required"`
// Whether to disable parallel tool use.
//
// Defaults to `false`. If set to `true`, the model will output at most one tool
// use.
- DisableParallelToolUse param.Field[bool] `json:"disable_parallel_tool_use"`
+ DisableParallelToolUse param.Opt[bool] `json:"disable_parallel_tool_use,omitzero"`
+ // This field can be elided, and will marshal its zero value as "auto".
+ Type constant.Auto `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ToolChoiceAutoParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ToolChoiceAutoParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r ToolChoiceAutoParam) implementsToolChoiceUnionParam() {}
-
-type ToolChoiceAutoType string
-
-const (
- ToolChoiceAutoTypeAuto ToolChoiceAutoType = "auto"
-)
-
-func (r ToolChoiceAutoType) IsKnown() bool {
- switch r {
- case ToolChoiceAutoTypeAuto:
- return true
- }
- return false
+ type shadow ToolChoiceAutoParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
// The model will not be allowed to use tools.
+//
+// The property Type is required.
type ToolChoiceNoneParam struct {
- Type param.Field[ToolChoiceNoneType] `json:"type,required"`
+ // This field can be elided, and will marshal its zero value as "none".
+ Type constant.None `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ToolChoiceNoneParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ToolChoiceNoneParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r ToolChoiceNoneParam) implementsToolChoiceUnionParam() {}
-
-type ToolChoiceNoneType string
-
-const (
- ToolChoiceNoneTypeNone ToolChoiceNoneType = "none"
-)
-
-func (r ToolChoiceNoneType) IsKnown() bool {
- switch r {
- case ToolChoiceNoneTypeNone:
- return true
- }
- return false
+ type shadow ToolChoiceNoneParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
// The model will use the specified tool with `tool_choice.name`.
+//
+// The properties Name, Type are required.
type ToolChoiceToolParam struct {
// The name of the tool to use.
- Name param.Field[string] `json:"name,required"`
- Type param.Field[ToolChoiceToolType] `json:"type,required"`
+ Name string `json:"name,required"`
// Whether to disable parallel tool use.
//
// Defaults to `false`. If set to `true`, the model will output exactly one tool
// use.
- DisableParallelToolUse param.Field[bool] `json:"disable_parallel_tool_use"`
+ DisableParallelToolUse param.Opt[bool] `json:"disable_parallel_tool_use,omitzero"`
+ // This field can be elided, and will marshal its zero value as "tool".
+ Type constant.Tool `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ToolChoiceToolParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ToolChoiceToolParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r ToolChoiceToolParam) implementsToolChoiceUnionParam() {}
-
-type ToolChoiceToolType string
-
-const (
- ToolChoiceToolTypeTool ToolChoiceToolType = "tool"
-)
-
-func (r ToolChoiceToolType) IsKnown() bool {
- switch r {
- case ToolChoiceToolTypeTool:
- return true
- }
- return false
+ type shadow ToolChoiceToolParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties ToolUseID, Type are required.
type ToolResultBlockParam struct {
- ToolUseID param.Field[string] `json:"tool_use_id,required"`
- Type param.Field[ToolResultBlockParamType] `json:"type,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
- Content param.Field[[]ToolResultBlockParamContentUnion] `json:"content"`
- IsError param.Field[bool] `json:"is_error"`
+ ToolUseID string `json:"tool_use_id,required"`
+ IsError param.Opt[bool] `json:"is_error,omitzero"`
+ CacheControl CacheControlEphemeralParam `json:"cache_control,omitzero"`
+ Content []ToolResultBlockParamContentUnion `json:"content,omitzero"`
+ // This field can be elided, and will marshal its zero value as "tool_result".
+ Type constant.ToolResult `json:"type,required"`
+ paramObj
}
-func NewToolResultBlock(toolUseID string, content string, isError bool) ToolResultBlockParam {
- return ToolResultBlockParam{
- Type: F(ToolResultBlockParamTypeToolResult),
- ToolUseID: F(toolUseID),
- Content: F([]ToolResultBlockParamContentUnion{NewTextBlock(content)}),
- IsError: F(isError),
+func NewToolResultBlock(toolUseID string, content string, isError bool) ContentBlockParamUnion {
+ blockParam := ToolResultBlockParam{
+ ToolUseID: toolUseID,
+ Content: []ToolResultBlockParamContentUnion{{OfRequestTextBlock: &TextBlockParam{
+ Text: content,
+ }}},
+ IsError: Bool(isError),
}
+ return ContentBlockParamUnion{OfRequestToolResultBlock: &blockParam}
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ToolResultBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ToolResultBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow ToolResultBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r ToolResultBlockParam) implementsContentBlockParamUnion() {}
-
-type ToolResultBlockParamType string
+// Only one field can be non-zero.
+//
+// Use [param.IsOmitted] to confirm if a field is set.
+type ToolResultBlockParamContentUnion struct {
+ OfRequestTextBlock *TextBlockParam `json:",omitzero,inline"`
+ OfRequestImageBlock *ImageBlockParam `json:",omitzero,inline"`
+ paramUnion
+}
-const (
- ToolResultBlockParamTypeToolResult ToolResultBlockParamType = "tool_result"
-)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u ToolResultBlockParamContentUnion) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u ToolResultBlockParamContentUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[ToolResultBlockParamContentUnion](u.OfRequestTextBlock, u.OfRequestImageBlock)
+}
-func (r ToolResultBlockParamType) IsKnown() bool {
- switch r {
- case ToolResultBlockParamTypeToolResult:
- return true
+func (u *ToolResultBlockParamContentUnion) asAny() any {
+ if !param.IsOmitted(u.OfRequestTextBlock) {
+ return u.OfRequestTextBlock
+ } else if !param.IsOmitted(u.OfRequestImageBlock) {
+ return u.OfRequestImageBlock
}
- return false
+ return nil
}
-type ToolResultBlockParamContent struct {
- Type param.Field[ToolResultBlockParamContentType] `json:"type,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
- Citations param.Field[interface{}] `json:"citations"`
- Source param.Field[interface{}] `json:"source"`
- Text param.Field[string] `json:"text"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolResultBlockParamContentUnion) GetText() *string {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return &vt.Text
+ }
+ return nil
}
-func (r ToolResultBlockParamContent) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolResultBlockParamContentUnion) GetCitations() []TextCitationParamUnion {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return vt.Citations
+ }
+ return nil
}
-func (r ToolResultBlockParamContent) implementsToolResultBlockParamContentUnion() {}
-
-// Satisfied by [TextBlockParam], [ImageBlockParam], [ToolResultBlockParamContent].
-type ToolResultBlockParamContentUnion interface {
- implementsToolResultBlockParamContentUnion()
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolResultBlockParamContentUnion) GetSource() *ImageBlockParamSourceUnion {
+ if vt := u.OfRequestImageBlock; vt != nil {
+ return &vt.Source
+ }
+ return nil
}
-type ToolResultBlockParamContentType string
-
-const (
- ToolResultBlockParamContentTypeText ToolResultBlockParamContentType = "text"
- ToolResultBlockParamContentTypeImage ToolResultBlockParamContentType = "image"
-)
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolResultBlockParamContentUnion) GetType() *string {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfRequestImageBlock; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
+}
-func (r ToolResultBlockParamContentType) IsKnown() bool {
- switch r {
- case ToolResultBlockParamContentTypeText, ToolResultBlockParamContentTypeImage:
- return true
+// Returns a pointer to the underlying variant's CacheControl property, if present.
+func (u ToolResultBlockParamContentUnion) GetCacheControl() *CacheControlEphemeralParam {
+ if vt := u.OfRequestTextBlock; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfRequestImageBlock; vt != nil {
+ return &vt.CacheControl
}
- return false
+ return nil
+}
+
+func init() {
+ apijson.RegisterUnion[ToolResultBlockParamContentUnion](
+ "type",
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(TextBlockParam{}),
+ DiscriminatorValue: "text",
+ },
+ apijson.UnionVariant{
+ TypeFilter: gjson.JSON,
+ Type: reflect.TypeOf(ImageBlockParam{}),
+ DiscriminatorValue: "image",
+ },
+ )
}
+// The properties Name, Type are required.
type ToolTextEditor20250124Param struct {
+ CacheControl CacheControlEphemeralParam `json:"cache_control,omitzero"`
// Name of the tool.
//
// This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[ToolTextEditor20250124Name] `json:"name,required"`
- Type param.Field[ToolTextEditor20250124Type] `json:"type,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
+ //
+ // This field can be elided, and will marshal its zero value as
+ // "str_replace_editor".
+ Name constant.StrReplaceEditor `json:"name,required"`
+ // This field can be elided, and will marshal its zero value as
+ // "text_editor_20250124".
+ Type constant.TextEditor20250124 `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ToolTextEditor20250124Param) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ToolTextEditor20250124Param) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow ToolTextEditor20250124Param
+ return param.MarshalObject(r, (*shadow)(&r))
}
-func (r ToolTextEditor20250124Param) implementsMessageCountTokensToolUnionParam() {}
-
-func (r ToolTextEditor20250124Param) implementsToolUnionUnionParam() {}
+func ToolUnionParamOfTool(inputSchema ToolInputSchemaParam, name string) ToolUnionParam {
+ var variant ToolParam
+ variant.InputSchema = inputSchema
+ variant.Name = name
+ return ToolUnionParam{OfTool: &variant}
+}
-// Name of the tool.
+// Only one field can be non-zero.
//
-// This is how the tool will be called by the model and in tool_use blocks.
-type ToolTextEditor20250124Name string
+// Use [param.IsOmitted] to confirm if a field is set.
+type ToolUnionParam struct {
+ OfTool *ToolParam `json:",omitzero,inline"`
+ OfBashTool20250124 *ToolBash20250124Param `json:",omitzero,inline"`
+ OfTextEditor20250124 *ToolTextEditor20250124Param `json:",omitzero,inline"`
+ paramUnion
+}
-const (
- ToolTextEditor20250124NameStrReplaceEditor ToolTextEditor20250124Name = "str_replace_editor"
-)
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u ToolUnionParam) IsPresent() bool { return !param.IsOmitted(u) && !u.IsNull() }
+func (u ToolUnionParam) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[ToolUnionParam](u.OfTool, u.OfBashTool20250124, u.OfTextEditor20250124)
+}
-func (r ToolTextEditor20250124Name) IsKnown() bool {
- switch r {
- case ToolTextEditor20250124NameStrReplaceEditor:
- return true
+func (u *ToolUnionParam) asAny() any {
+ if !param.IsOmitted(u.OfTool) {
+ return u.OfTool
+ } else if !param.IsOmitted(u.OfBashTool20250124) {
+ return u.OfBashTool20250124
+ } else if !param.IsOmitted(u.OfTextEditor20250124) {
+ return u.OfTextEditor20250124
}
- return false
+ return nil
}
-type ToolTextEditor20250124Type string
-
-const (
- ToolTextEditor20250124TypeTextEditor20250124 ToolTextEditor20250124Type = "text_editor_20250124"
-)
-
-func (r ToolTextEditor20250124Type) IsKnown() bool {
- switch r {
- case ToolTextEditor20250124TypeTextEditor20250124:
- return true
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolUnionParam) GetInputSchema() *ToolInputSchemaParam {
+ if vt := u.OfTool; vt != nil {
+ return &vt.InputSchema
}
- return false
+ return nil
}
-type ToolUnionParam struct {
- // Name of the tool.
- //
- // This is how the tool will be called by the model and in tool_use blocks.
- Name param.Field[string] `json:"name,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
- // Description of what this tool does.
- //
- // Tool descriptions should be as detailed as possible. The more information that
- // the model has about what the tool is and how to use it, the better it will
- // perform. You can use natural language descriptions to reinforce important
- // aspects of the tool input JSON schema.
- Description param.Field[string] `json:"description"`
- InputSchema param.Field[interface{}] `json:"input_schema"`
- Type param.Field[ToolUnionType] `json:"type"`
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolUnionParam) GetDescription() *string {
+ if vt := u.OfTool; vt != nil && vt.Description.IsPresent() {
+ return &vt.Description.Value
+ }
+ return nil
}
-func (r ToolUnionParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolUnionParam) GetName() *string {
+ if vt := u.OfTool; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfBashTool20250124; vt != nil {
+ return (*string)(&vt.Name)
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return (*string)(&vt.Name)
+ }
+ return nil
}
-func (r ToolUnionParam) implementsToolUnionUnionParam() {}
-
-// Satisfied by [ToolParam], [ToolBash20250124Param],
-// [ToolTextEditor20250124Param], [ToolUnionParam].
-type ToolUnionUnionParam interface {
- implementsToolUnionUnionParam()
+// Returns a pointer to the underlying variant's property, if present.
+func (u ToolUnionParam) GetType() *string {
+ if vt := u.OfBashTool20250124; vt != nil {
+ return (*string)(&vt.Type)
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return (*string)(&vt.Type)
+ }
+ return nil
}
-type ToolUnionType string
-
-const (
- ToolUnionTypeBash20250124 ToolUnionType = "bash_20250124"
- ToolUnionTypeTextEditor20250124 ToolUnionType = "text_editor_20250124"
-)
-
-func (r ToolUnionType) IsKnown() bool {
- switch r {
- case ToolUnionTypeBash20250124, ToolUnionTypeTextEditor20250124:
- return true
+// Returns a pointer to the underlying variant's CacheControl property, if present.
+func (u ToolUnionParam) GetCacheControl() *CacheControlEphemeralParam {
+ if vt := u.OfTool; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfBashTool20250124; vt != nil {
+ return &vt.CacheControl
+ } else if vt := u.OfTextEditor20250124; vt != nil {
+ return &vt.CacheControl
}
- return false
+ return nil
}
type ToolUseBlock struct {
ID string `json:"id,required"`
Input json.RawMessage `json:"input,required"`
Name string `json:"name,required"`
- Type ToolUseBlockType `json:"type,required"`
- JSON toolUseBlockJSON `json:"-"`
-}
-
-// toolUseBlockJSON contains the JSON metadata for the struct [ToolUseBlock]
-type toolUseBlockJSON struct {
- ID apijson.Field
- Input apijson.Field
- Name apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *ToolUseBlock) UnmarshalJSON(data []byte) (err error) {
+ Type constant.ToolUse `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ Input resp.Field
+ Name resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r ToolUseBlock) RawJSON() string { return r.JSON.raw }
+func (r *ToolUseBlock) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r toolUseBlockJSON) RawJSON() string {
- return r.raw
-}
-
-func (r ToolUseBlock) implementsContentBlock() {}
-
-func (r ToolUseBlock) implementsContentBlockStartEventContentBlock() {}
-
-type ToolUseBlockType string
-
-const (
- ToolUseBlockTypeToolUse ToolUseBlockType = "tool_use"
-)
-
-func (r ToolUseBlockType) IsKnown() bool {
- switch r {
- case ToolUseBlockTypeToolUse:
- return true
- }
- return false
+func (r ToolUseBlock) ToParam() ToolUseBlockParam {
+ var toolUse ToolUseBlockParam
+ toolUse.Type = r.Type
+ toolUse.ID = r.ID
+ toolUse.Input = r.Input
+ toolUse.Name = r.Name
+ return toolUse
}
+// The properties ID, Input, Name, Type are required.
type ToolUseBlockParam struct {
- ID param.Field[string] `json:"id,required"`
- Input param.Field[interface{}] `json:"input,required"`
- Name param.Field[string] `json:"name,required"`
- Type param.Field[ToolUseBlockParamType] `json:"type,required"`
- CacheControl param.Field[CacheControlEphemeralParam] `json:"cache_control"`
-}
-
-func NewToolUseBlockParam(id string, name string, input interface{}) ToolUseBlockParam {
- return ToolUseBlockParam{
- ID: F(id),
- Input: F(input),
- Name: F(name),
- Type: F(ToolUseBlockParamTypeToolUse),
- }
-}
-
+ ID string `json:"id,required"`
+ Input interface{} `json:"input,omitzero,required"`
+ Name string `json:"name,required"`
+ CacheControl CacheControlEphemeralParam `json:"cache_control,omitzero"`
+ // This field can be elided, and will marshal its zero value as "tool_use".
+ Type constant.ToolUse `json:"type,required"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ToolUseBlockParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r ToolUseBlockParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r ToolUseBlockParam) implementsContentBlockParamUnion() {}
-
-type ToolUseBlockParamType string
-
-const (
- ToolUseBlockParamTypeToolUse ToolUseBlockParamType = "tool_use"
-)
-
-func (r ToolUseBlockParamType) IsKnown() bool {
- switch r {
- case ToolUseBlockParamTypeToolUse:
- return true
- }
- return false
+ type shadow ToolUseBlockParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties Type, URL are required.
type URLImageSourceParam struct {
- Type param.Field[URLImageSourceType] `json:"type,required"`
- URL param.Field[string] `json:"url,required"`
+ URL string `json:"url,required"`
+ // This field can be elided, and will marshal its zero value as "url".
+ Type constant.URL `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f URLImageSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r URLImageSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r URLImageSourceParam) implementsImageBlockParamSourceUnion() {}
-
-type URLImageSourceType string
-
-const (
- URLImageSourceTypeURL URLImageSourceType = "url"
-)
-
-func (r URLImageSourceType) IsKnown() bool {
- switch r {
- case URLImageSourceTypeURL:
- return true
- }
- return false
+ type shadow URLImageSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties Type, URL are required.
type URLPDFSourceParam struct {
- Type param.Field[URLPDFSourceType] `json:"type,required"`
- URL param.Field[string] `json:"url,required"`
+ URL string `json:"url,required"`
+ // This field can be elided, and will marshal its zero value as "url".
+ Type constant.URL `json:"type,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f URLPDFSourceParam) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r URLPDFSourceParam) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
-}
-
-func (r URLPDFSourceParam) implementsDocumentBlockParamSourceUnion() {}
-
-type URLPDFSourceType string
-
-const (
- URLPDFSourceTypeURL URLPDFSourceType = "url"
-)
-
-func (r URLPDFSourceType) IsKnown() bool {
- switch r {
- case URLPDFSourceTypeURL:
- return true
- }
- return false
+ type shadow URLPDFSourceParam
+ return param.MarshalObject(r, (*shadow)(&r))
}
type Usage struct {
// The number of input tokens used to create the cache entry.
- CacheCreationInputTokens int64 `json:"cache_creation_input_tokens,required,nullable"`
+ CacheCreationInputTokens int64 `json:"cache_creation_input_tokens,required"`
// The number of input tokens read from the cache.
- CacheReadInputTokens int64 `json:"cache_read_input_tokens,required,nullable"`
+ CacheReadInputTokens int64 `json:"cache_read_input_tokens,required"`
// The number of input tokens which were used.
InputTokens int64 `json:"input_tokens,required"`
// The number of output tokens which were used.
- OutputTokens int64 `json:"output_tokens,required"`
- JSON usageJSON `json:"-"`
-}
-
-// usageJSON contains the JSON metadata for the struct [Usage]
-type usageJSON struct {
- CacheCreationInputTokens apijson.Field
- CacheReadInputTokens apijson.Field
- InputTokens apijson.Field
- OutputTokens apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *Usage) UnmarshalJSON(data []byte) (err error) {
+ OutputTokens int64 `json:"output_tokens,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ CacheCreationInputTokens resp.Field
+ CacheReadInputTokens resp.Field
+ InputTokens resp.Field
+ OutputTokens resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r Usage) RawJSON() string { return r.JSON.raw }
+func (r *Usage) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r usageJSON) RawJSON() string {
- return r.raw
-}
-
type MessageNewParams struct {
// The maximum number of tokens to generate before stopping.
//
@@ -3348,7 +3315,7 @@ type MessageNewParams struct {
//
// Different models have different maximum values for this parameter. See
// [models](https://docs.anthropic.com/en/docs/models-overview) for details.
- MaxTokens param.Field[int64] `json:"max_tokens,required"`
+ MaxTokens int64 `json:"max_tokens,required"`
// Input messages.
//
// Our models are trained to operate on alternating `user` and `assistant`
@@ -3441,13 +3408,40 @@ type MessageNewParams struct {
// [system prompt](https://docs.anthropic.com/en/docs/system-prompts), you can use
// the top-level `system` parameter — there is no `"system"` role for input
// messages in the Messages API.
- Messages param.Field[[]MessageParam] `json:"messages,required"`
+ Messages []MessageParam `json:"messages,omitzero,required"`
// The model that will complete your prompt.\n\nSee
// [models](https://docs.anthropic.com/en/docs/models-overview) for additional
// details and options.
- Model param.Field[Model] `json:"model,required"`
+ Model Model `json:"model,omitzero,required"`
+ // Amount of randomness injected into the response.
+ //
+ // Defaults to `1.0`. Ranges from `0.0` to `1.0`. Use `temperature` closer to `0.0`
+ // for analytical / multiple choice, and closer to `1.0` for creative and
+ // generative tasks.
+ //
+ // Note that even with `temperature` of `0.0`, the results will not be fully
+ // deterministic.
+ Temperature param.Opt[float64] `json:"temperature,omitzero"`
+ // Only sample from the top K options for each subsequent token.
+ //
+ // Used to remove "long tail" low probability responses.
+ // [Learn more technical details here](https://towardsdatascience.com/how-to-sample-from-language-models-682bceb97277).
+ //
+ // Recommended for advanced use cases only. You usually only need to use
+ // `temperature`.
+ TopK param.Opt[int64] `json:"top_k,omitzero"`
+ // Use nucleus sampling.
+ //
+ // In nucleus sampling, we compute the cumulative distribution over all the options
+ // for each subsequent token in decreasing probability order and cut it off once it
+ // reaches a particular probability specified by `top_p`. You should either alter
+ // `temperature` or `top_p`, but not both.
+ //
+ // Recommended for advanced use cases only. You usually only need to use
+ // `temperature`.
+ TopP param.Opt[float64] `json:"top_p,omitzero"`
// An object describing metadata about the request.
- Metadata param.Field[MetadataParam] `json:"metadata"`
+ Metadata MetadataParam `json:"metadata,omitzero"`
// Custom text sequences that will cause the model to stop generating.
//
// Our models will normally stop when they have naturally completed their turn,
@@ -3457,22 +3451,13 @@ type MessageNewParams struct {
// text, you can use the `stop_sequences` parameter. If the model encounters one of
// the custom sequences, the response `stop_reason` value will be `"stop_sequence"`
// and the response `stop_sequence` value will contain the matched stop sequence.
- StopSequences param.Field[[]string] `json:"stop_sequences"`
+ StopSequences []string `json:"stop_sequences,omitzero"`
// System prompt.
//
// A system prompt is a way of providing context and instructions to Claude, such
// as specifying a particular goal or role. See our
// [guide to system prompts](https://docs.anthropic.com/en/docs/system-prompts).
- System param.Field[[]TextBlockParam] `json:"system"`
- // Amount of randomness injected into the response.
- //
- // Defaults to `1.0`. Ranges from `0.0` to `1.0`. Use `temperature` closer to `0.0`
- // for analytical / multiple choice, and closer to `1.0` for creative and
- // generative tasks.
- //
- // Note that even with `temperature` of `0.0`, the results will not be fully
- // deterministic.
- Temperature param.Field[float64] `json:"temperature"`
+ System []TextBlockParam `json:"system,omitzero"`
// Configuration for enabling Claude's extended thinking.
//
// When enabled, responses include `thinking` content blocks showing Claude's
@@ -3482,10 +3467,10 @@ type MessageNewParams struct {
// See
// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
// for details.
- Thinking param.Field[ThinkingConfigParamUnion] `json:"thinking"`
+ Thinking ThinkingConfigParamUnion `json:"thinking,omitzero"`
// How the model should use the provided tools. The model can use a specific tool,
// any available tool, decide by itself, or not use tools at all.
- ToolChoice param.Field[ToolChoiceUnionParam] `json:"tool_choice"`
+ ToolChoice ToolChoiceUnionParam `json:"tool_choice,omitzero"`
// Definitions of tools that the model may use.
//
// If you include `tools` in your API request, the model may return `tool_use`
@@ -3561,29 +3546,17 @@ type MessageNewParams struct {
// JSON structure of output.
//
// See our [guide](https://docs.anthropic.com/en/docs/tool-use) for more details.
- Tools param.Field[[]ToolUnionUnionParam] `json:"tools"`
- // Only sample from the top K options for each subsequent token.
- //
- // Used to remove "long tail" low probability responses.
- // [Learn more technical details here](https://towardsdatascience.com/how-to-sample-from-language-models-682bceb97277).
- //
- // Recommended for advanced use cases only. You usually only need to use
- // `temperature`.
- TopK param.Field[int64] `json:"top_k"`
- // Use nucleus sampling.
- //
- // In nucleus sampling, we compute the cumulative distribution over all the options
- // for each subsequent token in decreasing probability order and cut it off once it
- // reaches a particular probability specified by `top_p`. You should either alter
- // `temperature` or `top_p`, but not both.
- //
- // Recommended for advanced use cases only. You usually only need to use
- // `temperature`.
- TopP param.Field[float64] `json:"top_p"`
+ Tools []ToolUnionParam `json:"tools,omitzero"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f MessageNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
func (r MessageNewParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow MessageNewParams
+ return param.MarshalObject(r, (*shadow)(&r))
}
type MessageCountTokensParams struct {
@@ -3679,17 +3652,17 @@ type MessageCountTokensParams struct {
// [system prompt](https://docs.anthropic.com/en/docs/system-prompts), you can use
// the top-level `system` parameter — there is no `"system"` role for input
// messages in the Messages API.
- Messages param.Field[[]MessageParam] `json:"messages,required"`
+ Messages []MessageParam `json:"messages,omitzero,required"`
// The model that will complete your prompt.\n\nSee
// [models](https://docs.anthropic.com/en/docs/models-overview) for additional
// details and options.
- Model param.Field[Model] `json:"model,required"`
+ Model Model `json:"model,omitzero,required"`
// System prompt.
//
// A system prompt is a way of providing context and instructions to Claude, such
// as specifying a particular goal or role. See our
// [guide to system prompts](https://docs.anthropic.com/en/docs/system-prompts).
- System param.Field[MessageCountTokensParamsSystemUnion] `json:"system"`
+ System MessageCountTokensParamsSystemUnion `json:"system,omitzero"`
// Configuration for enabling Claude's extended thinking.
//
// When enabled, responses include `thinking` content blocks showing Claude's
@@ -3699,10 +3672,10 @@ type MessageCountTokensParams struct {
// See
// [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
// for details.
- Thinking param.Field[ThinkingConfigParamUnion] `json:"thinking"`
+ Thinking ThinkingConfigParamUnion `json:"thinking,omitzero"`
// How the model should use the provided tools. The model can use a specific tool,
// any available tool, decide by itself, or not use tools at all.
- ToolChoice param.Field[ToolChoiceUnionParam] `json:"tool_choice"`
+ ToolChoice ToolChoiceUnionParam `json:"tool_choice,omitzero"`
// Definitions of tools that the model may use.
//
// If you include `tools` in your API request, the model may return `tool_use`
@@ -3778,24 +3751,42 @@ type MessageCountTokensParams struct {
// JSON structure of output.
//
// See our [guide](https://docs.anthropic.com/en/docs/tool-use) for more details.
- Tools param.Field[[]MessageCountTokensToolUnionParam] `json:"tools"`
+ Tools []MessageCountTokensToolUnionParam `json:"tools,omitzero"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f MessageCountTokensParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
func (r MessageCountTokensParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow MessageCountTokensParams
+ return param.MarshalObject(r, (*shadow)(&r))
}
-// System prompt.
+// Only one field can be non-zero.
//
-// A system prompt is a way of providing context and instructions to Claude, such
-// as specifying a particular goal or role. See our
-// [guide to system prompts](https://docs.anthropic.com/en/docs/system-prompts).
-//
-// Satisfied by [shared.UnionString], [MessageCountTokensParamsSystemArray].
-type MessageCountTokensParamsSystemUnion interface {
- ImplementsMessageCountTokensParamsSystemUnion()
+// Use [param.IsOmitted] to confirm if a field is set.
+type MessageCountTokensParamsSystemUnion struct {
+ OfString param.Opt[string] `json:",omitzero,inline"`
+ OfMessageCountTokenssSystemArray []TextBlockParam `json:",omitzero,inline"`
+ paramUnion
}
-type MessageCountTokensParamsSystemArray []TextBlockParam
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (u MessageCountTokensParamsSystemUnion) IsPresent() bool {
+ return !param.IsOmitted(u) && !u.IsNull()
+}
+func (u MessageCountTokensParamsSystemUnion) MarshalJSON() ([]byte, error) {
+ return param.MarshalUnion[MessageCountTokensParamsSystemUnion](u.OfString, u.OfMessageCountTokenssSystemArray)
+}
-func (r MessageCountTokensParamsSystemArray) ImplementsMessageCountTokensParamsSystemUnion() {}
+func (u *MessageCountTokensParamsSystemUnion) asAny() any {
+ if !param.IsOmitted(u.OfString) {
+ return &u.OfString.Value
+ } else if !param.IsOmitted(u.OfMessageCountTokenssSystemArray) {
+ return &u.OfMessageCountTokenssSystemArray
+ }
+ return nil
+}
diff --git a/message_test.go b/message_test.go
index 2791ec3..2d8f749 100644
--- a/message_test.go
+++ b/message_test.go
@@ -6,9 +6,7 @@ import (
"context"
"errors"
"os"
- "strings"
"testing"
- "time"
"github.com/anthropics/anthropic-sdk-go"
"github.com/anthropics/anthropic-sdk-go/internal/testutil"
@@ -28,48 +26,55 @@ func TestMessageNewWithOptionalParams(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- Metadata: anthropic.F(anthropic.MetadataParam{
- UserID: anthropic.F("13803d75-b4b5-4c3e-b2a2-6f21399b021b"),
- }),
- StopSequences: anthropic.F([]string{"string"}),
- System: anthropic.F([]anthropic.TextBlockParam{{Text: anthropic.F("x"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- Temperature: anthropic.F(1.000000),
- Thinking: anthropic.F[anthropic.ThinkingConfigParamUnion](anthropic.ThinkingConfigEnabledParam{
- BudgetTokens: anthropic.F(int64(1024)),
- Type: anthropic.F(anthropic.ThinkingConfigEnabledTypeEnabled),
- }),
- ToolChoice: anthropic.F[anthropic.ToolChoiceUnionParam](anthropic.ToolChoiceAutoParam{
- Type: anthropic.F(anthropic.ToolChoiceAutoTypeAuto),
- DisableParallelToolUse: anthropic.F(true),
- }),
- Tools: anthropic.F([]anthropic.ToolUnionUnionParam{anthropic.ToolParam{
- Description: anthropic.F("Get the current weather in a given location"),
- Name: anthropic.F("x"),
- InputSchema: anthropic.F[interface{}](map[string]interface{}{
- "type": "object",
- "properties": map[string]interface{}{
- "location": map[string]interface{}{
- "description": "The city and state, e.g. San Francisco, CA",
- "type": "string",
- },
- "unit": map[string]interface{}{
- "description": "Unit for the output - one of (celsius, fahrenheit)",
- "type": "string",
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ Role: anthropic.MessageParamRoleUser,
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ Metadata: anthropic.MetadataParam{
+ UserID: anthropic.String("13803d75-b4b5-4c3e-b2a2-6f21399b021b"),
+ },
+ StopSequences: []string{"string"},
+ System: []anthropic.TextBlockParam{{Text: "x", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}}},
+ Temperature: anthropic.Float(1),
+ Thinking: anthropic.ThinkingConfigParamUnion{
+ OfThinkingConfigEnabled: &anthropic.ThinkingConfigEnabledParam{
+ BudgetTokens: 1024,
+ },
+ },
+ ToolChoice: anthropic.ToolChoiceUnionParam{
+ OfToolChoiceAuto: &anthropic.ToolChoiceAutoParam{
+ DisableParallelToolUse: anthropic.Bool(true),
+ },
+ },
+ Tools: []anthropic.ToolUnionParam{{
+ OfTool: &anthropic.ToolParam{
+ InputSchema: anthropic.ToolInputSchemaParam{
+ Properties: map[string]interface{}{
+ "location": map[string]interface{}{
+ "description": "The city and state, e.g. San Francisco, CA",
+ "type": "string",
+ },
+ "unit": map[string]interface{}{
+ "description": "Unit for the output - one of (celsius, fahrenheit)",
+ "type": "string",
+ },
},
},
- }),
- CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{
- Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral),
- }),
- }}),
- TopK: anthropic.F(int64(5)),
- TopP: anthropic.F(0.700000),
+ Name: "name",
+ CacheControl: anthropic.CacheControlEphemeralParam{},
+ Description: anthropic.String("Get the current weather in a given location"),
+ },
+ }},
+ TopK: anthropic.Int(5),
+ TopP: anthropic.Float(0.7),
})
if err != nil {
var apierr *anthropic.Error
@@ -93,54 +98,59 @@ func TestMessageCountTokensWithOptionalParams(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Messages.CountTokens(context.TODO(), anthropic.MessageCountTokensParams{
- Messages: anthropic.F([]anthropic.MessageParam{{
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- System: anthropic.F[anthropic.MessageCountTokensParamsSystemUnion](anthropic.MessageCountTokensParamsSystemArray([]anthropic.TextBlockParam{{
- Text: anthropic.F("Today's date is 2024-06-01."),
- Type: anthropic.F(anthropic.TextBlockParamTypeText),
- CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{
- Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral),
- }),
- Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{
- CitedText: anthropic.F("cited_text"),
- DocumentIndex: anthropic.F(int64(0)),
- DocumentTitle: anthropic.F("x"),
- EndCharIndex: anthropic.F(int64(0)),
- StartCharIndex: anthropic.F(int64(0)),
- Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation),
- }}),
- }})),
- Thinking: anthropic.F[anthropic.ThinkingConfigParamUnion](anthropic.ThinkingConfigEnabledParam{
- BudgetTokens: anthropic.F(int64(1024)),
- Type: anthropic.F(anthropic.ThinkingConfigEnabledTypeEnabled),
- }),
- ToolChoice: anthropic.F[anthropic.ToolChoiceUnionParam](anthropic.ToolChoiceAutoParam{
- Type: anthropic.F(anthropic.ToolChoiceAutoTypeAuto),
- DisableParallelToolUse: anthropic.F(true),
- }),
- Tools: anthropic.F([]anthropic.MessageCountTokensToolUnionParam{anthropic.ToolParam{
- InputSchema: anthropic.F[interface{}](map[string]interface{}{
- "type": "object",
- "properties": map[string]interface{}{
- "location": map[string]interface{}{
- "description": "The city and state, e.g. San Francisco, CA",
- "type": "string",
+ Messages: []anthropic.MessageParam{{
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ Role: anthropic.MessageParamRoleUser,
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ System: anthropic.MessageCountTokensParamsSystemUnion{
+ OfMessageCountTokenssSystemArray: []anthropic.TextBlockParam{{
+ Text: "Today's date is 2024-06-01.",
+ CacheControl: anthropic.CacheControlEphemeralParam{},
+ Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{
+ CitedText: "cited_text",
+ DocumentIndex: 0,
+ DocumentTitle: anthropic.String("x"),
+ EndCharIndex: 0,
+ StartCharIndex: 0,
},
- "unit": map[string]interface{}{
- "description": "Unit for the output - one of (celsius, fahrenheit)",
- "type": "string",
+ }},
+ }},
+ },
+ Thinking: anthropic.ThinkingConfigParamUnion{
+ OfThinkingConfigEnabled: &anthropic.ThinkingConfigEnabledParam{
+ BudgetTokens: 1024,
+ },
+ },
+ ToolChoice: anthropic.ToolChoiceUnionParam{
+ OfToolChoiceAuto: &anthropic.ToolChoiceAutoParam{
+ DisableParallelToolUse: anthropic.Bool(true),
+ },
+ },
+ Tools: []anthropic.MessageCountTokensToolUnionParam{{
+ OfTool: &anthropic.ToolParam{
+ InputSchema: anthropic.ToolInputSchemaParam{
+ Properties: map[string]interface{}{
+ "location": map[string]interface{}{
+ "description": "The city and state, e.g. San Francisco, CA",
+ "type": "string",
+ },
+ "unit": map[string]interface{}{
+ "description": "Unit for the output - one of (celsius, fahrenheit)",
+ "type": "string",
+ },
},
},
- }),
- Name: anthropic.F("name"),
- CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{
- Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral),
- }),
- Description: anthropic.F("Get the current weather in a given location"),
- }}),
+ Name: "name",
+ CacheControl: anthropic.CacheControlEphemeralParam{},
+ Description: anthropic.String("Get the current weather in a given location"),
+ },
+ }},
})
if err != nil {
var apierr *anthropic.Error
@@ -150,62 +160,3 @@ func TestMessageCountTokensWithOptionalParams(t *testing.T) {
t.Fatalf("err should be nil: %s", err.Error())
}
}
-
-func TestMessageNewWithLargeMaxTokens(t *testing.T) {
- baseURL := "http://localhost:4010"
- if envURL, ok := os.LookupEnv("TEST_API_BASE_URL"); ok {
- baseURL = envURL
- }
- if !testutil.CheckTestServer(t, baseURL) {
- return
- }
- client := anthropic.NewClient(
- option.WithBaseURL(baseURL),
- option.WithAPIKey("my-anthropic-api-key"),
- )
- _, err := client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(23000)),
- Messages: anthropic.F([]anthropic.MessageParam{{}}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- })
- if err == nil {
- t.Fatalf("err should be set")
- }
- if !strings.Contains(err.Error(), "Streaming is strongly recommended") {
- t.Log(err.Error())
- t.Fatalf("err should be our streaming warning")
- }
-
- // with custom request timeout
- _, err = client.Messages.New(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(23000)),
- Messages: anthropic.F([]anthropic.MessageParam{{}}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- }, option.WithRequestTimeout(9999999999))
- if err != nil {
- t.Fatalf("err should be nil")
- }
-
- // with custom context timeout
- ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
- defer cancel()
- _, err = client.Messages.New(ctx, anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(23000)),
- Messages: anthropic.F([]anthropic.MessageParam{{}}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- })
- if err != nil {
- t.Fatalf("err should be nil")
- }
-
- // streaming does not error
- stream := client.Messages.NewStreaming(context.TODO(), anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(23000)),
- Messages: anthropic.F([]anthropic.MessageParam{{}}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- })
- if stream.Err() != nil {
- t.Log(stream.Err())
- t.Fatalf("err should be nil")
- }
-}
diff --git a/messagebatch.go b/messagebatch.go
index f691282..4be3fa3 100644
--- a/messagebatch.go
+++ b/messagebatch.go
@@ -4,22 +4,23 @@ package anthropic
import (
"context"
+ "encoding/json"
"errors"
"fmt"
"net/http"
"net/url"
- "reflect"
"time"
"github.com/anthropics/anthropic-sdk-go/internal/apijson"
"github.com/anthropics/anthropic-sdk-go/internal/apiquery"
- "github.com/anthropics/anthropic-sdk-go/internal/param"
"github.com/anthropics/anthropic-sdk-go/internal/requestconfig"
"github.com/anthropics/anthropic-sdk-go/option"
"github.com/anthropics/anthropic-sdk-go/packages/jsonl"
"github.com/anthropics/anthropic-sdk-go/packages/pagination"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
"github.com/anthropics/anthropic-sdk-go/shared"
- "github.com/tidwall/gjson"
+ "github.com/anthropics/anthropic-sdk-go/shared/constant"
)
// MessageBatchService contains methods and other services that help with
@@ -35,8 +36,8 @@ type MessageBatchService struct {
// NewMessageBatchService generates a new service that applies the given options to
// each request. These options are applied after the parent client's options (if
// there is one), and before any request-specific options.
-func NewMessageBatchService(opts ...option.RequestOption) (r *MessageBatchService) {
- r = &MessageBatchService{}
+func NewMessageBatchService(opts ...option.RequestOption) (r MessageBatchService) {
+ r = MessageBatchService{}
r.Options = opts
return
}
@@ -175,44 +176,23 @@ type DeletedMessageBatch struct {
// Deleted object type.
//
// For Message Batches, this is always `"message_batch_deleted"`.
- Type DeletedMessageBatchType `json:"type,required"`
- JSON deletedMessageBatchJSON `json:"-"`
-}
-
-// deletedMessageBatchJSON contains the JSON metadata for the struct
-// [DeletedMessageBatch]
-type deletedMessageBatchJSON struct {
- ID apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *DeletedMessageBatch) UnmarshalJSON(data []byte) (err error) {
+ Type constant.MessageBatchDeleted `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r DeletedMessageBatch) RawJSON() string { return r.JSON.raw }
+func (r *DeletedMessageBatch) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r deletedMessageBatchJSON) RawJSON() string {
- return r.raw
-}
-
-// Deleted object type.
-//
-// For Message Batches, this is always `"message_batch_deleted"`.
-type DeletedMessageBatchType string
-
-const (
- DeletedMessageBatchTypeMessageBatchDeleted DeletedMessageBatchType = "message_batch_deleted"
-)
-
-func (r DeletedMessageBatchType) IsKnown() bool {
- switch r {
- case DeletedMessageBatchTypeMessageBatchDeleted:
- return true
- }
- return false
-}
-
type MessageBatch struct {
// Unique object identifier.
//
@@ -220,10 +200,10 @@ type MessageBatch struct {
ID string `json:"id,required"`
// RFC 3339 datetime string representing the time at which the Message Batch was
// archived and its results became unavailable.
- ArchivedAt time.Time `json:"archived_at,required,nullable" format:"date-time"`
+ ArchivedAt time.Time `json:"archived_at,required" format:"date-time"`
// RFC 3339 datetime string representing the time at which cancellation was
// initiated for the Message Batch. Specified only if cancellation was initiated.
- CancelInitiatedAt time.Time `json:"cancel_initiated_at,required,nullable" format:"date-time"`
+ CancelInitiatedAt time.Time `json:"cancel_initiated_at,required" format:"date-time"`
// RFC 3339 datetime string representing the time at which the Message Batch was
// created.
CreatedAt time.Time `json:"created_at,required" format:"date-time"`
@@ -232,11 +212,13 @@ type MessageBatch struct {
//
// Processing ends when every request in a Message Batch has either succeeded,
// errored, canceled, or expired.
- EndedAt time.Time `json:"ended_at,required,nullable" format:"date-time"`
+ EndedAt time.Time `json:"ended_at,required" format:"date-time"`
// RFC 3339 datetime string representing the time at which the Message Batch will
// expire and end processing, which is 24 hours after creation.
ExpiresAt time.Time `json:"expires_at,required" format:"date-time"`
// Processing status of the Message Batch.
+ //
+ // Any of "in_progress", "canceling", "ended".
ProcessingStatus MessageBatchProcessingStatus `json:"processing_status,required"`
// Tallies requests within the Message Batch, categorized by their status.
//
@@ -249,38 +231,35 @@ type MessageBatch struct {
//
// Results in the file are not guaranteed to be in the same order as requests. Use
// the `custom_id` field to match results to requests.
- ResultsURL string `json:"results_url,required,nullable"`
+ ResultsURL string `json:"results_url,required"`
// Object type.
//
// For Message Batches, this is always `"message_batch"`.
- Type MessageBatchType `json:"type,required"`
- JSON messageBatchJSON `json:"-"`
-}
-
-// messageBatchJSON contains the JSON metadata for the struct [MessageBatch]
-type messageBatchJSON struct {
- ID apijson.Field
- ArchivedAt apijson.Field
- CancelInitiatedAt apijson.Field
- CreatedAt apijson.Field
- EndedAt apijson.Field
- ExpiresAt apijson.Field
- ProcessingStatus apijson.Field
- RequestCounts apijson.Field
- ResultsURL apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageBatch) UnmarshalJSON(data []byte) (err error) {
+ Type constant.MessageBatch `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ ArchivedAt resp.Field
+ CancelInitiatedAt resp.Field
+ CreatedAt resp.Field
+ EndedAt resp.Field
+ ExpiresAt resp.Field
+ ProcessingStatus resp.Field
+ RequestCounts resp.Field
+ ResultsURL resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageBatch) RawJSON() string { return r.JSON.raw }
+func (r *MessageBatch) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageBatchJSON) RawJSON() string {
- return r.raw
-}
-
// Processing status of the Message Batch.
type MessageBatchProcessingStatus string
@@ -290,144 +269,59 @@ const (
MessageBatchProcessingStatusEnded MessageBatchProcessingStatus = "ended"
)
-func (r MessageBatchProcessingStatus) IsKnown() bool {
- switch r {
- case MessageBatchProcessingStatusInProgress, MessageBatchProcessingStatusCanceling, MessageBatchProcessingStatusEnded:
- return true
- }
- return false
-}
-
-// Object type.
-//
-// For Message Batches, this is always `"message_batch"`.
-type MessageBatchType string
-
-const (
- MessageBatchTypeMessageBatch MessageBatchType = "message_batch"
-)
-
-func (r MessageBatchType) IsKnown() bool {
- switch r {
- case MessageBatchTypeMessageBatch:
- return true
- }
- return false
-}
-
type MessageBatchCanceledResult struct {
- Type MessageBatchCanceledResultType `json:"type,required"`
- JSON messageBatchCanceledResultJSON `json:"-"`
-}
-
-// messageBatchCanceledResultJSON contains the JSON metadata for the struct
-// [MessageBatchCanceledResult]
-type messageBatchCanceledResultJSON struct {
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageBatchCanceledResult) UnmarshalJSON(data []byte) (err error) {
+ Type constant.Canceled `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageBatchCanceledResult) RawJSON() string { return r.JSON.raw }
+func (r *MessageBatchCanceledResult) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageBatchCanceledResultJSON) RawJSON() string {
- return r.raw
-}
-
-func (r MessageBatchCanceledResult) implementsMessageBatchResult() {}
-
-type MessageBatchCanceledResultType string
-
-const (
- MessageBatchCanceledResultTypeCanceled MessageBatchCanceledResultType = "canceled"
-)
-
-func (r MessageBatchCanceledResultType) IsKnown() bool {
- switch r {
- case MessageBatchCanceledResultTypeCanceled:
- return true
- }
- return false
-}
-
type MessageBatchErroredResult struct {
- Error shared.ErrorResponse `json:"error,required"`
- Type MessageBatchErroredResultType `json:"type,required"`
- JSON messageBatchErroredResultJSON `json:"-"`
-}
-
-// messageBatchErroredResultJSON contains the JSON metadata for the struct
-// [MessageBatchErroredResult]
-type messageBatchErroredResultJSON struct {
- Error apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageBatchErroredResult) UnmarshalJSON(data []byte) (err error) {
+ Error shared.ErrorResponse `json:"error,required"`
+ Type constant.Errored `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Error resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageBatchErroredResult) RawJSON() string { return r.JSON.raw }
+func (r *MessageBatchErroredResult) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageBatchErroredResultJSON) RawJSON() string {
- return r.raw
-}
-
-func (r MessageBatchErroredResult) implementsMessageBatchResult() {}
-
-type MessageBatchErroredResultType string
-
-const (
- MessageBatchErroredResultTypeErrored MessageBatchErroredResultType = "errored"
-)
-
-func (r MessageBatchErroredResultType) IsKnown() bool {
- switch r {
- case MessageBatchErroredResultTypeErrored:
- return true
- }
- return false
-}
-
type MessageBatchExpiredResult struct {
- Type MessageBatchExpiredResultType `json:"type,required"`
- JSON messageBatchExpiredResultJSON `json:"-"`
-}
-
-// messageBatchExpiredResultJSON contains the JSON metadata for the struct
-// [MessageBatchExpiredResult]
-type messageBatchExpiredResultJSON struct {
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageBatchExpiredResult) UnmarshalJSON(data []byte) (err error) {
+ Type constant.Expired `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageBatchExpiredResult) RawJSON() string { return r.JSON.raw }
+func (r *MessageBatchExpiredResult) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageBatchExpiredResultJSON) RawJSON() string {
- return r.raw
-}
-
-func (r MessageBatchExpiredResult) implementsMessageBatchResult() {}
-
-type MessageBatchExpiredResultType string
-
-const (
- MessageBatchExpiredResultTypeExpired MessageBatchExpiredResultType = "expired"
-)
-
-func (r MessageBatchExpiredResultType) IsKnown() bool {
- switch r {
- case MessageBatchExpiredResultTypeExpired:
- return true
- }
- return false
-}
-
// This is a single line in the response `.jsonl` file and does not represent the
// response as a whole.
type MessageBatchIndividualResponse struct {
@@ -441,27 +335,23 @@ type MessageBatchIndividualResponse struct {
// Contains a Message output if processing was successful, an error response if
// processing failed, or the reason why processing was not attempted, such as
// cancellation or expiration.
- Result MessageBatchResult `json:"result,required"`
- JSON messageBatchIndividualResponseJSON `json:"-"`
-}
-
-// messageBatchIndividualResponseJSON contains the JSON metadata for the struct
-// [MessageBatchIndividualResponse]
-type messageBatchIndividualResponseJSON struct {
- CustomID apijson.Field
- Result apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageBatchIndividualResponse) UnmarshalJSON(data []byte) (err error) {
+ Result MessageBatchResultUnion `json:"result,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ CustomID resp.Field
+ Result resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageBatchIndividualResponse) RawJSON() string { return r.JSON.raw }
+func (r *MessageBatchIndividualResponse) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageBatchIndividualResponseJSON) RawJSON() string {
- return r.raw
-}
-
type MessageBatchRequestCounts struct {
// Number of requests in the Message Batch that have been canceled.
//
@@ -480,211 +370,439 @@ type MessageBatchRequestCounts struct {
// Number of requests in the Message Batch that have completed successfully.
//
// This is zero until processing of the entire Message Batch has ended.
- Succeeded int64 `json:"succeeded,required"`
- JSON messageBatchRequestCountsJSON `json:"-"`
-}
-
-// messageBatchRequestCountsJSON contains the JSON metadata for the struct
-// [MessageBatchRequestCounts]
-type messageBatchRequestCountsJSON struct {
- Canceled apijson.Field
- Errored apijson.Field
- Expired apijson.Field
- Processing apijson.Field
- Succeeded apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *MessageBatchRequestCounts) UnmarshalJSON(data []byte) (err error) {
+ Succeeded int64 `json:"succeeded,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Canceled resp.Field
+ Errored resp.Field
+ Expired resp.Field
+ Processing resp.Field
+ Succeeded resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageBatchRequestCounts) RawJSON() string { return r.JSON.raw }
+func (r *MessageBatchRequestCounts) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r messageBatchRequestCountsJSON) RawJSON() string {
- return r.raw
-}
-
-// Processing result for this request.
-//
-// Contains a Message output if processing was successful, an error response if
-// processing failed, or the reason why processing was not attempted, such as
-// cancellation or expiration.
-type MessageBatchResult struct {
- Type MessageBatchResultType `json:"type,required"`
- Error shared.ErrorResponse `json:"error"`
- Message Message `json:"message"`
- JSON messageBatchResultJSON `json:"-"`
- union MessageBatchResultUnion
-}
-
-// messageBatchResultJSON contains the JSON metadata for the struct
-// [MessageBatchResult]
-type messageBatchResultJSON struct {
- Type apijson.Field
- Error apijson.Field
- Message apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r messageBatchResultJSON) RawJSON() string {
- return r.raw
-}
-
-func (r *MessageBatchResult) UnmarshalJSON(data []byte) (err error) {
- *r = MessageBatchResult{}
- err = apijson.UnmarshalRoot(data, &r.union)
- if err != nil {
- return err
- }
- return apijson.Port(r.union, &r)
-}
-
-// AsUnion returns a [MessageBatchResultUnion] interface which you can cast to the
-// specific types for more type safety.
+// MessageBatchResultUnion contains all possible properties and values from
+// [MessageBatchSucceededResult], [MessageBatchErroredResult],
+// [MessageBatchCanceledResult], [MessageBatchExpiredResult].
//
-// Possible runtime types of the union are [MessageBatchSucceededResult],
-// [MessageBatchErroredResult], [MessageBatchCanceledResult],
-// [MessageBatchExpiredResult].
-func (r MessageBatchResult) AsUnion() MessageBatchResultUnion {
- return r.union
-}
-
-// Processing result for this request.
+// Use the [MessageBatchResultUnion.AsAny] method to switch on the variant.
//
-// Contains a Message output if processing was successful, an error response if
-// processing failed, or the reason why processing was not attempted, such as
-// cancellation or expiration.
+// Use the methods beginning with 'As' to cast the union to one of its variants.
+type MessageBatchResultUnion struct {
+ // This field is from variant [MessageBatchSucceededResult].
+ Message Message `json:"message"`
+ // Any of "succeeded", "errored", "canceled", "expired".
+ Type string `json:"type"`
+ // This field is from variant [MessageBatchErroredResult].
+ Error shared.ErrorResponse `json:"error"`
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ Error resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Use the following switch statement to find the correct variant
//
-// Union satisfied by [MessageBatchSucceededResult], [MessageBatchErroredResult],
-// [MessageBatchCanceledResult] or [MessageBatchExpiredResult].
-type MessageBatchResultUnion interface {
- implementsMessageBatchResult()
-}
-
-func init() {
- apijson.RegisterUnion(
- reflect.TypeOf((*MessageBatchResultUnion)(nil)).Elem(),
- "type",
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(MessageBatchSucceededResult{}),
- DiscriminatorValue: "succeeded",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(MessageBatchErroredResult{}),
- DiscriminatorValue: "errored",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(MessageBatchCanceledResult{}),
- DiscriminatorValue: "canceled",
- },
- apijson.UnionVariant{
- TypeFilter: gjson.JSON,
- Type: reflect.TypeOf(MessageBatchExpiredResult{}),
- DiscriminatorValue: "expired",
- },
- )
-}
-
-type MessageBatchResultType string
-
-const (
- MessageBatchResultTypeSucceeded MessageBatchResultType = "succeeded"
- MessageBatchResultTypeErrored MessageBatchResultType = "errored"
- MessageBatchResultTypeCanceled MessageBatchResultType = "canceled"
- MessageBatchResultTypeExpired MessageBatchResultType = "expired"
-)
-
-func (r MessageBatchResultType) IsKnown() bool {
- switch r {
- case MessageBatchResultTypeSucceeded, MessageBatchResultTypeErrored, MessageBatchResultTypeCanceled, MessageBatchResultTypeExpired:
- return true
+// switch variant := MessageBatchResultUnion.AsAny().(type) {
+// case MessageBatchSucceededResult:
+// case MessageBatchErroredResult:
+// case MessageBatchCanceledResult:
+// case MessageBatchExpiredResult:
+// default:
+// fmt.Errorf("no variant present")
+// }
+func (u MessageBatchResultUnion) AsAny() any {
+ switch u.Type {
+ case "succeeded":
+ return u.AsSucceededResult()
+ case "errored":
+ return u.AsErroredResult()
+ case "canceled":
+ return u.AsCanceledResult()
+ case "expired":
+ return u.AsExpiredResult()
}
- return false
+ return nil
}
-type MessageBatchSucceededResult struct {
- Message Message `json:"message,required"`
- Type MessageBatchSucceededResultType `json:"type,required"`
- JSON messageBatchSucceededResultJSON `json:"-"`
+func (u MessageBatchResultUnion) AsSucceededResult() (v MessageBatchSucceededResult) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-// messageBatchSucceededResultJSON contains the JSON metadata for the struct
-// [MessageBatchSucceededResult]
-type messageBatchSucceededResultJSON struct {
- Message apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
+func (u MessageBatchResultUnion) AsErroredResult() (v MessageBatchErroredResult) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r *MessageBatchSucceededResult) UnmarshalJSON(data []byte) (err error) {
- return apijson.UnmarshalRoot(data, r)
+func (u MessageBatchResultUnion) AsCanceledResult() (v MessageBatchCanceledResult) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r messageBatchSucceededResultJSON) RawJSON() string {
- return r.raw
+func (u MessageBatchResultUnion) AsExpiredResult() (v MessageBatchExpiredResult) {
+ apijson.UnmarshalRoot(json.RawMessage(u.JSON.raw), &v)
+ return
}
-func (r MessageBatchSucceededResult) implementsMessageBatchResult() {}
-
-type MessageBatchSucceededResultType string
+// Returns the unmodified JSON received from the API
+func (u MessageBatchResultUnion) RawJSON() string { return u.JSON.raw }
-const (
- MessageBatchSucceededResultTypeSucceeded MessageBatchSucceededResultType = "succeeded"
-)
+func (r *MessageBatchResultUnion) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
+}
-func (r MessageBatchSucceededResultType) IsKnown() bool {
- switch r {
- case MessageBatchSucceededResultTypeSucceeded:
- return true
- }
- return false
+type MessageBatchSucceededResult struct {
+ Message Message `json:"message,required"`
+ Type constant.Succeeded `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ Message resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
+}
+
+// Returns the unmodified JSON received from the API
+func (r MessageBatchSucceededResult) RawJSON() string { return r.JSON.raw }
+func (r *MessageBatchSucceededResult) UnmarshalJSON(data []byte) error {
+ return apijson.UnmarshalRoot(data, r)
}
type MessageBatchNewParams struct {
// List of requests for prompt completion. Each is an individual request to create
// a Message.
- Requests param.Field[[]MessageBatchNewParamsRequest] `json:"requests,required"`
+ Requests []MessageBatchNewParamsRequest `json:"requests,omitzero,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f MessageBatchNewParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
func (r MessageBatchNewParams) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow MessageBatchNewParams
+ return param.MarshalObject(r, (*shadow)(&r))
}
+// The properties CustomID, Params are required.
type MessageBatchNewParamsRequest struct {
// Developer-provided ID created for each request in a Message Batch. Useful for
// matching results to requests, as results may be given out of request order.
//
// Must be unique for each request within the Message Batch.
- CustomID param.Field[string] `json:"custom_id,required"`
+ CustomID string `json:"custom_id,required"`
// Messages API creation parameters for the individual request.
//
// See the [Messages API reference](/en/api/messages) for full documentation on
// available parameters.
- Params param.Field[MessageNewParams] `json:"params,required"`
+ Params MessageBatchNewParamsRequestParams `json:"params,omitzero,required"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f MessageBatchNewParamsRequest) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
func (r MessageBatchNewParamsRequest) MarshalJSON() (data []byte, err error) {
- return apijson.MarshalRoot(r)
+ type shadow MessageBatchNewParamsRequest
+ return param.MarshalObject(r, (*shadow)(&r))
+}
+
+// Messages API creation parameters for the individual request.
+//
+// See the [Messages API reference](/en/api/messages) for full documentation on
+// available parameters.
+//
+// The properties MaxTokens, Messages, Model are required.
+type MessageBatchNewParamsRequestParams struct {
+ // The maximum number of tokens to generate before stopping.
+ //
+ // Note that our models may stop _before_ reaching this maximum. This parameter
+ // only specifies the absolute maximum number of tokens to generate.
+ //
+ // Different models have different maximum values for this parameter. See
+ // [models](https://docs.anthropic.com/en/docs/models-overview) for details.
+ MaxTokens int64 `json:"max_tokens,required"`
+ // Input messages.
+ //
+ // Our models are trained to operate on alternating `user` and `assistant`
+ // conversational turns. When creating a new `Message`, you specify the prior
+ // conversational turns with the `messages` parameter, and the model then generates
+ // the next `Message` in the conversation. Consecutive `user` or `assistant` turns
+ // in your request will be combined into a single turn.
+ //
+ // Each input message must be an object with a `role` and `content`. You can
+ // specify a single `user`-role message, or you can include multiple `user` and
+ // `assistant` messages.
+ //
+ // If the final message uses the `assistant` role, the response content will
+ // continue immediately from the content in that message. This can be used to
+ // constrain part of the model's response.
+ //
+ // Example with a single `user` message:
+ //
+ // ```json
+ // [{ "role": "user", "content": "Hello, Claude" }]
+ // ```
+ //
+ // Example with multiple conversational turns:
+ //
+ // ```json
+ // [
+ //
+ // { "role": "user", "content": "Hello there." },
+ // { "role": "assistant", "content": "Hi, I'm Claude. How can I help you?" },
+ // { "role": "user", "content": "Can you explain LLMs in plain English?" }
+ //
+ // ]
+ // ```
+ //
+ // Example with a partially-filled response from Claude:
+ //
+ // ```json
+ // [
+ //
+ // {
+ // "role": "user",
+ // "content": "What's the Greek name for Sun? (A) Sol (B) Helios (C) Sun"
+ // },
+ // { "role": "assistant", "content": "The best answer is (" }
+ //
+ // ]
+ // ```
+ //
+ // Each input message `content` may be either a single `string` or an array of
+ // content blocks, where each block has a specific `type`. Using a `string` for
+ // `content` is shorthand for an array of one content block of type `"text"`. The
+ // following input messages are equivalent:
+ //
+ // ```json
+ // { "role": "user", "content": "Hello, Claude" }
+ // ```
+ //
+ // ```json
+ // { "role": "user", "content": [{ "type": "text", "text": "Hello, Claude" }] }
+ // ```
+ //
+ // Starting with Claude 3 models, you can also send image content blocks:
+ //
+ // ```json
+ //
+ // {
+ // "role": "user",
+ // "content": [
+ // {
+ // "type": "image",
+ // "source": {
+ // "type": "base64",
+ // "media_type": "image/jpeg",
+ // "data": "/9j/4AAQSkZJRg..."
+ // }
+ // },
+ // { "type": "text", "text": "What is in this image?" }
+ // ]
+ // }
+ //
+ // ```
+ //
+ // We currently support the `base64` source type for images, and the `image/jpeg`,
+ // `image/png`, `image/gif`, and `image/webp` media types.
+ //
+ // See [examples](https://docs.anthropic.com/en/api/messages-examples#vision) for
+ // more input examples.
+ //
+ // Note that if you want to include a
+ // [system prompt](https://docs.anthropic.com/en/docs/system-prompts), you can use
+ // the top-level `system` parameter — there is no `"system"` role for input
+ // messages in the Messages API.
+ Messages []MessageParam `json:"messages,omitzero,required"`
+ // The model that will complete your prompt.\n\nSee
+ // [models](https://docs.anthropic.com/en/docs/models-overview) for additional
+ // details and options.
+ Model Model `json:"model,omitzero,required"`
+ // Whether to incrementally stream the response using server-sent events.
+ //
+ // See [streaming](https://docs.anthropic.com/en/api/messages-streaming) for
+ // details.
+ Stream param.Opt[bool] `json:"stream,omitzero"`
+ // Amount of randomness injected into the response.
+ //
+ // Defaults to `1.0`. Ranges from `0.0` to `1.0`. Use `temperature` closer to `0.0`
+ // for analytical / multiple choice, and closer to `1.0` for creative and
+ // generative tasks.
+ //
+ // Note that even with `temperature` of `0.0`, the results will not be fully
+ // deterministic.
+ Temperature param.Opt[float64] `json:"temperature,omitzero"`
+ // Only sample from the top K options for each subsequent token.
+ //
+ // Used to remove "long tail" low probability responses.
+ // [Learn more technical details here](https://towardsdatascience.com/how-to-sample-from-language-models-682bceb97277).
+ //
+ // Recommended for advanced use cases only. You usually only need to use
+ // `temperature`.
+ TopK param.Opt[int64] `json:"top_k,omitzero"`
+ // Use nucleus sampling.
+ //
+ // In nucleus sampling, we compute the cumulative distribution over all the options
+ // for each subsequent token in decreasing probability order and cut it off once it
+ // reaches a particular probability specified by `top_p`. You should either alter
+ // `temperature` or `top_p`, but not both.
+ //
+ // Recommended for advanced use cases only. You usually only need to use
+ // `temperature`.
+ TopP param.Opt[float64] `json:"top_p,omitzero"`
+ // An object describing metadata about the request.
+ Metadata MetadataParam `json:"metadata,omitzero"`
+ // Custom text sequences that will cause the model to stop generating.
+ //
+ // Our models will normally stop when they have naturally completed their turn,
+ // which will result in a response `stop_reason` of `"end_turn"`.
+ //
+ // If you want the model to stop generating when it encounters custom strings of
+ // text, you can use the `stop_sequences` parameter. If the model encounters one of
+ // the custom sequences, the response `stop_reason` value will be `"stop_sequence"`
+ // and the response `stop_sequence` value will contain the matched stop sequence.
+ StopSequences []string `json:"stop_sequences,omitzero"`
+ // System prompt.
+ //
+ // A system prompt is a way of providing context and instructions to Claude, such
+ // as specifying a particular goal or role. See our
+ // [guide to system prompts](https://docs.anthropic.com/en/docs/system-prompts).
+ System []TextBlockParam `json:"system,omitzero"`
+ // Configuration for enabling Claude's extended thinking.
+ //
+ // When enabled, responses include `thinking` content blocks showing Claude's
+ // thinking process before the final answer. Requires a minimum budget of 1,024
+ // tokens and counts towards your `max_tokens` limit.
+ //
+ // See
+ // [extended thinking](https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking)
+ // for details.
+ Thinking ThinkingConfigParamUnion `json:"thinking,omitzero"`
+ // How the model should use the provided tools. The model can use a specific tool,
+ // any available tool, decide by itself, or not use tools at all.
+ ToolChoice ToolChoiceUnionParam `json:"tool_choice,omitzero"`
+ // Definitions of tools that the model may use.
+ //
+ // If you include `tools` in your API request, the model may return `tool_use`
+ // content blocks that represent the model's use of those tools. You can then run
+ // those tools using the tool input generated by the model and then optionally
+ // return results back to the model using `tool_result` content blocks.
+ //
+ // Each tool definition includes:
+ //
+ // - `name`: Name of the tool.
+ // - `description`: Optional, but strongly-recommended description of the tool.
+ // - `input_schema`: [JSON schema](https://json-schema.org/draft/2020-12) for the
+ // tool `input` shape that the model will produce in `tool_use` output content
+ // blocks.
+ //
+ // For example, if you defined `tools` as:
+ //
+ // ```json
+ // [
+ //
+ // {
+ // "name": "get_stock_price",
+ // "description": "Get the current stock price for a given ticker symbol.",
+ // "input_schema": {
+ // "type": "object",
+ // "properties": {
+ // "ticker": {
+ // "type": "string",
+ // "description": "The stock ticker symbol, e.g. AAPL for Apple Inc."
+ // }
+ // },
+ // "required": ["ticker"]
+ // }
+ // }
+ //
+ // ]
+ // ```
+ //
+ // And then asked the model "What's the S&P 500 at today?", the model might produce
+ // `tool_use` content blocks in the response like this:
+ //
+ // ```json
+ // [
+ //
+ // {
+ // "type": "tool_use",
+ // "id": "toolu_01D7FLrfh4GYq7yT1ULFeyMV",
+ // "name": "get_stock_price",
+ // "input": { "ticker": "^GSPC" }
+ // }
+ //
+ // ]
+ // ```
+ //
+ // You might then run your `get_stock_price` tool with `{"ticker": "^GSPC"}` as an
+ // input, and return the following back to the model in a subsequent `user`
+ // message:
+ //
+ // ```json
+ // [
+ //
+ // {
+ // "type": "tool_result",
+ // "tool_use_id": "toolu_01D7FLrfh4GYq7yT1ULFeyMV",
+ // "content": "259.75 USD"
+ // }
+ //
+ // ]
+ // ```
+ //
+ // Tools can be used for workflows that include running client-side tools and
+ // functions, or more generally whenever you want the model to produce a particular
+ // JSON structure of output.
+ //
+ // See our [guide](https://docs.anthropic.com/en/docs/tool-use) for more details.
+ Tools []ToolUnionParam `json:"tools,omitzero"`
+ paramObj
+}
+
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f MessageBatchNewParamsRequestParams) IsPresent() bool {
+ return !param.IsOmitted(f) && !f.IsNull()
+}
+func (r MessageBatchNewParamsRequestParams) MarshalJSON() (data []byte, err error) {
+ type shadow MessageBatchNewParamsRequestParams
+ return param.MarshalObject(r, (*shadow)(&r))
}
type MessageBatchListParams struct {
// ID of the object to use as a cursor for pagination. When provided, returns the
// page of results immediately after this object.
- AfterID param.Field[string] `query:"after_id"`
+ AfterID param.Opt[string] `query:"after_id,omitzero" json:"-"`
// ID of the object to use as a cursor for pagination. When provided, returns the
// page of results immediately before this object.
- BeforeID param.Field[string] `query:"before_id"`
+ BeforeID param.Opt[string] `query:"before_id,omitzero" json:"-"`
// Number of items to return per page.
//
// Defaults to `20`. Ranges from `1` to `1000`.
- Limit param.Field[int64] `query:"limit"`
+ Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f MessageBatchListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
// URLQuery serializes [MessageBatchListParams]'s query parameters as `url.Values`.
func (r MessageBatchListParams) URLQuery() (v url.Values) {
return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
diff --git a/messagebatch_test.go b/messagebatch_test.go
index 0fc6bf5..dc26d43 100644
--- a/messagebatch_test.go
+++ b/messagebatch_test.go
@@ -26,53 +26,61 @@ func TestMessageBatchNew(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Messages.Batches.New(context.TODO(), anthropic.MessageBatchNewParams{
- Requests: anthropic.F([]anthropic.MessageBatchNewParamsRequest{{
- CustomID: anthropic.F("my-custom-id-1"),
- Params: anthropic.F(anthropic.MessageNewParams{
- MaxTokens: anthropic.F(int64(1024)),
- Messages: anthropic.F([]anthropic.MessageParam{{
- Content: anthropic.F([]anthropic.ContentBlockParamUnion{anthropic.TextBlockParam{Text: anthropic.F("What is a quaternion?"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)}), Citations: anthropic.F([]anthropic.TextCitationParamUnion{anthropic.CitationCharLocationParam{CitedText: anthropic.F("cited_text"), DocumentIndex: anthropic.F(int64(0)), DocumentTitle: anthropic.F("x"), EndCharIndex: anthropic.F(int64(0)), StartCharIndex: anthropic.F(int64(0)), Type: anthropic.F(anthropic.CitationCharLocationParamTypeCharLocation)}})}}),
- Role: anthropic.F(anthropic.MessageParamRoleUser),
- }}),
- Model: anthropic.F(anthropic.ModelClaude3_7SonnetLatest),
- Metadata: anthropic.F(anthropic.MetadataParam{
- UserID: anthropic.F("13803d75-b4b5-4c3e-b2a2-6f21399b021b"),
- }),
- StopSequences: anthropic.F([]string{"string"}),
- System: anthropic.F([]anthropic.TextBlockParam{{Text: anthropic.F("x"), Type: anthropic.F(anthropic.TextBlockParamTypeText), CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral)})}}),
- Temperature: anthropic.F(1.000000),
- Thinking: anthropic.F[anthropic.ThinkingConfigParamUnion](anthropic.ThinkingConfigEnabledParam{
- BudgetTokens: anthropic.F(int64(1024)),
- Type: anthropic.F(anthropic.ThinkingConfigEnabledTypeEnabled),
- }),
- ToolChoice: anthropic.F[anthropic.ToolChoiceUnionParam](anthropic.ToolChoiceAutoParam{
- Type: anthropic.F(anthropic.ToolChoiceAutoTypeAuto),
- DisableParallelToolUse: anthropic.F(true),
- }),
- Tools: anthropic.F([]anthropic.ToolUnionUnionParam{anthropic.ToolParam{
- Description: anthropic.F("Get the current weather in a given location"),
- Name: anthropic.F("x"),
- InputSchema: anthropic.F[interface{}](map[string]interface{}{
- "type": "object",
- "properties": map[string]interface{}{
- "location": map[string]interface{}{
- "description": "The city and state, e.g. San Francisco, CA",
- "type": "string",
- },
- "unit": map[string]interface{}{
- "description": "Unit for the output - one of (celsius, fahrenheit)",
- "type": "string",
+ Requests: []anthropic.MessageBatchNewParamsRequest{{
+ CustomID: "my-custom-id-1",
+ Params: anthropic.MessageBatchNewParamsRequestParams{
+ MaxTokens: 1024,
+ Messages: []anthropic.MessageParam{{
+ Content: []anthropic.ContentBlockParamUnion{{
+ OfRequestTextBlock: &anthropic.TextBlockParam{Text: "What is a quaternion?", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}},
+ }},
+ Role: anthropic.MessageParamRoleUser,
+ }},
+ Model: anthropic.ModelClaude3_7SonnetLatest,
+ Metadata: anthropic.MetadataParam{
+ UserID: anthropic.String("13803d75-b4b5-4c3e-b2a2-6f21399b021b"),
+ },
+ StopSequences: []string{"string"},
+ Stream: anthropic.Bool(true),
+ System: []anthropic.TextBlockParam{{Text: "x", CacheControl: anthropic.CacheControlEphemeralParam{}, Citations: []anthropic.TextCitationParamUnion{{
+ OfRequestCharLocationCitation: &anthropic.CitationCharLocationParam{CitedText: "cited_text", DocumentIndex: 0, DocumentTitle: anthropic.String("x"), EndCharIndex: 0, StartCharIndex: 0},
+ }}}},
+ Temperature: anthropic.Float(1),
+ Thinking: anthropic.ThinkingConfigParamUnion{
+ OfThinkingConfigEnabled: &anthropic.ThinkingConfigEnabledParam{
+ BudgetTokens: 1024,
+ },
+ },
+ ToolChoice: anthropic.ToolChoiceUnionParam{
+ OfToolChoiceAuto: &anthropic.ToolChoiceAutoParam{
+ DisableParallelToolUse: anthropic.Bool(true),
+ },
+ },
+ Tools: []anthropic.ToolUnionParam{{
+ OfTool: &anthropic.ToolParam{
+ InputSchema: anthropic.ToolInputSchemaParam{
+ Properties: map[string]interface{}{
+ "location": map[string]interface{}{
+ "description": "The city and state, e.g. San Francisco, CA",
+ "type": "string",
+ },
+ "unit": map[string]interface{}{
+ "description": "Unit for the output - one of (celsius, fahrenheit)",
+ "type": "string",
+ },
},
},
- }),
- CacheControl: anthropic.F(anthropic.CacheControlEphemeralParam{
- Type: anthropic.F(anthropic.CacheControlEphemeralTypeEphemeral),
- }),
- }}),
- TopK: anthropic.F(int64(5)),
- TopP: anthropic.F(0.700000),
- }),
- }}),
+ Name: "name",
+ CacheControl: anthropic.CacheControlEphemeralParam{},
+ Description: anthropic.String("Get the current weather in a given location"),
+ },
+ }},
+ TopK: anthropic.Int(5),
+ TopP: anthropic.Float(0.7),
+ },
+ }},
})
if err != nil {
var apierr *anthropic.Error
@@ -118,9 +126,9 @@ func TestMessageBatchListWithOptionalParams(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Messages.Batches.List(context.TODO(), anthropic.MessageBatchListParams{
- AfterID: anthropic.F("after_id"),
- BeforeID: anthropic.F("before_id"),
- Limit: anthropic.F(int64(1)),
+ AfterID: anthropic.String("after_id"),
+ BeforeID: anthropic.String("before_id"),
+ Limit: anthropic.Int(1),
})
if err != nil {
var apierr *anthropic.Error
diff --git a/model.go b/model.go
index 09e542d..ff06749 100644
--- a/model.go
+++ b/model.go
@@ -12,10 +12,12 @@ import (
"github.com/anthropics/anthropic-sdk-go/internal/apijson"
"github.com/anthropics/anthropic-sdk-go/internal/apiquery"
- "github.com/anthropics/anthropic-sdk-go/internal/param"
"github.com/anthropics/anthropic-sdk-go/internal/requestconfig"
"github.com/anthropics/anthropic-sdk-go/option"
"github.com/anthropics/anthropic-sdk-go/packages/pagination"
+ "github.com/anthropics/anthropic-sdk-go/packages/param"
+ "github.com/anthropics/anthropic-sdk-go/packages/resp"
+ "github.com/anthropics/anthropic-sdk-go/shared/constant"
)
// ModelService contains methods and other services that help with interacting with
@@ -31,8 +33,8 @@ type ModelService struct {
// NewModelService generates a new service that applies the given options to each
// request. These options are applied after the parent client's options (if there
// is one), and before any request-specific options.
-func NewModelService(opts ...option.RequestOption) (r *ModelService) {
- r = &ModelService{}
+func NewModelService(opts ...option.RequestOption) (r ModelService) {
+ r = ModelService{}
r.Options = opts
return
}
@@ -92,58 +94,43 @@ type ModelInfo struct {
// Object type.
//
// For Models, this is always `"model"`.
- Type ModelInfoType `json:"type,required"`
- JSON modelInfoJSON `json:"-"`
+ Type constant.Model `json:"type,required"`
+ // Metadata for the response, check the presence of optional fields with the
+ // [resp.Field.IsPresent] method.
+ JSON struct {
+ ID resp.Field
+ CreatedAt resp.Field
+ DisplayName resp.Field
+ Type resp.Field
+ ExtraFields map[string]resp.Field
+ raw string
+ } `json:"-"`
}
-// modelInfoJSON contains the JSON metadata for the struct [ModelInfo]
-type modelInfoJSON struct {
- ID apijson.Field
- CreatedAt apijson.Field
- DisplayName apijson.Field
- Type apijson.Field
- raw string
- ExtraFields map[string]apijson.Field
-}
-
-func (r *ModelInfo) UnmarshalJSON(data []byte) (err error) {
+// Returns the unmodified JSON received from the API
+func (r ModelInfo) RawJSON() string { return r.JSON.raw }
+func (r *ModelInfo) UnmarshalJSON(data []byte) error {
return apijson.UnmarshalRoot(data, r)
}
-func (r modelInfoJSON) RawJSON() string {
- return r.raw
-}
-
-// Object type.
-//
-// For Models, this is always `"model"`.
-type ModelInfoType string
-
-const (
- ModelInfoTypeModel ModelInfoType = "model"
-)
-
-func (r ModelInfoType) IsKnown() bool {
- switch r {
- case ModelInfoTypeModel:
- return true
- }
- return false
-}
-
type ModelListParams struct {
// ID of the object to use as a cursor for pagination. When provided, returns the
// page of results immediately after this object.
- AfterID param.Field[string] `query:"after_id"`
+ AfterID param.Opt[string] `query:"after_id,omitzero" json:"-"`
// ID of the object to use as a cursor for pagination. When provided, returns the
// page of results immediately before this object.
- BeforeID param.Field[string] `query:"before_id"`
+ BeforeID param.Opt[string] `query:"before_id,omitzero" json:"-"`
// Number of items to return per page.
//
// Defaults to `20`. Ranges from `1` to `1000`.
- Limit param.Field[int64] `query:"limit"`
+ Limit param.Opt[int64] `query:"limit,omitzero" json:"-"`
+ paramObj
}
+// IsPresent returns true if the field's value is not omitted and not the JSON
+// "null". To check if this field is omitted, use [param.IsOmitted].
+func (f ModelListParams) IsPresent() bool { return !param.IsOmitted(f) && !f.IsNull() }
+
// URLQuery serializes [ModelListParams]'s query parameters as `url.Values`.
func (r ModelListParams) URLQuery() (v url.Values) {
return apiquery.MarshalWithSettings(r, apiquery.QuerySettings{
diff --git a/model_test.go b/model_test.go
index 5a53add..9cec548 100644
--- a/model_test.go
+++ b/model_test.go
@@ -48,9 +48,9 @@ func TestModelListWithOptionalParams(t *testing.T) {
option.WithAPIKey("my-anthropic-api-key"),
)
_, err := client.Models.List(context.TODO(), anthropic.ModelListParams{
- AfterID: anthropic.F("after_id"),
- BeforeID: anthropic.F("before_id"),
- Limit: anthropic.F(int64(1)),
+ AfterID: anthropic.String("after_id"),
+ BeforeID: anthropic.String("before_id"),
+ Limit: anthropic.Int(1),
})
if err != nil {
var apierr *anthropic.Error
diff --git a/option/requestoption.go b/option/requestoption.go
index 5594c6d..1a82a80 100644
--- a/option/requestoption.go
+++ b/option/requestoption.go
@@ -9,6 +9,7 @@ import (
"log"
"net/http"
"net/url"
+ "strings"
"time"
"github.com/anthropics/anthropic-sdk-go/internal/requestconfig"
@@ -20,27 +21,32 @@ import (
// options pattern in our [README].
//
// [README]: https://pkg.go.dev/github.com/anthropics/anthropic-sdk-go#readme-requestoptions
-type RequestOption = func(*requestconfig.RequestConfig) error
+type RequestOption = requestconfig.RequestOption
// WithBaseURL returns a RequestOption that sets the BaseURL for the client.
+//
+// For security reasons, ensure that the base URL is trusted.
func WithBaseURL(base string) RequestOption {
u, err := url.Parse(base)
if err != nil {
log.Fatalf("failed to parse BaseURL: %s\n", err)
}
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
+ if u.Path != "" && !strings.HasSuffix(u.Path, "/") {
+ u.Path += "/"
+ }
r.BaseURL = u
return nil
- }
+ })
}
// WithHTTPClient returns a RequestOption that changes the underlying [http.Client] used to make this
// request, which by default is [http.DefaultClient].
func WithHTTPClient(client *http.Client) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
r.HTTPClient = client
return nil
- }
+ })
}
// MiddlewareNext is a function which is called by a middleware to pass an HTTP request
@@ -55,10 +61,10 @@ type Middleware = func(*http.Request, MiddlewareNext) (*http.Response, error)
// WithMiddleware returns a RequestOption that applies the given middleware
// to the requests made. Each middleware will execute in the order they were given.
func WithMiddleware(middlewares ...Middleware) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
r.Middlewares = append(r.Middlewares, middlewares...)
return nil
- }
+ })
}
// WithMaxRetries returns a RequestOption that sets the maximum number of retries that the client
@@ -70,68 +76,68 @@ func WithMaxRetries(retries int) RequestOption {
if retries < 0 {
panic("option: cannot have fewer than 0 retries")
}
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
r.MaxRetries = retries
return nil
- }
+ })
}
// WithHeader returns a RequestOption that sets the header value to the associated key. It overwrites
// any value if there was one already present.
func WithHeader(key, value string) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
r.Request.Header.Set(key, value)
return nil
- }
+ })
}
// WithHeaderAdd returns a RequestOption that adds the header value to the associated key. It appends
// onto any existing values.
func WithHeaderAdd(key, value string) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
r.Request.Header.Add(key, value)
return nil
- }
+ })
}
// WithHeaderDel returns a RequestOption that deletes the header value(s) associated with the given key.
func WithHeaderDel(key string) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
r.Request.Header.Del(key)
return nil
- }
+ })
}
// WithQuery returns a RequestOption that sets the query value to the associated key. It overwrites
// any value if there was one already present.
func WithQuery(key, value string) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
query := r.Request.URL.Query()
query.Set(key, value)
r.Request.URL.RawQuery = query.Encode()
return nil
- }
+ })
}
// WithQueryAdd returns a RequestOption that adds the query value to the associated key. It appends
// onto any existing values.
func WithQueryAdd(key, value string) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
query := r.Request.URL.Query()
query.Add(key, value)
r.Request.URL.RawQuery = query.Encode()
return nil
- }
+ })
}
// WithQueryDel returns a RequestOption that deletes the query value(s) associated with the key.
func WithQueryDel(key string) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
query := r.Request.URL.Query()
query.Del(key)
r.Request.URL.RawQuery = query.Encode()
return nil
- }
+ })
}
// WithJSONSet returns a RequestOption that sets the body's JSON value associated with the key.
@@ -139,7 +145,7 @@ func WithQueryDel(key string) RequestOption {
//
// [sjson format]: https://github.com/tidwall/sjson
func WithJSONSet(key string, value interface{}) RequestOption {
- return func(r *requestconfig.RequestConfig) (err error) {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) (err error) {
if buffer, ok := r.Body.(*bytes.Buffer); ok {
b := buffer.Bytes()
b, err = sjson.SetBytes(b, key, value)
@@ -151,7 +157,7 @@ func WithJSONSet(key string, value interface{}) RequestOption {
}
return fmt.Errorf("cannot use WithJSONSet on a body that is not serialized as *bytes.Buffer")
- }
+ })
}
// WithJSONDel returns a RequestOption that deletes the body's JSON value associated with the key.
@@ -159,7 +165,7 @@ func WithJSONSet(key string, value interface{}) RequestOption {
//
// [sjson format]: https://github.com/tidwall/sjson
func WithJSONDel(key string) RequestOption {
- return func(r *requestconfig.RequestConfig) (err error) {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) (err error) {
if buffer, ok := r.Body.(*bytes.Buffer); ok {
b := buffer.Bytes()
b, err = sjson.DeleteBytes(b, key)
@@ -171,24 +177,24 @@ func WithJSONDel(key string) RequestOption {
}
return fmt.Errorf("cannot use WithJSONDel on a body that is not serialized as *bytes.Buffer")
- }
+ })
}
// WithResponseBodyInto returns a RequestOption that overwrites the deserialization target with
// the given destination. If provided, we don't deserialize into the default struct.
func WithResponseBodyInto(dst any) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
r.ResponseBodyInto = dst
return nil
- }
+ })
}
// WithResponseInto returns a RequestOption that copies the [*http.Response] into the given address.
func WithResponseInto(dst **http.Response) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
r.ResponseInto = dst
return nil
- }
+ })
}
// WithRequestBody returns a RequestOption that provides a custom serialized body with the given
@@ -196,7 +202,7 @@ func WithResponseInto(dst **http.Response) RequestOption {
//
// body accepts an io.Reader or raw []bytes.
func WithRequestBody(contentType string, body any) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
+ return requestconfig.RequestOptionFunc(func(r *requestconfig.RequestConfig) error {
if reader, ok := body.(io.Reader); ok {
r.Body = reader
return r.Apply(WithHeader("Content-Type", contentType))
@@ -208,17 +214,17 @@ func WithRequestBody(contentType string, body any) RequestOption {
}
return fmt.Errorf("body must be a byte slice or implement io.Reader")
- }
+ })
}
// WithRequestTimeout returns a RequestOption that sets the timeout for
// each request attempt. This should be smaller than the timeout defined in
// the context, which spans all retries.
func WithRequestTimeout(dur time.Duration) RequestOption {
- return func(r *requestconfig.RequestConfig) error {
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment