From 43df78101937a140c55be0865baef8ffb4e40a04 Mon Sep 17 00:00:00 2001 From: speakeasybot Date: Tue, 9 Jun 2026 03:46:11 +0000 Subject: [PATCH 1/2] =?UTF-8?q?##=20Python=20SDK=20Changes:=20*=20`glean.c?= =?UTF-8?q?lient.chat.create()`:=20=20`response.status[202]`=20**Added**?= =?UTF-8?q?=20(Breaking=20=E2=9A=A0=EF=B8=8F)=20*=20`glean.agents.create?= =?UTF-8?q?=5Fagent()`:=20**Added**?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .speakeasy/gen.lock | 99 ++++++--- .speakeasy/gen.yaml | 5 +- .speakeasy/glean-merged-spec.yaml | 189 ++++++++++------ .speakeasy/tests.arazzo.yaml | 16 ++ .speakeasy/workflow.lock | 12 +- README.md | 1 + RELEASES.md | 12 +- docs/models/createagentrequest.md | 10 + docs/models/createworkflowrequest.md | 10 + docs/sdks/agents/README.md | 45 ++++ pyproject.toml | 2 +- src/glean/api_client/_version.py | 6 +- src/glean/api_client/agents.py | 210 ++++++++++++++++++ src/glean/api_client/client_chat.py | 4 +- src/glean/api_client/models/__init__.py | 13 ++ src/glean/api_client/models/createagentop.py | 54 +++++ .../models/createworkflowrequest.py | 52 +++++ src/glean/api_client/utils/eventstreaming.py | 194 ++++++++-------- .../internal/handler/generated_handlers.go | 1 + .../handler/pathpostrestapiv1agents.go | 82 +++++++ .../components/createworkflowrequest.go | 33 +++ .../sdk/models/operations/createagent.go | 56 +++++ tests/test_agents.py | 14 ++ tests/test_summarize.py | 8 +- 24 files changed, 926 insertions(+), 202 deletions(-) create mode 100644 docs/models/createagentrequest.md create mode 100644 docs/models/createworkflowrequest.md create mode 100644 src/glean/api_client/models/createagentop.py create mode 100644 src/glean/api_client/models/createworkflowrequest.py create mode 100644 tests/mockserver/internal/handler/pathpostrestapiv1agents.go create mode 100644 tests/mockserver/internal/sdk/models/components/createworkflowrequest.go create mode 100644 tests/mockserver/internal/sdk/models/operations/createagent.go diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index c34ed015..08f03706 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: a20695749796cddfd0cc7c0e4a12a7ab + docChecksum: 729fb3927c97761f7f34dcf3600dc3c0 docVersion: 0.9.0 - speakeasyVersion: 1.770.0 - generationVersion: 2.893.0 - releaseVersion: 0.13.0 - configChecksum: fbdf6564dabfc66d8d43921f9aab9d41 + speakeasyVersion: 1.773.1 + generationVersion: 2.897.1 + releaseVersion: 0.13.1 + configChecksum: 5642a3757e64408ab9bdb96bb0edb5fa repoURL: https://github.com/gleanwork/api-client-python.git installationURL: https://github.com/gleanwork/api-client-python.git published: true persistentEdits: - generation_id: 987864f6-cd1e-4c05-a16b-4739643415d0 - pristine_commit_hash: 06cc8c7f7c551cc2f82ad39dd38c63fe2ca63e29 - pristine_tree_hash: 9cd8d96d15f384f677b54671075391a45cdd533f + generation_id: 9d6c29cf-02b3-440d-b832-0c1d3f443bf4 + pristine_commit_hash: 1f8bf7632a6fe6dcca800a023e5749a3fe35bcf0 + pristine_tree_hash: 7a1a6d87491f53740d2bacc0ba90f4c1c5e23421 features: python: acceptHeaders: 3.0.0 @@ -21,7 +21,7 @@ features: additionalProperties: 1.0.1 configurableModuleName: 0.2.0 constsAndDefaults: 1.0.7 - core: 6.0.24 + core: 6.0.27 defaultEnabledRetries: 0.2.0 deprecations: 3.0.2 devContainers: 3.0.0 @@ -612,6 +612,10 @@ trackedFiles: id: fdce0b0bc491 last_write_checksum: sha1:6ba12c90efff718bdd939e773d0426df695090d4 pristine_git_object: dd22b66754081ff30b9d76cfc937603c6d80d965 + docs/models/createagentrequest.md: + id: 9484bab389c1 + last_write_checksum: sha1:2d1e18eb538b82a4e4448cf66696872d8f138b9c + pristine_git_object: 6d556c537edb110ad9d80ee992b5f12a3974713e docs/models/createannouncementrequest.md: id: a37b0e57dfe9 last_write_checksum: sha1:5da6f2bd206ac915200248706e91c0601a4c7d79 @@ -672,6 +676,10 @@ trackedFiles: id: 82707fc9efe5 last_write_checksum: sha1:320bddb9b5ab5dec88760d844b2d585aea2d87f8 pristine_git_object: f3315390350a0db0d3eded212d626abc52c0c834 + docs/models/createworkflowrequest.md: + id: dd9173517846 + last_write_checksum: sha1:0c65e19e884a9444d65dbe54e93073f7d2f7d88f + pristine_git_object: e955a419d336ed9e949e8cab1f341aac83901665 docs/models/currentactiveusers.md: id: 8c45d84c2408 last_write_checksum: sha1:74a4477b894de8d1caca58492504b472a82a94c2 @@ -2838,8 +2846,8 @@ trackedFiles: pristine_git_object: 61dd41f0319201cc105e29174ab1cc0018cecbce docs/sdks/agents/README.md: id: 5965d8232fd8 - last_write_checksum: sha1:f78cc3314d4fdb3c52fcf5b49e01706bc2832bde - pristine_git_object: b929a12d5df1c8a99533448d6c5e6d60f4e17fc0 + last_write_checksum: sha1:48c7b15dfcda891f9a1a2e5ad4bd6eac6f1ca056 + pristine_git_object: 00789fbf58096090a54c254a0f112588042626cb docs/sdks/announcements/README.md: id: 3d2e130a217c last_write_checksum: sha1:ecfa655bb27dee6890656542cfafda0aa6ed1ab9 @@ -2990,8 +2998,8 @@ trackedFiles: pristine_git_object: 79e388be87446ab6a4064b372bad0e8376d0cb5e pyproject.toml: id: 5d07e7d72637 - last_write_checksum: sha1:a3a7799c7cc183344491cfa36f7a0b3c7aba85ff - pristine_git_object: f34dd6a5342bf6af6b1000135c5f479020c0c39b + last_write_checksum: sha1:3159bd445181fc0d0f3097d2b1a72e11f767d0db + pristine_git_object: af1e59cf30ac3ab37f9dc80989f7233e43882a7d scripts/prepare_readme.py: id: e0c5957a6035 last_write_checksum: sha1:c2c83f71dea61eb50c9e05da83b16d18b4da8794 @@ -3018,12 +3026,12 @@ trackedFiles: pristine_git_object: 58c4d70ac1797b86ff5c4237cafbc344c42d8f64 src/glean/api_client/_version.py: id: 0ce22b26136b - last_write_checksum: sha1:ea55ade5532c483da10f1cfec9b6ceccde7522d6 - pristine_git_object: 8d9da6a0d3001f2f5448cc7fb89443c4d02ba5ad + last_write_checksum: sha1:26bcef40f053706ba61db7993740f300c16f1960 + pristine_git_object: f46887e5f18169e78ba2639a09bc5d54bab5f0de src/glean/api_client/agents.py: id: b925701a9217 - last_write_checksum: sha1:c90940a6d28847540858c932148d29ef50cac7ec - pristine_git_object: 99f5f6604807830add51abbd79fa0fc82572a11c + last_write_checksum: sha1:c0ef88b0ad7565cfb342c2311587d70e0f18ae57 + pristine_git_object: 2be171859072eeaa3ea7c0bb77de271caa792ed6 src/glean/api_client/announcements.py: id: 452f3d593912 last_write_checksum: sha1:0767c840c29bba9e3c95bbbd714df374f2907b00 @@ -3062,8 +3070,8 @@ trackedFiles: pristine_git_object: b2e67417be8b3c4927603fb275831447988e9de6 src/glean/api_client/client_chat.py: id: 42cbb9b5acf3 - last_write_checksum: sha1:75b70a975b72b0a748a33fbea4c2e951c89265ca - pristine_git_object: f1e89630d067883690a6fe35687b58a8d2db627e + last_write_checksum: sha1:4b3f510b7d677a4e924a5b2aece7abff574c0dc7 + pristine_git_object: e396b274262b87aa94bac6f7fa278870c095db3d src/glean/api_client/client_documents.py: id: dac599de515c last_write_checksum: sha1:7a41dae11c9e0c58be6e2e8fe07be6f78d8f24bb @@ -3194,8 +3202,8 @@ trackedFiles: pristine_git_object: fd580d9a1b7770b488fc424b5f8735d8b9bf681e src/glean/api_client/models/__init__.py: id: d5f6ea5efcbe - last_write_checksum: sha1:5d16cf04d5ea346a12e547e4bfb5ec60f2a656a9 - pristine_git_object: 101111712c9ec0750a3b5599790b4acbf5c9b0e7 + last_write_checksum: sha1:250b75f85cff98c2b34cfdeae92a1178b18361a9 + pristine_git_object: 2563cb4df4dd05307338eb02843f57d7b6b5528e src/glean/api_client/models/actionauthtype.py: id: c7402f35092d last_write_checksum: sha1:7aaa5d1c11b105d0d7265e2a83cb005aafa89645 @@ -3616,6 +3624,10 @@ trackedFiles: id: 2ff7e2d8021d last_write_checksum: sha1:5203cc6e6506bd574e163b2b18d879c4b19c8a99 pristine_git_object: 83d1aa3b243827c0f27678d94a209aac0a4417b3 + src/glean/api_client/models/createagentop.py: + id: bca1b44cf62a + last_write_checksum: sha1:bc9b540e390ca872fe40d0188311660a039a3881 + pristine_git_object: 4ed4192dbb6da328182b40d002360698706b872e src/glean/api_client/models/createannouncementop.py: id: bf2cd073d77d last_write_checksum: sha1:a636cc5aa94d72878446b69b6ca0e3e91482de2c @@ -3664,6 +3676,10 @@ trackedFiles: id: 65fdd9436d15 last_write_checksum: sha1:285ec74a6e451aa0a6698d663cf501dbd0a24bd6 pristine_git_object: 7fd2e6eb90ed6027e2647312ca3550abc0292b74 + src/glean/api_client/models/createworkflowrequest.py: + id: d084964549e1 + last_write_checksum: sha1:8575c9df02747f481fa8723f4a985c0bded046a3 + pristine_git_object: 206d00f37547917505f9c5a54aaffe7dc6aaf224 src/glean/api_client/models/currentactiveusers.py: id: 0a092cf79074 last_write_checksum: sha1:989717f16473a1c661194af34f9940eb00a26e01 @@ -5454,8 +5470,8 @@ trackedFiles: pristine_git_object: 3324e1bc2668c54c4d5f5a1a845675319757a828 src/glean/api_client/utils/eventstreaming.py: id: fdc3230ebb0e - last_write_checksum: sha1:620d78a8b4e3b854e08d136e02e40a01a786bd70 - pristine_git_object: 3bdcd6d3d4fc772cb7f5fca8685dcdc8c85e13e8 + last_write_checksum: sha1:cad7e4feff4f1b2824afd0d30f2b1964a604f4dd + pristine_git_object: 1c189bf6fcad7ba90e0ec6d2f36ca7329d33bb99 src/glean/api_client/utils/forms.py: id: 00f73e14b0f0 last_write_checksum: sha1:0ca31459b99f761fcc6d0557a0a38daac4ad50f4 @@ -5570,8 +5586,8 @@ trackedFiles: pristine_git_object: 929558ef2e1165f7e09da6d0a64f016c90971655 tests/mockserver/internal/handler/generated_handlers.go: id: 61ac4f7cce9e - last_write_checksum: sha1:1efa96a429f9879c5cdb7bd064661b396b568d31 - pristine_git_object: 6400b090e0a8e321f6348ef79d2b14fb83571f7b + last_write_checksum: sha1:c68c837c6af8f55eb8172dbc62ba472d5dde04a8 + pristine_git_object: a8a0a7558361f126dcbf7f995c52b33e660daa37 tests/mockserver/internal/handler/pathdeleterestapiindexcustommetadataschemagroupname.go: id: 979e4583765b last_write_checksum: sha1:b1d4edb259d907c7a88b634bf16f0cf152321693 @@ -5752,6 +5768,10 @@ trackedFiles: id: 3c3d5555c20b last_write_checksum: sha1:8ef1b12ee725ee32fb6a0a1e0e812594df97e06f pristine_git_object: 26fdfdd7e2d2fdffa6ecc736b7a70d6eb1aa5327 + tests/mockserver/internal/handler/pathpostrestapiv1agents.go: + id: b5d188f39094 + last_write_checksum: sha1:b625a3bbaf0748388febcf87d2b92782167c2c63 + pristine_git_object: 6c1367d61758e68e6cb415247e7473355d17c03a tests/mockserver/internal/handler/pathpostrestapiv1autocomplete.go: id: 9830ef01b25b last_write_checksum: sha1:094d64ddc73a91d38e64e3be18690ebb9d4ef3d3 @@ -6428,6 +6448,10 @@ trackedFiles: id: c5f526844132 last_write_checksum: sha1:aa8fbfc7682edb55f79cd9e241d9795d4c8579ea pristine_git_object: df363e8a9dfca1f872da7b286ab2cf7505b2c127 + tests/mockserver/internal/sdk/models/components/createworkflowrequest.go: + id: 92b0c1ccd3f0 + last_write_checksum: sha1:8febb494a066873172f0229af2880901e5f44ef5 + pristine_git_object: 277dd8b7d18f4aa926904cdf892e3475e6e998a6 tests/mockserver/internal/sdk/models/components/currentactiveusers.go: id: 220e7dbe04c9 last_write_checksum: sha1:4c876d24b835be3c5975308c132a4599bc11a71a @@ -7892,6 +7916,10 @@ trackedFiles: id: 89e5236173f5 last_write_checksum: sha1:4ea8a844fedb81791dbff6fd5b45031943c118ed pristine_git_object: 55046755b604159689bf327aa7174a0e080a970e + tests/mockserver/internal/sdk/models/operations/createagent.go: + id: 4338e91202b4 + last_write_checksum: sha1:80daff65223d9d23afb599cb4af805f35c29919b + pristine_git_object: 255e835e82fba8bf4023a2f99c5c2d1af40dd2cf tests/mockserver/internal/sdk/models/operations/createandstreamrun.go: id: e9a974b86a39 last_write_checksum: sha1:ff0bc51a66cdb65f5d36415c82e92377fd0d2cff @@ -8478,8 +8506,8 @@ trackedFiles: pristine_git_object: db4221c9f5953adc8f8219979060f1248ae5c342 tests/test_agents.py: id: 2eb70a860f3a - last_write_checksum: sha1:0c2472116b756d6985f893ff62edb5505e2a260d - pristine_git_object: 1d18b7662e493260672cbaabfcbc8461355ffeba + last_write_checksum: sha1:18a474b39a964820ec42a6d5552ab7961871d286 + pristine_git_object: 46852ff43f1fdbc1c65619cccb7a22f51509104b tests/test_announcements.py: id: 720cc07fca06 last_write_checksum: sha1:1d0dcab6446633bc6809bc67e14b6cc1755aa319 @@ -8598,8 +8626,8 @@ trackedFiles: pristine_git_object: df2944ebda36db652b2770dd1c23be83df90fc99 tests/test_summarize.py: id: a255d8a6f627 - last_write_checksum: sha1:884caf9e9ba6ac6d6577682c45419d3fd6312dd9 - pristine_git_object: df71d57de672c7e6967ba36b3671d957ef075d55 + last_write_checksum: sha1:ac09a1189221f7d330d0ef0297311e19527dcf17 + pristine_git_object: c8dd49d6b33f70890710b270df94bf2fe7f06407 tests/test_tools.py: id: 70889bdf7321 last_write_checksum: sha1:293cea8c046c30086e5d57cb48aa59ab8da308f1 @@ -9520,6 +9548,13 @@ examples: application/json: {"status": "MISSING"} "400": application/json: {} + createAgent: + speakeasy-default-create-agent: + requestBody: + application/json: {} + responses: + "200": + application/json: {"workflow": {"author": {"name": "George Clooney", "obfuscatedId": "abc123"}, "lastDraftSavedBy": {"name": "George Clooney", "obfuscatedId": "abc123"}, "lastUpdatedBy": {"name": "George Clooney", "obfuscatedId": "abc123"}}} examplesVersion: 1.0.2 generatedTests: activity: "2025-04-28T22:05:12+01:00" @@ -9681,7 +9716,11 @@ generatedTests: delete_/rest/api/index/custom-metadata/schema/{groupName}: "2026-06-05T03:54:47Z" getDatasourceCredentialStatus: "2026-06-05T03:54:47Z" rotateDatasourceCredentials: "2026-06-05T03:54:47Z" -releaseNotes: "## Python SDK Changes:\n* `glean.client.collections.add_items()`: `response` **Changed** (Breaking ⚠️)\n* `glean.chat.get_chat_file()`: **Added**\n* `glean.agents.edit_agent()`: **Added**\n* `glean.entities.get_person_photo()`: **Added**\n* `glean.tools.get_action_pack_auth_status()`: **Added**\n* `glean.tools.authorize_action_pack()`: **Added**\n* `glean.indexing.custom_metadata.upsert()`: **Added**\n* `glean.indexing.custom_metadata.delete()`: **Added**\n* `glean.indexing.custom_metadata.get_schema()`: **Added**\n* `glean.indexing.custom_metadata.upsert_schema()`: **Added**\n* `glean.indexing.custom_metadata.delete_schema()`: **Added**\n* `glean.troubleshooting.post_/api/index/v1/debug/{datasource}/document/events()`: **Added**\n* `glean.datasources.get_datasource_credential_status()`: **Added**\n* `glean.datasources.rotate_datasource_credentials()`: **Added**\n* `glean.client.activity.feedback()`: \n * `request.feedback1.category` **Changed**\n* `glean.client.announcements.create()`: \n * `request.body.structured_list[].document.metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n * `response` **Changed**\n* `glean.client.announcements.update()`: \n * `request.body.structured_list[].document.metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n * `response` **Changed**\n* `glean.client.answers.create()`: \n * `request.data.added_roles[].person.related_documents[]` **Changed**\n * `response` **Changed**\n* `glean.client.answers.update()`: \n * `request.added_roles[].person.related_documents[]` **Changed**\n * `response` **Changed**\n* `glean.client.answers.retrieve()`: `response.answer_result.answer` **Changed**\n* `glean.client.answers.list()`: `response.answer_results[].answer` **Changed**\n* `glean.client.chat.create()`: \n * `request.messages[].citations[].source_document.metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n * `response.messages[].citations[].source_document.metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n* `glean.client.chat.retrieve()`: `response.chat_result.chat.created_by.related_documents[]` **Changed**\n* `glean.client.chat.list()`: `response.chat_results[].chat.created_by.related_documents[]` **Changed**\n* `glean.client.chat.create_stream()`: \n * `request.messages[].citations[].source_document.metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n* `glean.client.collections.create()`: \n * `request.added_roles[].person.related_documents[]` **Changed**\n * `response.union(class (0))` **Changed**\n * `error_code.enum(corrupt_item)` **Added**\n* `glean.client.collections.delete()`: `error_code.enum(corrupt_item)` **Added**\n* `glean.client.collections.delete_item()`: `response.collection` **Changed**\n* `glean.client.collections.update()`: \n * `request.added_roles[].person.related_documents[]` **Changed**\n * `response` **Changed**\n * `error_code.enum(corrupt_item)` **Added**\n* `glean.client.collections.update_item()`: `response.collection` **Changed**\n* `glean.client.collections.retrieve()`: `response` **Changed**\n* `glean.client.collections.list()`: `response.collections[]` **Changed**\n* `glean.client.documents.retrieve()`: `response.documents.Map.union(Document).metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n* `glean.client.documents.retrieve_by_facets()`: `response.documents[].metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n* `glean.client.insights.retrieve()`: \n * `request` **Changed**\n * `response` **Changed**\n* `glean.client.messages.retrieve()`: `response.search_response.results[].structured_results[]` **Changed**\n* `glean.client.pins.update()`: `response.attribution.related_documents[]` **Changed**\n* `glean.client.pins.retrieve()`: `response.pin.attribution.related_documents[]` **Changed**\n* `glean.client.pins.list()`: `response.pins[].attribution.related_documents[]` **Changed**\n* `glean.client.pins.create()`: `response.attribution.related_documents[]` **Changed**\n* `glean.client.search.query_as_admin()`: \n * `request.source_document.metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n * `response.results[].structured_results[]` **Changed**\n* `glean.client.search.autocomplete()`: `response.results[].document.metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n* `glean.client.search.retrieve_feed()`: \n * `request.categories[]` **Changed**\n * `response.results[]` **Changed**\n* `glean.client.search.recommendations()`: \n * `request.source_document.metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n * `response.results[].structured_results[]` **Changed**\n* `glean.client.search.query()`: \n * `request.source_document.metadata.author.related_documents[].results[].structured_results[].answer` **Changed**\n * `response.results[].structured_results[]` **Changed**\n* `glean.client.entities.list()`: `response.results[].related_documents[]` **Changed**\n* `glean.client.entities.read_people()`: `response.results[].related_documents[]` **Changed**\n* `glean.client.shortcuts.create()`: \n * `request.data.added_roles[].person.related_documents[]` **Changed**\n * `response.shortcut.added_roles[].person.related_documents[]` **Changed**\n* `glean.client.shortcuts.retrieve()`: `response.shortcut.added_roles[].person.related_documents[]` **Changed**\n* `glean.client.shortcuts.list()`: `response.shortcuts[].added_roles[].person.related_documents[]` **Changed**\n* `glean.client.shortcuts.update()`: \n * `request.added_roles[].person.related_documents[]` **Changed**\n * `response.shortcut.added_roles[].person.related_documents[]` **Changed**\n* `glean.client.verification.add_reminder()`: `response.metadata.last_verifier.related_documents[]` **Changed**\n* `glean.client.verification.list()`: `response.documents[].metadata.last_verifier.related_documents[]` **Changed**\n* `glean.client.verification.verify()`: `response.metadata.last_verifier.related_documents[]` **Changed**\n" + createAgent: "2026-06-09T03:43:36Z" +releaseNotes: | + ## Python SDK Changes: + * `glean.client.chat.create()`: `response.status[202]` **Added** (Breaking ⚠️) + * `glean.agents.create_agent()`: **Added** generatedFiles: - .devcontainer/README.md - .devcontainer/devcontainer.json diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index 8423ecdd..680717db 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -34,7 +34,7 @@ generation: generateNewTests: true skipResponseBodyAssertions: true python: - version: 0.13.0 + version: 0.13.1 additionalDependencies: dev: {} main: {} @@ -54,6 +54,9 @@ python: enableCustomCodeRegions: false enumFormat: enum envVarPrefix: GLEAN + eventStreamClassNames: + async: EventStreamAsync + sync: EventStream fixFlags: asyncPaginationSep2025: false conflictResistantModelImportsFeb2026: false diff --git a/.speakeasy/glean-merged-spec.yaml b/.speakeasy/glean-merged-spec.yaml index bd780d7e..dccedcb9 100644 --- a/.speakeasy/glean-merged-spec.yaml +++ b/.speakeasy/glean-merged-spec.yaml @@ -2,7 +2,7 @@ openapi: 3.0.0 info: version: 0.9.0 title: Glean API - x-source-commit-sha: deacbe1e0fd0b5074c1b1445f05b4a5df529f487 + x-source-commit-sha: b9ccec7d05a7bdb183fded5c10a67ae457d71853 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. @@ -22,7 +22,7 @@ info: These API clients provide type-safe, idiomatic interfaces for working with Glean IndexingAPIs in your language of choice. x-logo: url: https://app.glean.com/images/glean-text2.svg - x-open-api-commit-sha: 7de1c5956c93a8bdd7b4a2c6a4c6fd98b0c4df70 + x-open-api-commit-sha: 04d057a1ee884ee7cd054bc62ae2048c76d90b02 x-speakeasy-name: 'Glean API' servers: - url: https://{instance}-be.glean.com @@ -569,6 +569,23 @@ paths: startIndex: 0 endIndex: 12 type: CITATION + "202": + description: | + Request accepted but not yet processed. Returned when another + in-flight request is already running for the same chat session; + the body's `queuedRequestId` identifies the deferred run and + output will be persisted to the chat session referenced by + `chatId`. + content: + application/json: + schema: + $ref: "#/components/schemas/ChatResponse" + examples: + queuedExample: + value: + chatId: abc123 + queuedRequestId: qr-xyz + isSavedToChatHistory: true "400": description: Invalid request "401": @@ -893,6 +910,40 @@ paths: description: Internal server error. security: - APIToken: [] + /rest/api/v1/agents: + post: + tags: + - Agents + summary: Create an agent + description: Create an agent. + operationId: createAgent + x-visibility: Preview + parameters: + - $ref: "#/components/parameters/locale" + - $ref: "#/components/parameters/timezoneOffset" + requestBody: + required: true + content: + application/json: + schema: + $ref: "#/components/schemas/CreateWorkflowRequest" + responses: + "200": + description: Success + content: + application/json: + schema: + $ref: "#/components/schemas/CreateWorkflowResponse" + "400": + description: Bad request + "401": + description: Not Authorized + "403": + description: Forbidden + "500": + description: Internal server error + security: + - APIToken: [] /rest/api/v1/agents/{agent_id}: get: tags: @@ -8973,6 +9024,80 @@ components: items: type: string description: IDs of files to delete. + WorkflowDraftableProperties: + properties: + name: + type: string + description: The name of the workflow. + WorkflowMutableProperties: + type: object + allOf: + - $ref: "#/components/schemas/WorkflowDraftableProperties" + - type: object + CreateWorkflowRequest: + allOf: + - $ref: "#/components/schemas/WorkflowMutableProperties" + - type: object + properties: + transient: + type: boolean + description: Used to create a transient workflow. + parentWorkflowId: + type: string + description: id of the parent workflow for transient workflows + WorkflowMetadata: + allOf: + - type: object + properties: + author: + $ref: "#/components/schemas/Person" + createTimestamp: + type: integer + description: Server Unix timestamp of the creation time. + lastUpdateTimestamp: + type: integer + description: Server Unix timestamp of the last update time. + lastDraftSavedAt: + type: integer + description: Server Unix timestamp of the last time the draft was saved. + lastDraftSavedBy: + description: The person who last saved the draft. + $ref: "#/components/schemas/Person" + lastDraftGitAuthorId: + type: string + description: ID of the VCS user (e.g. GitHub username) who last saved the draft. Set only by the draft save path via the external Git integration API. + lastUpdatedBy: + $ref: "#/components/schemas/Person" + AttributionProperties: {} + Workflow: + allOf: + - $ref: "#/components/schemas/PermissionedObject" + - $ref: "#/components/schemas/WorkflowMutableProperties" + - $ref: "#/components/schemas/WorkflowMetadata" + - $ref: "#/components/schemas/AttributionProperties" + - type: object + properties: + id: + type: string + description: The ID of the workflow. + verified: + type: boolean + readOnly: true + description: When present, indicates this workflow is admin-verified. Set via the dedicated admin settings endpoint, not by regular edits. + showOrganizationAsAuthor: + type: boolean + readOnly: true + description: When true, displays organization name instead of author name in agent card. Set via the dedicated admin settings endpoint, not by regular edits. + WorkflowResult: + type: object + required: + - workflow + properties: + workflow: + $ref: "#/components/schemas/Workflow" + CreateWorkflowResponse: + allOf: + - $ref: "#/components/schemas/WorkflowResult" Agent: title: Agent type: object @@ -9025,16 +9150,6 @@ components: message: type: string description: Client-facing error message describing what went wrong - WorkflowDraftableProperties: - properties: - name: - type: string - description: The name of the workflow. - WorkflowMutableProperties: - type: object - allOf: - - $ref: "#/components/schemas/WorkflowDraftableProperties" - - type: object EditWorkflowRequest: allOf: - $ref: "#/components/schemas/WorkflowMutableProperties" @@ -11293,7 +11408,6 @@ components: description: A list of removed user roles for the Workflow. items: $ref: "#/components/schemas/UserRoleSpecification" - AttributionProperties: {} PromptTemplate: allOf: - $ref: "#/components/schemas/PromptTemplateMutableProperties" @@ -11369,55 +11483,6 @@ components: runCount: $ref: "#/components/schemas/CountInfo" description: This tracks how many times this prompt template was run. If user runs a prompt template after modifying the original one, it still counts as a run for the original template. - WorkflowMetadata: - allOf: - - type: object - properties: - author: - $ref: "#/components/schemas/Person" - createTimestamp: - type: integer - description: Server Unix timestamp of the creation time. - lastUpdateTimestamp: - type: integer - description: Server Unix timestamp of the last update time. - lastDraftSavedAt: - type: integer - description: Server Unix timestamp of the last time the draft was saved. - lastDraftSavedBy: - description: The person who last saved the draft. - $ref: "#/components/schemas/Person" - lastDraftGitAuthorId: - type: string - description: ID of the VCS user (e.g. GitHub username) who last saved the draft. Set only by the draft save path via the external Git integration API. - lastUpdatedBy: - $ref: "#/components/schemas/Person" - Workflow: - allOf: - - $ref: "#/components/schemas/PermissionedObject" - - $ref: "#/components/schemas/WorkflowMutableProperties" - - $ref: "#/components/schemas/WorkflowMetadata" - - $ref: "#/components/schemas/AttributionProperties" - - type: object - properties: - id: - type: string - description: The ID of the workflow. - verified: - type: boolean - readOnly: true - description: When present, indicates this workflow is admin-verified. Set via the dedicated admin settings endpoint, not by regular edits. - showOrganizationAsAuthor: - type: boolean - readOnly: true - description: When true, displays organization name instead of author name in agent card. Set via the dedicated admin settings endpoint, not by regular edits. - WorkflowResult: - type: object - required: - - workflow - properties: - workflow: - $ref: "#/components/schemas/Workflow" UserActivity: properties: actor: diff --git a/.speakeasy/tests.arazzo.yaml b/.speakeasy/tests.arazzo.yaml index 48029e67..4f92272d 100644 --- a/.speakeasy/tests.arazzo.yaml +++ b/.speakeasy/tests.arazzo.yaml @@ -158705,3 +158705,19 @@ workflows: type: simple x-speakeasy-test-group: Datasources x-speakeasy-test-rebuild: true + - workflowId: createAgent + steps: + - stepId: test + operationId: createAgent + requestBody: + contentType: application/json + payload: {} + successCriteria: + - condition: $statusCode == 200 + - condition: $response.header.Content-Type == application/json + - context: $response.body + condition: | + {"workflow":{"author":{"name":"George Clooney","obfuscatedId":"abc123"},"lastDraftSavedBy":{"name":"George Clooney","obfuscatedId":"abc123"},"lastUpdatedBy":{"name":"George Clooney","obfuscatedId":"abc123"}}} + type: simple + x-speakeasy-test-group: Agents + x-speakeasy-test-rebuild: true diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 92827bbf..4bb73210 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -1,9 +1,9 @@ -speakeasyVersion: 1.770.0 +speakeasyVersion: 1.773.1 sources: Glean API: sourceNamespace: glean-api-specs - sourceRevisionDigest: sha256:500649ecd919cc2dcfeb6c54fe552ddcf8628a42b2f67a2ef0f206ad8561a56c - sourceBlobDigest: sha256:cb8902f4548ad637f07f6be9b7ef3f0d5fda8fe6f6540c7eea338bf4dde98413 + sourceRevisionDigest: sha256:b7175ea063b56dd93b27f307044f5d68103ceca629274570a0933bd9af493f2e + sourceBlobDigest: sha256:cfa7e1503a2c59e44a2d44bf69a2db12324cb1a152d29942c68a969962ea5c09 tags: - latest Glean Client API: @@ -16,10 +16,10 @@ targets: glean: source: Glean API sourceNamespace: glean-api-specs - sourceRevisionDigest: sha256:500649ecd919cc2dcfeb6c54fe552ddcf8628a42b2f67a2ef0f206ad8561a56c - sourceBlobDigest: sha256:cb8902f4548ad637f07f6be9b7ef3f0d5fda8fe6f6540c7eea338bf4dde98413 + sourceRevisionDigest: sha256:b7175ea063b56dd93b27f307044f5d68103ceca629274570a0933bd9af493f2e + sourceBlobDigest: sha256:cfa7e1503a2c59e44a2d44bf69a2db12324cb1a152d29942c68a969962ea5c09 codeSamplesNamespace: glean-api-specs-python-code-samples - codeSamplesRevisionDigest: sha256:cc23275cb351da5ef6256061aed3868dab2d09e7764658ea22e4958928b42d8c + codeSamplesRevisionDigest: sha256:60aa38a0f093349fa189ac4f535bcdf0b2bc99464ffb48ebf83b4318400ff5de workflow: workflowVersion: 1.0.0 speakeasyVersion: latest diff --git a/README.md b/README.md index 203405ee..f5a59cba 100644 --- a/README.md +++ b/README.md @@ -339,6 +339,7 @@ For more information on obtaining the appropriate token type, please contact you ### [Agents](docs/sdks/agents/README.md) +* [create_agent](docs/sdks/agents/README.md#create_agent) - Create an agent * [edit_agent](docs/sdks/agents/README.md#edit_agent) - Edit an agent ### [Authentication](docs/sdks/authentication/README.md) diff --git a/RELEASES.md b/RELEASES.md index 87ea457d..8ed065f0 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -748,4 +748,14 @@ Based on: ### Generated - [python v0.13.0] . ### Releases -- [PyPI v0.13.0] https://pypi.org/project/glean-api-client/0.13.0 - . \ No newline at end of file +- [PyPI v0.13.0] https://pypi.org/project/glean-api-client/0.13.0 - . + +## 2026-06-09 03:42:45 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.773.1 (2.897.1) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v0.13.1] . +### Releases +- [PyPI v0.13.1] https://pypi.org/project/glean-api-client/0.13.1 - . \ No newline at end of file diff --git a/docs/models/createagentrequest.md b/docs/models/createagentrequest.md new file mode 100644 index 00000000..6d556c53 --- /dev/null +++ b/docs/models/createagentrequest.md @@ -0,0 +1,10 @@ +# CreateAgentRequest + + +## Fields + +| Field | Type | Required | Description | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `locale` | *Optional[str]* | :heavy_minus_sign: | The client's preferred locale in rfc5646 format (e.g. `en`, `ja`, `pt-BR`). If omitted, the `Accept-Language` will be used. If not present or not supported, defaults to the closest match or `en`. | +| `timezone_offset` | *Optional[int]* | :heavy_minus_sign: | The offset of the client's timezone in minutes from UTC. e.g. PDT is -420 because it's 7 hours behind UTC. | +| `create_workflow_request` | [models.CreateWorkflowRequest](../models/createworkflowrequest.md) | :heavy_check_mark: | N/A | \ No newline at end of file diff --git a/docs/models/createworkflowrequest.md b/docs/models/createworkflowrequest.md new file mode 100644 index 00000000..e955a419 --- /dev/null +++ b/docs/models/createworkflowrequest.md @@ -0,0 +1,10 @@ +# CreateWorkflowRequest + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- | ------------------------------------------------- | +| `name` | *Optional[str]* | :heavy_minus_sign: | The name of the workflow. | +| `transient` | *Optional[bool]* | :heavy_minus_sign: | Used to create a transient workflow. | +| `parent_workflow_id` | *Optional[str]* | :heavy_minus_sign: | id of the parent workflow for transient workflows | \ No newline at end of file diff --git a/docs/sdks/agents/README.md b/docs/sdks/agents/README.md index b929a12d..00789fbf 100644 --- a/docs/sdks/agents/README.md +++ b/docs/sdks/agents/README.md @@ -4,8 +4,53 @@ ### Available Operations +* [create_agent](#create_agent) - Create an agent * [edit_agent](#edit_agent) - Edit an agent +## create_agent + +Create an agent. + +### Example Usage + + +```python +from glean.api_client import Glean +import os + + +with Glean( + api_token=os.getenv("GLEAN_API_TOKEN", ""), +) as glean: + + res = glean.agents.create_agent() + + # Handle response + print(res) + +``` + +### Parameters + +| Parameter | Type | Required | Description | +| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `locale` | *Optional[str]* | :heavy_minus_sign: | The client's preferred locale in rfc5646 format (e.g. `en`, `ja`, `pt-BR`). If omitted, the `Accept-Language` will be used. If not present or not supported, defaults to the closest match or `en`. | +| `timezone_offset` | *Optional[int]* | :heavy_minus_sign: | The offset of the client's timezone in minutes from UTC. e.g. PDT is -420 because it's 7 hours behind UTC. | +| `name` | *Optional[str]* | :heavy_minus_sign: | The name of the workflow. | +| `transient` | *Optional[bool]* | :heavy_minus_sign: | Used to create a transient workflow. | +| `parent_workflow_id` | *Optional[str]* | :heavy_minus_sign: | id of the parent workflow for transient workflows | +| `retries` | [Optional[utils.RetryConfig]](../../models/utils/retryconfig.md) | :heavy_minus_sign: | Configuration to override the default retry behavior of the client. | + +### Response + +**[models.WorkflowResult](../../models/workflowresult.md)** + +### Errors + +| Error Type | Status Code | Content Type | +| ----------------- | ----------------- | ----------------- | +| errors.GleanError | 4XX, 5XX | \*/\* | + ## edit_agent Creates a draft or publishes an [agent](https://developers.glean.com/agents/agents-api). Use `isDraft=true` to save a draft, or `isDraft=false` (or omit) to publish immediately. Only draft and publish modes are supported. diff --git a/pyproject.toml b/pyproject.toml index f34dd6a5..af1e59cf 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "glean-api-client" -version = "0.13.0" +version = "0.13.1" 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 8d9da6a0..f46887e5 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.13.0" +__version__: str = "0.13.1" __openapi_doc_version__: str = "0.9.0" -__gen_version__: str = "2.893.0" -__user_agent__: str = "speakeasy-sdk/python 0.13.0 2.893.0 0.9.0 glean-api-client" +__gen_version__: str = "2.897.1" +__user_agent__: str = "speakeasy-sdk/python 0.13.1 2.897.1 0.9.0 glean-api-client" try: if __package__ is not None: diff --git a/src/glean/api_client/agents.py b/src/glean/api_client/agents.py index 99f5f660..2be17185 100644 --- a/src/glean/api_client/agents.py +++ b/src/glean/api_client/agents.py @@ -10,6 +10,216 @@ class Agents(BaseSDK): + def create_agent( + self, + *, + locale: Optional[str] = None, + timezone_offset: Optional[int] = None, + name: Optional[str] = None, + transient: Optional[bool] = None, + parent_workflow_id: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.WorkflowResult: + r"""Create an agent + + Create an agent. + + :param locale: The client's preferred locale in rfc5646 format (e.g. `en`, `ja`, `pt-BR`). If omitted, the `Accept-Language` will be used. If not present or not supported, defaults to the closest match or `en`. + :param timezone_offset: The offset of the client's timezone in minutes from UTC. e.g. PDT is -420 because it's 7 hours behind UTC. + :param name: The name of the workflow. + :param transient: Used to create a transient workflow. + :param parent_workflow_id: id of the parent workflow for transient workflows + :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.CreateAgentRequest( + locale=locale, + timezone_offset=timezone_offset, + create_workflow_request=models.CreateWorkflowRequest( + name=name, + transient=transient, + parent_workflow_id=parent_workflow_id, + ), + ) + + req = self._build_request( + method="POST", + path="/rest/api/v1/agents", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=False, + 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.create_workflow_request, + False, + False, + "json", + models.CreateWorkflowRequest, + ), + 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="createAgent", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + ), + 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.WorkflowResult, http_res) + if utils.match_response(http_res, ["400", "401", "403", "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, ["500", "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 create_agent_async( + self, + *, + locale: Optional[str] = None, + timezone_offset: Optional[int] = None, + name: Optional[str] = None, + transient: Optional[bool] = None, + parent_workflow_id: Optional[str] = None, + retries: OptionalNullable[utils.RetryConfig] = UNSET, + server_url: Optional[str] = None, + timeout_ms: Optional[int] = None, + http_headers: Optional[Mapping[str, str]] = None, + ) -> models.WorkflowResult: + r"""Create an agent + + Create an agent. + + :param locale: The client's preferred locale in rfc5646 format (e.g. `en`, `ja`, `pt-BR`). If omitted, the `Accept-Language` will be used. If not present or not supported, defaults to the closest match or `en`. + :param timezone_offset: The offset of the client's timezone in minutes from UTC. e.g. PDT is -420 because it's 7 hours behind UTC. + :param name: The name of the workflow. + :param transient: Used to create a transient workflow. + :param parent_workflow_id: id of the parent workflow for transient workflows + :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.CreateAgentRequest( + locale=locale, + timezone_offset=timezone_offset, + create_workflow_request=models.CreateWorkflowRequest( + name=name, + transient=transient, + parent_workflow_id=parent_workflow_id, + ), + ) + + req = self._build_request_async( + method="POST", + path="/rest/api/v1/agents", + base_url=base_url, + url_variables=url_variables, + request=request, + request_body_required=True, + request_has_path_params=False, + 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.create_workflow_request, + False, + False, + "json", + models.CreateWorkflowRequest, + ), + 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="createAgent", + oauth2_scopes=None, + security_source=get_security_from_env( + self.sdk_configuration.security, models.Security + ), + ), + 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.WorkflowResult, http_res) + if utils.match_response(http_res, ["400", "401", "403", "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, ["500", "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 edit_agent( self, *, diff --git a/src/glean/api_client/client_chat.py b/src/glean/api_client/client_chat.py index f1e89630..e396b274 100644 --- a/src/glean/api_client/client_chat.py +++ b/src/glean/api_client/client_chat.py @@ -140,7 +140,7 @@ def create( retry_config=retry_config, ) - if utils.match_response(http_res, "200", "application/json"): + if utils.match_response(http_res, ["200", "202"], "application/json"): return unmarshal_json_response(models.ChatResponse, http_res) if utils.match_response(http_res, ["400", "401", "408", "429", "4XX"], "*"): http_res_text = utils.stream_to_text(http_res) @@ -281,7 +281,7 @@ async def create_async( retry_config=retry_config, ) - if utils.match_response(http_res, "200", "application/json"): + if utils.match_response(http_res, ["200", "202"], "application/json"): return unmarshal_json_response(models.ChatResponse, http_res) if utils.match_response(http_res, ["400", "401", "408", "429", "4XX"], "*"): http_res_text = await utils.stream_to_text_async(http_res) diff --git a/src/glean/api_client/models/__init__.py b/src/glean/api_client/models/__init__.py index 10111171..2563cb4d 100644 --- a/src/glean/api_client/models/__init__.py +++ b/src/glean/api_client/models/__init__.py @@ -342,6 +342,7 @@ from .contentdefinition import ContentDefinition, ContentDefinitionTypedDict from .contenttype import ContentType from .countinfo import CountInfo, CountInfoTypedDict + from .createagentop import CreateAgentRequest, CreateAgentRequestTypedDict from .createannouncementop import ( CreateannouncementRequestRequest, CreateannouncementRequestRequestTypedDict, @@ -395,6 +396,10 @@ CreateShortcutResponse, CreateShortcutResponseTypedDict, ) + from .createworkflowrequest import ( + CreateWorkflowRequest, + CreateWorkflowRequestTypedDict, + ) from .currentactiveusers import CurrentActiveUsers, CurrentActiveUsersTypedDict from .customdatasourceconfig import ( CustomDatasourceConfig, @@ -1799,6 +1804,8 @@ "ContentType", "CountInfo", "CountInfoTypedDict", + "CreateAgentRequest", + "CreateAgentRequestTypedDict", "CreateAnnouncementRequest", "CreateAnnouncementRequestChannel", "CreateAnnouncementRequestPostType", @@ -1817,6 +1824,8 @@ "CreateShortcutRequestTypedDict", "CreateShortcutResponse", "CreateShortcutResponseTypedDict", + "CreateWorkflowRequest", + "CreateWorkflowRequestTypedDict", "CreateannouncementRequestRequest", "CreateannouncementRequestRequestTypedDict", "CreateanswerRequestRequest", @@ -3019,6 +3028,8 @@ "ContentType": ".contenttype", "CountInfo": ".countinfo", "CountInfoTypedDict": ".countinfo", + "CreateAgentRequest": ".createagentop", + "CreateAgentRequestTypedDict": ".createagentop", "CreateannouncementRequestRequest": ".createannouncementop", "CreateannouncementRequestRequestTypedDict": ".createannouncementop", "CreateAnnouncementRequest": ".createannouncementrequest", @@ -3051,6 +3062,8 @@ "CreateShortcutRequestTypedDict": ".createshortcutrequest", "CreateShortcutResponse": ".createshortcutresponse", "CreateShortcutResponseTypedDict": ".createshortcutresponse", + "CreateWorkflowRequest": ".createworkflowrequest", + "CreateWorkflowRequestTypedDict": ".createworkflowrequest", "CurrentActiveUsers": ".currentactiveusers", "CurrentActiveUsersTypedDict": ".currentactiveusers", "CustomDatasourceConfig": ".customdatasourceconfig", diff --git a/src/glean/api_client/models/createagentop.py b/src/glean/api_client/models/createagentop.py new file mode 100644 index 00000000..4ed4192d --- /dev/null +++ b/src/glean/api_client/models/createagentop.py @@ -0,0 +1,54 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .createworkflowrequest import CreateWorkflowRequest, CreateWorkflowRequestTypedDict +from glean.api_client.types import BaseModel, UNSET_SENTINEL +from glean.api_client.utils import FieldMetadata, QueryParamMetadata, RequestMetadata +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class CreateAgentRequestTypedDict(TypedDict): + create_workflow_request: CreateWorkflowRequestTypedDict + locale: NotRequired[str] + r"""The client's preferred locale in rfc5646 format (e.g. `en`, `ja`, `pt-BR`). If omitted, the `Accept-Language` will be used. If not present or not supported, defaults to the closest match or `en`.""" + timezone_offset: NotRequired[int] + r"""The offset of the client's timezone in minutes from UTC. e.g. PDT is -420 because it's 7 hours behind UTC.""" + + +class CreateAgentRequest(BaseModel): + create_workflow_request: Annotated[ + CreateWorkflowRequest, + FieldMetadata(request=RequestMetadata(media_type="application/json")), + ] + + locale: Annotated[ + Optional[str], + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""The client's preferred locale in rfc5646 format (e.g. `en`, `ja`, `pt-BR`). If omitted, the `Accept-Language` will be used. If not present or not supported, defaults to the closest match or `en`.""" + + timezone_offset: Annotated[ + Optional[int], + pydantic.Field(alias="timezoneOffset"), + FieldMetadata(query=QueryParamMetadata(style="form", explode=True)), + ] = None + r"""The offset of the client's timezone in minutes from UTC. e.g. PDT is -420 because it's 7 hours behind UTC.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["locale", "timezoneOffset"]) + 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 diff --git a/src/glean/api_client/models/createworkflowrequest.py b/src/glean/api_client/models/createworkflowrequest.py new file mode 100644 index 00000000..206d00f3 --- /dev/null +++ b/src/glean/api_client/models/createworkflowrequest.py @@ -0,0 +1,52 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from glean.api_client.types import BaseModel, UNSET_SENTINEL +import pydantic +from pydantic import model_serializer +from typing import Optional +from typing_extensions import Annotated, NotRequired, TypedDict + + +class CreateWorkflowRequestTypedDict(TypedDict): + name: NotRequired[str] + r"""The name of the workflow.""" + transient: NotRequired[bool] + r"""Used to create a transient workflow.""" + parent_workflow_id: NotRequired[str] + r"""id of the parent workflow for transient workflows""" + + +class CreateWorkflowRequest(BaseModel): + name: Optional[str] = None + r"""The name of the workflow.""" + + transient: Optional[bool] = None + r"""Used to create a transient workflow.""" + + parent_workflow_id: Annotated[ + Optional[str], pydantic.Field(alias="parentWorkflowId") + ] = None + r"""id of the parent workflow for transient workflows""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["name", "transient", "parentWorkflowId"]) + 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: + CreateWorkflowRequest.model_rebuild() +except NameError: + pass diff --git a/src/glean/api_client/utils/eventstreaming.py b/src/glean/api_client/utils/eventstreaming.py index 3bdcd6d3..1c189bf6 100644 --- a/src/glean/api_client/utils/eventstreaming.py +++ b/src/glean/api_client/utils/eventstreaming.py @@ -53,6 +53,9 @@ def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): + self.close() + + def close(self): self._closed = True self.response.close() @@ -92,6 +95,9 @@ async def __aenter__(self): return self async def __aexit__(self, exc_type, exc_val, exc_tb): + await self.close() + + async def close(self): self._closed = True await self.response.aclose() @@ -124,52 +130,54 @@ async def stream_events_async( sentinel: Optional[str] = None, data_required: bool = True, ) -> AsyncGenerator[T, None]: - buffer = bytearray() - position = 0 - event_id: Optional[str] = None - async for chunk in response.aiter_bytes(): - if len(buffer) == 0 and chunk.startswith(UTF8_BOM): - chunk = chunk[len(UTF8_BOM) :] - buffer += chunk - for i in range(position, len(buffer)): - char = buffer[i : i + 1] - seq: Optional[bytes] = None - if char in [b"\r", b"\n"]: - for boundary in MESSAGE_BOUNDARIES: - seq = _peek_sequence(i, buffer, boundary) - if seq is not None: - break - if seq is None: - continue - - block = buffer[position:i] - position = i + len(seq) - event, discard, event_id = _parse_event( - raw=block, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, - ) - if event is not None: - yield event - if discard: - await response.aclose() - return - - if position > 0: - buffer = buffer[position:] - position = 0 - - event, discard, _ = _parse_event( - raw=buffer, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, - ) - if event is not None: - yield event + try: + buffer = bytearray() + position = 0 + event_id: Optional[str] = None + async for chunk in response.aiter_bytes(): + if len(buffer) == 0 and chunk.startswith(UTF8_BOM): + chunk = chunk[len(UTF8_BOM) :] + buffer += chunk + for i in range(position, len(buffer)): + char = buffer[i : i + 1] + seq: Optional[bytes] = None + if char in [b"\r", b"\n"]: + for boundary in MESSAGE_BOUNDARIES: + seq = _peek_sequence(i, buffer, boundary) + if seq is not None: + break + if seq is None: + continue + + block = buffer[position:i] + position = i + len(seq) + event, discard, event_id = _parse_event( + raw=block, + decoder=decoder, + sentinel=sentinel, + event_id=event_id, + data_required=data_required, + ) + if event is not None: + yield event + if discard: + return + + if position > 0: + buffer = buffer[position:] + position = 0 + + event, discard, _ = _parse_event( + raw=buffer, + decoder=decoder, + sentinel=sentinel, + event_id=event_id, + data_required=data_required, + ) + if event is not None: + yield event + finally: + await response.aclose() def stream_events( @@ -178,52 +186,54 @@ def stream_events( sentinel: Optional[str] = None, data_required: bool = True, ) -> Generator[T, None, None]: - buffer = bytearray() - position = 0 - event_id: Optional[str] = None - for chunk in response.iter_bytes(): - if len(buffer) == 0 and chunk.startswith(UTF8_BOM): - chunk = chunk[len(UTF8_BOM) :] - buffer += chunk - for i in range(position, len(buffer)): - char = buffer[i : i + 1] - seq: Optional[bytes] = None - if char in [b"\r", b"\n"]: - for boundary in MESSAGE_BOUNDARIES: - seq = _peek_sequence(i, buffer, boundary) - if seq is not None: - break - if seq is None: - continue - - block = buffer[position:i] - position = i + len(seq) - event, discard, event_id = _parse_event( - raw=block, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, - ) - if event is not None: - yield event - if discard: - response.close() - return - - if position > 0: - buffer = buffer[position:] - position = 0 - - event, discard, _ = _parse_event( - raw=buffer, - decoder=decoder, - sentinel=sentinel, - event_id=event_id, - data_required=data_required, - ) - if event is not None: - yield event + try: + buffer = bytearray() + position = 0 + event_id: Optional[str] = None + for chunk in response.iter_bytes(): + if len(buffer) == 0 and chunk.startswith(UTF8_BOM): + chunk = chunk[len(UTF8_BOM) :] + buffer += chunk + for i in range(position, len(buffer)): + char = buffer[i : i + 1] + seq: Optional[bytes] = None + if char in [b"\r", b"\n"]: + for boundary in MESSAGE_BOUNDARIES: + seq = _peek_sequence(i, buffer, boundary) + if seq is not None: + break + if seq is None: + continue + + block = buffer[position:i] + position = i + len(seq) + event, discard, event_id = _parse_event( + raw=block, + decoder=decoder, + sentinel=sentinel, + event_id=event_id, + data_required=data_required, + ) + if event is not None: + yield event + if discard: + return + + if position > 0: + buffer = buffer[position:] + position = 0 + + event, discard, _ = _parse_event( + raw=buffer, + decoder=decoder, + sentinel=sentinel, + event_id=event_id, + data_required=data_required, + ) + if event is not None: + yield event + finally: + response.close() def _parse_event( diff --git a/tests/mockserver/internal/handler/generated_handlers.go b/tests/mockserver/internal/handler/generated_handlers.go index 6400b090..a8a0a755 100644 --- a/tests/mockserver/internal/handler/generated_handlers.go +++ b/tests/mockserver/internal/handler/generated_handlers.go @@ -57,6 +57,7 @@ func GeneratedHandlers(ctx context.Context, dir *logging.HTTPFileDirectory, rt * NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/addcollectionitems", pathPostRestAPIV1Addcollectionitems(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/addverificationreminder", pathPostRestAPIV1Addverificationreminder(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/adminsearch", pathPostRestAPIV1Adminsearch(dir, rt)), + NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/agents", pathPostRestAPIV1Agents(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/autocomplete", pathPostRestAPIV1Autocomplete(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/chat", pathPostRestAPIV1Chat(dir, rt)), NewGeneratedHandler(ctx, http.MethodPost, "/rest/api/v1/checkdatasourceauth", pathPostRestAPIV1Checkdatasourceauth(dir, rt)), diff --git a/tests/mockserver/internal/handler/pathpostrestapiv1agents.go b/tests/mockserver/internal/handler/pathpostrestapiv1agents.go new file mode 100644 index 00000000..6c1367d6 --- /dev/null +++ b/tests/mockserver/internal/handler/pathpostrestapiv1agents.go @@ -0,0 +1,82 @@ +// 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 pathPostRestAPIV1Agents(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 "createAgent[0]": + dir.HandlerFunc("createAgent", testCreateAgentCreateAgent0)(w, req) + default: + http.Error(w, fmt.Sprintf("Unknown test: %s[%d]", test, count), http.StatusBadRequest) + } + } +} + +func testCreateAgentCreateAgent0(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.WorkflowResult = &components.WorkflowResult{ + Workflow: components.Workflow{ + Author: &components.Person{ + Name: "George Clooney", + ObfuscatedID: "abc123", + }, + LastDraftSavedBy: &components.Person{ + Name: "George Clooney", + ObfuscatedID: "abc123", + }, + LastUpdatedBy: &components.Person{ + Name: "George Clooney", + ObfuscatedID: "abc123", + }, + }, + } + 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/createworkflowrequest.go b/tests/mockserver/internal/sdk/models/components/createworkflowrequest.go new file mode 100644 index 00000000..277dd8b7 --- /dev/null +++ b/tests/mockserver/internal/sdk/models/components/createworkflowrequest.go @@ -0,0 +1,33 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package components + +type CreateWorkflowRequest struct { + // The name of the workflow. + Name *string `json:"name,omitempty"` + // Used to create a transient workflow. + Transient *bool `json:"transient,omitempty"` + // id of the parent workflow for transient workflows + ParentWorkflowID *string `json:"parentWorkflowId,omitempty"` +} + +func (o *CreateWorkflowRequest) GetName() *string { + if o == nil { + return nil + } + return o.Name +} + +func (o *CreateWorkflowRequest) GetTransient() *bool { + if o == nil { + return nil + } + return o.Transient +} + +func (o *CreateWorkflowRequest) GetParentWorkflowID() *string { + if o == nil { + return nil + } + return o.ParentWorkflowID +} diff --git a/tests/mockserver/internal/sdk/models/operations/createagent.go b/tests/mockserver/internal/sdk/models/operations/createagent.go new file mode 100644 index 00000000..255e835e --- /dev/null +++ b/tests/mockserver/internal/sdk/models/operations/createagent.go @@ -0,0 +1,56 @@ +// Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT. + +package operations + +import ( + "mockserver/internal/sdk/models/components" +) + +type CreateAgentRequest struct { + // The client's preferred locale in rfc5646 format (e.g. `en`, `ja`, `pt-BR`). If omitted, the `Accept-Language` will be used. If not present or not supported, defaults to the closest match or `en`. + Locale *string `queryParam:"style=form,explode=true,name=locale"` + // The offset of the client's timezone in minutes from UTC. e.g. PDT is -420 because it's 7 hours behind UTC. + TimezoneOffset *int64 `queryParam:"style=form,explode=true,name=timezoneOffset"` + Body components.CreateWorkflowRequest `request:"mediaType=application/json"` +} + +func (o *CreateAgentRequest) GetLocale() *string { + if o == nil { + return nil + } + return o.Locale +} + +func (o *CreateAgentRequest) GetTimezoneOffset() *int64 { + if o == nil { + return nil + } + return o.TimezoneOffset +} + +func (o *CreateAgentRequest) GetBody() components.CreateWorkflowRequest { + if o == nil { + return components.CreateWorkflowRequest{} + } + return o.Body +} + +type CreateAgentResponse struct { + HTTPMeta components.HTTPMetadata `json:"-"` + // Success + WorkflowResult *components.WorkflowResult +} + +func (o *CreateAgentResponse) GetHTTPMeta() components.HTTPMetadata { + if o == nil { + return components.HTTPMetadata{} + } + return o.HTTPMeta +} + +func (o *CreateAgentResponse) GetWorkflowResult() *components.WorkflowResult { + if o == nil { + return nil + } + return o.WorkflowResult +} diff --git a/tests/test_agents.py b/tests/test_agents.py index 1d18b766..46852ff4 100644 --- a/tests/test_agents.py +++ b/tests/test_agents.py @@ -74,3 +74,17 @@ def test_agents_create_and_stream_run(): ) def test_agents_create_and_wait_run(): pass + + +def test_agents_create_agent(): + test_http_client = create_test_http_client("createAgent") + + 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.agents.create_agent() + assert res is not None diff --git a/tests/test_summarize.py b/tests/test_summarize.py index df71d57d..c8dd49d6 100644 --- a/tests/test_summarize.py +++ b/tests/test_summarize.py @@ -18,12 +18,12 @@ def test_summarize_summarize(): res = glean.client.documents.summarize( document_specs=[ { - "ugc_type": models.DocumentSpecUgcType2.ANNOUNCEMENTS, - "ugc_id": "", + "ugc_type": models.DocumentSpecUgcType1.ANSWERS, + "content_id": 123467, }, { - "ugc_type": models.DocumentSpecUgcType1.COLLECTIONS, - "content_id": 885812, + "ugc_type": models.DocumentSpecUgcType1.ANSWERS, + "content_id": 123467, }, ] ) From 2ee4aa2f4ea71c47ada575f0612512e83093467d Mon Sep 17 00:00:00 2001 From: "speakeasy-github[bot]" <128539517+speakeasy-github[bot]@users.noreply.github.com> Date: Tue, 9 Jun 2026 03:46:28 +0000 Subject: [PATCH 2/2] empty commit to trigger [run-tests] workflow