From 4c521ac881dfa96f0b97a3f5b9af22b5fed85bc9 Mon Sep 17 00:00:00 2001 From: speakeasybot Date: Wed, 8 Jul 2026 02:49:12 +0000 Subject: [PATCH 1/2] ## Python SDK Changes: * `glean.client.tools.retrieve_tool_server_auth_status()`: **Added** * `glean.client.tools.authorize_tool_server()`: **Added** * `glean.client.search.retrieve_feed()`: * `request.categories[].enum(admin_health_center)` **Added** * `response.results[]` **Changed** --- .speakeasy/gen.lock | 202 ++++++--- .speakeasy/gen.yaml | 4 +- .speakeasy/glean-merged-spec.yaml | 200 ++++++++- .speakeasy/tests.arazzo.yaml | 38 ++ .speakeasy/workflow.lock | 12 +- README.md | 2 + RELEASES.md | 12 +- docs/errors/platformproblemdetailerror.md | 4 +- docs/models/authorizetoolserverrequest.md | 8 + .../authorizetoolserverrequestrequest.md | 9 + docs/models/authorizetoolserverresponse.md | 8 + docs/models/feedrequestcategory.md | 3 +- docs/models/feedresultcategory.md | 3 +- docs/models/gettoolserverauthstatusrequest.md | 8 + docs/models/justificationtype.md | 3 +- docs/models/toolserverauthstatus.md | 21 + docs/models/toolserverauthstatusresponse.md | 12 + docs/sdks/tools/README.md | 92 ++++ pyproject.toml | 2 +- src/glean/api_client/_version.py | 6 +- src/glean/api_client/models/__init__.py | 43 ++ .../models/authorizetoolserverop.py | 31 ++ .../models/authorizetoolserverrequest.py | 28 ++ .../models/authorizetoolserverresponse.py | 28 ++ src/glean/api_client/models/feedentry.py | 1 + src/glean/api_client/models/feedrequest.py | 1 + src/glean/api_client/models/feedresult.py | 1 + .../models/gettoolserverauthstatusop.py | 21 + .../api_client/models/toolserverauthstatus.py | 12 + .../models/toolserverauthstatusresponse.py | 91 ++++ src/glean/api_client/tools.py | 422 ++++++++++++++++++ src/glean/api_client/utils/__init__.py | 4 +- src/glean/api_client/utils/datetimes.py | 16 +- .../internal/handler/generated_handlers.go | 2 + ...pathgetrestapiv1toolserversserveridauth.go | 65 +++ ...athpostrestapiv1toolserversserveridauth.go | 69 +++ .../components/authorizetoolserverrequest.go | 17 + .../components/authorizetoolserverresponse.go | 17 + .../sdk/models/components/feedentry.go | 3 + .../sdk/models/components/feedrequest.go | 3 + .../sdk/models/components/feedresult.go | 3 + .../models/components/toolserverauthstatus.go | 35 ++ .../toolserverauthstatusresponse.go | 55 +++ .../models/operations/authorizetoolserver.go | 47 ++ .../operations/gettoolserverauthstatus.go | 39 ++ tests/test_messages.py | 2 +- tests/test_summarize.py | 6 +- tests/test_tools.py | 30 ++ 48 files changed, 1663 insertions(+), 78 deletions(-) create mode 100644 docs/models/authorizetoolserverrequest.md create mode 100644 docs/models/authorizetoolserverrequestrequest.md create mode 100644 docs/models/authorizetoolserverresponse.md create mode 100644 docs/models/gettoolserverauthstatusrequest.md create mode 100644 docs/models/toolserverauthstatus.md create mode 100644 docs/models/toolserverauthstatusresponse.md create mode 100644 src/glean/api_client/models/authorizetoolserverop.py create mode 100644 src/glean/api_client/models/authorizetoolserverrequest.py create mode 100644 src/glean/api_client/models/authorizetoolserverresponse.py create mode 100644 src/glean/api_client/models/gettoolserverauthstatusop.py create mode 100644 src/glean/api_client/models/toolserverauthstatus.py create mode 100644 src/glean/api_client/models/toolserverauthstatusresponse.py create mode 100644 tests/mockserver/internal/handler/pathgetrestapiv1toolserversserveridauth.go create mode 100644 tests/mockserver/internal/handler/pathpostrestapiv1toolserversserveridauth.go create mode 100644 tests/mockserver/internal/sdk/models/components/authorizetoolserverrequest.go create mode 100644 tests/mockserver/internal/sdk/models/components/authorizetoolserverresponse.go create mode 100644 tests/mockserver/internal/sdk/models/components/toolserverauthstatus.go create mode 100644 tests/mockserver/internal/sdk/models/components/toolserverauthstatusresponse.go create mode 100644 tests/mockserver/internal/sdk/models/operations/authorizetoolserver.go create mode 100644 tests/mockserver/internal/sdk/models/operations/gettoolserverauthstatus.go diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index ef97b174..040f92c5 100644 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,19 +1,19 @@ lockVersion: 2.0.0 id: 3e3290ca-0ee8-4981-b1bc-14536048fa63 management: - docChecksum: 6718837b4405c131be50d0c12e238d38 + docChecksum: d810ce32845f4c2f67f6f7a0ef8a3dce docVersion: 0.9.0 - speakeasyVersion: 1.788.1 - generationVersion: 2.915.1 - releaseVersion: 0.15.1 - configChecksum: 0fea7f4aaac66263fda0c21272e8eeba + speakeasyVersion: 1.789.0 + generationVersion: 2.916.2 + releaseVersion: 0.15.2 + configChecksum: 05845a5e3fac1b5914b13a72aac189ac repoURL: https://github.com/gleanwork/api-client-python.git installationURL: https://github.com/gleanwork/api-client-python.git published: true persistentEdits: - generation_id: d32fa9cd-98e3-4a64-9898-7ee6be99e66d - pristine_commit_hash: c376161f7f5713bcb0fe8203a66b568913ecd91e - pristine_tree_hash: 0b0f141b116cb9ebc3007f9a5dcc6f1baefca32a + generation_id: 996c83eb-67df-45cd-90f6-aaba7cf326b7 + pristine_commit_hash: bcac9138de97b8d384310b5f9d38495fe3a41eb3 + pristine_tree_hash: 0d48eb2b22f15933e4a98d6d198a1d6235bfcf4d features: python: acceptHeaders: 3.0.0 @@ -91,8 +91,8 @@ trackedFiles: pristine_git_object: 7c4c0d90fd0a2de3e48b99ce691c1e9a6ab03041 docs/errors/platformproblemdetailerror.md: id: e92c15ace3bc - last_write_checksum: sha1:2c438a675ff111a84e2781a56952f53a1bfd0d3b - pristine_git_object: 68870011d1db67faa97b25d43461d2981ad29562 + last_write_checksum: sha1:5208ac53c3ccef42decf04d32f2e415299bc7ac6 + pristine_git_object: d5a6d0abd3cce2307eafb570c8d03387a73f809f docs/models/actionauthtype.md: id: f6c3ce39f190 last_write_checksum: sha1:6fe1004cc273d5e15dff5ba82f42bd218774a83b @@ -317,6 +317,18 @@ trackedFiles: id: 259c7805d864 last_write_checksum: sha1:a2a36f4376b5550c02047bfe1b528b10b039cf80 pristine_git_object: 24363138d837adc7e9c840c941f1caae2054bb21 + docs/models/authorizetoolserverrequest.md: + id: 55dfb72f6638 + last_write_checksum: sha1:b5c9e704d32ad79e3c824812e7cbf55a283e4f06 + pristine_git_object: f6697f2598adc4cbf20044f498cf77799721411a + docs/models/authorizetoolserverrequestrequest.md: + id: e80ef1e8bff8 + last_write_checksum: sha1:a57640146deaef7519f3d438ec88f9a86965413e + pristine_git_object: 31792316e795dc1ff13975b63ba0a8cec3d06536 + docs/models/authorizetoolserverresponse.md: + id: 7b884b58873b + last_write_checksum: sha1:da887cd86b6d22514259e71f22f9f21cc70548c4 + pristine_git_object: b74d0886cf0cb12321f41aba776a23a52dd11c6a docs/models/authstatus.md: id: a3855939ee61 last_write_checksum: sha1:2aaf208024005706afc64573d4904c31ed107f55 @@ -1355,8 +1367,8 @@ trackedFiles: pristine_git_object: a851a7f13eb25d515fa9b9244c5dfdc98fa14e2c docs/models/feedrequestcategory.md: id: 31a02f3064c7 - last_write_checksum: sha1:1b56c500af7ec3f6d7934c9b91fe580bc29562b3 - pristine_git_object: 7b5663c5df293adb640bf5f880e3d792c9ca6f1c + last_write_checksum: sha1:1e711eadbe44031143a3fceccf87c16f5c4b57fa + pristine_git_object: c3cd02f12ff93953e0bc4b3c8fccc75126b7eb77 docs/models/feedrequestoptions.md: id: 58eb26b19e77 last_write_checksum: sha1:fd2ab08736cef8156169b0cfee8c52e7aed1accf @@ -1375,8 +1387,8 @@ trackedFiles: pristine_git_object: f14153ca4fc73e08d620714d4ed5ef2c0bad05c5 docs/models/feedresultcategory.md: id: a5f77f38d0a7 - last_write_checksum: sha1:ffd2bead15c34c2a0d4b201b77ae5864a8012bf2 - pristine_git_object: 27fb02eafb29b42875e5e25e19f38b71e9bc612c + last_write_checksum: sha1:560b6764d385f7fdc407d5c060df2ab1f36dfb26 + pristine_git_object: 1e183ef4398672f0489ebeb7b2ea622063c36331 docs/models/fieldscope.md: id: e6b52bcb22a6 last_write_checksum: sha1:13a1492ce39d2f89a01d626996a345a1339a1873 @@ -1629,6 +1641,10 @@ trackedFiles: id: 9aa3fd9aebdb last_write_checksum: sha1:98dc39c0164b5baef1dd0ed8f1a60d59da7abaf4 pristine_git_object: 5c43f37b52c456342ca156d3ccdb8ed988116606 + docs/models/gettoolserverauthstatusrequest.md: + id: 8d5b6b8336ff + last_write_checksum: sha1:9fe6a4ff332c3de18ceadcd6d52ca582321a6885 + pristine_git_object: a0ca5b754fcdd8a68325df5c82d24a0985d93043 docs/models/getusercountrequest.md: id: b0cf45ad2c01 last_write_checksum: sha1:47972cc017eec42ff9e6572c938cccd1fa047471 @@ -1791,8 +1807,8 @@ trackedFiles: pristine_git_object: 4203309096512cab077b45bc77906df389c01421 docs/models/justificationtype.md: id: 8286affacee4 - last_write_checksum: sha1:d0b804fa19ffbe300a0ecdf9bdc77534e05130bf - pristine_git_object: 8cf76ec634dd4ebc3ef2967b7c7debd5e4cd5d72 + last_write_checksum: sha1:b109c7106199ccbc7e24c15618efb4d624602465 + pristine_git_object: ebf3754e99ca28d158a721d0c9eeed4fbe726071 docs/models/knowledgetype.md: id: 1e0c90679228 last_write_checksum: sha1:0030a7539b9362bbb59e0bbd36580676058b3540 @@ -2725,6 +2741,14 @@ trackedFiles: id: cf3f9152cd7b last_write_checksum: sha1:97ee5f6b52e1de5814bc36a1a677146011aeb311 pristine_git_object: aa65d98a224fe146196e2e787ddae4d7293d198b + docs/models/toolserverauthstatus.md: + id: ff4ad4a9f781 + last_write_checksum: sha1:268b4abf4561e8d693d75e0d9899ffb0de4ec497 + pristine_git_object: 58b891edcdac7c4e4a808bc8b3fabc69742d34df + docs/models/toolserverauthstatusresponse.md: + id: c05f1aa2afc1 + last_write_checksum: sha1:b4c8a50486cb88ab6d4ac287768bad72bce76a20 + pristine_git_object: c45e28a5fc483b7e514b71a8ac6ce7cd74628870 docs/models/toolsets.md: id: a965e94026ac last_write_checksum: sha1:b1adf4e7412e880a27756e105778d4cff3c258ce @@ -3083,8 +3107,8 @@ trackedFiles: pristine_git_object: 6ee4030db167df0a2c0146c712f65c8efdb3eb68 docs/sdks/tools/README.md: id: 044286549bac - last_write_checksum: sha1:da531d872e83e3a0245228a6b99e9d1fd33daca6 - pristine_git_object: 9d515f2409214c35ce374f396b022a78a297e434 + last_write_checksum: sha1:a4916d6065377693c59cfbe6ff5072e83f204965 + pristine_git_object: 991a44e9177387acbfde88764b4aff351180edac docs/sdks/visibilityoverrides/README.md: id: c7d003d6a68f last_write_checksum: sha1:738c52c3b0964cfb441542710e10c51ca226f177 @@ -3103,8 +3127,8 @@ trackedFiles: pristine_git_object: 79e388be87446ab6a4064b372bad0e8376d0cb5e pyproject.toml: id: 5d07e7d72637 - last_write_checksum: sha1:5f7e360f8a179576d3f6466d10e90d1defa27cd3 - pristine_git_object: 5d871374479a3e6ef8c1cf4c30ef210db70a6693 + last_write_checksum: sha1:274f6abe53180c51a4595b5bb91cd183df2f2611 + pristine_git_object: a5d4d8d27c4fcef73cb3c0180ee3b32dede0c760 scripts/prepare_readme.py: id: e0c5957a6035 last_write_checksum: sha1:c2c83f71dea61eb50c9e05da83b16d18b4da8794 @@ -3131,8 +3155,8 @@ trackedFiles: pristine_git_object: 55f23c1feabfedeb7e8cd5bea8b910f0ae0b77d9 src/glean/api_client/_version.py: id: 0ce22b26136b - last_write_checksum: sha1:dcee6727523bcffb320455819599e594bb232d82 - pristine_git_object: 46c900ce7a3ad10546571c32020e028ed3f9e3e2 + last_write_checksum: sha1:a76ff61eb6ab064e77e8d700e0ce5873e1807dec + pristine_git_object: 5309d82e948d43abb1b28627de1375b58389c37c src/glean/api_client/agents.py: id: b925701a9217 last_write_checksum: sha1:d80196ac5b252a938055308b99efa4830a763ea6 @@ -3299,8 +3323,8 @@ trackedFiles: pristine_git_object: 77016bfff6209866592fd8b42f2f3527f900992b src/glean/api_client/models/__init__.py: id: d5f6ea5efcbe - last_write_checksum: sha1:d487b121fba5e00278c93d324fa64f332265304b - pristine_git_object: 4338fc863abbfe9d877962e4e3bdb619b30505c9 + last_write_checksum: sha1:a7f23dd82201f2797ea6ea8c2cdd36b650a8b2d7 + pristine_git_object: 715c7a49dc50d95ee497805c47635200986bec1a src/glean/api_client/models/actionauthtype.py: id: c7402f35092d last_write_checksum: sha1:7aaa5d1c11b105d0d7265e2a83cb005aafa89645 @@ -3465,6 +3489,18 @@ trackedFiles: id: e685f2ce2a71 last_write_checksum: sha1:d75d59513a8b813a24ce41889f62390633bfba8e pristine_git_object: 7d8a75da5e934e205215da3df9dff20a224c8a82 + src/glean/api_client/models/authorizetoolserverop.py: + id: f66e52efcb98 + last_write_checksum: sha1:0cbda711bfdabcadc72f6c9478932e2c11cdeb92 + pristine_git_object: 9bca9ad417db954a9b7e764714c8adca8ba1b3bd + src/glean/api_client/models/authorizetoolserverrequest.py: + id: f50706ba7123 + last_write_checksum: sha1:3fc91c67cf2d2d83773ec76365b9377e0e2ab3ba + pristine_git_object: fda6a51bbe417fce2caad49e9310fd9af039fc26 + src/glean/api_client/models/authorizetoolserverresponse.py: + id: 8a18ab4a529c + last_write_checksum: sha1:ff55a5920c37e6b8160079c1fffe43785d0fc271 + pristine_git_object: c5e52da0a475add87033ce04ceb86119e2a0ff5d src/glean/api_client/models/authstatus.py: id: 75167e3b3ad0 last_write_checksum: sha1:4cdc7988894d6c50dbc42d0613bc22dbe6a29666 @@ -4319,16 +4355,16 @@ trackedFiles: pristine_git_object: 44041cb376d89949c815ea1e7813505940605855 src/glean/api_client/models/feedentry.py: id: 023eb6c10ae1 - last_write_checksum: sha1:ace4571b9b5f8922498b858cd9eb55506f168879 - pristine_git_object: 6f604353c35d9c2b2e4f64470cd51867a4e847c9 + last_write_checksum: sha1:97d930a5b3aa989715b02d0823c58aeb2bd466b1 + pristine_git_object: 0c7309ee58376ec34729438fd688a1aab61805ec src/glean/api_client/models/feedop.py: id: b8067ac0a127 last_write_checksum: sha1:c58cb0a3a01925eb14d84176c5c6e9d8f4d84cf1 pristine_git_object: f39626285f84630e5a9233736d652914b759d44b src/glean/api_client/models/feedrequest.py: id: 33496b6a5bab - last_write_checksum: sha1:eca2a1979afbcd03c36b9cbbbc9b68740d9f2ba2 - pristine_git_object: f4aeb9e3a546a7a4c5051119af5c1ff94580730e + last_write_checksum: sha1:28ef772d89ffd87ffe654fa49550534be70dad35 + pristine_git_object: 00be41500f9eac0bcae31b08d20bfc9eb66c4e4b src/glean/api_client/models/feedrequestoptions.py: id: b99003fbf522 last_write_checksum: sha1:d5ffee29242075cbe6d2dd5ec916b0c3d40acf54 @@ -4339,8 +4375,8 @@ trackedFiles: pristine_git_object: 683438c837601f483526ec18756fadc7222edb24 src/glean/api_client/models/feedresult.py: id: ae187332b37a - last_write_checksum: sha1:d87717c9119f57d0448a8fef692df86a412275bd - pristine_git_object: a077074388a0f6dadc07c29a4c4b5e9fda0deec6 + last_write_checksum: sha1:ea65cfa99f0db35dc30bf81348571ee81ffb4363 + pristine_git_object: de49202bb74a185d54462e46aa0d7b1999018999 src/glean/api_client/models/followupaction.py: id: e2de5c4c8524 last_write_checksum: sha1:49e1a826449081fecfcd828c940604db949a8533 @@ -4557,6 +4593,10 @@ trackedFiles: id: 2d10a576bd7c last_write_checksum: sha1:d8df32d525b0631a0261f888b89ef14b54dc03fe pristine_git_object: b20fa7417eb5341f53bdc78ecdf42db7a1488678 + src/glean/api_client/models/gettoolserverauthstatusop.py: + id: caa449cca979 + last_write_checksum: sha1:bf1850bce3e5468612e5e067cd8c6098b7a9d5ff + pristine_git_object: 91b8c13d4ebf6f1fc2e1f5eda73490db39906025 src/glean/api_client/models/getusercountrequest.py: id: f313059beab2 last_write_checksum: sha1:f2a54a902e9dfa08b5ed7ccf4e542b9b8b24e4a5 @@ -5413,6 +5453,14 @@ trackedFiles: id: fe536f511452 last_write_checksum: sha1:cfbece61e77a75264b9969fe7197135393087b29 pristine_git_object: 9949402b2ffc01f5070ca7153d7269151ea1e3b2 + src/glean/api_client/models/toolserverauthstatus.py: + id: 82f4cd9ac482 + last_write_checksum: sha1:76f2229bcd262a4cc24610fc778247aa9530a439 + pristine_git_object: 3a96ab186ed724155a9ff8743cad28248a21dce2 + src/glean/api_client/models/toolserverauthstatusresponse.py: + id: c6b7976340b5 + last_write_checksum: sha1:4ff21869aaecf7e045b9915ae866a21f54879296 + pristine_git_object: 8af7af9ce7802ca78089f6020e54998783b6ec48 src/glean/api_client/models/toolsets.py: id: 72b778695427 last_write_checksum: sha1:769b67c2c1f91052572476e4815eb7c86df25703 @@ -5635,8 +5683,8 @@ trackedFiles: pristine_git_object: 571fc8909a3c8be6c852a995894ac61c9d743a6f src/glean/api_client/tools.py: id: 3ea40147c1cc - last_write_checksum: sha1:8d802229c822e4945e5de8198a137588ae4b363a - pristine_git_object: 7751bb5027c3a9003cd12dfd35569ef652e32e75 + last_write_checksum: sha1:9c353defdddf1c89f58a4b7d7cb8b22e4cb0be1d + pristine_git_object: 9c0699260ef8c6836ff9fbadca8c59a2393ff8e6 src/glean/api_client/types/__init__.py: id: f63c790831ee last_write_checksum: sha1:f9ad14217f832e74f594285960125add50324be9 @@ -5651,16 +5699,16 @@ trackedFiles: pristine_git_object: a9a640a1a7048736383f96c67c6290c86bf536ee src/glean/api_client/utils/__init__.py: id: d681dc4f06b3 - last_write_checksum: sha1:0f93d821f9cb3e061ea125d881bb6f61166738dd - pristine_git_object: aded7597c2bbc4e3fa7f555755d894671ac57741 + last_write_checksum: sha1:527db7a6c93948ecdec6a33f56b6551ae44f0180 + pristine_git_object: c48a36ca3d6e47e384b133bc0bcb482c6d8589b9 src/glean/api_client/utils/annotations.py: id: 8431a3a9fc4f last_write_checksum: sha1:a4824ad65f730303e4e1e3ec1febf87b4eb46dbc pristine_git_object: 12e0aa4f1151bb52474cc02e88397329b90703f6 src/glean/api_client/utils/datetimes.py: id: cc5f732df6a7 - last_write_checksum: sha1:c721e4123000e7dc61ec52b28a739439d9e17341 - pristine_git_object: a6c52cd61bbe2d459046c940ce5e8c469f2f0664 + last_write_checksum: sha1:fa47d54c549ff9b95496ce91930fadfb04a36be9 + pristine_git_object: adad24762cf452d137abe94fda0fd26224cef593 src/glean/api_client/utils/dynamic_imports.py: id: cc87d9ea2304 last_write_checksum: sha1:a1940c63feb8eddfd8026de53384baf5056d5dcc @@ -5787,8 +5835,8 @@ trackedFiles: pristine_git_object: 929558ef2e1165f7e09da6d0a64f016c90971655 tests/mockserver/internal/handler/generated_handlers.go: id: 61ac4f7cce9e - last_write_checksum: sha1:6496589b844c61d821b877b856e26635ffaad66d - pristine_git_object: 67af751e8eacdf3eda5028f67e51509df4315c20 + last_write_checksum: sha1:504888816904477536564a19b80f4284b6823e27 + pristine_git_object: d5fe2f854992c1454456ccbe2b496a6446cb6904 tests/mockserver/internal/handler/pathdeleterestapiindexcustommetadataschemagroupname.go: id: 979e4583765b last_write_checksum: sha1:b1d4edb259d907c7a88b634bf16f0cf152321693 @@ -5849,6 +5897,10 @@ trackedFiles: id: ab4b35f72782 last_write_checksum: sha1:086d9b020ab7cd0e78ed6d28933e95c09b82e498 pristine_git_object: 253b4d87e6614dac4673d9387be09f0bd3258062 + tests/mockserver/internal/handler/pathgetrestapiv1toolserversserveridauth.go: + id: 6c9f22f1b9d6 + last_write_checksum: sha1:abe99a9d9076d3c0d944630fa94f3a83fdc10ceb + pristine_git_object: 53c86d01a47aa5d7802b7b20da09d44ab1ce0907 tests/mockserver/internal/handler/pathgetrestapiv1toolslist.go: id: 1598fa297cf6 last_write_checksum: sha1:8b0d26cd221009e78396ed0c573e78c0ac719e36 @@ -6185,6 +6237,10 @@ trackedFiles: id: ad6776df2ba3 last_write_checksum: sha1:97d094dbdeba08fc395322c0048c259ecf0035fc pristine_git_object: 1676df61ea2406ad36a967ea58ff4022922d133c + tests/mockserver/internal/handler/pathpostrestapiv1toolserversserveridauth.go: + id: ec9262467bda + last_write_checksum: sha1:d9ae76d001db8e14db7bbc7e88edff85f2355350 + pristine_git_object: 93aadc88bb832e4d0d91ce711f39e18cf3ebf3f4 tests/mockserver/internal/handler/pathpostrestapiv1unpin.go: id: 08da240877b4 last_write_checksum: sha1:4ad6d409b1f7c8e66b8e3ec423016f5bc7e94605 @@ -6393,6 +6449,14 @@ trackedFiles: id: 84cdf6495063 last_write_checksum: sha1:2a458d0fb35074c83cd5dc41543c300942f5b7e5 pristine_git_object: de205e6fb6d56ead5c64014571a336b54f0136d5 + tests/mockserver/internal/sdk/models/components/authorizetoolserverrequest.go: + id: c0e58fdb688e + last_write_checksum: sha1:762a4926f6c3004e70d5d6e0205b58874f9e37bc + pristine_git_object: 2af86c39938b0cd67e47222d67a9be860d657467 + tests/mockserver/internal/sdk/models/components/authorizetoolserverresponse.go: + id: 9adc5ed4f113 + last_write_checksum: sha1:acadba9fc6b8e09ccd520bd634c2a7f05181502f + pristine_git_object: c5202d3ba84a4eb474e02ffa74e32a6f8f468bab tests/mockserver/internal/sdk/models/components/authstatus.go: id: c12f2870beb7 last_write_checksum: sha1:ca2727d0dcddf2ee072f3b26529d2952d7e72a21 @@ -7135,12 +7199,12 @@ trackedFiles: pristine_git_object: 04cc3a93272ac70933b0485bee31b335e05ab623 tests/mockserver/internal/sdk/models/components/feedentry.go: id: d25fd66fcf7a - last_write_checksum: sha1:b08b41d397fda41cd7dddbed15a4c236a171894a - pristine_git_object: 665efb1ed25d51cbae6b1e931f879ca43caec5db + last_write_checksum: sha1:024e9f5995f171ffcf2a54189669a79dadf9da7b + pristine_git_object: 3786e358703d09f737b4c2f43f1db79b3ca13e68 tests/mockserver/internal/sdk/models/components/feedrequest.go: id: b06bc4cef0cf - last_write_checksum: sha1:b33d5393c7c69d7ebd04b48e39cef3362d759440 - pristine_git_object: 24e197cad0c5e854787ba16b4f45d3a8d9dc6e35 + last_write_checksum: sha1:7e7ef66203861889ad3ae7f7a668809b2abedc14 + pristine_git_object: 2eff19ff52109057e7dc57092172bb81beb74ecb tests/mockserver/internal/sdk/models/components/feedrequestoptions.go: id: fd9245fe1bf2 last_write_checksum: sha1:fa30b7fd6ee3e45896d7bbe36e33e7c0cb9000ba @@ -7151,8 +7215,8 @@ trackedFiles: pristine_git_object: 54f9d1a8997983156c84e69f888c59a80d06c2b1 tests/mockserver/internal/sdk/models/components/feedresult.go: id: 47411573e67a - last_write_checksum: sha1:cc33234add58c980eaa8c35b118b8f7ad8174c2b - pristine_git_object: 510f01451494a5f947af81a555fceae89ee0fdff + last_write_checksum: sha1:0aecb808064634d971c60a6aa4a0e6c256dc93ff + pristine_git_object: 8e2124ebb433fadd413196d7f35dd227c85f3423 tests/mockserver/internal/sdk/models/components/followupaction.go: id: 38179fec19b1 last_write_checksum: sha1:32a31f7af77a58ce6f3284e8550d01fcf0d3bddd @@ -8037,6 +8101,14 @@ trackedFiles: id: ce1add8ce3b1 last_write_checksum: sha1:526fa5ff943d8fe623fbfbfb4e33bbfe9cf5e3ce pristine_git_object: 03e9af73e5d69f93976218dea9bef90eaef0f02d + tests/mockserver/internal/sdk/models/components/toolserverauthstatus.go: + id: 7688e01624a9 + last_write_checksum: sha1:82d5d759e6d7dd4422526fcd410b8cc4a717dfe6 + pristine_git_object: d6715ec49771c2715fba9d007d9a7094751407fb + tests/mockserver/internal/sdk/models/components/toolserverauthstatusresponse.go: + id: 740fdab1d2ad + last_write_checksum: sha1:199fcd464b82a25094252f4ab32609636d00630d + pristine_git_object: 4328a09e55db5a7edbf5421457c6b59cfe50f4fb tests/mockserver/internal/sdk/models/components/toolsets.go: id: 75b43b793fdd last_write_checksum: sha1:d92cd83151d1a51109858e7ebbfae0b95c8f1e37 @@ -8217,6 +8289,10 @@ trackedFiles: id: a0a71987d741 last_write_checksum: sha1:c78c40c14e10717246e43461e2168240ccbb6a52 pristine_git_object: 9c7fd68f3990aff22648a954f8883593d19f446e + tests/mockserver/internal/sdk/models/operations/authorizetoolserver.go: + id: 6bacf66a9801 + last_write_checksum: sha1:0657ac18a74bc4d75e8cbfe09ee26748e9a5cbad + pristine_git_object: df8f15054a3f283399947b45cc04495a174d6823 tests/mockserver/internal/sdk/models/operations/autocomplete.go: id: 15fbad3e639d last_write_checksum: sha1:242f4ac0044ef328043fc3a5d0effdeccb7f291f @@ -8449,6 +8525,10 @@ trackedFiles: id: a3ff8d97b66f last_write_checksum: sha1:9d3a3758b295b8ee5b1bcc3f433ab0fe9a663644 pristine_git_object: feebc4377fd3e995e6e40a153536a25e5995332d + tests/mockserver/internal/sdk/models/operations/gettoolserverauthstatus.go: + id: 47caf49ab6ed + last_write_checksum: sha1:ca3e16bedf97f0f8606d6d9c82b6a7a886c071a3 + pristine_git_object: 26d8a0ccfca2b2e6585958cacc77a7a359f88749 tests/mockserver/internal/sdk/models/operations/insights.go: id: 9bf374c79662 last_write_checksum: sha1:3091cfd7f0f9ad34caa7ba644bd79bfcbf009f6b @@ -8943,8 +9023,8 @@ trackedFiles: pristine_git_object: 6cc8aeec3c52329d389081db0a27f10f53f214b9 tests/test_messages.py: id: be23089b1f8b - last_write_checksum: sha1:2404e23964ef6a1f5ddc900402b34e597d2d9617 - pristine_git_object: 132005ec7d1e35f805b6a8c28e07e043bce22f0a + last_write_checksum: sha1:b7415512608102fa07b1990a350a7da66946fe46 + pristine_git_object: 636f01d348f30db3ee81985044634511b615af16 tests/test_people.py: id: 37c243940039 last_write_checksum: sha1:7c7268ffeebe48d81ed25e9b1cfc3a395abf5c1f @@ -8967,12 +9047,12 @@ trackedFiles: pristine_git_object: e8c5284c48f176453cea23043502af55cac7df1a tests/test_summarize.py: id: a255d8a6f627 - last_write_checksum: sha1:a327189497f3a2b98c2e277757da4e4ba22cf768 - pristine_git_object: 072b3207b89ff92c8a22b828c32ce23e2ae0ba88 + last_write_checksum: sha1:8880f40a7c62cc87c1eed2b5180893c13ea021b3 + pristine_git_object: 8763da581da72f8aefe52080dd2fd95c5cbf3aa3 tests/test_tools.py: id: 70889bdf7321 - last_write_checksum: sha1:3dbc1795fdf4aa1c013a9684535e7e46bd4cd031 - pristine_git_object: 6dfee17cd10500fded4803aaf37d812a63c74beb + last_write_checksum: sha1:d26d83639f731281bb518886f10571c7b0dbf935 + pristine_git_object: e4d534d43d9f638318985c8cb91d54f8c501a053 tests/test_troubleshooting.py: id: 784c409f631e last_write_checksum: sha1:5af30befb8fffd54210e313bf98c24a64a685c50 @@ -9959,6 +10039,24 @@ examples: application/problem+json: {"type": "https://developer.glean.com/errors/invalid-cursor", "title": "Invalid Pagination Cursor", "status": 400, "detail": "The provided cursor has expired. Start a new search to get a fresh cursor.\n", "code": "invalid_cursor", "documentation_url": "https://developer.glean.com/errors/invalid-cursor", "request_id": "req_7f8a9b0c1d2e", "errors": [{"pointer": "/messages/0/role", "detail": "Must be one of: USER, GLEAN_AI.", "code": "invalid_cursor"}]} "500": application/problem+json: {"type": "https://developer.glean.com/errors/invalid-cursor", "title": "Invalid Pagination Cursor", "status": 400, "detail": "The provided cursor has expired. Start a new search to get a fresh cursor.\n", "code": "invalid_cursor", "documentation_url": "https://developer.glean.com/errors/invalid-cursor", "request_id": "req_7f8a9b0c1d2e", "errors": [{"pointer": "/messages/0/role", "detail": "Must be one of: USER, GLEAN_AI.", "code": "invalid_cursor"}]} + getToolServerAuthStatus: + speakeasy-default-get-tool-server-auth-status: + parameters: + path: + serverId: "" + responses: + "200": + application/json: {"authStatus": "AUTHORIZED", "authType": "AUTH_NONE"} + authorizeToolServer: + speakeasy-default-authorize-tool-server: + parameters: + path: + serverId: "" + requestBody: + application/json: {"returnUrl": "https://lucky-disadvantage.com"} + responses: + "200": + application/json: {"authorizationUrl": "https://shocked-casket.name/"} examplesVersion: 1.0.2 generatedTests: activity: "2025-04-28T22:05:12+01:00" @@ -10126,7 +10224,9 @@ generatedTests: platform-agents-get-schemas: "2026-07-02T17:48:17Z" platform-agents-create-run: "2026-07-02T17:48:17Z" platform-search: "2026-07-02T17:48:17Z" -releaseNotes: "## Python SDK Changes:\n* `glean.agents.search()`: `error` **Changed**\n* `glean.agents.get()`: `error.code.enum(request_too_large)` **Added**\n* `glean.agents.get_schemas()`: `error.code.enum(request_too_large)` **Added**\n* `glean.agents.create_run()`: `error` **Changed**\n* `glean.search.query()`: `error` **Changed**\n* `glean.client.announcements.create()`: \n * `request.body.structured_list[].document.metadata.author.related_documents[].results[]` **Changed**\n * `response` **Changed**\n* `glean.client.announcements.update()`: \n * `request.body.structured_list[].document.metadata.author.related_documents[].results[]` **Changed**\n * `response` **Changed**\n* `glean.client.answers.create()`: \n * `request.data.added_roles[].person.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n * `response.added_roles[].person.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n* `glean.client.answers.update()`: \n * `request.added_roles[].person.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n * `response.added_roles[].person.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n* `glean.client.answers.retrieve()`: `response.answer_result` **Changed**\n* `glean.client.answers.list()`: `response.answer_results[]` **Changed**\n* `glean.client.chat.create()`: \n * `request.messages[].citations[].source_document.metadata.author.related_documents[].results[]` **Changed**\n * `response.messages[].citations[].source_document.metadata.author.related_documents[].results[]` **Changed**\n* `glean.client.chat.retrieve()`: `response.chat_result.chat.created_by.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n* `glean.client.chat.list()`: `response.chat_results[].chat.created_by.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n* `glean.client.chat.create_stream()`: \n * `request.messages[].citations[].source_document.metadata.author.related_documents[].results[]` **Changed**\n* `glean.client.agents.create()`: `response.workflow.author.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n* `glean.client.collections.add_items()`: `response.collection` **Changed**\n* `glean.client.collections.create()`: \n * `request.added_roles[].person.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n * `response.union(class (0)).collection` **Changed**\n* `glean.client.collections.delete_item()`: `response.collection` **Changed**\n* `glean.client.collections.update()`: \n * `request.added_roles[].person.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n * `response` **Changed**\n* `glean.client.collections.update_item()`: `response.collection` **Changed**\n* `glean.client.collections.retrieve()`: `response.collection` **Changed**\n* `glean.client.collections.list()`: `response.collections[]` **Changed**\n* `glean.client.documents.retrieve()`: `response.documents.Map.union(Document).metadata.author.related_documents[].results[]` **Changed**\n* `glean.client.documents.retrieve_by_facets()`: `response.documents[].metadata.author.related_documents[].results[]` **Changed**\n* `glean.client.insights.retrieve()`: `response.glean_assist.activity_insights[].user.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n* `glean.client.messages.retrieve()`: `response.search_response.results[].structured_results[].document.metadata` **Changed**\n* `glean.client.pins.update()`: `response` **Changed**\n* `glean.client.pins.retrieve()`: `response.pin` **Changed**\n* `glean.client.pins.list()`: `response.pins[]` **Changed**\n* `glean.client.pins.create()`: `response` **Changed**\n* `glean.client.search.query_as_admin()`: \n * `request.source_document.metadata.author.related_documents[].results[]` **Changed**\n * `response.results[].structured_results[].document.metadata` **Changed**\n* `glean.client.search.autocomplete()`: `response.results[].document.metadata.author.related_documents[].results[]` **Changed**\n* `glean.client.search.retrieve_feed()`: \n * `request.categories[].enum(podcast)` **Added**\n * `response.results[]` **Changed**\n* `glean.client.search.recommendations()`: \n * `request.source_document.metadata.author.related_documents[].results[]` **Changed**\n * `response.results[].structured_results[].document.metadata` **Changed**\n* `glean.client.search.query()`: \n * `request.source_document.metadata.author.related_documents[].results[]` **Changed**\n * `response.results[].structured_results[].document.metadata` **Changed**\n* `glean.client.entities.list()`: `response.results[].related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n* `glean.client.entities.read_people()`: `response.results[].related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n* `glean.client.shortcuts.create()`: \n * `request.data.added_roles[].person.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n * `response.shortcut` **Changed**\n* `glean.client.shortcuts.retrieve()`: `response.shortcut` **Changed**\n* `glean.client.shortcuts.list()`: `response.shortcuts[]` **Changed**\n* `glean.client.shortcuts.update()`: \n * `request.added_roles[].person.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n * `response.shortcut` **Changed**\n* `glean.client.verification.add_reminder()`: `response.metadata.last_verifier.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n* `glean.client.verification.list()`: `response.documents[].metadata.last_verifier.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n* `glean.client.verification.verify()`: `response.metadata.last_verifier.related_documents[].query_suggestion.ranges[].document.metadata` **Changed**\n" + getToolServerAuthStatus: "2026-07-08T02:46:37Z" + authorizeToolServer: "2026-07-08T02:46:37Z" +releaseNotes: "## Python SDK Changes:\n* `glean.client.tools.retrieve_tool_server_auth_status()`: **Added**\n* `glean.client.tools.authorize_tool_server()`: **Added**\n* `glean.client.search.retrieve_feed()`: \n * `request.categories[].enum(admin_health_center)` **Added**\n * `response.results[]` **Changed**\n" generatedFiles: - .devcontainer/README.md - .devcontainer/devcontainer.json diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index bbd3baf4..41262171 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -34,7 +34,7 @@ generation: generateNewTests: true skipResponseBodyAssertions: true python: - version: 0.15.1 + version: 0.15.2 additionalDependencies: dev: {} main: {} @@ -51,6 +51,7 @@ python: constFieldCasing: upper defaultErrorName: GleanError description: Python Client SDK Generated by Speakeasy. + durationFormat: false enableCustomCodeRegions: false enumFormat: enum envVarPrefix: GLEAN @@ -99,3 +100,4 @@ python: sseFlatResponse: false templateVersion: v2 useAsyncHooks: false + uuidFormat: false diff --git a/.speakeasy/glean-merged-spec.yaml b/.speakeasy/glean-merged-spec.yaml index a7a10ca3..a3dfce76 100644 --- a/.speakeasy/glean-merged-spec.yaml +++ b/.speakeasy/glean-merged-spec.yaml @@ -2,8 +2,8 @@ openapi: 3.0.0 info: version: "0.9.0" title: Glean API - x-source-commit-sha: 33bf057cf0f948a83126e81582717aebdb622bfa - x-open-api-commit-sha: 4f3a4abf8f003a4edc5522021b22184c76d051ad + x-source-commit-sha: 1ccc408fdb2c210e136239b5b42a53c7b9b4abe5 + x-open-api-commit-sha: 1bf9887187c8200b2881b1768fc50ae4fae41796 description: | # Introduction In addition to the data sources that Glean has built-in support for, Glean also provides a REST API that enables customers to put arbitrary content in the search index. This is useful, for example, for doing permissions-aware search over content in internal tools that reside on-prem as well as for searching over applications that Glean does not currently support first class. In addition these APIs allow the customer to push organization data (people info, organization structure etc) into Glean. @@ -2973,6 +2973,89 @@ paths: required: true schema: type: string + /rest/api/v1/tool-servers/{serverId}/auth: + get: + operationId: getToolServerAuthStatus + summary: Get end-user authentication status for a tool server. + description: | + Returns display information and the calling user's current authentication status + for the specified tool server. + tags: + - Tools + security: + - APIToken: [] + responses: + "200": + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/ToolServerAuthStatusResponse' + "400": + description: Bad Request + "401": + description: Unauthorized + "404": + description: Tool server not found + "429": + description: Too Many Requests + x-visibility: Preview + x-glean-experimental: + id: 52fde6ec-c18b-4de6-b761-f82008542ae7 + introduced: "2026-07-02" + x-speakeasy-name-override: retrieveToolServerAuthStatus + x-speakeasy-group: client.tools + post: + operationId: authorizeToolServer + summary: Start the OAuth authorization flow for a tool server. + description: | + Initiates the third-party OAuth flow for the specified tool server and returns the + authorization URL that the client should navigate the end user to. After the OAuth + callback completes, the user's browser is redirected back to `returnUrl` with query + parameters indicating the result. + + `returnUrl` must match the tenant's configured return URL allowlist; otherwise the + request is rejected with 400. + tags: + - Tools + security: + - APIToken: [] + requestBody: + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizeToolServerRequest' + required: true + responses: + "200": + description: Successful operation + content: + application/json: + schema: + $ref: '#/components/schemas/AuthorizeToolServerResponse' + "400": + description: Invalid request (e.g. returnUrl not in allowlist, unsupported auth type) + "401": + description: Unauthorized + "403": + description: User not entitled to the tool server + "404": + description: Tool server not found + "429": + description: Too Many Requests + x-visibility: Preview + x-glean-experimental: + id: 1935476e-ecaf-4c1f-a9fd-1e768cf68f30 + introduced: "2026-07-02" + x-speakeasy-name-override: authorizeToolServer + x-speakeasy-group: client.tools + parameters: + - name: serverId + in: path + description: Unique identifier of the tool server. + required: true + schema: + type: string /api/index/v1/indexdocument: post: summary: Index document @@ -5091,6 +5174,67 @@ components: - rate_limit_exceeded - internal_error - service_unavailable + x-glean-problem-detail-codes: + invalid_request: + status: 400 + title: Invalid Request + missing_required_field: + status: 400 + title: Missing Required Field + invalid_parameter: + status: 400 + title: Invalid Parameter + invalid_cursor: + status: 400 + title: Invalid Pagination Cursor + expired_cursor: + status: 400 + title: Expired Pagination Cursor + invalid_filter: + status: 400 + title: Invalid Filter + invalid_datasource: + status: 400 + title: Invalid Datasource + authentication_required: + status: 401 + title: Authentication Required + token_expired: + status: 401 + title: Token Expired + insufficient_permissions: + status: 403 + title: Insufficient Permissions + resource_not_found: + status: 404 + title: Resource Not Found + method_not_allowed: + status: 405 + title: Method Not Allowed + request_timeout: + status: 408 + title: Request Timeout + request_too_large: + status: 413 + title: Request Too Large + conflict: + status: 409 + title: Conflict + gone: + status: 410 + title: Gone + unprocessable_query: + status: 422 + title: Unprocessable Query + rate_limit_exceeded: + status: 429 + title: Rate Limit Exceeded + internal_error: + status: 500 + title: Internal Error + service_unavailable: + status: 503 + title: Service Unavailable example: invalid_cursor PlatformProblemDetailError: type: object @@ -5125,7 +5269,7 @@ components: type: string format: uri description: URI identifying the error type. - example: https://developer.glean.com/errors/invalid-cursor + example: https://developers.glean.com/errors/invalid-cursor title: type: string description: Short, human-readable summary of the error. @@ -5145,7 +5289,7 @@ components: type: string format: uri description: Direct URL to documentation for this error code. - example: https://developer.glean.com/errors/invalid-cursor + example: https://developers.glean.com/errors/invalid-cursor request_id: type: string description: Platform-generated request ID for support correlation. @@ -11970,6 +12114,7 @@ components: - DEMO_CARD - OOO_PLANNER - OOO_CATCH_UP + - ADMIN_HEALTH_CENTER description: Categories of content requested. An allowlist gives flexibility to request content separately or together. requestOptions: $ref: '#/components/schemas/FeedRequestOptions' @@ -12413,6 +12558,7 @@ components: - DEMO_CARD - OOO_PLANNER - OOO_CATCH_UP + - ADMIN_HEALTH_CENTER description: Type of the justification. justification: type: string @@ -12502,6 +12648,7 @@ components: - DEMO_CARD - OOO_PLANNER - OOO_CATCH_UP + - ADMIN_HEALTH_CENTER description: Category of the result, one of the requested categories in incoming request. primaryEntry: $ref: '#/components/schemas/FeedEntry' @@ -13135,6 +13282,51 @@ components: After the user consents, control returns to `returnUrl` from the request. required: - redirectUrl + ToolServerAuthStatus: + type: string + enum: + - AWAITING_AUTH + - AUTHORIZED + description: Authentication status for the calling user. + ToolServerAuthStatusResponse: + type: object + properties: + displayName: + type: string + description: Human-readable name of the tool server. + logoUrl: + type: string + description: Logo URL for the tool server. + description: + type: string + description: Brief description of the tool server. + authStatus: + $ref: '#/components/schemas/ToolServerAuthStatus' + authType: + $ref: '#/components/schemas/ActionAuthType' + required: + - authStatus + - authType + AuthorizeToolServerRequest: + type: object + properties: + returnUrl: + type: string + description: | + URL to redirect the end user's browser back to after the OAuth flow completes. + Must be present in the tenant's configured return URL allowlist. + required: + - returnUrl + AuthorizeToolServerResponse: + type: object + properties: + authorizationUrl: + type: string + description: | + URL that the client should navigate the end user to in order to begin the OAuth flow. + After the user consents, control returns to `returnUrl` from the request. + required: + - authorizationUrl IndexDocumentRequest: type: object properties: diff --git a/.speakeasy/tests.arazzo.yaml b/.speakeasy/tests.arazzo.yaml index b21ef140..8c5152a9 100644 --- a/.speakeasy/tests.arazzo.yaml +++ b/.speakeasy/tests.arazzo.yaml @@ -158828,3 +158828,41 @@ workflows: type: simple x-speakeasy-test-group: search x-speakeasy-test-rebuild: true + - workflowId: getToolServerAuthStatus + steps: + - stepId: test + operationId: getToolServerAuthStatus + parameters: + - name: serverId + in: path + value: + successCriteria: + - condition: $statusCode == 200 + - condition: $response.header.Content-Type == application/json + - context: $response.body + condition: | + {"authStatus":"AUTHORIZED","authType":"AUTH_NONE"} + type: simple + x-speakeasy-test-group: tools + x-speakeasy-test-rebuild: true + - workflowId: authorizeToolServer + steps: + - stepId: test + operationId: authorizeToolServer + parameters: + - name: serverId + in: path + value: + requestBody: + contentType: application/json + payload: + returnUrl: https://lucky-disadvantage.com + successCriteria: + - condition: $statusCode == 200 + - condition: $response.header.Content-Type == application/json + - context: $response.body + condition: | + {"authorizationUrl":"https://shocked-casket.name/"} + type: simple + x-speakeasy-test-group: tools + x-speakeasy-test-rebuild: true diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index f54ee465..f77ae612 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,9 +1,9 @@ -speakeasyVersion: 1.788.1 +speakeasyVersion: 1.789.0 sources: Glean API: sourceNamespace: glean-api-specs - sourceRevisionDigest: sha256:8b1b5374e6d5c2f98bc7cddfa619249cd150deba48f6c8b9f2637f723ff73fd2 - sourceBlobDigest: sha256:3373213fc1a05b08aad1cf828d00ce46e1da651645fc1ccde24fcdf3efca5861 + sourceRevisionDigest: sha256:38135f10206267ef24935fe6f997edba535c1d95313a1bfd30066f791e2f692b + sourceBlobDigest: sha256:cabd9d3d8eb34d9f7324632354255e5b224c05443dd6f8f27094c47cd4839d01 tags: - latest Glean Client API: @@ -16,10 +16,10 @@ targets: glean: source: Glean API sourceNamespace: glean-api-specs - sourceRevisionDigest: sha256:8b1b5374e6d5c2f98bc7cddfa619249cd150deba48f6c8b9f2637f723ff73fd2 - sourceBlobDigest: sha256:3373213fc1a05b08aad1cf828d00ce46e1da651645fc1ccde24fcdf3efca5861 + sourceRevisionDigest: sha256:38135f10206267ef24935fe6f997edba535c1d95313a1bfd30066f791e2f692b + sourceBlobDigest: sha256:cabd9d3d8eb34d9f7324632354255e5b224c05443dd6f8f27094c47cd4839d01 codeSamplesNamespace: glean-api-specs-python-code-samples - codeSamplesRevisionDigest: sha256:42ee88e1e120eaba45acb7fec56cd56a4a6c0988876f4b9be96e2ac3adf98ea9 + codeSamplesRevisionDigest: sha256:0c2ffb1bbb551c0718176c53dd5fdd322c6c78ec6ab0979f9469cfef459b051e workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/README.md b/README.md index 70ab7040..ee043e79 100644 --- a/README.md +++ b/README.md @@ -464,6 +464,8 @@ For more information on obtaining the appropriate token type, please contact you * [run](docs/sdks/tools/README.md#run) - Execute the specified tool * [retrieve_action_pack_auth_status](docs/sdks/tools/README.md#retrieve_action_pack_auth_status) - Get end-user authentication status for an action pack. * [authorize_action_pack](docs/sdks/tools/README.md#authorize_action_pack) - Start the OAuth authorization flow for an action pack. +* [retrieve_tool_server_auth_status](docs/sdks/tools/README.md#retrieve_tool_server_auth_status) - Get end-user authentication status for a tool server. +* [authorize_tool_server](docs/sdks/tools/README.md#authorize_tool_server) - Start the OAuth authorization flow for a tool server. ### [Client.Verification](docs/sdks/clientverification/README.md) diff --git a/RELEASES.md b/RELEASES.md index bc7ce85c..9a7321b9 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -778,4 +778,14 @@ Based on: ### Generated - [python v0.15.1] . ### Releases -- [PyPI v0.15.1] https://pypi.org/project/glean-api-client/0.15.1 - . \ No newline at end of file +- [PyPI v0.15.1] https://pypi.org/project/glean-api-client/0.15.1 - . + +## 2026-07-08 02:45:44 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.789.0 (2.916.2) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v0.15.2] . +### Releases +- [PyPI v0.15.2] https://pypi.org/project/glean-api-client/0.15.2 - . \ No newline at end of file diff --git a/docs/errors/platformproblemdetailerror.md b/docs/errors/platformproblemdetailerror.md index 68870011..d5a6d0ab 100644 --- a/docs/errors/platformproblemdetailerror.md +++ b/docs/errors/platformproblemdetailerror.md @@ -8,11 +8,11 @@ Error response following RFC 9457, extended with `code` and `documentation_url` | Field | Type | Required | Description | Example | | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | -| `type` | *str* | :heavy_check_mark: | URI identifying the error type. | https://developer.glean.com/errors/invalid-cursor | +| `type` | *str* | :heavy_check_mark: | URI identifying the error type. | https://developers.glean.com/errors/invalid-cursor | | `title` | *str* | :heavy_check_mark: | Short, human-readable summary of the error. | Invalid Pagination Cursor | | `status` | *int* | :heavy_check_mark: | HTTP status code mirrored from the response. | 400 | | `detail` | *str* | :heavy_check_mark: | Human-readable explanation specific to this occurrence. | The provided cursor has expired. Start a new search to get a fresh cursor.
| | `code` | [models.PlatformProblemDetailCode](../models/platformproblemdetailcode.md) | :heavy_check_mark: | Stable machine-readable error code. | invalid_cursor | -| `documentation_url` | *Optional[str]* | :heavy_minus_sign: | Direct URL to documentation for this error code. | https://developer.glean.com/errors/invalid-cursor | +| `documentation_url` | *Optional[str]* | :heavy_minus_sign: | Direct URL to documentation for this error code. | https://developers.glean.com/errors/invalid-cursor | | `request_id` | *str* | :heavy_check_mark: | Platform-generated request ID for support correlation. | req_7f8a9b0c1d2e | | `errors` | List[[models.PlatformProblemDetailError](../models/platformproblemdetailerror.md)] | :heavy_minus_sign: | Field-level validation problems, one entry per offending field. | | \ No newline at end of file diff --git a/docs/models/authorizetoolserverrequest.md b/docs/models/authorizetoolserverrequest.md new file mode 100644 index 00000000..f6697f25 --- /dev/null +++ b/docs/models/authorizetoolserverrequest.md @@ -0,0 +1,8 @@ +# AuthorizeToolServerRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `return_url` | *str* | :heavy_check_mark: | URL to redirect the end user's browser back to after the OAuth flow completes.
Must be present in the tenant's configured return URL allowlist.
| \ No newline at end of file diff --git a/docs/models/authorizetoolserverrequestrequest.md b/docs/models/authorizetoolserverrequestrequest.md new file mode 100644 index 00000000..31792316 --- /dev/null +++ b/docs/models/authorizetoolserverrequestrequest.md @@ -0,0 +1,9 @@ +# AuthorizeToolServerRequestRequest + + +## Fields + +| Field | Type | Required | Description | +| ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | ---------------------------------------------------------------------------- | +| `server_id` | *str* | :heavy_check_mark: | Unique identifier of the tool server. | +| `authorize_tool_server_request` | [models.AuthorizeToolServerRequest](../models/authorizetoolserverrequest.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/models/authorizetoolserverresponse.md b/docs/models/authorizetoolserverresponse.md new file mode 100644 index 00000000..b74d0886 --- /dev/null +++ b/docs/models/authorizetoolserverresponse.md @@ -0,0 +1,8 @@ +# AuthorizeToolServerResponse + + +## Fields + +| Field | Type | Required | Description | +| ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `authorization_url` | *str* | :heavy_check_mark: | URL that the client should navigate the end user to in order to begin the OAuth flow.
After the user consents, control returns to `returnUrl` from the request.
| \ No newline at end of file diff --git a/docs/models/feedrequestcategory.md b/docs/models/feedrequestcategory.md index 7b5663c5..c3cd02f1 100644 --- a/docs/models/feedrequestcategory.md +++ b/docs/models/feedrequestcategory.md @@ -55,4 +55,5 @@ value = FeedRequestCategory.DOCUMENT_SUGGESTION | `PROJECT_NEXT_STEP` | PROJECT_NEXT_STEP | | `DEMO_CARD` | DEMO_CARD | | `OOO_PLANNER` | OOO_PLANNER | -| `OOO_CATCH_UP` | OOO_CATCH_UP | \ No newline at end of file +| `OOO_CATCH_UP` | OOO_CATCH_UP | +| `ADMIN_HEALTH_CENTER` | ADMIN_HEALTH_CENTER | \ No newline at end of file diff --git a/docs/models/feedresultcategory.md b/docs/models/feedresultcategory.md index 27fb02ea..1e183ef4 100644 --- a/docs/models/feedresultcategory.md +++ b/docs/models/feedresultcategory.md @@ -59,4 +59,5 @@ value = FeedResultCategory.DOCUMENT_SUGGESTION | `PROJECT_NEXT_STEP` | PROJECT_NEXT_STEP | | `DEMO_CARD` | DEMO_CARD | | `OOO_PLANNER` | OOO_PLANNER | -| `OOO_CATCH_UP` | OOO_CATCH_UP | \ No newline at end of file +| `OOO_CATCH_UP` | OOO_CATCH_UP | +| `ADMIN_HEALTH_CENTER` | ADMIN_HEALTH_CENTER | \ No newline at end of file diff --git a/docs/models/gettoolserverauthstatusrequest.md b/docs/models/gettoolserverauthstatusrequest.md new file mode 100644 index 00000000..a0ca5b75 --- /dev/null +++ b/docs/models/gettoolserverauthstatusrequest.md @@ -0,0 +1,8 @@ +# GetToolServerAuthStatusRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------- | ------------------------------------- | ------------------------------------- | ------------------------------------- | +| `server_id` | *str* | :heavy_check_mark: | Unique identifier of the tool server. | \ No newline at end of file diff --git a/docs/models/justificationtype.md b/docs/models/justificationtype.md index 8cf76ec6..ebf3754e 100644 --- a/docs/models/justificationtype.md +++ b/docs/models/justificationtype.md @@ -72,4 +72,5 @@ value = JustificationType.FREQUENTLY_ACCESSED | `PROJECT_NEXT_STEP` | PROJECT_NEXT_STEP | | `DEMO_CARD` | DEMO_CARD | | `OOO_PLANNER` | OOO_PLANNER | -| `OOO_CATCH_UP` | OOO_CATCH_UP | \ No newline at end of file +| `OOO_CATCH_UP` | OOO_CATCH_UP | +| `ADMIN_HEALTH_CENTER` | ADMIN_HEALTH_CENTER | \ No newline at end of file diff --git a/docs/models/toolserverauthstatus.md b/docs/models/toolserverauthstatus.md new file mode 100644 index 00000000..58b891ed --- /dev/null +++ b/docs/models/toolserverauthstatus.md @@ -0,0 +1,21 @@ +# ToolServerAuthStatus + +Authentication status for the calling user. + +## Example Usage + +```python +from glean.api_client.models import ToolServerAuthStatus + +value = ToolServerAuthStatus.AWAITING_AUTH + +# Open enum: unrecognized values are captured as UnrecognizedStr +``` + + +## Values + +| Name | Value | +| --------------- | --------------- | +| `AWAITING_AUTH` | AWAITING_AUTH | +| `AUTHORIZED` | AUTHORIZED | \ No newline at end of file diff --git a/docs/models/toolserverauthstatusresponse.md b/docs/models/toolserverauthstatusresponse.md new file mode 100644 index 00000000..c45e28a5 --- /dev/null +++ b/docs/models/toolserverauthstatusresponse.md @@ -0,0 +1,12 @@ +# ToolServerAuthStatusResponse + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `display_name` | *Optional[str]* | :heavy_minus_sign: | Human-readable name of the tool server. | +| `logo_url` | *Optional[str]* | :heavy_minus_sign: | Logo URL for the tool server. | +| `description` | *Optional[str]* | :heavy_minus_sign: | Brief description of the tool server. | +| `auth_status` | [models.ToolServerAuthStatus](../models/toolserverauthstatus.md) | :heavy_check_mark: | Authentication status for the calling user. | +| `auth_type` | [models.ActionAuthType](../models/actionauthtype.md) | :heavy_check_mark: | Authentication mechanism used by an action pack.
- `AUTH_USER_OAUTH`: Requires per-user OAuth consent to the third-party tool.
- `AUTH_ADMIN`: Uses a service-account / admin-owned credential. End users do not authorize individually.
- `AUTH_NONE`: Action pack requires no authentication.
| \ No newline at end of file diff --git a/docs/sdks/tools/README.md b/docs/sdks/tools/README.md index 9d515f24..991a44e9 100644 --- a/docs/sdks/tools/README.md +++ b/docs/sdks/tools/README.md @@ -8,6 +8,8 @@ * [run](#run) - Execute the specified tool * [retrieve_action_pack_auth_status](#retrieve_action_pack_auth_status) - Get end-user authentication status for an action pack. * [authorize_action_pack](#authorize_action_pack) - Start the OAuth authorization flow for an action pack. +* [retrieve_tool_server_auth_status](#retrieve_tool_server_auth_status) - Get end-user authentication status for a tool server. +* [authorize_tool_server](#authorize_tool_server) - Start the OAuth authorization flow for a tool server. ## list @@ -179,6 +181,96 @@ with Glean( ### Errors +| Error Type | Status Code | Content Type | +| ----------------- | ----------------- | ----------------- | +| errors.GleanError | 4XX, 5XX | \*/\* | + +## retrieve_tool_server_auth_status + +Returns display information and the calling user's current authentication status +for the specified tool server. + + +### Example Usage + + +```python +from glean.api_client import Glean +import os + + +with Glean( + api_token=os.getenv("GLEAN_API_TOKEN", ""), +) as glean: + + res = glean.client.tools.retrieve_tool_server_auth_status(server_id="") + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | ------------------------------------------------------------------- | +| `server_id` | *str* | :heavy_check_mark: | Unique identifier of the tool server. | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Response + +**[models.ToolServerAuthStatusResponse](../../models/toolserverauthstatusresponse.md)** + +### Errors + +| Error Type | Status Code | Content Type | +| ----------------- | ----------------- | ----------------- | +| errors.GleanError | 4XX, 5XX | \*/\* | + +## authorize_tool_server + +Initiates the third-party OAuth flow for the specified tool server and returns the +authorization URL that the client should navigate the end user to. After the OAuth +callback completes, the user's browser is redirected back to `returnUrl` with query +parameters indicating the result. + +`returnUrl` must match the tenant's configured return URL allowlist; otherwise the +request is rejected with 400. + + +### Example Usage + + +```python +from glean.api_client import Glean +import os + + +with Glean( + api_token=os.getenv("GLEAN_API_TOKEN", ""), +) as glean: + + res = glean.client.tools.authorize_tool_server(server_id="", return_url="https://lucky-disadvantage.com") + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `server_id` | *str* | :heavy_check_mark: | Unique identifier of the tool server. | +| `return_url` | *str* | :heavy_check_mark: | URL to redirect the end user's browser back to after the OAuth flow completes.
Must be present in the tenant's configured return URL allowlist.
| +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Response + +**[models.AuthorizeToolServerResponse](../../models/authorizetoolserverresponse.md)** + +### Errors + | Error Type | Status Code | Content Type | | ----------------- | ----------------- | ----------------- | | errors.GleanError | 4XX, 5XX | \*/\* | \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index 5d871374..a5d4d8d2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "glean-api-client" -version = "0.15.1" +version = "0.15.2" description = "Python Client SDK Generated by Speakeasy." authors = [{ name = "Glean Technologies, Inc." },] readme = "README-PYPI.md" diff --git a/src/glean/api_client/_version.py b/src/glean/api_client/_version.py index 46c900ce..5309d82e 100644 --- a/src/glean/api_client/_version.py +++ b/src/glean/api_client/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "glean-api-client" -__version__: str = "0.15.1" +__version__: str = "0.15.2" __openapi_doc_version__: str = "0.9.0" -__gen_version__: str = "2.915.1" -__user_agent__: str = "speakeasy-sdk/python 0.15.1 2.915.1 0.9.0 glean-api-client" +__gen_version__: str = "2.916.2" +__user_agent__: str = "speakeasy-sdk/python 0.15.2 2.916.2 0.9.0 glean-api-client" try: if __package__ is not None: diff --git a/src/glean/api_client/models/__init__.py b/src/glean/api_client/models/__init__.py index 4338fc86..715c7a49 100644 --- a/src/glean/api_client/models/__init__.py +++ b/src/glean/api_client/models/__init__.py @@ -203,6 +203,18 @@ AuthorizeActionPackResponse, AuthorizeActionPackResponseTypedDict, ) + from .authorizetoolserverop import ( + AuthorizeToolServerRequestRequest, + AuthorizeToolServerRequestRequestTypedDict, + ) + from .authorizetoolserverrequest import ( + AuthorizeToolServerRequest, + AuthorizeToolServerRequestTypedDict, + ) + from .authorizetoolserverresponse import ( + AuthorizeToolServerResponse, + AuthorizeToolServerResponseTypedDict, + ) from .authstatus import AuthStatus from .authtoken import AuthToken, AuthTokenTypedDict from .autocompleteop import ( @@ -974,6 +986,10 @@ GetShortcutRequestTypedDict, ) from .getshortcutresponse import GetShortcutResponse, GetShortcutResponseTypedDict + from .gettoolserverauthstatusop import ( + GetToolServerAuthStatusRequest, + GetToolServerAuthStatusRequestTypedDict, + ) from .getusercountrequest import GetUserCountRequest, GetUserCountRequestTypedDict from .getusercountresponse import ( GetUserCountResponse, @@ -1479,6 +1495,11 @@ from .toolscallparameter import ToolsCallParameter, ToolsCallParameterTypedDict from .toolscallrequest import ToolsCallRequest, ToolsCallRequestTypedDict from .toolscallresponse import ToolsCallResponse, ToolsCallResponseTypedDict + from .toolserverauthstatus import ToolServerAuthStatus + from .toolserverauthstatusresponse import ( + ToolServerAuthStatusResponse, + ToolServerAuthStatusResponseTypedDict, + ) from .toolsets import ToolSets, ToolSetsTypedDict from .toolslistresponse import ToolsListResponse, ToolsListResponseTypedDict from .ugctype import UgcType @@ -1759,6 +1780,12 @@ "AuthorizeActionPackRequestTypedDict", "AuthorizeActionPackResponse", "AuthorizeActionPackResponseTypedDict", + "AuthorizeToolServerRequest", + "AuthorizeToolServerRequestRequest", + "AuthorizeToolServerRequestRequestTypedDict", + "AuthorizeToolServerRequestTypedDict", + "AuthorizeToolServerResponse", + "AuthorizeToolServerResponseTypedDict", "AutocompleteRequest", "AutocompleteRequestRequest", "AutocompleteRequestRequestTypedDict", @@ -2327,6 +2354,8 @@ "GetShortcutRequestTypedDict", "GetShortcutResponse", "GetShortcutResponseTypedDict", + "GetToolServerAuthStatusRequest", + "GetToolServerAuthStatusRequestTypedDict", "GetUserCountRequest", "GetUserCountRequestTypedDict", "GetUserCountResponse", @@ -2838,6 +2867,9 @@ "ToolParameter", "ToolParameterType", "ToolParameterTypedDict", + "ToolServerAuthStatus", + "ToolServerAuthStatusResponse", + "ToolServerAuthStatusResponseTypedDict", "ToolSets", "ToolSetsTypedDict", "ToolType", @@ -3050,6 +3082,12 @@ "AuthorizeActionPackRequestTypedDict": ".authorizeactionpackrequest", "AuthorizeActionPackResponse": ".authorizeactionpackresponse", "AuthorizeActionPackResponseTypedDict": ".authorizeactionpackresponse", + "AuthorizeToolServerRequestRequest": ".authorizetoolserverop", + "AuthorizeToolServerRequestRequestTypedDict": ".authorizetoolserverop", + "AuthorizeToolServerRequest": ".authorizetoolserverrequest", + "AuthorizeToolServerRequestTypedDict": ".authorizetoolserverrequest", + "AuthorizeToolServerResponse": ".authorizetoolserverresponse", + "AuthorizeToolServerResponseTypedDict": ".authorizetoolserverresponse", "AuthStatus": ".authstatus", "AuthToken": ".authtoken", "AuthTokenTypedDict": ".authtoken", @@ -3617,6 +3655,8 @@ "GetShortcutRequestTypedDict": ".getshortcutrequest", "GetShortcutResponse": ".getshortcutresponse", "GetShortcutResponseTypedDict": ".getshortcutresponse", + "GetToolServerAuthStatusRequest": ".gettoolserverauthstatusop", + "GetToolServerAuthStatusRequestTypedDict": ".gettoolserverauthstatusop", "GetUserCountRequest": ".getusercountrequest", "GetUserCountRequestTypedDict": ".getusercountrequest", "GetUserCountResponse": ".getusercountresponse", @@ -4046,6 +4086,9 @@ "ToolsCallRequestTypedDict": ".toolscallrequest", "ToolsCallResponse": ".toolscallresponse", "ToolsCallResponseTypedDict": ".toolscallresponse", + "ToolServerAuthStatus": ".toolserverauthstatus", + "ToolServerAuthStatusResponse": ".toolserverauthstatusresponse", + "ToolServerAuthStatusResponseTypedDict": ".toolserverauthstatusresponse", "ToolSets": ".toolsets", "ToolSetsTypedDict": ".toolsets", "ToolsListResponse": ".toolslistresponse", diff --git a/src/glean/api_client/models/authorizetoolserverop.py b/src/glean/api_client/models/authorizetoolserverop.py new file mode 100644 index 00000000..9bca9ad4 --- /dev/null +++ b/src/glean/api_client/models/authorizetoolserverop.py @@ -0,0 +1,31 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .authorizetoolserverrequest import ( + AuthorizeToolServerRequest, + AuthorizeToolServerRequestTypedDict, +) +from glean.api_client.types import BaseModel +from glean.api_client.utils import FieldMetadata, PathParamMetadata, RequestMetadata +import pydantic +from typing_extensions import Annotated, TypedDict + + +class AuthorizeToolServerRequestRequestTypedDict(TypedDict): + server_id: str + r"""Unique identifier of the tool server.""" + authorize_tool_server_request: AuthorizeToolServerRequestTypedDict + + +class AuthorizeToolServerRequestRequest(BaseModel): + server_id: Annotated[ + str, + pydantic.Field(alias="serverId"), + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] + r"""Unique identifier of the tool server.""" + + authorize_tool_server_request: Annotated[ + AuthorizeToolServerRequest, + FieldMetadata(request=RequestMetadata(media_type="application/json")), + ] diff --git a/src/glean/api_client/models/authorizetoolserverrequest.py b/src/glean/api_client/models/authorizetoolserverrequest.py new file mode 100644 index 00000000..fda6a51b --- /dev/null +++ b/src/glean/api_client/models/authorizetoolserverrequest.py @@ -0,0 +1,28 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from glean.api_client.types import BaseModel +import pydantic +from typing_extensions import Annotated, TypedDict + + +class AuthorizeToolServerRequestTypedDict(TypedDict): + return_url: str + r"""URL to redirect the end user's browser back to after the OAuth flow completes. + Must be present in the tenant's configured return URL allowlist. + + """ + + +class AuthorizeToolServerRequest(BaseModel): + return_url: Annotated[str, pydantic.Field(alias="returnUrl")] + r"""URL to redirect the end user's browser back to after the OAuth flow completes. + Must be present in the tenant's configured return URL allowlist. + + """ + + +try: + AuthorizeToolServerRequest.model_rebuild() +except NameError: + pass diff --git a/src/glean/api_client/models/authorizetoolserverresponse.py b/src/glean/api_client/models/authorizetoolserverresponse.py new file mode 100644 index 00000000..c5e52da0 --- /dev/null +++ b/src/glean/api_client/models/authorizetoolserverresponse.py @@ -0,0 +1,28 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from glean.api_client.types import BaseModel +import pydantic +from typing_extensions import Annotated, TypedDict + + +class AuthorizeToolServerResponseTypedDict(TypedDict): + authorization_url: str + r"""URL that the client should navigate the end user to in order to begin the OAuth flow. + After the user consents, control returns to `returnUrl` from the request. + + """ + + +class AuthorizeToolServerResponse(BaseModel): + authorization_url: Annotated[str, pydantic.Field(alias="authorizationUrl")] + r"""URL that the client should navigate the end user to in order to begin the OAuth flow. + After the user consents, control returns to `returnUrl` from the request. + + """ + + +try: + AuthorizeToolServerResponse.model_rebuild() +except NameError: + pass diff --git a/src/glean/api_client/models/feedentry.py b/src/glean/api_client/models/feedentry.py index 6f604353..0c7309ee 100644 --- a/src/glean/api_client/models/feedentry.py +++ b/src/glean/api_client/models/feedentry.py @@ -126,6 +126,7 @@ class JustificationType(str, Enum, metaclass=utils.OpenEnumMeta): DEMO_CARD = "DEMO_CARD" OOO_PLANNER = "OOO_PLANNER" OOO_CATCH_UP = "OOO_CATCH_UP" + ADMIN_HEALTH_CENTER = "ADMIN_HEALTH_CENTER" class FeedEntryTypedDict(TypedDict): diff --git a/src/glean/api_client/models/feedrequest.py b/src/glean/api_client/models/feedrequest.py index f4aeb9e3..00be4150 100644 --- a/src/glean/api_client/models/feedrequest.py +++ b/src/glean/api_client/models/feedrequest.py @@ -55,6 +55,7 @@ class FeedRequestCategory(str, Enum): DEMO_CARD = "DEMO_CARD" OOO_PLANNER = "OOO_PLANNER" OOO_CATCH_UP = "OOO_CATCH_UP" + ADMIN_HEALTH_CENTER = "ADMIN_HEALTH_CENTER" class FeedRequestTypedDict(TypedDict): diff --git a/src/glean/api_client/models/feedresult.py b/src/glean/api_client/models/feedresult.py index a0770743..de49202b 100644 --- a/src/glean/api_client/models/feedresult.py +++ b/src/glean/api_client/models/feedresult.py @@ -57,6 +57,7 @@ class FeedResultCategory(str, Enum, metaclass=utils.OpenEnumMeta): DEMO_CARD = "DEMO_CARD" OOO_PLANNER = "OOO_PLANNER" OOO_CATCH_UP = "OOO_CATCH_UP" + ADMIN_HEALTH_CENTER = "ADMIN_HEALTH_CENTER" class PlacementReason(str, Enum, metaclass=utils.OpenEnumMeta): diff --git a/src/glean/api_client/models/gettoolserverauthstatusop.py b/src/glean/api_client/models/gettoolserverauthstatusop.py new file mode 100644 index 00000000..91b8c13d --- /dev/null +++ b/src/glean/api_client/models/gettoolserverauthstatusop.py @@ -0,0 +1,21 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from glean.api_client.types import BaseModel +from glean.api_client.utils import FieldMetadata, PathParamMetadata +import pydantic +from typing_extensions import Annotated, TypedDict + + +class GetToolServerAuthStatusRequestTypedDict(TypedDict): + server_id: str + r"""Unique identifier of the tool server.""" + + +class GetToolServerAuthStatusRequest(BaseModel): + server_id: Annotated[ + str, + pydantic.Field(alias="serverId"), + FieldMetadata(path=PathParamMetadata(style="simple", explode=False)), + ] + r"""Unique identifier of the tool server.""" diff --git a/src/glean/api_client/models/toolserverauthstatus.py b/src/glean/api_client/models/toolserverauthstatus.py new file mode 100644 index 00000000..3a96ab18 --- /dev/null +++ b/src/glean/api_client/models/toolserverauthstatus.py @@ -0,0 +1,12 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from enum import Enum +from glean.api_client import utils + + +class ToolServerAuthStatus(str, Enum, metaclass=utils.OpenEnumMeta): + r"""Authentication status for the calling user.""" + + AWAITING_AUTH = "AWAITING_AUTH" + AUTHORIZED = "AUTHORIZED" diff --git a/src/glean/api_client/models/toolserverauthstatusresponse.py b/src/glean/api_client/models/toolserverauthstatusresponse.py new file mode 100644 index 00000000..8af7af9c --- /dev/null +++ b/src/glean/api_client/models/toolserverauthstatusresponse.py @@ -0,0 +1,91 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .actionauthtype import ActionAuthType +from .toolserverauthstatus import ToolServerAuthStatus +from glean.api_client import models +from glean.api_client.types import BaseModel, UNSET_SENTINEL +import pydantic +from pydantic import field_serializer, model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class ToolServerAuthStatusResponseTypedDict(TypedDict): + auth_status: ToolServerAuthStatus + r"""Authentication status for the calling user.""" + auth_type: ActionAuthType + r"""Authentication mechanism used by an action pack. + - `AUTH_USER_OAUTH`: Requires per-user OAuth consent to the third-party tool. + - `AUTH_ADMIN`: Uses a service-account / admin-owned credential. End users do not authorize individually. + - `AUTH_NONE`: Action pack requires no authentication. + + """ + display_name: NotRequired[str] + r"""Human-readable name of the tool server.""" + logo_url: NotRequired[str] + r"""Logo URL for the tool server.""" + description: NotRequired[str] + r"""Brief description of the tool server.""" + + +class ToolServerAuthStatusResponse(BaseModel): + auth_status: Annotated[ToolServerAuthStatus, pydantic.Field(alias="authStatus")] + r"""Authentication status for the calling user.""" + + auth_type: Annotated[ActionAuthType, pydantic.Field(alias="authType")] + r"""Authentication mechanism used by an action pack. + - `AUTH_USER_OAUTH`: Requires per-user OAuth consent to the third-party tool. + - `AUTH_ADMIN`: Uses a service-account / admin-owned credential. End users do not authorize individually. + - `AUTH_NONE`: Action pack requires no authentication. + + """ + + display_name: Annotated[Optional[str], pydantic.Field(alias="displayName")] = None + r"""Human-readable name of the tool server.""" + + logo_url: Annotated[Optional[str], pydantic.Field(alias="logoUrl")] = None + r"""Logo URL for the tool server.""" + + description: Optional[str] = None + r"""Brief description of the tool server.""" + + @field_serializer("auth_status") + def serialize_auth_status(self, value): + if isinstance(value, str): + try: + return models.ToolServerAuthStatus(value) + except ValueError: + return value + return value + + @field_serializer("auth_type") + def serialize_auth_type(self, value): + if isinstance(value, str): + try: + return models.ActionAuthType(value) + except ValueError: + return value + return value + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["displayName", "logoUrl", "description"]) + serialized = handler(self) + m = {} + + for n, f in type(self).model_fields.items(): + k = f.alias or n + val = serialized.get(k, serialized.get(n)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + + return m + + +try: + ToolServerAuthStatusResponse.model_rebuild() +except NameError: + pass diff --git a/src/glean/api_client/tools.py b/src/glean/api_client/tools.py index 7751bb50..9c069926 100644 --- a/src/glean/api_client/tools.py +++ b/src/glean/api_client/tools.py @@ -775,3 +775,425 @@ async def authorize_action_pack_async( raise errors.GleanError("API error occurred", http_res, http_res_text) raise errors.GleanError("Unexpected response received", http_res) + + def retrieve_tool_server_auth_status( + self, + *, + server_id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.ToolServerAuthStatusResponse: + r"""Get end-user authentication status for a tool server. + + Returns display information and the calling user's current authentication status + for the specified tool server. + + + :param server_id: Unique identifier of the tool server. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.GetToolServerAuthStatusRequest( + server_id=server_id, + ) + + req = self._build_request( + method="GET", + path="/rest/api/v1/tool-servers/{serverId}/auth", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = self.do_request( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="getToolServerAuthStatus", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Tools"], + extensions={ + "x-glean-experimental": { + "id": "52fde6ec-c18b-4de6-b761-f82008542ae7", + "introduced": "2026-07-02", + }, + "x-visibility": "Preview", + }, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response( + models.ToolServerAuthStatusResponse, http_res + ) + if utils.match_response(http_res, ["400", "401", "404", "429", "4XX"], "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GleanError("API error occurred", http_res, http_res_text) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GleanError("API error occurred", http_res, http_res_text) + + raise errors.GleanError("Unexpected response received", http_res) + + async def retrieve_tool_server_auth_status_async( + self, + *, + server_id: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.ToolServerAuthStatusResponse: + r"""Get end-user authentication status for a tool server. + + Returns display information and the calling user's current authentication status + for the specified tool server. + + + :param server_id: Unique identifier of the tool server. + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.GetToolServerAuthStatusRequest( + server_id=server_id, + ) + + req = self._build_request_async( + method="GET", + path="/rest/api/v1/tool-servers/{serverId}/auth", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=False, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = await self.do_request_async( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="getToolServerAuthStatus", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Tools"], + extensions={ + "x-glean-experimental": { + "id": "52fde6ec-c18b-4de6-b761-f82008542ae7", + "introduced": "2026-07-02", + }, + "x-visibility": "Preview", + }, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response( + models.ToolServerAuthStatusResponse, http_res + ) + if utils.match_response(http_res, ["400", "401", "404", "429", "4XX"], "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GleanError("API error occurred", http_res, http_res_text) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GleanError("API error occurred", http_res, http_res_text) + + raise errors.GleanError("Unexpected response received", http_res) + + def authorize_tool_server( + self, + *, + server_id: str, + return_url: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.AuthorizeToolServerResponse: + r"""Start the OAuth authorization flow for a tool server. + + Initiates the third-party OAuth flow for the specified tool server and returns the + authorization URL that the client should navigate the end user to. After the OAuth + callback completes, the user's browser is redirected back to `returnUrl` with query + parameters indicating the result. + + `returnUrl` must match the tenant's configured return URL allowlist; otherwise the + request is rejected with 400. + + + :param server_id: Unique identifier of the tool server. + :param return_url: URL to redirect the end user's browser back to after the OAuth flow completes. + Must be present in the tenant's configured return URL allowlist. + + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.AuthorizeToolServerRequestRequest( + server_id=server_id, + authorize_tool_server_request=models.AuthorizeToolServerRequest( + return_url=return_url, + ), + ) + + req = self._build_request( + method="POST", + path="/rest/api/v1/tool-servers/{serverId}/auth", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.authorize_tool_server_request, + False, + False, + "json", + models.AuthorizeToolServerRequest, + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = self.do_request( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="authorizeToolServer", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Tools"], + extensions={ + "x-glean-experimental": { + "id": "1935476e-ecaf-4c1f-a9fd-1e768cf68f30", + "introduced": "2026-07-02", + }, + "x-visibility": "Preview", + }, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.AuthorizeToolServerResponse, http_res) + if utils.match_response( + http_res, ["400", "401", "403", "404", "429", "4XX"], "*" + ): + http_res_text = utils.stream_to_text(http_res) + raise errors.GleanError("API error occurred", http_res, http_res_text) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = utils.stream_to_text(http_res) + raise errors.GleanError("API error occurred", http_res, http_res_text) + + raise errors.GleanError("Unexpected response received", http_res) + + async def authorize_tool_server_async( + self, + *, + server_id: str, + return_url: str, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.AuthorizeToolServerResponse: + r"""Start the OAuth authorization flow for a tool server. + + Initiates the third-party OAuth flow for the specified tool server and returns the + authorization URL that the client should navigate the end user to. After the OAuth + callback completes, the user's browser is redirected back to `returnUrl` with query + parameters indicating the result. + + `returnUrl` must match the tenant's configured return URL allowlist; otherwise the + request is rejected with 400. + + + :param server_id: Unique identifier of the tool server. + :param return_url: URL to redirect the end user's browser back to after the OAuth flow completes. + Must be present in the tenant's configured return URL allowlist. + + :param retries: Override the default retry configuration for this method + :param server_url: Override the default server URL for this method + :param timeout_ms: Override the default request timeout configuration for this method in milliseconds + :param http_headers: Additional headers to set or replace on requests. + """ + base_url = None + url_variables = None + if timeout_ms is None: + timeout_ms = self.sdk_configuration.timeout_ms + + if server_url is not None: + base_url = server_url + else: + base_url = self._get_url(base_url, url_variables) + + request = models.AuthorizeToolServerRequestRequest( + server_id=server_id, + authorize_tool_server_request=models.AuthorizeToolServerRequest( + return_url=return_url, + ), + ) + + req = self._build_request_async( + method="POST", + path="/rest/api/v1/tool-servers/{serverId}/auth", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=True, + request_has_query_params=True, + user_agent_header="user-agent", + accept_header_value="application/json", + http_headers=http_headers, + security=self.sdk_configuration.security, + get_serialized_body=lambda: utils.serialize_request_body( + request.authorize_tool_server_request, + False, + False, + "json", + models.AuthorizeToolServerRequest, + ), + allow_empty_value=None, + timeout_ms=timeout_ms, + ) + + if retries == UNSET: + if self.sdk_configuration.retry_config is not UNSET: + retries = self.sdk_configuration.retry_config + + retry_config = None + if isinstance(retries, utils.RetryConfig): + retry_config = (retries, ["429", "500", "502", "503", "504"]) + + http_res = await self.do_request_async( + hook_ctx=HookContext( + config=self.sdk_configuration, + base_url=base_url or "", + operation_id="authorizeToolServer", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + tags=["Tools"], + extensions={ + "x-glean-experimental": { + "id": "1935476e-ecaf-4c1f-a9fd-1e768cf68f30", + "introduced": "2026-07-02", + }, + "x-visibility": "Preview", + }, + ), + request=req, + is_error_status_code=lambda c: utils.match_status_codes(["4XX", "5XX"], c), + retry_config=retry_config, + ) + + if utils.match_response(http_res, "200", "application/json"): + return unmarshal_json_response(models.AuthorizeToolServerResponse, http_res) + if utils.match_response( + http_res, ["400", "401", "403", "404", "429", "4XX"], "*" + ): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GleanError("API error occurred", http_res, http_res_text) + if utils.match_response(http_res, "5XX", "*"): + http_res_text = await utils.stream_to_text_async(http_res) + raise errors.GleanError("API error occurred", http_res, http_res_text) + + raise errors.GleanError("Unexpected response received", http_res) diff --git a/src/glean/api_client/utils/__init__.py b/src/glean/api_client/utils/__init__.py index aded7597..c48a36ca 100644 --- a/src/glean/api_client/utils/__init__.py +++ b/src/glean/api_client/utils/__init__.py @@ -15,7 +15,7 @@ async def run_sync_in_thread(func: Callable[..., _T], *args) -> _T: if TYPE_CHECKING: from .annotations import get_discriminator - from .datetimes import parse_datetime + from .datetimes import parse_datetime, parse_duration from .enums import OpenEnumMeta from .headers import get_headers, get_response_headers from .metadata import ( @@ -71,6 +71,7 @@ async def run_sync_in_thread(func: Callable[..., _T], *args) -> _T: "get_default_logger", "get_discriminator", "parse_datetime", + "parse_duration", "get_global_from_env", "get_headers", "get_pydantic_model", @@ -124,6 +125,7 @@ async def run_sync_in_thread(func: Callable[..., _T], *args) -> _T: "get_default_logger": ".logger", "get_discriminator": ".annotations", "parse_datetime": ".datetimes", + "parse_duration": ".datetimes", "get_global_from_env": ".values", "get_headers": ".headers", "get_pydantic_model": ".serializers", diff --git a/src/glean/api_client/utils/datetimes.py b/src/glean/api_client/utils/datetimes.py index a6c52cd6..adad2476 100644 --- a/src/glean/api_client/utils/datetimes.py +++ b/src/glean/api_client/utils/datetimes.py @@ -1,8 +1,10 @@ """Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" -from datetime import datetime +from datetime import datetime, timedelta import sys +from pydantic import TypeAdapter + def parse_datetime(datetime_string: str) -> datetime: """ @@ -21,3 +23,15 @@ def parse_datetime(datetime_string: str) -> datetime: datetime_string = datetime_string[:-1] + "+00:00" return datetime.fromisoformat(datetime_string) + + +_DURATION_ADAPTER = TypeAdapter(timedelta) + + +def parse_duration(duration_string: str) -> timedelta: + """ + Convert an ISO 8601 duration string (e.g. "PT1H30M") into a timedelta. + The standard library has no ISO 8601 duration parser, so this delegates to + pydantic, which is already a runtime dependency of the SDK. + """ + return _DURATION_ADAPTER.validate_python(duration_string) diff --git a/tests/mockserver/internal/handler/generated_handlers.go b/tests/mockserver/internal/handler/generated_handlers.go index 67af751e..d5fe2f85 100644 --- a/tests/mockserver/internal/handler/generated_handlers.go +++ b/tests/mockserver/internal/handler/generated_handlers.go @@ -27,6 +27,7 @@ func GeneratedHandlers(ctx context.Context, dir *logging.HTTPFileDirectory, rt * NewGeneratedHandler(ctx, http.MethodGet, "/rest/api/v1/governance/data/policies", pathGetRestAPIV1GovernanceDataPolicies(dir, rt)), NewGeneratedHandler(ctx, http.MethodGet, "/rest/api/v1/governance/data/policies/{id}", pathGetRestAPIV1GovernanceDataPoliciesID(dir, rt)), NewGeneratedHandler(ctx, http.MethodGet, "/rest/api/v1/people/{person_id}/photo", pathGetRestAPIV1PeoplePersonIDPhoto(dir, rt)), + NewGeneratedHandler(ctx, http.MethodGet, "/rest/api/v1/tool-servers/{serverId}/auth", pathGetRestAPIV1ToolServersServerIDAuth(dir, rt)), NewGeneratedHandler(ctx, http.MethodGet, "/rest/api/v1/tools/list", pathGetRestAPIV1ToolsList(dir, rt)), NewGeneratedHandler(ctx, http.MethodPatch, "/rest/api/v1/configure/datasources/{datasourceId}/instances/{instanceId}", pathPatchRestAPIV1ConfigureDatasourcesDatasourceIDInstancesInstanceID(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/api/agents/search", pathPostAPIAgentsSearch(dir, rt)), @@ -110,6 +111,7 @@ func GeneratedHandlers(ctx context.Context, dir *logging.HTTPFileDirectory, rt * NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/recommendations", pathPostRestAPIV1Recommendations(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/search", pathPostRestAPIV1Search(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/summarize", pathPostRestAPIV1Summarize(dir, rt)), + NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/tool-servers/{serverId}/auth", pathPostRestAPIV1ToolServersServerIDAuth(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/tools/call", pathPostRestAPIV1ToolsCall(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/unpin", pathPostRestAPIV1Unpin(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/updateannouncement", pathPostRestAPIV1Updateannouncement(dir, rt)), diff --git a/tests/mockserver/internal/handler/pathgetrestapiv1toolserversserveridauth.go b/tests/mockserver/internal/handler/pathgetrestapiv1toolserversserveridauth.go new file mode 100644 index 00000000..53c86d01 --- /dev/null +++ b/tests/mockserver/internal/handler/pathgetrestapiv1toolserversserveridauth.go @@ -0,0 +1,65 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package handler + +import ( + "fmt" + "log" + "mockserver/internal/handler/assert" + "mockserver/internal/logging" + "mockserver/internal/sdk/models/components" + "mockserver/internal/sdk/utils" + "mockserver/internal/tracking" + "net/http" +) + +func pathGetRestAPIV1ToolServersServerIDAuth(dir *logging.HTTPFileDirectory, rt *tracking.RequestTracker) http.HandlerFunc { + return func(w http.ResponseWriter, req *http.Request) { + test := req.Header.Get("x-speakeasy-test-name") + instanceID := req.Header.Get("x-speakeasy-test-instance-id") + + count := rt.GetRequestCount(test, instanceID) + + switch fmt.Sprintf("%s[%d]", test, count) { + case "getToolServerAuthStatus[0]": + dir.HandlerFunc("getToolServerAuthStatus", testGetToolServerAuthStatusGetToolServerAuthStatus0)(w, req) + default: + http.Error(w, fmt.Sprintf("Unknown test: %s[%d]", test, count), http.StatusBadRequest) + } + } +} + +func testGetToolServerAuthStatusGetToolServerAuthStatus0(w http.ResponseWriter, req *http.Request) { + if err := assert.SecurityAuthorizationHeader(req, false, "Bearer"); err != nil { + log.Printf("assertion error: %s\n", err) + http.Error(w, err.Error(), http.StatusUnauthorized) + return + } + if err := assert.AcceptHeader(req, []string{"application/json"}); err != nil { + log.Printf("assertion error: %s\n", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err := assert.HeaderExists(req, "User-Agent"); err != nil { + log.Printf("assertion error: %s\n", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + var respBody *components.ToolServerAuthStatusResponse = &components.ToolServerAuthStatusResponse{ + AuthStatus: components.ToolServerAuthStatusAuthorized, + AuthType: components.ActionAuthTypeAuthNone, + } + respBodyBytes, err := utils.MarshalJSON(respBody, "", true) + + if err != nil { + http.Error( + w, + "Unable to encode response body as JSON: "+err.Error(), + http.StatusInternalServerError, + ) + return + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(respBodyBytes) +} diff --git a/tests/mockserver/internal/handler/pathpostrestapiv1toolserversserveridauth.go b/tests/mockserver/internal/handler/pathpostrestapiv1toolserversserveridauth.go new file mode 100644 index 00000000..93aadc88 --- /dev/null +++ b/tests/mockserver/internal/handler/pathpostrestapiv1toolserversserveridauth.go @@ -0,0 +1,69 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package handler + +import ( + "fmt" + "log" + "mockserver/internal/handler/assert" + "mockserver/internal/logging" + "mockserver/internal/sdk/models/components" + "mockserver/internal/sdk/utils" + "mockserver/internal/tracking" + "net/http" +) + +func pathPostRestAPIV1ToolServersServerIDAuth(dir *logging.HTTPFileDirectory, rt *tracking.RequestTracker) http.HandlerFunc { + return func(w http.ResponseWriter, req *http.Request) { + test := req.Header.Get("x-speakeasy-test-name") + instanceID := req.Header.Get("x-speakeasy-test-instance-id") + + count := rt.GetRequestCount(test, instanceID) + + switch fmt.Sprintf("%s[%d]", test, count) { + case "authorizeToolServer[0]": + dir.HandlerFunc("authorizeToolServer", testAuthorizeToolServerAuthorizeToolServer0)(w, req) + default: + http.Error(w, fmt.Sprintf("Unknown test: %s[%d]", test, count), http.StatusBadRequest) + } + } +} + +func testAuthorizeToolServerAuthorizeToolServer0(w http.ResponseWriter, req *http.Request) { + if err := assert.SecurityAuthorizationHeader(req, false, "Bearer"); err != nil { + log.Printf("assertion error: %s\n", err) + http.Error(w, err.Error(), http.StatusUnauthorized) + return + } + if err := assert.ContentType(req, "application/json", true); err != nil { + log.Printf("assertion error: %s\n", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err := assert.AcceptHeader(req, []string{"application/json"}); err != nil { + log.Printf("assertion error: %s\n", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + if err := assert.HeaderExists(req, "User-Agent"); err != nil { + log.Printf("assertion error: %s\n", err) + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + var respBody *components.AuthorizeToolServerResponse = &components.AuthorizeToolServerResponse{ + AuthorizationURL: "https://shocked-casket.name/", + } + respBodyBytes, err := utils.MarshalJSON(respBody, "", true) + + if err != nil { + http.Error( + w, + "Unable to encode response body as JSON: "+err.Error(), + http.StatusInternalServerError, + ) + return + } + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + _, _ = w.Write(respBodyBytes) +} diff --git a/tests/mockserver/internal/sdk/models/components/authorizetoolserverrequest.go b/tests/mockserver/internal/sdk/models/components/authorizetoolserverrequest.go new file mode 100644 index 00000000..2af86c39 --- /dev/null +++ b/tests/mockserver/internal/sdk/models/components/authorizetoolserverrequest.go @@ -0,0 +1,17 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package components + +type AuthorizeToolServerRequest struct { + // URL to redirect the end user's browser back to after the OAuth flow completes. + // Must be present in the tenant's configured return URL allowlist. + // + ReturnURL string `json:"returnUrl"` +} + +func (o *AuthorizeToolServerRequest) GetReturnURL() string { + if o == nil { + return "" + } + return o.ReturnURL +} diff --git a/tests/mockserver/internal/sdk/models/components/authorizetoolserverresponse.go b/tests/mockserver/internal/sdk/models/components/authorizetoolserverresponse.go new file mode 100644 index 00000000..c5202d3b --- /dev/null +++ b/tests/mockserver/internal/sdk/models/components/authorizetoolserverresponse.go @@ -0,0 +1,17 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package components + +type AuthorizeToolServerResponse struct { + // URL that the client should navigate the end user to in order to begin the OAuth flow. + // After the user consents, control returns to `returnUrl` from the request. + // + AuthorizationURL string `json:"authorizationUrl"` +} + +func (o *AuthorizeToolServerResponse) GetAuthorizationURL() string { + if o == nil { + return "" + } + return o.AuthorizationURL +} diff --git a/tests/mockserver/internal/sdk/models/components/feedentry.go b/tests/mockserver/internal/sdk/models/components/feedentry.go index 665efb1e..3786e358 100644 --- a/tests/mockserver/internal/sdk/models/components/feedentry.go +++ b/tests/mockserver/internal/sdk/models/components/feedentry.go @@ -112,6 +112,7 @@ const ( JustificationTypeDemoCard JustificationType = "DEMO_CARD" JustificationTypeOooPlanner JustificationType = "OOO_PLANNER" JustificationTypeOooCatchUp JustificationType = "OOO_CATCH_UP" + JustificationTypeAdminHealthCenter JustificationType = "ADMIN_HEALTH_CENTER" ) func (e JustificationType) ToPointer() *JustificationType { @@ -234,6 +235,8 @@ func (e *JustificationType) UnmarshalJSON(data []byte) error { case "OOO_PLANNER": fallthrough case "OOO_CATCH_UP": + fallthrough + case "ADMIN_HEALTH_CENTER": *e = JustificationType(v) return nil default: diff --git a/tests/mockserver/internal/sdk/models/components/feedrequest.go b/tests/mockserver/internal/sdk/models/components/feedrequest.go index 24e197ca..2eff19ff 100644 --- a/tests/mockserver/internal/sdk/models/components/feedrequest.go +++ b/tests/mockserver/internal/sdk/models/components/feedrequest.go @@ -53,6 +53,7 @@ const ( FeedRequestCategoryDemoCard FeedRequestCategory = "DEMO_CARD" FeedRequestCategoryOooPlanner FeedRequestCategory = "OOO_PLANNER" FeedRequestCategoryOooCatchUp FeedRequestCategory = "OOO_CATCH_UP" + FeedRequestCategoryAdminHealthCenter FeedRequestCategory = "ADMIN_HEALTH_CENTER" ) func (e FeedRequestCategory) ToPointer() *FeedRequestCategory { @@ -149,6 +150,8 @@ func (e *FeedRequestCategory) UnmarshalJSON(data []byte) error { case "OOO_PLANNER": fallthrough case "OOO_CATCH_UP": + fallthrough + case "ADMIN_HEALTH_CENTER": *e = FeedRequestCategory(v) return nil default: diff --git a/tests/mockserver/internal/sdk/models/components/feedresult.go b/tests/mockserver/internal/sdk/models/components/feedresult.go index 510f0145..8e2124eb 100644 --- a/tests/mockserver/internal/sdk/models/components/feedresult.go +++ b/tests/mockserver/internal/sdk/models/components/feedresult.go @@ -54,6 +54,7 @@ const ( FeedResultCategoryDemoCard FeedResultCategory = "DEMO_CARD" FeedResultCategoryOooPlanner FeedResultCategory = "OOO_PLANNER" FeedResultCategoryOooCatchUp FeedResultCategory = "OOO_CATCH_UP" + FeedResultCategoryAdminHealthCenter FeedResultCategory = "ADMIN_HEALTH_CENTER" ) func (e FeedResultCategory) ToPointer() *FeedResultCategory { @@ -150,6 +151,8 @@ func (e *FeedResultCategory) UnmarshalJSON(data []byte) error { case "OOO_PLANNER": fallthrough case "OOO_CATCH_UP": + fallthrough + case "ADMIN_HEALTH_CENTER": *e = FeedResultCategory(v) return nil default: diff --git a/tests/mockserver/internal/sdk/models/components/toolserverauthstatus.go b/tests/mockserver/internal/sdk/models/components/toolserverauthstatus.go new file mode 100644 index 00000000..d6715ec4 --- /dev/null +++ b/tests/mockserver/internal/sdk/models/components/toolserverauthstatus.go @@ -0,0 +1,35 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package components + +import ( + "encoding/json" + "fmt" +) + +// ToolServerAuthStatus - Authentication status for the calling user. +type ToolServerAuthStatus string + +const ( + ToolServerAuthStatusAwaitingAuth ToolServerAuthStatus = "AWAITING_AUTH" + ToolServerAuthStatusAuthorized ToolServerAuthStatus = "AUTHORIZED" +) + +func (e ToolServerAuthStatus) ToPointer() *ToolServerAuthStatus { + return &e +} +func (e *ToolServerAuthStatus) UnmarshalJSON(data []byte) error { + var v string + if err := json.Unmarshal(data, &v); err != nil { + return err + } + switch v { + case "AWAITING_AUTH": + fallthrough + case "AUTHORIZED": + *e = ToolServerAuthStatus(v) + return nil + default: + return fmt.Errorf("invalid value for ToolServerAuthStatus: %v", v) + } +} diff --git a/tests/mockserver/internal/sdk/models/components/toolserverauthstatusresponse.go b/tests/mockserver/internal/sdk/models/components/toolserverauthstatusresponse.go new file mode 100644 index 00000000..4328a09e --- /dev/null +++ b/tests/mockserver/internal/sdk/models/components/toolserverauthstatusresponse.go @@ -0,0 +1,55 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package components + +type ToolServerAuthStatusResponse struct { + // Human-readable name of the tool server. + DisplayName *string `json:"displayName,omitempty"` + // Logo URL for the tool server. + LogoURL *string `json:"logoUrl,omitempty"` + // Brief description of the tool server. + Description *string `json:"description,omitempty"` + // Authentication status for the calling user. + AuthStatus ToolServerAuthStatus `json:"authStatus"` + // Authentication mechanism used by an action pack. + // - `AUTH_USER_OAUTH`: Requires per-user OAuth consent to the third-party tool. + // - `AUTH_ADMIN`: Uses a service-account / admin-owned credential. End users do not authorize individually. + // - `AUTH_NONE`: Action pack requires no authentication. + // + AuthType ActionAuthType `json:"authType"` +} + +func (o *ToolServerAuthStatusResponse) GetDisplayName() *string { + if o == nil { + return nil + } + return o.DisplayName +} + +func (o *ToolServerAuthStatusResponse) GetLogoURL() *string { + if o == nil { + return nil + } + return o.LogoURL +} + +func (o *ToolServerAuthStatusResponse) GetDescription() *string { + if o == nil { + return nil + } + return o.Description +} + +func (o *ToolServerAuthStatusResponse) GetAuthStatus() ToolServerAuthStatus { + if o == nil { + return ToolServerAuthStatus("") + } + return o.AuthStatus +} + +func (o *ToolServerAuthStatusResponse) GetAuthType() ActionAuthType { + if o == nil { + return ActionAuthType("") + } + return o.AuthType +} diff --git a/tests/mockserver/internal/sdk/models/operations/authorizetoolserver.go b/tests/mockserver/internal/sdk/models/operations/authorizetoolserver.go new file mode 100644 index 00000000..df8f1505 --- /dev/null +++ b/tests/mockserver/internal/sdk/models/operations/authorizetoolserver.go @@ -0,0 +1,47 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package operations + +import ( + "mockserver/internal/sdk/models/components" +) + +type AuthorizeToolServerRequest struct { + // Unique identifier of the tool server. + ServerID string `pathParam:"style=simple,explode=false,name=serverId"` + Body components.AuthorizeToolServerRequest `request:"mediaType=application/json"` +} + +func (o *AuthorizeToolServerRequest) GetServerID() string { + if o == nil { + return "" + } + return o.ServerID +} + +func (o *AuthorizeToolServerRequest) GetBody() components.AuthorizeToolServerRequest { + if o == nil { + return components.AuthorizeToolServerRequest{} + } + return o.Body +} + +type AuthorizeToolServerResponse struct { + HTTPMeta components.HTTPMetadata `json:"-"` + // Successful operation + AuthorizeToolServerResponse *components.AuthorizeToolServerResponse +} + +func (o *AuthorizeToolServerResponse) GetHTTPMeta() components.HTTPMetadata { + if o == nil { + return components.HTTPMetadata{} + } + return o.HTTPMeta +} + +func (o *AuthorizeToolServerResponse) GetAuthorizeToolServerResponse() *components.AuthorizeToolServerResponse { + if o == nil { + return nil + } + return o.AuthorizeToolServerResponse +} diff --git a/tests/mockserver/internal/sdk/models/operations/gettoolserverauthstatus.go b/tests/mockserver/internal/sdk/models/operations/gettoolserverauthstatus.go new file mode 100644 index 00000000..26d8a0cc --- /dev/null +++ b/tests/mockserver/internal/sdk/models/operations/gettoolserverauthstatus.go @@ -0,0 +1,39 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package operations + +import ( + "mockserver/internal/sdk/models/components" +) + +type GetToolServerAuthStatusRequest struct { + // Unique identifier of the tool server. + ServerID string `pathParam:"style=simple,explode=false,name=serverId"` +} + +func (o *GetToolServerAuthStatusRequest) GetServerID() string { + if o == nil { + return "" + } + return o.ServerID +} + +type GetToolServerAuthStatusResponse struct { + HTTPMeta components.HTTPMetadata `json:"-"` + // Successful operation + ToolServerAuthStatusResponse *components.ToolServerAuthStatusResponse +} + +func (o *GetToolServerAuthStatusResponse) GetHTTPMeta() components.HTTPMetadata { + if o == nil { + return components.HTTPMetadata{} + } + return o.HTTPMeta +} + +func (o *GetToolServerAuthStatusResponse) GetToolServerAuthStatusResponse() *components.ToolServerAuthStatusResponse { + if o == nil { + return nil + } + return o.ToolServerAuthStatusResponse +} diff --git a/tests/test_messages.py b/tests/test_messages.py index 132005ec..636f01d3 100644 --- a/tests/test_messages.py +++ b/tests/test_messages.py @@ -18,7 +18,7 @@ def test_messages_messages(): res = glean.client.messages.retrieve( id_type=models.IDType.CONVERSATION_ID, id="", - datasource=models.Datasource.FACEBOOKWORKPLACE, + datasource=models.Datasource.GCHAT, timestamp_millis=558834, ) assert res is not None diff --git a/tests/test_summarize.py b/tests/test_summarize.py index 072b3207..8763da58 100644 --- a/tests/test_summarize.py +++ b/tests/test_summarize.py @@ -18,11 +18,11 @@ def test_summarize_summarize(): res = glean.client.documents.summarize( document_specs=[ { - "id": "", + "ugc_type": models.DocumentSpecUgcType1.COLLECTIONS, + "content_id": 993975, }, { - "ugc_type": models.DocumentSpecUgcType2.SHORTCUTS, - "ugc_id": "", + "id": "", }, ] ) diff --git a/tests/test_tools.py b/tests/test_tools.py index 6dfee17c..e4d534d4 100644 --- a/tests/test_tools.py +++ b/tests/test_tools.py @@ -69,3 +69,33 @@ def test_tools_authorize_action_pack(): action_pack_id="", return_url="https://merry-allocation.org/" ) assert res is not None + + +def test_tools_get_tool_server_auth_status(): + test_http_client = create_test_http_client("getToolServerAuthStatus") + + with Glean( + server_url=os.getenv("TEST_SERVER_URL", "http://localhost:18080"), + client=test_http_client, + api_token=os.getenv("GLEAN_API_TOKEN", "value"), + ) as glean: + assert glean is not None + + res = glean.client.tools.retrieve_tool_server_auth_status(server_id="") + assert res is not None + + +def test_tools_authorize_tool_server(): + test_http_client = create_test_http_client("authorizeToolServer") + + with Glean( + server_url=os.getenv("TEST_SERVER_URL", "http://localhost:18080"), + client=test_http_client, + api_token=os.getenv("GLEAN_API_TOKEN", "value"), + ) as glean: + assert glean is not None + + res = glean.client.tools.authorize_tool_server( + server_id="", return_url="https://lucky-disadvantage.com" + ) + assert res is not None From b48827d918d93dc7251ea85d13c8a2a2e4f16ce8 Mon Sep 17 00:00:00 2001 From: "speakeasy-github[bot]" <128539517+speakeasy-github[bot]@users.noreply.github.com> Date: Wed, 8 Jul 2026 02:49:20 +0000 Subject: [PATCH 2/2] empty commit to trigger [run-tests] workflow