diff --git a/.speakeasy/gen.lock b/.speakeasy/gen.lock index 7c809bb0..688e5d4d 100644 --- a/.speakeasy/gen.lock +++ b/.speakeasy/gen.lock @@ -1,19 +1,19 @@ lockVersion: 2.0.0 id: c48cf606-fb42-4a45-9c23-8f0555307828 management: - docChecksum: 114e19b9b3a859d7c9f39dd9cb83d240 + docChecksum: 2eccfa7a729ff2b0018b0a12fae4c6bc docVersion: 1.0.0 speakeasyVersion: 1.787.0 generationVersion: 2.914.0 - releaseVersion: 1.3.50 - configChecksum: 0223539fd1a287a53438bc7ec3d8bf05 + releaseVersion: 1.3.51 + configChecksum: 42c786fcb3f642846ab5debebe68fb64 repoURL: https://github.com/OpenRouterTeam/python-sdk.git installationURL: https://github.com/OpenRouterTeam/python-sdk.git published: true persistentEdits: - generation_id: 7ad8f9b8-605c-4f26-bdb4-dc0d87c2e836 - pristine_commit_hash: c11f6d9af61357d9ee1a9891def0342207679f4a - pristine_tree_hash: acbf8b78e0992478927ff2a3d45f16d7cf4c5666 + generation_id: 06c77232-c97c-468e-a4a2-e78aaedbd796 + pristine_commit_hash: 74630426eda728d6ce5df2f27cfec65172ae1ceb + pristine_tree_hash: fbd0ccb9ecf77c3064549a1d835a0fcfe6dbe645 features: python: acceptHeaders: 3.0.0 @@ -274,6 +274,10 @@ trackedFiles: id: 8dba3ac579a2 last_write_checksum: sha1:8dadde1dad73e125a97400827b19766e36f2a0f2 pristine_git_object: 0454dd875b965e1ec985a5877c2f72d880b6e690 + docs/components/allow.mdx: + id: f0240e4c81df + last_write_checksum: sha1:c456f41de971d64e3bd7bad4aa3fc5f698944cc8 + pristine_git_object: 9e51317c7ac0c2e04b03bb0c1aa30eec06d854b3 docs/components/allowedtools.mdx: id: bc9b06183311 last_write_checksum: sha1:9b19ddb249037404d76b5c8f7cd8b40e20cf598d @@ -1210,6 +1214,46 @@ trackedFiles: id: 2092a26b770f last_write_checksum: sha1:24138ca8d82a454360a8a7cfc058bc00dc14d4c3 pristine_git_object: 1c451e3fe0473f1e3d1da6f19125b9e6869e2d33 + docs/components/armorautomode.mdx: + id: 216687a0ff81 + last_write_checksum: sha1:5ac37fb0f4a3460f06277cda2f1826dfdd76f22f + pristine_git_object: 38eee368f308a7b7cb5153917a444bbfdb8e2215 + docs/components/armorcontext.mdx: + id: 2471d80e954f + last_write_checksum: sha1:1d5da88ee176de7801b504ba8d3ad991041b470d + pristine_git_object: 443cf253b8f9cc5571f82b173309a7e41e6731c0 + docs/components/armorenvironmententry.mdx: + id: 6167a3caea03 + last_write_checksum: sha1:28e02e2284998db00435053ad241c973c2bc23e7 + pristine_git_object: 319ddde2aeeacd0d4f563bd88435c52a9997eecc + docs/components/armorplugin.mdx: + id: ba12e2f5bccc + last_write_checksum: sha1:abb81ea1831cccc19803420c9a4239b52fa26662 + pristine_git_object: 8021ade6adf3180abf88c4a3cf28545825be1f57 + docs/components/armorpluginid.mdx: + id: b270c399d513 + last_write_checksum: sha1:4117f686453f6eee1da7511cc0b496ad7d1d4a2d + pristine_git_object: a8d7dbf1aaf4a211b33af3cb4e0a0f117ad61f45 + docs/components/armorpluginmode.mdx: + id: 47e4aa4468b1 + last_write_checksum: sha1:f86df139826a75a3a1d57cea86ed011a48970e08 + pristine_git_object: b2d6e8ebedc973230a575ea388083b669b888e37 + docs/components/armorrule.mdx: + id: 9a38f0d9aae9 + last_write_checksum: sha1:944c7a53195c16cdae5e9e41a4c22cb6bee0abf9 + pristine_git_object: 94f084ab48bb7fb56ee03e093d576ae37be357c9 + docs/components/armorsafeguardresult.mdx: + id: 0f85a627579d + last_write_checksum: sha1:0f5e6ddec7ee68a339a5fbbc1e305aba97d883bc + pristine_git_object: 1b1137dc3dae2a32abe687790426495764c20b1b + docs/components/armorsafeguardresultoutcome.mdx: + id: ae0bae708f6c + last_write_checksum: sha1:d25aba02889a7a33b45de13e12050a731fae6aa0 + pristine_git_object: 1b87e5afd98f6399549d31b96e09d77eda2afbf1 + docs/components/armorsafeguardresultstatus.mdx: + id: b6cf4ec2516f + last_write_checksum: sha1:81984c080c3487529af4b69aae1785ebd4b1ba93 + pristine_git_object: 138040e18c43cc589cb2217f4d2f791273464d07 docs/components/audiourl.mdx: id: c457db82a4ac last_write_checksum: sha1:eda63702a1bab370efe326a661950ea0b864169e @@ -1552,8 +1596,8 @@ trackedFiles: pristine_git_object: 8871db442a93fb93e245159c6bf52a758e734c28 docs/components/bodychatcompletion.mdx: id: e03ae2d0f8d2 - last_write_checksum: sha1:9acf9b439014180d834bb1f4e64c07f000d3c48b - pristine_git_object: 607d4c6878ef24430052a80e3bdd3e28dcbf3dce + last_write_checksum: sha1:15f89540811af45810a7609f1df1ac0322d92b81 + pristine_git_object: aed7d0ea5e3ea3aacd2f96d5c6a2d9aad30e4206 docs/components/bodycompletiontokensdetails.mdx: id: 1509f7a0b29d last_write_checksum: sha1:e90b07448ffa1edad6115ae6b0055c956840af0f @@ -1900,8 +1944,8 @@ trackedFiles: pristine_git_object: 643c118fe458c24cdaeca90edceadf1c7d1c9cc2 docs/components/chatrequestplugin.mdx: id: 157782a43de6 - last_write_checksum: sha1:1d0497c437cd3f474328cbc82bfd177c3e80bd5d - pristine_git_object: b0428cd9095543968a49928b769099d5a5bd6fc6 + last_write_checksum: sha1:ce1805386e4f19287ca30cb335ca5144529f3337 + pristine_git_object: e2ecd460775d54a5b43c5bc597f8027424462b8d docs/components/chatrequestreasoning.mdx: id: 8f0176992b3e last_write_checksum: sha1:84576cd6513f125955685c7bdfe315ef886160eb @@ -1916,8 +1960,8 @@ trackedFiles: pristine_git_object: d215d672c97f91fcb38cd5a5bed5c00703545161 docs/components/chatresult.mdx: id: 1d855f0d207b - last_write_checksum: sha1:f14ef500e59b22704c7640ab6c7bc712e7867570 - pristine_git_object: f091e7e3152939218af0d772a62e0032a45f5a5d + last_write_checksum: sha1:021eeb08406e5e1c4043f6297e8975601ff7cba7 + pristine_git_object: 734846a0c170c1c884f0049fe2cacb9660297721 docs/components/chatresultobject.mdx: id: adc07397bfc0 last_write_checksum: sha1:0323dc5815ea2b95d85785afc089cacd90cb13f0 @@ -1940,8 +1984,8 @@ trackedFiles: pristine_git_object: d6bd70fb2627a85b2db13a1f23c179f2fe3ad194 docs/components/chatstreamchunk.mdx: id: 90a2741f18cd - last_write_checksum: sha1:3d38b313ac623710246bbacd79830b79f64ef727 - pristine_git_object: c7ad08b4c0f7e3a60ae7d96c2542512adfe9ff7c + last_write_checksum: sha1:3c6a12128b95790ee47dd030498e6d7492cc5369 + pristine_git_object: 10448681be6191f7831ee1f221f7da695bf22ffb docs/components/chatstreamchunkerror.mdx: id: 15ce1e8c2a5d last_write_checksum: sha1:adc488f464df961a969a36414ee90988e2866a6b @@ -2216,8 +2260,8 @@ trackedFiles: pristine_git_object: ab1137191a1f5d0a971c05fdc4cf9a526f597863 docs/components/computeruseservertool.mdx: id: 4276b38e93fb - last_write_checksum: sha1:3185088a2bf62deb4be775f44498de8a47d7cc0d - pristine_git_object: 3021debd985fbc08ffa78a4bbee9fd4e1a7c5d9b + last_write_checksum: sha1:a40f41803dba17e031de98cae0db5f57ce2bf444 + pristine_git_object: d9b3bb6077c33148e4faea2bd92e21a7401e4f5f docs/components/computeruseservertooltype.mdx: id: e4aadaca19bc last_write_checksum: sha1:d7024f63ad66f7701809f41907d35f4b08e21c2b @@ -2984,8 +3028,12 @@ trackedFiles: pristine_git_object: 1b43e9ba3a50d3ea814e584c50293291a9333a1d docs/components/environment.mdx: id: 10d9f9dbcaf3 - last_write_checksum: sha1:415cb68d86a5d9bfd2ddb9bfa3ecd2794870721b - pristine_git_object: c08a3d8fa9bad83e57d5baa9be9995f30b16a24f + last_write_checksum: sha1:c6f95d1af84064e63d3a9af57c621065b07571d4 + pristine_git_object: 00277e093ff3e48873e1b98ed4cab49c59504ded + docs/components/environmentenum.mdx: + id: e44bc88cd4bf + last_write_checksum: sha1:59c04fb0870d900edd85bd5cda125aa048b4e288 + pristine_git_object: f92ca831fd7184761b14c663c3b88643ba20e99b docs/components/errorenum.mdx: id: 722594694be3 last_write_checksum: sha1:2049d2c991cd1fc6b678b44cba040d382eb3b133 @@ -3450,6 +3498,10 @@ trackedFiles: id: ccedea0ab250 last_write_checksum: sha1:08342a9cceb4f7a5dc0b574a429d46af9d9a13f4 pristine_git_object: 9e0a058e6a19b68f470eb0938670dff51b47f4b5 + docs/components/harddeny.mdx: + id: 31284663ba89 + last_write_checksum: sha1:471394bf5cb83396ec048d7eee07bf9e876e1553 + pristine_git_object: 3a56c4df1b08f3f794d1fd5fa8ba0559bf42f88a docs/components/image.mdx: id: fcfab5677d29 last_write_checksum: sha1:5d184152b5cfdb57d8120b8308b2cebf871f039b @@ -4500,8 +4552,8 @@ trackedFiles: pristine_git_object: fb2a55630750a5c10fe509403c6d95cbfa8373c5 docs/components/messagesrequestplugin.mdx: id: 45918e4b5c26 - last_write_checksum: sha1:c30551678456716bfed628ea68c15ff30e94ab06 - pristine_git_object: 684c25cf9124f2c87bd0d449b73e8d511e7910d4 + last_write_checksum: sha1:113109958fc7bb1df6f501653a83467909b3d4bc + pristine_git_object: c8bcb6562eccec77f87cab070818536f571a3d48 docs/components/messagesrequesttool.mdx: id: f9dc5aede7ad last_write_checksum: sha1:dfa67d1bcd58e5743ba4bcd14d50bb1f5d2b836c @@ -4990,6 +5042,10 @@ trackedFiles: id: 35262d81b0a1 last_write_checksum: sha1:53220ed66cf059d9f06df81b7f5bb0f2d87f5283 pristine_git_object: bf3c27b8d2da352bd80bb18179159839e69b9b0a + docs/components/onerror.mdx: + id: 652a1db16dbe + last_write_checksum: sha1:e9b7ccb3ef20c9c5c1536fa88bfdc57e94d3717a + pristine_git_object: fd5c6bab1fcc801cfc9d41077f7ae22c3c89f2ac docs/components/openaifile.mdx: id: 455c97feac56 last_write_checksum: sha1:177e114084bb0761a3c7b1a1c419048dabb55d18 @@ -5212,8 +5268,8 @@ trackedFiles: pristine_git_object: 09effe2d3fe45536c8b0aa0f23c02ce19b15f62c docs/components/openresponsesresult.mdx: id: d0fed85674d2 - last_write_checksum: sha1:4b0b67ae26fd0da7134b249e112a5ec06aefbb0f - pristine_git_object: 41abe10b2506de62292517b112e900aaee18913b + last_write_checksum: sha1:b6c1d992504f8e50fe4f8426d715edad28522394 + pristine_git_object: af726f8f63aec89960dd73120b02677c82159420 docs/components/openresponsesresultallowedcaller.mdx: id: 09e2289416bf last_write_checksum: sha1:5971a2111c35fa89208cf827bb317262e14915ba @@ -5826,6 +5882,10 @@ trackedFiles: id: ff4d9d7b9e07 last_write_checksum: sha1:a9bbd20b85b23f8d3affe92d5c8b0a6d5b717142 pristine_git_object: 2d9b6fc6d382ef371eb85f9c53f0a6d7130f7668 + docs/components/outputmode.mdx: + id: 1cb413d956d2 + last_write_checksum: sha1:1e5bb656a13011242c140b962c2ed1b592596195 + pristine_git_object: 4f1252fbfa58befd6d5c6f79c8e5419ad9f85f9e docs/components/outputreasoningitem.mdx: id: 820bd777266f last_write_checksum: sha1:33efff22e99dd52d274e791933388fdaeb91c582 @@ -6632,8 +6692,8 @@ trackedFiles: pristine_git_object: 336dddcd54b549c4572c7d4f316396ae6449d303 docs/components/responsesrequestplugin.mdx: id: 4d550c41c85f - last_write_checksum: sha1:71efa872e28d2d17a6f4b7a775b83f22ea0e24b8 - pristine_git_object: 8d1ff98621d10c237fed0e5b18eeb0e457447ecd + last_write_checksum: sha1:33fd23a59ea84d642dbe158a27e48621b5514a06 + pristine_git_object: b13aa07c261950095a6cc82c9f74d0f667630658 docs/components/responsesrequestservicetier.mdx: id: 5000ee5983ff last_write_checksum: sha1:833cacf1f124cb94079d80eb80a894cd51f12ba4 @@ -6890,6 +6950,10 @@ trackedFiles: id: e86dd4c94fe2 last_write_checksum: sha1:ae1a817ee130d525983e7d42615ac7a64ba4cdff pristine_git_object: d989162b01084a3c272851642eab332009f68512 + docs/components/softdeny.mdx: + id: d113e0c596b9 + last_write_checksum: sha1:56c1888fc6437e170d31ceabfa505cc1aad87ce2 + pristine_git_object: ff6088eccbdf64207e67fd644fe3bb8a536f4056 docs/components/sourcecontent.mdx: id: d211413b56ad last_write_checksum: sha1:e9ec235c28760da429e35fea006321e7a697e5c4 @@ -7426,6 +7490,22 @@ trackedFiles: id: ac3c7f5f5fa6 last_write_checksum: sha1:bfbecb3b4e70cb8a4aa0379246f4ffbaae71b341 pristine_git_object: f5ff9bfa009e34e0326ff7ef88e82082e54b20cb + docs/components/tooluses.mdx: + id: f2dd81f9b4e4 + last_write_checksum: sha1:2fd614451dd8e83cbddb25b320058b63ba1f10fe + pristine_git_object: 41964d299e37f61778da2843bd6ac18eccef44a2 + docs/components/toolusesevaluated.mdx: + id: 810cfcaff095 + last_write_checksum: sha1:722b5420d4b579621d760842542682b6e42d1dc7 + pristine_git_object: 5494a7e155ab98f2b95be4e3d24f21c4b4d761ac + docs/components/toolusesskipped.mdx: + id: 42a56dd7e6da + last_write_checksum: sha1:8569fe99bdcd0986cb5ca1216f11cb8dee09caf7 + pristine_git_object: 02a125081d01e98670153efcbe8e45084c283f06 + docs/components/toolusesunavailable.mdx: + id: 2cc45259ce90 + last_write_checksum: sha1:1675ef5e1c06ba7721542d669079fa5b67841784 + pristine_git_object: 6fead4227ab922832021e7c6e50c1dfdfc7afc85 docs/components/toolwebsearch20250305.mdx: id: e583eb0b3bd1 last_write_checksum: sha1:a750dd139f327bf53d4cde02e6b897afa274475b @@ -7502,6 +7582,10 @@ trackedFiles: id: b3bd6b0de96e last_write_checksum: sha1:7d4c65b6740216e057d36ea498509249d9c97354 pristine_git_object: 658b179115ff4db7f09c792544b5fae73a480520 + docs/components/typeavailable.mdx: + id: 497347c01b9b + last_write_checksum: sha1:05e7d05deed0895cb806dcccf13c8b5005d6331d + pristine_git_object: bbd9c9abb3d0c1fcd8022730bc01e3ef7efdf0a8 docs/components/typebash20250124.mdx: id: 0f1fed4892ca last_write_checksum: sha1:b57f67ff665ddf959a9078d1fcbd2b1eb9df7a6d @@ -7526,6 +7610,10 @@ trackedFiles: id: 6afc200110eb last_write_checksum: sha1:67b122fb7d678523303b419575d85075c6cf260a pristine_git_object: 8c90b7c0c4ccd514fd2b06a1e10c9879298978ef + docs/components/typedangeroustooluse.mdx: + id: c8cdcd4734e2 + last_write_checksum: sha1:d8090bb610e2fc9a15623871c329b3d200c5f571 + pristine_git_object: 4d4a11a1921fafd66e06979f1d99a0c9693326e2 docs/components/typeenabled.mdx: id: 2107f66972cb last_write_checksum: sha1:47c1d819d31519b3d19a87f3389786d5c23206d4 @@ -7534,6 +7622,10 @@ trackedFiles: id: 7e29de8a1874 last_write_checksum: sha1:19b66fd2808ce791e8ec41203dd91bf1eeb9a996 pristine_git_object: 62d36e211de192914adac3fd60dc58b52956f57a + docs/components/typeevaluated.mdx: + id: cb010b5183b4 + last_write_checksum: sha1:b098425e6b65c7de0432c492a27886f5684c32ae + pristine_git_object: eea25abb57b80574eba5b30c400754e0258ec4b7 docs/components/typeexec.mdx: id: bdffae9225e9 last_write_checksum: sha1:adcee4778c3a095280c7e3541c1bfec21eba0139 @@ -7554,6 +7646,10 @@ trackedFiles: id: 1fbbd27c03b6 last_write_checksum: sha1:003d0b57065e35457a5f365aec76783fd735125c pristine_git_object: 797eb174cde7ef02e12c4379cb24208c1406bef2 + docs/components/typeskipped.mdx: + id: 8f843e75d342 + last_write_checksum: sha1:8212acfffc9f3f7b7272dd791b0fffedaf868d58 + pristine_git_object: c5ce724db3d2644b7ba6f7c074512a28d584938e docs/components/typetexteditor20250124.mdx: id: 6104a1c13bf2 last_write_checksum: sha1:041007e5b9c7d4ef048d0c380cdadedad4c6066e @@ -7586,6 +7682,10 @@ trackedFiles: id: 16b1e85474e0 last_write_checksum: sha1:a747849f24b7447aa71129a9857e6b48c2496775 pristine_git_object: c59f9693a1160d7d2d54d10756eb4df0c579a818 + docs/components/typeunavailable.mdx: + id: f5e16e3838f3 + last_write_checksum: sha1:4a7a35b4b66c86f65dcafe1e6fa313fcfa17e68a + pristine_git_object: 9d06705d9db71cc0685cc3afc669f965f4a98d0f docs/components/typewebsearch20250305.mdx: id: c5cd64905a32 last_write_checksum: sha1:70d29a41edfb246a4e50bf98bfca9df61809d075 @@ -10188,8 +10288,8 @@ trackedFiles: pristine_git_object: 3e38f1a929f7d6b1d6de74604aa87e3d8f010544 pyproject.toml: id: 5d07e7d72637 - last_write_checksum: sha1:d38c2aa8eb0ebc4c51df0b9755aaae1a4cd3366e - pristine_git_object: abed0d06c5ec64121955d712ca32f3f58512dd39 + last_write_checksum: sha1:6a1ae75d8efe03a70119b451c44288c8bf678175 + pristine_git_object: 874397dbfeb9f018fc6af88bb4f0f87ae67bc263 scripts/prepare_readme.py: id: e0c5957a6035 last_write_checksum: sha1:77f44b60b98bc126557ec27391f91dfba764bb54 @@ -10216,8 +10316,8 @@ trackedFiles: pristine_git_object: 86713cfea633e09d33b3d4e65281071fe20e6137 src/openrouter/_version.py: id: d8d15ad6c586 - last_write_checksum: sha1:370e28156af8445de16e8f15e0ae5440a1ba0d71 - pristine_git_object: d35001c0df00d89de2644b99da2a25b4121c815c + last_write_checksum: sha1:cf60e78489d5b26972a3e812d16a23c0ba95821c + pristine_git_object: 77be04ec9f7f57f2e31297c26b772632914806d2 src/openrouter/alpha.py: id: 306c4d93308d last_write_checksum: sha1:30f55a360f41376ab194b9ea725fe4e001a5ae1a @@ -10264,8 +10364,8 @@ trackedFiles: pristine_git_object: ad3d247954547814054c01989a2dff3d12b3e4e1 src/openrouter/components/__init__.py: id: 81754e97b3f4 - last_write_checksum: sha1:34d047eda07f613ceab60a78cecdaab927e85389 - pristine_git_object: 9aa15b5afbeb4b957ab9adbe170c2b70602c11cc + last_write_checksum: sha1:4ebf0abc8f838113bc4a1ef520e3fc6b5914e7b0 + pristine_git_object: e858066a694593b119b38a2b9fc1d20cd622433b src/openrouter/components/aabenchmarkentry.py: id: e2e0f0b48c82 last_write_checksum: sha1:fab4d9a24d2cea937bb749d46c5f83941e99d65c @@ -10826,6 +10926,30 @@ trackedFiles: id: 9152f7bbc9bd last_write_checksum: sha1:3995ff20e5a93c96f2160a143434e89feded1dd3 pristine_git_object: 2ccc3d9be586133e5d5138c77eacefa243987fb5 + src/openrouter/components/armorautomode.py: + id: e87e3cabdf02 + last_write_checksum: sha1:3cd027a4b0371907092c45ebb49a97afbfeee66c + pristine_git_object: 8d9915e44c0fbc6c1450ea861755ef85867ed4cb + src/openrouter/components/armorcontext.py: + id: 258fe2809faf + last_write_checksum: sha1:4a6c0e658982a2d78b0688558f692cc509de2806 + pristine_git_object: dc5da7beef9eb6fc92fb816ebb8f867d1ce2398a + src/openrouter/components/armorenvironmententry.py: + id: ef3f8e30774d + last_write_checksum: sha1:ecf13b068425833f91bb8de4c123f33387f7db95 + pristine_git_object: fcc6d267178e9f01f1faef96854a1cc3bf40ff02 + src/openrouter/components/armorplugin.py: + id: f3ea1534eb32 + last_write_checksum: sha1:bb4a0aa6f8ccebcdc45d5fabec8e4c2014b57189 + pristine_git_object: 4ce09db97abadf52e70a4280202ef2414a1a2047 + src/openrouter/components/armorrule.py: + id: c8005fb10846 + last_write_checksum: sha1:58fe830186d915730ff8acb8a124378a13a7272f + pristine_git_object: 3c773ad1e9008e0e260fc379841dd3231d16ae93 + src/openrouter/components/armorsafeguardresult.py: + id: 7b28c8e2b84b + last_write_checksum: sha1:65f232d3f909f129334f3105e5cbad0603a2ba48 + pristine_git_object: af7c7510866c59a0c51b1315766578d9d166601f src/openrouter/components/autobetarouterplugin.py: id: bb4119e5d4dc last_write_checksum: sha1:c49d24e4c19d232bed7ada63ccbffbaca55cbc7e @@ -10900,8 +11024,8 @@ trackedFiles: pristine_git_object: 4c81a5f783873a99d67ae90ffacbdda63b61cea6 src/openrouter/components/batchobject.py: id: caf1ef2414a3 - last_write_checksum: sha1:c4c9d1d347e397c314a2379d4eeb8436e3e08a6e - pristine_git_object: 463384701dd07066862fe6eef0f8054458f989ff + last_write_checksum: sha1:f7c063b502e77e8991f129cbc90ae2dd402c11cf + pristine_git_object: d455e6658b85d318dc66633923c9b02257c210b6 src/openrouter/components/batchpaymentrequiredresponse_error.py: id: 29d3620e8858 last_write_checksum: sha1:c797fbfd8a88561c101aca8a4d556352213b8096 @@ -11084,12 +11208,12 @@ trackedFiles: pristine_git_object: 8bbde153b53887e426989fd5b0486b6dc1122810 src/openrouter/components/chatrequest.py: id: 5e39eaefa9cf - last_write_checksum: sha1:7a7f5c767829aac42e5e30558ec7ccbff9d74da7 - pristine_git_object: 8d0a9a0113e2e1549e0e6660fc402efbdafbf64d + last_write_checksum: sha1:452bed063aac003c04ac862c6071ff496ad002d1 + pristine_git_object: 98cc04a70c2118d7338ef18b0b09419d59fee972 src/openrouter/components/chatresult.py: id: 9062fe2935fe - last_write_checksum: sha1:9bda60f433938ffce62346b2802e5911656224a1 - pristine_git_object: fb343f06ef87d688cc5c206a79ff75daaa54fa2a + last_write_checksum: sha1:832ad4df3f9f92818e36e9d26a73da3bcff3eb7a + pristine_git_object: afaa56a669d74a13ed9d5747083b7ca8d0c3768d src/openrouter/components/chatsearchmodelsservertool.py: id: e280d3720327 last_write_checksum: sha1:4fd2e8787d4c8dd0e85ffd2d945b9b685e8222f9 @@ -11104,8 +11228,8 @@ trackedFiles: pristine_git_object: 688a877f59a952691935907b0c49c9bd2bbaddca src/openrouter/components/chatstreamchunk.py: id: 16cdd8d4a3d1 - last_write_checksum: sha1:4ad12438e18d4c933fbb83a8bb8d15fee4dfba75 - pristine_git_object: 470fe2787920f88380297a9fc8141d43459c78a2 + last_write_checksum: sha1:2af4361c7b142ff3aba884ecb155bf5f8c42ad3d + pristine_git_object: 417c2c4270fce24cc67dfd5cb089345812067344 src/openrouter/components/chatstreamdelta.py: id: 7484252729d4 last_write_checksum: sha1:c7317ebedb5092f9cf645bb3f349edc547e7f191 @@ -11212,8 +11336,8 @@ trackedFiles: pristine_git_object: f6386f18dfaf8a2bb9a317a0f8401e41e561a350 src/openrouter/components/computeruseservertool.py: id: 10d96ee539dc - last_write_checksum: sha1:ae5e0b764f246b7d8c65598cdd788cb890a8bdc4 - pristine_git_object: f8c70070d4069fcb7ad697a1d1012ea0a95c1a02 + last_write_checksum: sha1:303bd561791e19e9f90b5f827dd4b48383c7560b + pristine_git_object: 142b18a2755af4d57085b1086bb3ad45286e37c1 src/openrouter/components/configurationupdateitem.py: id: c4b8a6acaa9c last_write_checksum: sha1:8983a895f7c6e57c4ed90f8da530092d84c91b9d @@ -12220,8 +12344,8 @@ trackedFiles: pristine_git_object: 7e69d1f775baece5f94b03d35bcd884d5e6f519d src/openrouter/components/messagesrequest.py: id: 72b1f339024d - last_write_checksum: sha1:1be10b575ab8c6f1a77e041d88f275c90dbb24cb - pristine_git_object: afc5f2c3a6769221a12cd0f814d5bfd618f1f402 + last_write_checksum: sha1:23f209d859436f2fc8f9102f27df98ef7a548de3 + pristine_git_object: fd81e321afdec9175f2b21cdf56581578e787b3c src/openrouter/components/messagessearchmodelsservertool.py: id: 53d755edb120 last_write_checksum: sha1:389786fc22ba4bb47b0a086b7aa321f2f04fe943 @@ -12472,8 +12596,8 @@ trackedFiles: pristine_git_object: 08d990d8cc07b7928158fc55784cd9d613f4c58b src/openrouter/components/openresponsesresult.py: id: 78f7e33b19e6 - last_write_checksum: sha1:4fe74e71df4ca9b5c58bcadbaf5a88ce653d3e9f - pristine_git_object: 59b5d79ba26077a29ca4983b80f2ad9626ace0d0 + last_write_checksum: sha1:757fb758c6726dbd75032a6fcf14f3fe3d9bf564 + pristine_git_object: b270324acd6131ff55b6ccc6bb67cb97814a066f src/openrouter/components/openrouterfile.py: id: df1961bcb130 last_write_checksum: sha1:1a9a1b1e640f4d0ef78ce0caa160b5ab342f02cc @@ -13028,8 +13152,8 @@ trackedFiles: pristine_git_object: 900bf08ec940565a8cbf55712a437775db00ca46 src/openrouter/components/responsesrequest.py: id: 8c850080ec5d - last_write_checksum: sha1:587bb3e35cfe411530fe6465e8c5d2821d14ec93 - pristine_git_object: 2a62f91630702148e1a22e75f80c361fac91defb + last_write_checksum: sha1:f2152089c0acd6e493d53c8342c0a0fabbdf7c43 + pristine_git_object: dcbcb267516773e7a91bdd08da076b6f59eedcf3 src/openrouter/components/responsesstreamingresponse.py: id: 142379f3bd90 last_write_checksum: sha1:a48d6f3610f5d15248ef4d25a0d88a0a4a1a9db7 @@ -18614,9 +18738,4 @@ examples: "500": application/json: {"error": {"code": 404, "message": "Intern not found"}} examplesVersion: 1.0.2 -releaseNotes: | - ## Python SDK Changes: - * `open_router.containers.promote_container_file()`: `error.status[499]` **Added** - * `open_router.embeddings.generate()`: `error.status[499]` **Added** - * `open_router.files.upload()`: `error.status[499]` **Added** - * `open_router.video_generation.generate()`: `error` **Changed** +releaseNotes: "## Python SDK Changes:\n* `open_router.batch.create_batches()`: `response.results[].response.body` **Changed**\n* `open_router.batch.get_batches()`: `response.results[].response.body` **Changed**\n* `open_router.chat.send()`: \n * `request.plugins[].union(armor)` **Added**\n * `response` **Changed**\n* `open_router.presets.create_presets_chat_completions()`: \n * `request.plugins[].union(armor)` **Added**\n* `open_router.presets.create_presets_messages()`: \n * `request.plugins[].union(armor)` **Added**\n* `open_router.presets.create_presets_responses()`: \n * `request.plugins[].union(armor)` **Added**\n* `open_router.responses.send()`: \n * `request.plugins[].union(armor)` **Added**\n * `response` **Changed**\n* `open_router.beta.responses.send()`: \n * `request.plugins[].union(armor)` **Added**\n * `response` **Changed**\n" diff --git a/.speakeasy/gen.yaml b/.speakeasy/gen.yaml index 5cdae7d3..d12f5712 100644 --- a/.speakeasy/gen.yaml +++ b/.speakeasy/gen.yaml @@ -36,7 +36,7 @@ generation: documentation: mintlify preApplyUnionDiscriminators: true python: - version: 1.3.50 + version: 1.3.51 additionalDependencies: dev: {} main: {} diff --git a/.speakeasy/out.openapi.yaml b/.speakeasy/out.openapi.yaml index ef38c53d..0b16a9c7 100644 --- a/.speakeasy/out.openapi.yaml +++ b/.speakeasy/out.openapi.yaml @@ -3525,6 +3525,232 @@ components: - 'data' - 'meta' type: 'object' + ArmorAutoMode: + properties: + allow: + items: + anyOf: + - maxLength: 8122 + minLength: 1 + type: 'string' + - $ref: '#/components/schemas/ArmorRule' + type: 'array' + environment: + items: + anyOf: + - maxLength: 4122 + minLength: 1 + type: 'string' + - $ref: '#/components/schemas/ArmorEnvironmentEntry' + type: 'array' + hard_deny: + items: + anyOf: + - maxLength: 8122 + minLength: 1 + type: 'string' + - $ref: '#/components/schemas/ArmorRule' + type: 'array' + soft_deny: + items: + anyOf: + - maxLength: 8122 + minLength: 1 + type: 'string' + - $ref: '#/components/schemas/ArmorRule' + type: 'array' + type: 'object' + ArmorContext: + additionalProperties: + description: 'Carried unchanged; any JSON value.' + description: 'The Armor context: Claude Code''s `classifier_context` (v1), with `auto_mode.{hard_deny,soft_deny,allow}` rules as strings or `{ id, instructions, threshold? }` objects and `auto_mode.environment` entries as `"Name: value"` strings or `{ name, value }` objects. `threshold` applies when Armor evaluates; when the provider evaluates natively (Anthropic dangerous-tool-use beta) rules are judged at the provider''s own boundary.' + example: + auto_mode: + allow: [] + environment: + - 'Trusted repo: github.com/acme/app' + hard_deny: [] + soft_deny: + - id: 'secrets-in-vcs' + instructions: 'Staging, committing or pushing a file that holds secrets, including indirectly through git add -A when the tree shows one.' + v: 1 + properties: + auto_mode: + $ref: '#/components/schemas/ArmorAutoMode' + v: + enum: + - 1 + type: 'number' + required: + - 'v' + type: 'object' + ArmorEnvironmentEntry: + properties: + name: + maxLength: 120 + minLength: 1 + type: 'string' + value: + maxLength: 4000 + type: 'string' + required: + - 'name' + - 'value' + type: 'object' + ArmorPlugin: + additionalProperties: false + description: 'Evaluates every client tool call the model emits against a rule stack (hard-deny, soft-deny, allow) before it reaches the caller. The stack merges the workspace guardrail, this plugin, and any Anthropic `safeguards`; on endpoints that support Anthropic''s `dangerous-tool-use` beta the evaluation is native, elsewhere it is one decisions call per tool call. Evaluation is not billed during the beta. Verdicts are reported as `safeguard_results`.' + example: + classifier_context: + auto_mode: + environment: + - 'Trusted repo: github.com/acme/app' + soft_deny: + - id: 'no-migrations-delete' + instructions: 'Deleting a file under db/migrations.' + v: 1 + id: 'armor' + use_cc_style_default_rules: true + properties: + classifier_context: + $ref: '#/components/schemas/ArmorContext' + enabled: + description: 'Set to false to disable Armor for this request. Defaults to true.' + type: 'boolean' + evaluate_native_tools: + description: 'Run provider-native server tools (web search, code execution, ...) through the agent loop so Armor evaluates them too. Defaults to false: native passthrough stands and such calls are reported `skipped`.' + type: 'boolean' + id: + enum: + - 'armor' + type: 'string' + mode: + description: '`enforce` withholds blocked calls; `audit` evaluates and reports the same verdicts without withholding any calls, regardless of `on_error`. Default `enforce`.' + enum: + - 'enforce' + - 'audit' + type: 'string' + x-speakeasy-unknown-values: allow + on_error: + description: 'When the classifier cannot answer (timeout, upstream error, context too long) the call is reported `unavailable`; `block` rejects it and `log` releases it. Default `block`.' + enum: + - 'log' + - 'block' + type: 'string' + x-speakeasy-unknown-values: allow + output_mode: + description: 'How a blocked call reaches the caller. `text` (the default): the call is withheld and an `` marker stands in assistant text. `custom_item` (Responses API only): the call is withheld and an `openrouter:armor_blocked` output item carries its id, name, arguments and the rule that fired. `claude_code_compatibility` (Messages API only; the default when the request carries a `dangerous_tool_use` safeguard, i.e. the client speaks Claude Code''s protocol): the `tool_use` stays in `content[]` and the verdict is `flagged` in `safeguard_results`, so the client withholds execution and writes the error tool result as under the native classifier. Under `text` and `custom_item` the model received a failure result in the loop and continued in the same request; under `claude_code_compatibility` the turn ends on the flagged call and the model continues on the next request, after the client''s denial.' + enum: + - 'text' + - 'custom_item' + - 'claude_code_compatibility' + type: 'string' + x-speakeasy-unknown-values: allow + use_cc_style_default_rules: + description: 'Prepend Claude Code''s built-in auto-mode rule set (1 hard-deny, 72 soft-deny, 17 allow, 21 environment slots) ahead of every configured rule. Defaults to true on the Anthropic Messages API and false elsewhere.' + type: 'boolean' + required: + - 'id' + type: 'object' + ArmorRule: + properties: + id: + description: 'Stable id, unique within its source; reported as the deciding rule when it fires.' + maxLength: 64 + minLength: 1 + pattern: '^[a-z0-9][a-z0-9_-]*$' + type: 'string' + instructions: + description: 'What the rule matches, written for the classifier.' + maxLength: 8000 + minLength: 1 + type: 'string' + name: + description: 'Display name shown in verdict explanations; defaults to the id.' + maxLength: 120 + minLength: 1 + type: 'string' + threshold: + description: 'Probability at or above which the rule counts as matched. Defaults to 0.6 for hard-deny and soft-deny rules and 0.7 for allow rules (an exception needs stronger evidence to clear a matched soft deny).' + format: 'double' + type: 'number' + required: + - 'id' + - 'instructions' + type: 'object' + ArmorSafeguardResult: + description: 'The outcome of OpenRouter Armor for each client tool call of the response, keyed by tool-call id, in the same shape Anthropic reports its server-side safeguards.' + example: + status: + tool_uses: + call_abc: + explanation: '[Data Exfiltration]' + outcome: 'flagged' + type: 'evaluated' + call_def: + outcome: 'not_flagged' + type: 'evaluated' + type: 'available' + type: 'dangerous_tool_use' + properties: + status: + properties: + tool_uses: + additionalProperties: + oneOf: + - properties: + explanation: + type: 'string' + outcome: + enum: + - 'flagged' + - 'not_flagged' + type: 'string' + x-speakeasy-unknown-values: allow + type: + enum: + - 'evaluated' + type: 'string' + required: + - 'type' + - 'outcome' + type: 'object' + - properties: + type: + enum: + - 'skipped' + type: 'string' + required: + - 'type' + type: 'object' + - properties: + reason: + type: 'string' + type: + enum: + - 'unavailable' + type: 'string' + required: + - 'type' + - 'reason' + type: 'object' + type: 'object' + type: + enum: + - 'available' + type: 'string' + required: + - 'type' + - 'tool_uses' + type: 'object' + type: + enum: + - 'dangerous_tool_use' + type: 'string' + required: + - 'type' + - 'status' + type: 'object' AutoBetaRouterPlugin: example: allowed_models: @@ -5536,6 +5762,11 @@ components: type: - 'string' - 'null' + safeguard_results: + description: 'OpenRouter Armor''s verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.' + items: + $ref: '#/components/schemas/ArmorSafeguardResult' + type: 'array' service_tier: type: - 'string' @@ -7508,6 +7739,7 @@ components: discriminator: mapping: alignment: '#/components/schemas/AlignmentPlugin' + armor: '#/components/schemas/ArmorPlugin' auto-beta-router: '#/components/schemas/AutoBetaRouterPlugin' auto-router: '#/components/schemas/AutoRouterPlugin' context-compression: '#/components/schemas/ContextCompressionPlugin' @@ -7535,6 +7767,7 @@ components: - $ref: '#/components/schemas/SwitchyardRouterPlugin' - $ref: '#/components/schemas/JevRouterPlugin' - $ref: '#/components/schemas/AlignmentPlugin' + - $ref: '#/components/schemas/ArmorPlugin' type: 'array' prediction: $ref: '#/components/schemas/Prediction' @@ -7765,6 +7998,11 @@ components: type: 'string' openrouter_metadata: $ref: '#/components/schemas/OpenRouterMetadata' + safeguard_results: + description: 'OpenRouter Armor''s verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.' + items: + $ref: '#/components/schemas/ArmorSafeguardResult' + type: 'array' service_tier: description: 'The service tier used by the upstream provider for this request' example: 'default' @@ -7912,6 +8150,11 @@ components: type: 'string' openrouter_metadata: $ref: '#/components/schemas/OpenRouterMetadata' + safeguard_results: + description: 'OpenRouter Armor''s verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.' + items: + $ref: '#/components/schemas/ArmorSafeguardResult' + type: 'array' service_tier: description: 'The service tier used by the upstream provider for this request' example: 'default' @@ -17651,6 +17894,7 @@ components: discriminator: mapping: alignment: '#/components/schemas/AlignmentPlugin' + armor: '#/components/schemas/ArmorPlugin' auto-beta-router: '#/components/schemas/AutoBetaRouterPlugin' auto-router: '#/components/schemas/AutoRouterPlugin' context-compression: '#/components/schemas/ContextCompressionPlugin' @@ -17678,6 +17922,7 @@ components: - $ref: '#/components/schemas/SwitchyardRouterPlugin' - $ref: '#/components/schemas/JevRouterPlugin' - $ref: '#/components/schemas/AlignmentPlugin' + - $ref: '#/components/schemas/ArmorPlugin' type: 'array' provider: $ref: '#/components/schemas/ProviderPreferences' @@ -22770,6 +23015,11 @@ components: items: $ref: '#/components/schemas/OutputItems' type: 'array' + safeguard_results: + description: 'OpenRouter Armor''s verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.' + items: + $ref: '#/components/schemas/ArmorSafeguardResult' + type: 'array' service_tier: type: - 'string' @@ -28350,6 +28600,7 @@ components: discriminator: mapping: alignment: '#/components/schemas/AlignmentPlugin' + armor: '#/components/schemas/ArmorPlugin' auto-beta-router: '#/components/schemas/AutoBetaRouterPlugin' auto-router: '#/components/schemas/AutoRouterPlugin' context-compression: '#/components/schemas/ContextCompressionPlugin' @@ -28377,6 +28628,7 @@ components: - $ref: '#/components/schemas/SwitchyardRouterPlugin' - $ref: '#/components/schemas/JevRouterPlugin' - $ref: '#/components/schemas/AlignmentPlugin' + - $ref: '#/components/schemas/ArmorPlugin' type: 'array' presence_penalty: format: 'double' diff --git a/.speakeasy/workflow.lock b/.speakeasy/workflow.lock index 71421ee3..7a583955 100644 --- a/.speakeasy/workflow.lock +++ b/.speakeasy/workflow.lock @@ -2,8 +2,8 @@ speakeasyVersion: 1.787.0 sources: OpenRouter API: sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:16296a47c2aaceda7bf9b800026bfc9bfc0f9dc7208592c357778c586c4e6685 - sourceBlobDigest: sha256:5053e13680878fb5e3220166cd240b24d57d6b62118d0ce7e96133b86210517c + sourceRevisionDigest: sha256:e2169a770b941899e588257c4a70ea18f0b4c48a6de2f1032609d7b5b8bf6267 + sourceBlobDigest: sha256:199b89e56ea9f453448a916e5c38422d9d4196dfb5955aab34bbc0a55d01507b tags: - latest - 1.0.0 @@ -11,10 +11,10 @@ targets: open-router: source: OpenRouter API sourceNamespace: open-router-chat-completions-api - sourceRevisionDigest: sha256:16296a47c2aaceda7bf9b800026bfc9bfc0f9dc7208592c357778c586c4e6685 - sourceBlobDigest: sha256:5053e13680878fb5e3220166cd240b24d57d6b62118d0ce7e96133b86210517c + sourceRevisionDigest: sha256:e2169a770b941899e588257c4a70ea18f0b4c48a6de2f1032609d7b5b8bf6267 + sourceBlobDigest: sha256:199b89e56ea9f453448a916e5c38422d9d4196dfb5955aab34bbc0a55d01507b codeSamplesNamespace: open-router-python-code-samples - codeSamplesRevisionDigest: sha256:ec820930c43abfd607c9dcea3f9a481a9046009afcab47fa46e1a173282cf28c + codeSamplesRevisionDigest: sha256:0040c3bdfdf4a39c108fe13d2fc1a9ed73c4f2e41595d7602577c75ed22728f9 workflow: workflowVersion: 1.0.0 speakeasyVersion: 1.787.0 diff --git a/RELEASES.md b/RELEASES.md index d10dcd8f..a101449d 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -3269,4 +3269,14 @@ Based on: ### Generated - [python v1.3.50] . ### Releases -- [PyPI v1.3.50] https://pypi.org/project/openrouter/1.3.50 - . \ No newline at end of file +- [PyPI v1.3.50] https://pypi.org/project/openrouter/1.3.50 - . + +## 2026-10-14 14:13:02 +### Changes +Based on: +- OpenAPI Doc +- Speakeasy CLI 1.787.0 (2.914.0) https://github.com/speakeasy-api/speakeasy +### Generated +- [python v1.3.51] . +### Releases +- [PyPI v1.3.51] https://pypi.org/project/openrouter/1.3.51 - . \ No newline at end of file diff --git a/docs/components/allow.mdx b/docs/components/allow.mdx new file mode 100644 index 00000000..9e51317c --- /dev/null +++ b/docs/components/allow.mdx @@ -0,0 +1,18 @@ +--- +title: "Allow" +--- + +## Supported Types + +### `str` + +```python +value: str = /* values here */ +``` + +### `components.ArmorRule` + +```python +value: components.ArmorRule = /* values here */ +``` + diff --git a/docs/components/armorautomode.mdx b/docs/components/armorautomode.mdx new file mode 100644 index 00000000..ab08c541 --- /dev/null +++ b/docs/components/armorautomode.mdx @@ -0,0 +1,12 @@ +--- +title: "ArmorAutoMode" +--- + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | ------------------------------------------------------------ | +| `allow` | List[[components.Allow](../components/allow.mdx)] | ➖ | N/A | +| `environment` | List[[components.Environment](../components/environment.mdx)] | ➖ | N/A | +| `hard_deny` | List[[components.HardDeny](../components/harddeny.mdx)] | ➖ | N/A | +| `soft_deny` | List[[components.SoftDeny](../components/softdeny.mdx)] | ➖ | N/A | \ No newline at end of file diff --git a/docs/components/armorcontext.mdx b/docs/components/armorcontext.mdx new file mode 100644 index 00000000..bd381c96 --- /dev/null +++ b/docs/components/armorcontext.mdx @@ -0,0 +1,14 @@ +--- +title: "ArmorContext" +--- + +The Armor context: Claude Code's `classifier_context` (v1), with `auto_mode.{hard_deny,soft_deny,allow}` rules as strings or `{ id, instructions, threshold? }` objects and `auto_mode.environment` entries as `"Name: value"` strings or `{ name, value }` objects. `threshold` applies when Armor evaluates; when the provider evaluates natively (Anthropic dangerous-tool-use beta) rules are judged at the provider's own boundary. + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `auto_mode` | [Optional[components.ArmorAutoMode]](../components/armorautomode.mdx) | ➖ | N/A | | +| `v` | *float* | ✅ | N/A | | +| `__pydantic_extra__` | Dict[str, *Any*] | ➖ | N/A | \{
"auto_mode": \{
"allow": [],
"environment": [
"Trusted repo: github.com/acme/app"
],
"hard_deny": [],
"soft_deny": [
\{
"id": "secrets-in-vcs",
"instructions": "Staging, committing or pushing a file that holds secrets, including indirectly through git add -A when the tree shows one."
}
]
},
"v": 1
} | \ No newline at end of file diff --git a/docs/components/armorenvironmententry.mdx b/docs/components/armorenvironmententry.mdx new file mode 100644 index 00000000..8111557f --- /dev/null +++ b/docs/components/armorenvironmententry.mdx @@ -0,0 +1,10 @@ +--- +title: "ArmorEnvironmentEntry" +--- + +## Fields + +| Field | Type | Required | Description | +| ------------------ | ------------------ | ------------------ | ------------------ | +| `name` | *str* | ✅ | N/A | +| `value` | *str* | ✅ | N/A | \ No newline at end of file diff --git a/docs/components/armorplugin.mdx b/docs/components/armorplugin.mdx new file mode 100644 index 00000000..9c37417e --- /dev/null +++ b/docs/components/armorplugin.mdx @@ -0,0 +1,19 @@ +--- +title: "ArmorPlugin" +--- + +Evaluates every client tool call the model emits against a rule stack (hard-deny, soft-deny, allow) before it reaches the caller. The stack merges the workspace guardrail, this plugin, and any Anthropic `safeguards`; on endpoints that support Anthropic's `dangerous-tool-use` beta the evaluation is native, elsewhere it is one decisions call per tool call. Evaluation is not billed during the beta. Verdicts are reported as `safeguard_results`. + + +## Fields + +| Field | Type | Required | Description | Example | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `classifier_context` | [Optional[components.ArmorContext]](../components/armorcontext.mdx) | ➖ | The Armor context: Claude Code's `classifier_context` (v1), with `auto_mode.{hard_deny,soft_deny,allow}` rules as strings or `{ id, instructions, threshold? }` objects and `auto_mode.environment` entries as `"Name: value"` strings or `{ name, value }` objects. `threshold` applies when Armor evaluates; when the provider evaluates natively (Anthropic dangerous-tool-use beta) rules are judged at the provider's own boundary. | \{
"auto_mode": \{
"allow": [],
"environment": [
"Trusted repo: github.com/acme/app"
],
"hard_deny": [],
"soft_deny": [
\{
"id": "secrets-in-vcs",
"instructions": "Staging, committing or pushing a file that holds secrets, including indirectly through git add -A when the tree shows one."
}
]
},
"v": 1
} | +| `enabled` | *Optional[bool]* | ➖ | Set to false to disable Armor for this request. Defaults to true. | | +| `evaluate_native_tools` | *Optional[bool]* | ➖ | Run provider-native server tools (web search, code execution, ...) through the agent loop so Armor evaluates them too. Defaults to false: native passthrough stands and such calls are reported `skipped`. | | +| `id` | [components.ArmorPluginID](../components/armorpluginid.mdx) | ✅ | N/A | | +| `mode` | [Optional[components.ArmorPluginMode]](../components/armorpluginmode.mdx) | ➖ | `enforce` withholds blocked calls; `audit` evaluates and reports the same verdicts without withholding any calls, regardless of `on_error`. Default `enforce`. | | +| `on_error` | [Optional[components.OnError]](../components/onerror.mdx) | ➖ | When the classifier cannot answer (timeout, upstream error, context too long) the call is reported `unavailable`; `block` rejects it and `log` releases it. Default `block`. | | +| `output_mode` | [Optional[components.OutputMode]](../components/outputmode.mdx) | ➖ | How a blocked call reaches the caller. `text` (the default): the call is withheld and an `` marker stands in assistant text. `custom_item` (Responses API only): the call is withheld and an `openrouter:armor_blocked` output item carries its id, name, arguments and the rule that fired. `claude_code_compatibility` (Messages API only; the default when the request carries a `dangerous_tool_use` safeguard, i.e. the client speaks Claude Code's protocol): the `tool_use` stays in `content[]` and the verdict is `flagged` in `safeguard_results`, so the client withholds execution and writes the error tool result as under the native classifier. Under `text` and `custom_item` the model received a failure result in the loop and continued in the same request; under `claude_code_compatibility` the turn ends on the flagged call and the model continues on the next request, after the client's denial. | | +| `use_cc_style_default_rules` | *Optional[bool]* | ➖ | Prepend Claude Code's built-in auto-mode rule set (1 hard-deny, 72 soft-deny, 17 allow, 21 environment slots) ahead of every configured rule. Defaults to true on the Anthropic Messages API and false elsewhere. | | \ No newline at end of file diff --git a/docs/components/armorpluginid.mdx b/docs/components/armorpluginid.mdx new file mode 100644 index 00000000..a8d7dbf1 --- /dev/null +++ b/docs/components/armorpluginid.mdx @@ -0,0 +1,15 @@ +--- +title: "ArmorPluginID" +--- + +## Example Usage + +```python +from openrouter.components import ArmorPluginID +value: ArmorPluginID = "armor" +``` + + +## Values + +- `"armor"` diff --git a/docs/components/armorpluginmode.mdx b/docs/components/armorpluginmode.mdx new file mode 100644 index 00000000..b2d6e8eb --- /dev/null +++ b/docs/components/armorpluginmode.mdx @@ -0,0 +1,22 @@ +--- +title: "ArmorPluginMode" +--- + +`enforce` withholds blocked calls; `audit` evaluates and reports the same verdicts without withholding any calls, regardless of `on_error`. Default `enforce`. + +## Example Usage + +```python +from openrouter.components import ArmorPluginMode + +# Open enum: unrecognized values are captured as UnrecognizedStr +value: ArmorPluginMode = "enforce" +``` + + +## Values + +This is an open enum. Unrecognized values will not fail type checks. + +- `"enforce"` +- `"audit"` diff --git a/docs/components/armorrule.mdx b/docs/components/armorrule.mdx new file mode 100644 index 00000000..fd9f016f --- /dev/null +++ b/docs/components/armorrule.mdx @@ -0,0 +1,12 @@ +--- +title: "ArmorRule" +--- + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | *str* | ✅ | Stable id, unique within its source; reported as the deciding rule when it fires. | +| `instructions` | *str* | ✅ | What the rule matches, written for the classifier. | +| `name` | *Optional[str]* | ➖ | Display name shown in verdict explanations; defaults to the id. | +| `threshold` | *Optional[float]* | ➖ | Probability at or above which the rule counts as matched. Defaults to 0.6 for hard-deny and soft-deny rules and 0.7 for allow rules (an exception needs stronger evidence to clear a matched soft deny). | \ No newline at end of file diff --git a/docs/components/armorsafeguardresult.mdx b/docs/components/armorsafeguardresult.mdx new file mode 100644 index 00000000..a5d9a030 --- /dev/null +++ b/docs/components/armorsafeguardresult.mdx @@ -0,0 +1,13 @@ +--- +title: "ArmorSafeguardResult" +--- + +The outcome of OpenRouter Armor for each client tool call of the response, keyed by tool-call id, in the same shape Anthropic reports its server-side safeguards. + + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------ | +| `status` | [components.ArmorSafeguardResultStatus](../components/armorsafeguardresultstatus.mdx) | ✅ | N/A | +| `type` | [components.TypeDangerousToolUse](../components/typedangeroustooluse.mdx) | ✅ | N/A | \ No newline at end of file diff --git a/docs/components/armorsafeguardresultoutcome.mdx b/docs/components/armorsafeguardresultoutcome.mdx new file mode 100644 index 00000000..1b87e5af --- /dev/null +++ b/docs/components/armorsafeguardresultoutcome.mdx @@ -0,0 +1,20 @@ +--- +title: "ArmorSafeguardResultOutcome" +--- + +## Example Usage + +```python +from openrouter.components import ArmorSafeguardResultOutcome + +# Open enum: unrecognized values are captured as UnrecognizedStr +value: ArmorSafeguardResultOutcome = "flagged" +``` + + +## Values + +This is an open enum. Unrecognized values will not fail type checks. + +- `"flagged"` +- `"not_flagged"` diff --git a/docs/components/armorsafeguardresultstatus.mdx b/docs/components/armorsafeguardresultstatus.mdx new file mode 100644 index 00000000..598952ce --- /dev/null +++ b/docs/components/armorsafeguardresultstatus.mdx @@ -0,0 +1,10 @@ +--- +title: "ArmorSafeguardResultStatus" +--- + +## Fields + +| Field | Type | Required | Description | +| ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------- | +| `tool_uses` | Dict[str, [components.ToolUses](../components/tooluses.mdx)] | ✅ | N/A | +| `type` | [components.TypeAvailable](../components/typeavailable.mdx) | ✅ | N/A | \ No newline at end of file diff --git a/docs/components/bodychatcompletion.mdx b/docs/components/bodychatcompletion.mdx index ec40d504..4b4b116c 100644 --- a/docs/components/bodychatcompletion.mdx +++ b/docs/components/bodychatcompletion.mdx @@ -15,6 +15,7 @@ title: "BodyChatCompletion" | `object` | [components.BodyObjectChatCompletion](../components/bodyobjectchatcompletion.mdx) | ✅ | N/A | | | `openrouter_metadata` | [Optional[components.OpenRouterMetadata]](../components/openroutermetadata.mdx) | ➖ | N/A | \{
"attempt": 1,
"endpoints": \{
"available": [
\{
"model": "openai/gpt-4o",
"provider": "OpenAI",
"selected": true
}
],
"total": 1
},
"generation_time": 2016,
"is_byok": false,
"region": "iad",
"requested": "openai/gpt-4o",
"strategy": "direct",
"summary": "available=1, selected=OpenAI"
} | | `provider` | *OptionalNullable[str]* | ➖ | N/A | | +| `safeguard_results` | List[[components.ArmorSafeguardResult](../components/armorsafeguardresult.mdx)] | ➖ | OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in. | | | `service_tier` | *OptionalNullable[str]* | ➖ | N/A | | | `system_fingerprint` | *OptionalNullable[str]* | ➖ | N/A | | | `usage` | [Optional[components.BodyUsage1]](../components/bodyusage1.mdx) | ➖ | N/A | | \ No newline at end of file diff --git a/docs/components/chatrequestplugin.mdx b/docs/components/chatrequestplugin.mdx index b0428cd9..e2ecd460 100644 --- a/docs/components/chatrequestplugin.mdx +++ b/docs/components/chatrequestplugin.mdx @@ -10,6 +10,12 @@ title: "ChatRequestPlugin" value: components.AlignmentPlugin = /* values here */ ``` +### `components.ArmorPlugin` + +```python +value: components.ArmorPlugin = /* values here */ +``` + ### `components.AutoBetaRouterPlugin` ```python diff --git a/docs/components/chatresult.mdx b/docs/components/chatresult.mdx index 3e2ece68..64a7bf45 100644 --- a/docs/components/chatresult.mdx +++ b/docs/components/chatresult.mdx @@ -16,6 +16,7 @@ Chat completion response | `model` | *str* | ✅ | Model used for completion | openai/gpt-4 | | `object` | [components.ChatResultObject](../components/chatresultobject.mdx) | ✅ | N/A | | | `openrouter_metadata` | [Optional[components.OpenRouterMetadata]](../components/openroutermetadata.mdx) | ➖ | N/A | \{
"attempt": 1,
"endpoints": \{
"available": [
\{
"model": "openai/gpt-4o",
"provider": "OpenAI",
"selected": true
}
],
"total": 1
},
"generation_time": 2016,
"is_byok": false,
"region": "iad",
"requested": "openai/gpt-4o",
"strategy": "direct",
"summary": "available=1, selected=OpenAI"
} | +| `safeguard_results` | List[[components.ArmorSafeguardResult](../components/armorsafeguardresult.mdx)] | ➖ | OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in. | | | `service_tier` | *OptionalNullable[str]* | ➖ | The service tier used by the upstream provider for this request | default | | `system_fingerprint` | *Nullable[str]* | ✅ | System fingerprint | fp_44709d6fcb | | `usage` | [Optional[components.ChatUsage]](../components/chatusage.mdx) | ➖ | Token usage statistics | \{
"completion_tokens": 15,
"completion_tokens_details": \{
"reasoning_tokens": 5
},
"cost": 0.0012,
"cost_details": \{
"upstream_inference_completions_cost": 0.0004,
"upstream_inference_cost": null,
"upstream_inference_prompt_cost": 0.0008
},
"is_byok": false,
"prompt_tokens": 10,
"prompt_tokens_details": \{
"cached_tokens": 2
},
"server_tool_use_details": \{
"tool_calls_executed": 2,
"tool_calls_requested": 2
},
"total_tokens": 25
} | \ No newline at end of file diff --git a/docs/components/chatstreamchunk.mdx b/docs/components/chatstreamchunk.mdx index 18f8cb5b..6c917ce2 100644 --- a/docs/components/chatstreamchunk.mdx +++ b/docs/components/chatstreamchunk.mdx @@ -17,6 +17,7 @@ Streaming chat completion chunk | `model` | *str* | ✅ | Model used for completion | openai/gpt-4 | | `object` | [components.ChatStreamChunkObject](../components/chatstreamchunkobject.mdx) | ✅ | N/A | | | `openrouter_metadata` | [Optional[components.OpenRouterMetadata]](../components/openroutermetadata.mdx) | ➖ | N/A | \{
"attempt": 1,
"endpoints": \{
"available": [
\{
"model": "openai/gpt-4o",
"provider": "OpenAI",
"selected": true
}
],
"total": 1
},
"generation_time": 2016,
"is_byok": false,
"region": "iad",
"requested": "openai/gpt-4o",
"strategy": "direct",
"summary": "available=1, selected=OpenAI"
} | +| `safeguard_results` | List[[components.ArmorSafeguardResult](../components/armorsafeguardresult.mdx)] | ➖ | OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in. | | | `service_tier` | *OptionalNullable[str]* | ➖ | The service tier used by the upstream provider for this request | default | | `system_fingerprint` | *Optional[str]* | ➖ | System fingerprint | fp_44709d6fcb | | `usage` | [Optional[components.ChatUsage]](../components/chatusage.mdx) | ➖ | Token usage statistics | \{
"completion_tokens": 15,
"completion_tokens_details": \{
"reasoning_tokens": 5
},
"cost": 0.0012,
"cost_details": \{
"upstream_inference_completions_cost": 0.0004,
"upstream_inference_cost": null,
"upstream_inference_prompt_cost": 0.0008
},
"is_byok": false,
"prompt_tokens": 10,
"prompt_tokens_details": \{
"cached_tokens": 2
},
"server_tool_use_details": \{
"tool_calls_executed": 2,
"tool_calls_requested": 2
},
"total_tokens": 25
} | \ No newline at end of file diff --git a/docs/components/computeruseservertool.mdx b/docs/components/computeruseservertool.mdx index 87de2572..895069d4 100644 --- a/docs/components/computeruseservertool.mdx +++ b/docs/components/computeruseservertool.mdx @@ -11,5 +11,5 @@ Computer use preview tool configuration | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------- | | `display_height` | *int* | ✅ | N/A | | `display_width` | *int* | ✅ | N/A | -| `environment` | [components.Environment](../components/environment.mdx) | ✅ | N/A | +| `environment` | [components.EnvironmentEnum](../components/environmentenum.mdx) | ✅ | N/A | | `type` | [components.ComputerUseServerToolType](../components/computeruseservertooltype.mdx) | ✅ | N/A | \ No newline at end of file diff --git a/docs/components/environment.mdx b/docs/components/environment.mdx index c08a3d8f..00277e09 100644 --- a/docs/components/environment.mdx +++ b/docs/components/environment.mdx @@ -2,22 +2,17 @@ title: "Environment" --- -## Example Usage +## Supported Types -```python -from openrouter.components import Environment +### `str` -# Open enum: unrecognized values are captured as UnrecognizedStr -value: Environment = "windows" +```python +value: str = /* values here */ ``` +### `components.ArmorEnvironmentEntry` -## Values - -This is an open enum. Unrecognized values will not fail type checks. +```python +value: components.ArmorEnvironmentEntry = /* values here */ +``` -- `"windows"` -- `"mac"` -- `"linux"` -- `"ubuntu"` -- `"browser"` diff --git a/docs/components/environmentenum.mdx b/docs/components/environmentenum.mdx new file mode 100644 index 00000000..f92ca831 --- /dev/null +++ b/docs/components/environmentenum.mdx @@ -0,0 +1,23 @@ +--- +title: "EnvironmentEnum" +--- + +## Example Usage + +```python +from openrouter.components import EnvironmentEnum + +# Open enum: unrecognized values are captured as UnrecognizedStr +value: EnvironmentEnum = "windows" +``` + + +## Values + +This is an open enum. Unrecognized values will not fail type checks. + +- `"windows"` +- `"mac"` +- `"linux"` +- `"ubuntu"` +- `"browser"` diff --git a/docs/components/harddeny.mdx b/docs/components/harddeny.mdx new file mode 100644 index 00000000..3a56c4df --- /dev/null +++ b/docs/components/harddeny.mdx @@ -0,0 +1,18 @@ +--- +title: "HardDeny" +--- + +## Supported Types + +### `str` + +```python +value: str = /* values here */ +``` + +### `components.ArmorRule` + +```python +value: components.ArmorRule = /* values here */ +``` + diff --git a/docs/components/messagesrequestplugin.mdx b/docs/components/messagesrequestplugin.mdx index 684c25cf..c8bcb656 100644 --- a/docs/components/messagesrequestplugin.mdx +++ b/docs/components/messagesrequestplugin.mdx @@ -10,6 +10,12 @@ title: "MessagesRequestPlugin" value: components.AlignmentPlugin = /* values here */ ``` +### `components.ArmorPlugin` + +```python +value: components.ArmorPlugin = /* values here */ +``` + ### `components.AutoBetaRouterPlugin` ```python diff --git a/docs/components/onerror.mdx b/docs/components/onerror.mdx new file mode 100644 index 00000000..fd5c6bab --- /dev/null +++ b/docs/components/onerror.mdx @@ -0,0 +1,22 @@ +--- +title: "OnError" +--- + +When the classifier cannot answer (timeout, upstream error, context too long) the call is reported `unavailable`; `block` rejects it and `log` releases it. Default `block`. + +## Example Usage + +```python +from openrouter.components import OnError + +# Open enum: unrecognized values are captured as UnrecognizedStr +value: OnError = "log" +``` + + +## Values + +This is an open enum. Unrecognized values will not fail type checks. + +- `"log"` +- `"block"` diff --git a/docs/components/openresponsesresult.mdx b/docs/components/openresponsesresult.mdx index e88c642a..3717d0f7 100644 --- a/docs/components/openresponsesresult.mdx +++ b/docs/components/openresponsesresult.mdx @@ -46,4 +46,5 @@ Complete non-streaming response from the Responses API | `user` | *OptionalNullable[str]* | ➖ | N/A | | | `alignment` | [Optional[components.Alignment]](../components/alignment.mdx) | ➖ | Beta. The result of the alignment plugin for this request; the shape may change. | \{
"calls": [
\{
"call": 1,
"outcome": "allowed",
"rules": [
\{
"applicable": true,
"broken": false,
"probability": 0.04
}
]
}
]
} | | `error_type` | [Optional[components.APIErrorType]](../components/apierrortype.mdx) | ➖ | Canonical OpenRouter error type, stable across all API formats | rate_limit_exceeded | -| `openrouter_metadata` | [Optional[components.OpenRouterMetadata]](../components/openroutermetadata.mdx) | ➖ | N/A | \{
"attempt": 1,
"endpoints": \{
"available": [
\{
"model": "openai/gpt-4o",
"provider": "OpenAI",
"selected": true
}
],
"total": 1
},
"generation_time": 2016,
"is_byok": false,
"region": "iad",
"requested": "openai/gpt-4o",
"strategy": "direct",
"summary": "available=1, selected=OpenAI"
} | \ No newline at end of file +| `openrouter_metadata` | [Optional[components.OpenRouterMetadata]](../components/openroutermetadata.mdx) | ➖ | N/A | \{
"attempt": 1,
"endpoints": \{
"available": [
\{
"model": "openai/gpt-4o",
"provider": "OpenAI",
"selected": true
}
],
"total": 1
},
"generation_time": 2016,
"is_byok": false,
"region": "iad",
"requested": "openai/gpt-4o",
"strategy": "direct",
"summary": "available=1, selected=OpenAI"
} | +| `safeguard_results` | List[[components.ArmorSafeguardResult](../components/armorsafeguardresult.mdx)] | ➖ | OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in. | | \ No newline at end of file diff --git a/docs/components/outputmode.mdx b/docs/components/outputmode.mdx new file mode 100644 index 00000000..4f1252fb --- /dev/null +++ b/docs/components/outputmode.mdx @@ -0,0 +1,23 @@ +--- +title: "OutputMode" +--- + +How a blocked call reaches the caller. `text` (the default): the call is withheld and an `` marker stands in assistant text. `custom_item` (Responses API only): the call is withheld and an `openrouter:armor_blocked` output item carries its id, name, arguments and the rule that fired. `claude_code_compatibility` (Messages API only; the default when the request carries a `dangerous_tool_use` safeguard, i.e. the client speaks Claude Code's protocol): the `tool_use` stays in `content[]` and the verdict is `flagged` in `safeguard_results`, so the client withholds execution and writes the error tool result as under the native classifier. Under `text` and `custom_item` the model received a failure result in the loop and continued in the same request; under `claude_code_compatibility` the turn ends on the flagged call and the model continues on the next request, after the client's denial. + +## Example Usage + +```python +from openrouter.components import OutputMode + +# Open enum: unrecognized values are captured as UnrecognizedStr +value: OutputMode = "text" +``` + + +## Values + +This is an open enum. Unrecognized values will not fail type checks. + +- `"text"` +- `"custom_item"` +- `"claude_code_compatibility"` diff --git a/docs/components/responsesrequestplugin.mdx b/docs/components/responsesrequestplugin.mdx index 8d1ff986..b13aa07c 100644 --- a/docs/components/responsesrequestplugin.mdx +++ b/docs/components/responsesrequestplugin.mdx @@ -10,6 +10,12 @@ title: "ResponsesRequestPlugin" value: components.AlignmentPlugin = /* values here */ ``` +### `components.ArmorPlugin` + +```python +value: components.ArmorPlugin = /* values here */ +``` + ### `components.AutoBetaRouterPlugin` ```python diff --git a/docs/components/softdeny.mdx b/docs/components/softdeny.mdx new file mode 100644 index 00000000..ff6088ec --- /dev/null +++ b/docs/components/softdeny.mdx @@ -0,0 +1,18 @@ +--- +title: "SoftDeny" +--- + +## Supported Types + +### `str` + +```python +value: str = /* values here */ +``` + +### `components.ArmorRule` + +```python +value: components.ArmorRule = /* values here */ +``` + diff --git a/docs/components/tooluses.mdx b/docs/components/tooluses.mdx new file mode 100644 index 00000000..41964d29 --- /dev/null +++ b/docs/components/tooluses.mdx @@ -0,0 +1,24 @@ +--- +title: "ToolUses" +--- + +## Supported Types + +### `components.ToolUsesEvaluated` + +```python +value: components.ToolUsesEvaluated = /* values here */ +``` + +### `components.ToolUsesSkipped` + +```python +value: components.ToolUsesSkipped = /* values here */ +``` + +### `components.ToolUsesUnavailable` + +```python +value: components.ToolUsesUnavailable = /* values here */ +``` + diff --git a/docs/components/toolusesevaluated.mdx b/docs/components/toolusesevaluated.mdx new file mode 100644 index 00000000..9c1f545d --- /dev/null +++ b/docs/components/toolusesevaluated.mdx @@ -0,0 +1,11 @@ +--- +title: "ToolUsesEvaluated" +--- + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| `explanation` | *Optional[str]* | ➖ | N/A | +| `outcome` | [components.ArmorSafeguardResultOutcome](../components/armorsafeguardresultoutcome.mdx) | ✅ | N/A | +| `type` | [components.TypeEvaluated](../components/typeevaluated.mdx) | ✅ | N/A | \ No newline at end of file diff --git a/docs/components/toolusesskipped.mdx b/docs/components/toolusesskipped.mdx new file mode 100644 index 00000000..aac400fa --- /dev/null +++ b/docs/components/toolusesskipped.mdx @@ -0,0 +1,9 @@ +--- +title: "ToolUsesSkipped" +--- + +## Fields + +| Field | Type | Required | Description | +| ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ | ------------------------------------------------------ | +| `type` | [components.TypeSkipped](../components/typeskipped.mdx) | ✅ | N/A | \ No newline at end of file diff --git a/docs/components/toolusesunavailable.mdx b/docs/components/toolusesunavailable.mdx new file mode 100644 index 00000000..58ddc1ff --- /dev/null +++ b/docs/components/toolusesunavailable.mdx @@ -0,0 +1,10 @@ +--- +title: "ToolUsesUnavailable" +--- + +## Fields + +| Field | Type | Required | Description | +| -------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- | -------------------------------------------------------------- | +| `reason` | *str* | ✅ | N/A | +| `type` | [components.TypeUnavailable](../components/typeunavailable.mdx) | ✅ | N/A | \ No newline at end of file diff --git a/docs/components/typeavailable.mdx b/docs/components/typeavailable.mdx new file mode 100644 index 00000000..bbd9c9ab --- /dev/null +++ b/docs/components/typeavailable.mdx @@ -0,0 +1,15 @@ +--- +title: "TypeAvailable" +--- + +## Example Usage + +```python +from openrouter.components import TypeAvailable +value: TypeAvailable = "available" +``` + + +## Values + +- `"available"` diff --git a/docs/components/typedangeroustooluse.mdx b/docs/components/typedangeroustooluse.mdx new file mode 100644 index 00000000..4d4a11a1 --- /dev/null +++ b/docs/components/typedangeroustooluse.mdx @@ -0,0 +1,15 @@ +--- +title: "TypeDangerousToolUse" +--- + +## Example Usage + +```python +from openrouter.components import TypeDangerousToolUse +value: TypeDangerousToolUse = "dangerous_tool_use" +``` + + +## Values + +- `"dangerous_tool_use"` diff --git a/docs/components/typeevaluated.mdx b/docs/components/typeevaluated.mdx new file mode 100644 index 00000000..eea25abb --- /dev/null +++ b/docs/components/typeevaluated.mdx @@ -0,0 +1,15 @@ +--- +title: "TypeEvaluated" +--- + +## Example Usage + +```python +from openrouter.components import TypeEvaluated +value: TypeEvaluated = "evaluated" +``` + + +## Values + +- `"evaluated"` diff --git a/docs/components/typeskipped.mdx b/docs/components/typeskipped.mdx new file mode 100644 index 00000000..c5ce724d --- /dev/null +++ b/docs/components/typeskipped.mdx @@ -0,0 +1,15 @@ +--- +title: "TypeSkipped" +--- + +## Example Usage + +```python +from openrouter.components import TypeSkipped +value: TypeSkipped = "skipped" +``` + + +## Values + +- `"skipped"` diff --git a/docs/components/typeunavailable.mdx b/docs/components/typeunavailable.mdx new file mode 100644 index 00000000..9d06705d --- /dev/null +++ b/docs/components/typeunavailable.mdx @@ -0,0 +1,15 @@ +--- +title: "TypeUnavailable" +--- + +## Example Usage + +```python +from openrouter.components import TypeUnavailable +value: TypeUnavailable = "unavailable" +``` + + +## Values + +- `"unavailable"` diff --git a/pyproject.toml b/pyproject.toml index abed0d06..874397db 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "openrouter" -version = "1.3.50" +version = "1.3.51" description = "Official Python Client SDK for OpenRouter." authors = [{ name = "OpenRouter" },] readme = "README-PYPI.md" diff --git a/src/openrouter/_version.py b/src/openrouter/_version.py index d35001c0..77be04ec 100644 --- a/src/openrouter/_version.py +++ b/src/openrouter/_version.py @@ -3,10 +3,10 @@ import importlib.metadata __title__: str = "openrouter" -__version__: str = "1.3.50" +__version__: str = "1.3.51" __openapi_doc_version__: str = "1.0.0" __gen_version__: str = "2.914.0" -__user_agent__: str = "speakeasy-sdk/python 1.3.50 2.914.0 1.0.0 openrouter" +__user_agent__: str = "speakeasy-sdk/python 1.3.51 2.914.0 1.0.0 openrouter" try: if __package__ is not None: diff --git a/src/openrouter/components/__init__.py b/src/openrouter/components/__init__.py index 9aa15b5a..e858066a 100644 --- a/src/openrouter/components/__init__.py +++ b/src/openrouter/components/__init__.py @@ -660,6 +660,53 @@ ) from .apprankingsitem import AppRankingsItem, AppRankingsItemTypedDict from .apprankingsresponse import AppRankingsResponse, AppRankingsResponseTypedDict + from .armorautomode import ( + Allow, + AllowTypedDict, + ArmorAutoMode, + ArmorAutoModeTypedDict, + Environment, + EnvironmentTypedDict, + HardDeny, + HardDenyTypedDict, + SoftDeny, + SoftDenyTypedDict, + ) + from .armorcontext import ArmorContext, ArmorContextTypedDict + from .armorenvironmententry import ( + ArmorEnvironmentEntry, + ArmorEnvironmentEntryTypedDict, + ) + from .armorplugin import ( + ArmorPlugin, + ArmorPluginID, + ArmorPluginMode, + ArmorPluginTypedDict, + OnError, + OutputMode, + ) + from .armorrule import ArmorRule, ArmorRuleTypedDict + from .armorsafeguardresult import ( + ArmorSafeguardResult, + ArmorSafeguardResultOutcome, + ArmorSafeguardResultStatus, + ArmorSafeguardResultStatusTypedDict, + ArmorSafeguardResultTypedDict, + ToolUses, + ToolUsesEvaluated, + ToolUsesEvaluatedTypedDict, + ToolUsesSkipped, + ToolUsesSkippedTypedDict, + ToolUsesTypedDict, + ToolUsesUnavailable, + ToolUsesUnavailableTypedDict, + TypeAvailable, + TypeDangerousToolUse, + TypeEvaluated, + TypeSkipped, + TypeUnavailable, + UnknownToolUses, + ) from .autobetarouterplugin import ( AutoBetaRouterPlugin, AutoBetaRouterPluginCostTier, @@ -1281,7 +1328,7 @@ ComputerUseServerTool, ComputerUseServerToolType, ComputerUseServerToolTypedDict, - Environment, + EnvironmentEnum, ) from .configurationupdateitem import ( ConfigurationUpdateItem, @@ -4507,6 +4554,8 @@ "AlignmentUnavailableCallRecordOutcome", "AlignmentUnavailableCallRecordReason", "AlignmentUnavailableCallRecordTypedDict", + "Allow", + "AllowTypedDict", "AllowedTools", "AllowedToolsTypedDict", "AllowedToolsUnion", @@ -4863,6 +4912,23 @@ "ApplyPatchUpdateFileOperationTypedDict", "Architecture", "ArchitectureTypedDict", + "ArmorAutoMode", + "ArmorAutoModeTypedDict", + "ArmorContext", + "ArmorContextTypedDict", + "ArmorEnvironmentEntry", + "ArmorEnvironmentEntryTypedDict", + "ArmorPlugin", + "ArmorPluginID", + "ArmorPluginMode", + "ArmorPluginTypedDict", + "ArmorRule", + "ArmorRuleTypedDict", + "ArmorSafeguardResult", + "ArmorSafeguardResultOutcome", + "ArmorSafeguardResultStatus", + "ArmorSafeguardResultStatusTypedDict", + "ArmorSafeguardResultTypedDict", "AudioURL", "AudioURLTypedDict", "AutoBetaRouterPlugin", @@ -5596,6 +5662,8 @@ "EnumCapabilityType", "EnumCapabilityTypedDict", "Environment", + "EnvironmentEnum", + "EnvironmentTypedDict", "ErrorEnum", "ErrorEvent", "ErrorEventType", @@ -5784,6 +5852,8 @@ "GuardrailDataRegion", "GuardrailInterval", "GuardrailTypedDict", + "HardDeny", + "HardDenyTypedDict", "Image", "ImageConfig", "ImageConfigTypedDict", @@ -6431,6 +6501,7 @@ "ObservabilityWebhookDestinationConfigTypedDict", "ObservabilityWebhookDestinationType", "ObservabilityWebhookDestinationTypedDict", + "OnError", "OpenAIFile", "OpenAIFileDeleted", "OpenAIFileDeletedObject", @@ -6712,6 +6783,7 @@ "OutputMessageTypedDict", "OutputModality", "OutputModalityEnum", + "OutputMode", "OutputReasoningItem", "OutputReasoningItemStatusCompleted", "OutputReasoningItemStatusInProgress", @@ -7157,6 +7229,8 @@ "SignInternDaemonRequestTypedDict", "SignInternDaemonResponse", "SignInternDaemonResponseTypedDict", + "SoftDeny", + "SoftDenyTypedDict", "SourceContent", "SourceContentTypedDict", "SourceType", @@ -7355,6 +7429,14 @@ "ToolTextEditor20250124", "ToolTextEditor20250124TypedDict", "ToolTypeCustom", + "ToolUses", + "ToolUsesEvaluated", + "ToolUsesEvaluatedTypedDict", + "ToolUsesSkipped", + "ToolUsesSkippedTypedDict", + "ToolUsesTypedDict", + "ToolUsesUnavailable", + "ToolUsesUnavailableTypedDict", "ToolWebSearch20250305", "ToolWebSearch20250305TypedDict", "ToolWebSearch20260209", @@ -7380,19 +7462,23 @@ "TypeAgentMessage", "TypeAllowlist", "TypeAny", + "TypeAvailable", "TypeBash20250124", "TypeBetweenTools", "TypeClearThinking20251015", "TypeClearToolUses20250919", "TypeCodeInterpreter", "TypeCompact20260112", + "TypeDangerousToolUse", "TypeEnabled", "TypeEncryptedContent", + "TypeEvaluated", "TypeExec", "TypeExit", "TypeFileSearch", "TypeLocalShellCall", "TypeNone", + "TypeSkipped", "TypeTextEditor20250124", "TypeTimeout", "TypeTokens", @@ -7402,6 +7488,7 @@ "TypeToolResult", "TypeToolSearchOutput", "TypeTypedDict", + "TypeUnavailable", "TypeWebSearch20250305", "TypeWebSearch20260209", "TypeWebSearchCitation", @@ -7486,6 +7573,7 @@ "UnknownReasoningDetail", "UnknownReasoningDetailUnion", "UnknownStreamEvents", + "UnknownToolUses", "UnknownTypedDict", "UnprocessableEntityResponseErrorData", "UnprocessableEntityResponseErrorDataTypedDict", @@ -8083,6 +8171,47 @@ "AppRankingsItemTypedDict": ".apprankingsitem", "AppRankingsResponse": ".apprankingsresponse", "AppRankingsResponseTypedDict": ".apprankingsresponse", + "Allow": ".armorautomode", + "AllowTypedDict": ".armorautomode", + "ArmorAutoMode": ".armorautomode", + "ArmorAutoModeTypedDict": ".armorautomode", + "Environment": ".armorautomode", + "EnvironmentTypedDict": ".armorautomode", + "HardDeny": ".armorautomode", + "HardDenyTypedDict": ".armorautomode", + "SoftDeny": ".armorautomode", + "SoftDenyTypedDict": ".armorautomode", + "ArmorContext": ".armorcontext", + "ArmorContextTypedDict": ".armorcontext", + "ArmorEnvironmentEntry": ".armorenvironmententry", + "ArmorEnvironmentEntryTypedDict": ".armorenvironmententry", + "ArmorPlugin": ".armorplugin", + "ArmorPluginID": ".armorplugin", + "ArmorPluginMode": ".armorplugin", + "ArmorPluginTypedDict": ".armorplugin", + "OnError": ".armorplugin", + "OutputMode": ".armorplugin", + "ArmorRule": ".armorrule", + "ArmorRuleTypedDict": ".armorrule", + "ArmorSafeguardResult": ".armorsafeguardresult", + "ArmorSafeguardResultOutcome": ".armorsafeguardresult", + "ArmorSafeguardResultStatus": ".armorsafeguardresult", + "ArmorSafeguardResultStatusTypedDict": ".armorsafeguardresult", + "ArmorSafeguardResultTypedDict": ".armorsafeguardresult", + "ToolUses": ".armorsafeguardresult", + "ToolUsesEvaluated": ".armorsafeguardresult", + "ToolUsesEvaluatedTypedDict": ".armorsafeguardresult", + "ToolUsesSkipped": ".armorsafeguardresult", + "ToolUsesSkippedTypedDict": ".armorsafeguardresult", + "ToolUsesTypedDict": ".armorsafeguardresult", + "ToolUsesUnavailable": ".armorsafeguardresult", + "ToolUsesUnavailableTypedDict": ".armorsafeguardresult", + "TypeAvailable": ".armorsafeguardresult", + "TypeDangerousToolUse": ".armorsafeguardresult", + "TypeEvaluated": ".armorsafeguardresult", + "TypeSkipped": ".armorsafeguardresult", + "TypeUnavailable": ".armorsafeguardresult", + "UnknownToolUses": ".armorsafeguardresult", "AutoBetaRouterPlugin": ".autobetarouterplugin", "AutoBetaRouterPluginCostTier": ".autobetarouterplugin", "AutoBetaRouterPluginID": ".autobetarouterplugin", @@ -8558,7 +8687,7 @@ "ComputerUseServerTool": ".computeruseservertool", "ComputerUseServerToolType": ".computeruseservertool", "ComputerUseServerToolTypedDict": ".computeruseservertool", - "Environment": ".computeruseservertool", + "EnvironmentEnum": ".computeruseservertool", "ConfigurationUpdateItem": ".configurationupdateitem", "ConfigurationUpdateItemType": ".configurationupdateitem", "ConfigurationUpdateItemTypedDict": ".configurationupdateitem", diff --git a/src/openrouter/components/armorautomode.py b/src/openrouter/components/armorautomode.py new file mode 100644 index 00000000..8d9915e4 --- /dev/null +++ b/src/openrouter/components/armorautomode.py @@ -0,0 +1,68 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .armorenvironmententry import ArmorEnvironmentEntry, ArmorEnvironmentEntryTypedDict +from .armorrule import ArmorRule, ArmorRuleTypedDict +from openrouter.types import BaseModel, UNSET_SENTINEL +from pydantic import model_serializer +from typing import List, Optional, Union +from typing_extensions import NotRequired, TypeAliasType, TypedDict + + +AllowTypedDict = TypeAliasType("AllowTypedDict", Union[ArmorRuleTypedDict, str]) + + +Allow = TypeAliasType("Allow", Union[ArmorRule, str]) + + +EnvironmentTypedDict = TypeAliasType( + "EnvironmentTypedDict", Union[ArmorEnvironmentEntryTypedDict, str] +) + + +Environment = TypeAliasType("Environment", Union[ArmorEnvironmentEntry, str]) + + +HardDenyTypedDict = TypeAliasType("HardDenyTypedDict", Union[ArmorRuleTypedDict, str]) + + +HardDeny = TypeAliasType("HardDeny", Union[ArmorRule, str]) + + +SoftDenyTypedDict = TypeAliasType("SoftDenyTypedDict", Union[ArmorRuleTypedDict, str]) + + +SoftDeny = TypeAliasType("SoftDeny", Union[ArmorRule, str]) + + +class ArmorAutoModeTypedDict(TypedDict): + allow: NotRequired[List[AllowTypedDict]] + environment: NotRequired[List[EnvironmentTypedDict]] + hard_deny: NotRequired[List[HardDenyTypedDict]] + soft_deny: NotRequired[List[SoftDenyTypedDict]] + + +class ArmorAutoMode(BaseModel): + allow: Optional[List[Allow]] = None + + environment: Optional[List[Environment]] = None + + hard_deny: Optional[List[HardDeny]] = None + + soft_deny: Optional[List[SoftDeny]] = None + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["allow", "environment", "hard_deny", "soft_deny"]) + 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/openrouter/components/armorcontext.py b/src/openrouter/components/armorcontext.py new file mode 100644 index 00000000..dc5da7be --- /dev/null +++ b/src/openrouter/components/armorcontext.py @@ -0,0 +1,56 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .armorautomode import ArmorAutoMode, ArmorAutoModeTypedDict +from openrouter.types import BaseModel, UNSET_SENTINEL +import pydantic +from pydantic import ConfigDict, model_serializer +from typing import Any, Dict, Optional +from typing_extensions import NotRequired, TypedDict + + +class ArmorContextTypedDict(TypedDict): + r"""The Armor context: Claude Code's `classifier_context` (v1), with `auto_mode.{hard_deny,soft_deny,allow}` rules as strings or `{ id, instructions, threshold? }` objects and `auto_mode.environment` entries as `\"Name: value\"` strings or `{ name, value }` objects. `threshold` applies when Armor evaluates; when the provider evaluates natively (Anthropic dangerous-tool-use beta) rules are judged at the provider's own boundary.""" + + v: float + auto_mode: NotRequired[ArmorAutoModeTypedDict] + + +class ArmorContext(BaseModel): + r"""The Armor context: Claude Code's `classifier_context` (v1), with `auto_mode.{hard_deny,soft_deny,allow}` rules as strings or `{ id, instructions, threshold? }` objects and `auto_mode.environment` entries as `\"Name: value\"` strings or `{ name, value }` objects. `threshold` applies when Armor evaluates; when the provider evaluates natively (Anthropic dangerous-tool-use beta) rules are judged at the provider's own boundary.""" + + model_config = ConfigDict( + populate_by_name=True, arbitrary_types_allowed=True, extra="allow" + ) + __pydantic_extra__: Dict[str, Any] = pydantic.Field(init=False) + + v: float + + auto_mode: Optional[ArmorAutoMode] = None + + @property + def additional_properties(self): + return self.__pydantic_extra__ + + @additional_properties.setter + def additional_properties(self, value): + self.__pydantic_extra__ = value # pyright: ignore[reportIncompatibleVariableOverride] + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["auto_mode"]) + 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)) + serialized.pop(k, serialized.pop(n, None)) + + if val != UNSET_SENTINEL: + if val is not None or k not in optional_fields: + m[k] = val + for k, v in serialized.items(): + m[k] = v + + return m diff --git a/src/openrouter/components/armorenvironmententry.py b/src/openrouter/components/armorenvironmententry.py new file mode 100644 index 00000000..fcc6d267 --- /dev/null +++ b/src/openrouter/components/armorenvironmententry.py @@ -0,0 +1,16 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from openrouter.types import BaseModel +from typing_extensions import TypedDict + + +class ArmorEnvironmentEntryTypedDict(TypedDict): + name: str + value: str + + +class ArmorEnvironmentEntry(BaseModel): + name: str + + value: str diff --git a/src/openrouter/components/armorplugin.py b/src/openrouter/components/armorplugin.py new file mode 100644 index 00000000..4ce09db9 --- /dev/null +++ b/src/openrouter/components/armorplugin.py @@ -0,0 +1,115 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from .armorcontext import ArmorContext, ArmorContextTypedDict +from openrouter.types import BaseModel, UNSET_SENTINEL, UnrecognizedStr +from pydantic import model_serializer +from typing import Literal, Optional, Union +from typing_extensions import NotRequired, TypedDict + + +ArmorPluginID = Literal["armor",] + + +ArmorPluginMode = Union[ + Literal[ + "enforce", + "audit", + ], + UnrecognizedStr, +] +r"""`enforce` withholds blocked calls; `audit` evaluates and reports the same verdicts without withholding any calls, regardless of `on_error`. Default `enforce`.""" + + +OnError = Union[ + Literal[ + "log", + "block", + ], + UnrecognizedStr, +] +r"""When the classifier cannot answer (timeout, upstream error, context too long) the call is reported `unavailable`; `block` rejects it and `log` releases it. Default `block`.""" + + +OutputMode = Union[ + Literal[ + "text", + "custom_item", + "claude_code_compatibility", + ], + UnrecognizedStr, +] +r"""How a blocked call reaches the caller. `text` (the default): the call is withheld and an `` marker stands in assistant text. `custom_item` (Responses API only): the call is withheld and an `openrouter:armor_blocked` output item carries its id, name, arguments and the rule that fired. `claude_code_compatibility` (Messages API only; the default when the request carries a `dangerous_tool_use` safeguard, i.e. the client speaks Claude Code's protocol): the `tool_use` stays in `content[]` and the verdict is `flagged` in `safeguard_results`, so the client withholds execution and writes the error tool result as under the native classifier. Under `text` and `custom_item` the model received a failure result in the loop and continued in the same request; under `claude_code_compatibility` the turn ends on the flagged call and the model continues on the next request, after the client's denial.""" + + +class ArmorPluginTypedDict(TypedDict): + r"""Evaluates every client tool call the model emits against a rule stack (hard-deny, soft-deny, allow) before it reaches the caller. The stack merges the workspace guardrail, this plugin, and any Anthropic `safeguards`; on endpoints that support Anthropic's `dangerous-tool-use` beta the evaluation is native, elsewhere it is one decisions call per tool call. Evaluation is not billed during the beta. Verdicts are reported as `safeguard_results`.""" + + id: ArmorPluginID + classifier_context: NotRequired[ArmorContextTypedDict] + r"""The Armor context: Claude Code's `classifier_context` (v1), with `auto_mode.{hard_deny,soft_deny,allow}` rules as strings or `{ id, instructions, threshold? }` objects and `auto_mode.environment` entries as `\"Name: value\"` strings or `{ name, value }` objects. `threshold` applies when Armor evaluates; when the provider evaluates natively (Anthropic dangerous-tool-use beta) rules are judged at the provider's own boundary.""" + enabled: NotRequired[bool] + r"""Set to false to disable Armor for this request. Defaults to true.""" + evaluate_native_tools: NotRequired[bool] + r"""Run provider-native server tools (web search, code execution, ...) through the agent loop so Armor evaluates them too. Defaults to false: native passthrough stands and such calls are reported `skipped`.""" + mode: NotRequired[ArmorPluginMode] + r"""`enforce` withholds blocked calls; `audit` evaluates and reports the same verdicts without withholding any calls, regardless of `on_error`. Default `enforce`.""" + on_error: NotRequired[OnError] + r"""When the classifier cannot answer (timeout, upstream error, context too long) the call is reported `unavailable`; `block` rejects it and `log` releases it. Default `block`.""" + output_mode: NotRequired[OutputMode] + r"""How a blocked call reaches the caller. `text` (the default): the call is withheld and an `` marker stands in assistant text. `custom_item` (Responses API only): the call is withheld and an `openrouter:armor_blocked` output item carries its id, name, arguments and the rule that fired. `claude_code_compatibility` (Messages API only; the default when the request carries a `dangerous_tool_use` safeguard, i.e. the client speaks Claude Code's protocol): the `tool_use` stays in `content[]` and the verdict is `flagged` in `safeguard_results`, so the client withholds execution and writes the error tool result as under the native classifier. Under `text` and `custom_item` the model received a failure result in the loop and continued in the same request; under `claude_code_compatibility` the turn ends on the flagged call and the model continues on the next request, after the client's denial.""" + use_cc_style_default_rules: NotRequired[bool] + r"""Prepend Claude Code's built-in auto-mode rule set (1 hard-deny, 72 soft-deny, 17 allow, 21 environment slots) ahead of every configured rule. Defaults to true on the Anthropic Messages API and false elsewhere.""" + + +class ArmorPlugin(BaseModel): + r"""Evaluates every client tool call the model emits against a rule stack (hard-deny, soft-deny, allow) before it reaches the caller. The stack merges the workspace guardrail, this plugin, and any Anthropic `safeguards`; on endpoints that support Anthropic's `dangerous-tool-use` beta the evaluation is native, elsewhere it is one decisions call per tool call. Evaluation is not billed during the beta. Verdicts are reported as `safeguard_results`.""" + + id: ArmorPluginID + + classifier_context: Optional[ArmorContext] = None + r"""The Armor context: Claude Code's `classifier_context` (v1), with `auto_mode.{hard_deny,soft_deny,allow}` rules as strings or `{ id, instructions, threshold? }` objects and `auto_mode.environment` entries as `\"Name: value\"` strings or `{ name, value }` objects. `threshold` applies when Armor evaluates; when the provider evaluates natively (Anthropic dangerous-tool-use beta) rules are judged at the provider's own boundary.""" + + enabled: Optional[bool] = None + r"""Set to false to disable Armor for this request. Defaults to true.""" + + evaluate_native_tools: Optional[bool] = None + r"""Run provider-native server tools (web search, code execution, ...) through the agent loop so Armor evaluates them too. Defaults to false: native passthrough stands and such calls are reported `skipped`.""" + + mode: Optional[ArmorPluginMode] = None + r"""`enforce` withholds blocked calls; `audit` evaluates and reports the same verdicts without withholding any calls, regardless of `on_error`. Default `enforce`.""" + + on_error: Optional[OnError] = None + r"""When the classifier cannot answer (timeout, upstream error, context too long) the call is reported `unavailable`; `block` rejects it and `log` releases it. Default `block`.""" + + output_mode: Optional[OutputMode] = None + r"""How a blocked call reaches the caller. `text` (the default): the call is withheld and an `` marker stands in assistant text. `custom_item` (Responses API only): the call is withheld and an `openrouter:armor_blocked` output item carries its id, name, arguments and the rule that fired. `claude_code_compatibility` (Messages API only; the default when the request carries a `dangerous_tool_use` safeguard, i.e. the client speaks Claude Code's protocol): the `tool_use` stays in `content[]` and the verdict is `flagged` in `safeguard_results`, so the client withholds execution and writes the error tool result as under the native classifier. Under `text` and `custom_item` the model received a failure result in the loop and continued in the same request; under `claude_code_compatibility` the turn ends on the flagged call and the model continues on the next request, after the client's denial.""" + + use_cc_style_default_rules: Optional[bool] = None + r"""Prepend Claude Code's built-in auto-mode rule set (1 hard-deny, 72 soft-deny, 17 allow, 21 environment slots) ahead of every configured rule. Defaults to true on the Anthropic Messages API and false elsewhere.""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set( + [ + "classifier_context", + "enabled", + "evaluate_native_tools", + "mode", + "on_error", + "output_mode", + "use_cc_style_default_rules", + ] + ) + 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/openrouter/components/armorrule.py b/src/openrouter/components/armorrule.py new file mode 100644 index 00000000..3c773ad1 --- /dev/null +++ b/src/openrouter/components/armorrule.py @@ -0,0 +1,48 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from openrouter.types import BaseModel, UNSET_SENTINEL +from pydantic import model_serializer +from typing import Optional +from typing_extensions import NotRequired, TypedDict + + +class ArmorRuleTypedDict(TypedDict): + id: str + r"""Stable id, unique within its source; reported as the deciding rule when it fires.""" + instructions: str + r"""What the rule matches, written for the classifier.""" + name: NotRequired[str] + r"""Display name shown in verdict explanations; defaults to the id.""" + threshold: NotRequired[float] + r"""Probability at or above which the rule counts as matched. Defaults to 0.6 for hard-deny and soft-deny rules and 0.7 for allow rules (an exception needs stronger evidence to clear a matched soft deny).""" + + +class ArmorRule(BaseModel): + id: str + r"""Stable id, unique within its source; reported as the deciding rule when it fires.""" + + instructions: str + r"""What the rule matches, written for the classifier.""" + + name: Optional[str] = None + r"""Display name shown in verdict explanations; defaults to the id.""" + + threshold: Optional[float] = None + r"""Probability at or above which the rule counts as matched. Defaults to 0.6 for hard-deny and soft-deny rules and 0.7 for allow rules (an exception needs stronger evidence to clear a matched soft deny).""" + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["name", "threshold"]) + 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/openrouter/components/armorsafeguardresult.py b/src/openrouter/components/armorsafeguardresult.py new file mode 100644 index 00000000..af7c7510 --- /dev/null +++ b/src/openrouter/components/armorsafeguardresult.py @@ -0,0 +1,150 @@ +"""Code generated by Speakeasy (https://speakeasy.com). DO NOT EDIT.""" + +from __future__ import annotations +from functools import partial +from openrouter.types import BaseModel, UNSET_SENTINEL, UnrecognizedStr +from openrouter.utils.unions import parse_open_union +from pydantic import ConfigDict, model_serializer +from pydantic.functional_validators import BeforeValidator +from typing import Any, Dict, Literal, Optional, Union +from typing_extensions import Annotated, NotRequired, TypeAliasType, TypedDict + + +TypeUnavailable = Literal["unavailable",] + + +class ToolUsesUnavailableTypedDict(TypedDict): + reason: str + type: TypeUnavailable + + +class ToolUsesUnavailable(BaseModel): + reason: str + + type: TypeUnavailable + + +TypeSkipped = Literal["skipped",] + + +class ToolUsesSkippedTypedDict(TypedDict): + type: TypeSkipped + + +class ToolUsesSkipped(BaseModel): + type: TypeSkipped + + +ArmorSafeguardResultOutcome = Union[ + Literal[ + "flagged", + "not_flagged", + ], + UnrecognizedStr, +] + + +TypeEvaluated = Literal["evaluated",] + + +class ToolUsesEvaluatedTypedDict(TypedDict): + outcome: ArmorSafeguardResultOutcome + type: TypeEvaluated + explanation: NotRequired[str] + + +class ToolUsesEvaluated(BaseModel): + outcome: ArmorSafeguardResultOutcome + + type: TypeEvaluated + + explanation: Optional[str] = None + + @model_serializer(mode="wrap") + def serialize_model(self, handler): + optional_fields = set(["explanation"]) + 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 + + +ToolUsesTypedDict = TypeAliasType( + "ToolUsesTypedDict", + Union[ + ToolUsesSkippedTypedDict, + ToolUsesUnavailableTypedDict, + ToolUsesEvaluatedTypedDict, + ], +) + + +class UnknownToolUses(BaseModel): + r"""A ToolUses variant the SDK doesn't recognize. Preserves the raw payload.""" + + type: Literal["UNKNOWN"] = "UNKNOWN" + raw: Any + is_unknown: Literal[True] = True + + model_config = ConfigDict(frozen=True) + + +_TOOL_USES_VARIANTS: dict[str, Any] = { + "evaluated": ToolUsesEvaluated, + "skipped": ToolUsesSkipped, + "unavailable": ToolUsesUnavailable, +} + + +ToolUses = Annotated[ + Union[ToolUsesEvaluated, ToolUsesSkipped, ToolUsesUnavailable, UnknownToolUses], + BeforeValidator( + partial( + parse_open_union, + disc_key="type", + variants=_TOOL_USES_VARIANTS, + unknown_cls=UnknownToolUses, + union_name="ToolUses", + ) + ), +] + + +TypeAvailable = Literal["available",] + + +class ArmorSafeguardResultStatusTypedDict(TypedDict): + tool_uses: Dict[str, ToolUsesTypedDict] + type: TypeAvailable + + +class ArmorSafeguardResultStatus(BaseModel): + tool_uses: Dict[str, ToolUses] + + type: TypeAvailable + + +TypeDangerousToolUse = Literal["dangerous_tool_use",] + + +class ArmorSafeguardResultTypedDict(TypedDict): + r"""The outcome of OpenRouter Armor for each client tool call of the response, keyed by tool-call id, in the same shape Anthropic reports its server-side safeguards.""" + + status: ArmorSafeguardResultStatusTypedDict + type: TypeDangerousToolUse + + +class ArmorSafeguardResult(BaseModel): + r"""The outcome of OpenRouter Armor for each client tool call of the response, keyed by tool-call id, in the same shape Anthropic reports its server-side safeguards.""" + + status: ArmorSafeguardResultStatus + + type: TypeDangerousToolUse diff --git a/src/openrouter/components/batchobject.py b/src/openrouter/components/batchobject.py index 46338470..d455e665 100644 --- a/src/openrouter/components/batchobject.py +++ b/src/openrouter/components/batchobject.py @@ -30,6 +30,7 @@ AnthropicUsageIterationTypedDict, ) from .apierrortype import APIErrorType +from .armorsafeguardresult import ArmorSafeguardResult, ArmorSafeguardResultTypedDict from .costdetails import CostDetails, CostDetailsTypedDict from .finishreason import FinishReason from .openresponsesresult import OpenResponsesResult, OpenResponsesResultTypedDict @@ -1528,6 +1529,8 @@ class BodyChatCompletionTypedDict(TypedDict): debug: NotRequired[BatchObjectDebugTypedDict] openrouter_metadata: NotRequired[OpenRouterMetadataTypedDict] provider: NotRequired[Nullable[str]] + safeguard_results: NotRequired[List[ArmorSafeguardResultTypedDict]] + r"""OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.""" service_tier: NotRequired[Nullable[str]] system_fingerprint: NotRequired[Nullable[str]] usage: NotRequired[BodyUsage1TypedDict] @@ -1553,6 +1556,9 @@ class BodyChatCompletion(BaseModel): provider: OptionalNullable[str] = UNSET + safeguard_results: Optional[List[ArmorSafeguardResult]] = None + r"""OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.""" + service_tier: OptionalNullable[str] = UNSET system_fingerprint: OptionalNullable[str] = UNSET @@ -1567,6 +1573,7 @@ def serialize_model(self, handler): "debug", "openrouter_metadata", "provider", + "safeguard_results", "service_tier", "system_fingerprint", "usage", diff --git a/src/openrouter/components/chatrequest.py b/src/openrouter/components/chatrequest.py index 8d0a9a01..98cc04a7 100644 --- a/src/openrouter/components/chatrequest.py +++ b/src/openrouter/components/chatrequest.py @@ -6,6 +6,7 @@ AnthropicCacheControlDirective, AnthropicCacheControlDirectiveTypedDict, ) +from .armorplugin import ArmorPlugin, ArmorPluginTypedDict from .autobetarouterplugin import AutoBetaRouterPlugin, AutoBetaRouterPluginTypedDict from .autorouterplugin import AutoRouterPlugin, AutoRouterPluginTypedDict from .chatdebugoptions import ChatDebugOptions, ChatDebugOptionsTypedDict @@ -96,6 +97,7 @@ AlignmentPluginTypedDict, FusionPluginTypedDict, AutoRouterPluginTypedDict, + ArmorPluginTypedDict, WebSearchPluginTypedDict, ], ) @@ -104,6 +106,7 @@ ChatRequestPlugin = Annotated[ Union[ Annotated[AlignmentPlugin, Tag("alignment")], + Annotated[ArmorPlugin, Tag("armor")], Annotated[AutoBetaRouterPlugin, Tag("auto-beta-router")], Annotated[AutoRouterPlugin, Tag("auto-router")], Annotated[ContextCompressionPlugin, Tag("context-compression")], diff --git a/src/openrouter/components/chatresult.py b/src/openrouter/components/chatresult.py index fb343f06..afaa56a6 100644 --- a/src/openrouter/components/chatresult.py +++ b/src/openrouter/components/chatresult.py @@ -2,6 +2,7 @@ from __future__ import annotations from .alignment import Alignment, AlignmentTypedDict +from .armorsafeguardresult import ArmorSafeguardResult, ArmorSafeguardResultTypedDict from .chatchoice import ChatChoice, ChatChoiceTypedDict from .chatusage import ChatUsage, ChatUsageTypedDict from .openroutermetadata import OpenRouterMetadata, OpenRouterMetadataTypedDict @@ -37,6 +38,8 @@ class ChatResultTypedDict(TypedDict): alignment: NotRequired[AlignmentTypedDict] r"""Beta. The result of the alignment plugin for this request; the shape may change.""" openrouter_metadata: NotRequired[OpenRouterMetadataTypedDict] + safeguard_results: NotRequired[List[ArmorSafeguardResultTypedDict]] + r"""OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.""" service_tier: NotRequired[Nullable[str]] r"""The service tier used by the upstream provider for this request""" usage: NotRequired[ChatUsageTypedDict] @@ -68,6 +71,9 @@ class ChatResult(BaseModel): openrouter_metadata: Optional[OpenRouterMetadata] = None + safeguard_results: Optional[List[ArmorSafeguardResult]] = None + r"""OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.""" + service_tier: OptionalNullable[str] = UNSET r"""The service tier used by the upstream provider for this request""" @@ -77,7 +83,13 @@ class ChatResult(BaseModel): @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set( - ["alignment", "openrouter_metadata", "service_tier", "usage"] + [ + "alignment", + "openrouter_metadata", + "safeguard_results", + "service_tier", + "usage", + ] ) nullable_fields = set(["service_tier", "system_fingerprint"]) serialized = handler(self) diff --git a/src/openrouter/components/chatstreamchunk.py b/src/openrouter/components/chatstreamchunk.py index 470fe278..417c2c42 100644 --- a/src/openrouter/components/chatstreamchunk.py +++ b/src/openrouter/components/chatstreamchunk.py @@ -3,6 +3,7 @@ from __future__ import annotations from .alignment import Alignment, AlignmentTypedDict from .apierrortype import APIErrorType +from .armorsafeguardresult import ArmorSafeguardResult, ArmorSafeguardResultTypedDict from .chatstreamchoice import ChatStreamChoice, ChatStreamChoiceTypedDict from .chatusage import ChatUsage, ChatUsageTypedDict from .openroutermetadata import OpenRouterMetadata, OpenRouterMetadataTypedDict @@ -112,6 +113,8 @@ class ChatStreamChunkTypedDict(TypedDict): error: NotRequired[ChatStreamChunkErrorTypedDict] r"""Error information""" openrouter_metadata: NotRequired[OpenRouterMetadataTypedDict] + safeguard_results: NotRequired[List[ArmorSafeguardResultTypedDict]] + r"""OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.""" service_tier: NotRequired[Nullable[str]] r"""The service tier used by the upstream provider for this request""" system_fingerprint: NotRequired[str] @@ -144,6 +147,9 @@ class ChatStreamChunk(BaseModel): openrouter_metadata: Optional[OpenRouterMetadata] = None + safeguard_results: Optional[List[ArmorSafeguardResult]] = None + r"""OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.""" + service_tier: OptionalNullable[str] = UNSET r"""The service tier used by the upstream provider for this request""" @@ -160,6 +166,7 @@ def serialize_model(self, handler): "alignment", "error", "openrouter_metadata", + "safeguard_results", "service_tier", "system_fingerprint", "usage", diff --git a/src/openrouter/components/computeruseservertool.py b/src/openrouter/components/computeruseservertool.py index f8c70070..142b18a2 100644 --- a/src/openrouter/components/computeruseservertool.py +++ b/src/openrouter/components/computeruseservertool.py @@ -6,7 +6,7 @@ from typing_extensions import TypedDict -Environment = Union[ +EnvironmentEnum = Union[ Literal[ "windows", "mac", @@ -26,7 +26,7 @@ class ComputerUseServerToolTypedDict(TypedDict): display_height: int display_width: int - environment: Environment + environment: EnvironmentEnum type: ComputerUseServerToolType @@ -37,6 +37,6 @@ class ComputerUseServerTool(BaseModel): display_width: int - environment: Environment + environment: EnvironmentEnum type: ComputerUseServerToolType diff --git a/src/openrouter/components/messagesrequest.py b/src/openrouter/components/messagesrequest.py index afc5f2c3..fd81e321 100644 --- a/src/openrouter/components/messagesrequest.py +++ b/src/openrouter/components/messagesrequest.py @@ -46,6 +46,7 @@ AnthropicWebSearchToolUserLocation, AnthropicWebSearchToolUserLocationTypedDict, ) +from .armorplugin import ArmorPlugin, ArmorPluginTypedDict from .autobetarouterplugin import AutoBetaRouterPlugin, AutoBetaRouterPluginTypedDict from .autorouterplugin import AutoRouterPlugin, AutoRouterPluginTypedDict from .bashservertool import BashServerTool, BashServerToolTypedDict @@ -388,6 +389,7 @@ def serialize_model(self, handler): AlignmentPluginTypedDict, FusionPluginTypedDict, AutoRouterPluginTypedDict, + ArmorPluginTypedDict, WebSearchPluginTypedDict, ], ) @@ -396,6 +398,7 @@ def serialize_model(self, handler): MessagesRequestPlugin = Annotated[ Union[ Annotated[AlignmentPlugin, Tag("alignment")], + Annotated[ArmorPlugin, Tag("armor")], Annotated[AutoBetaRouterPlugin, Tag("auto-beta-router")], Annotated[AutoRouterPlugin, Tag("auto-router")], Annotated[ContextCompressionPlugin, Tag("context-compression")], diff --git a/src/openrouter/components/openresponsesresult.py b/src/openrouter/components/openresponsesresult.py index 59b5d79b..b270324a 100644 --- a/src/openrouter/components/openresponsesresult.py +++ b/src/openrouter/components/openresponsesresult.py @@ -4,6 +4,7 @@ from .alignment import Alignment, AlignmentTypedDict from .apierrortype import APIErrorType from .applypatchservertool import ApplyPatchServerTool, ApplyPatchServerToolTypedDict +from .armorsafeguardresult import ArmorSafeguardResult, ArmorSafeguardResultTypedDict from .baseinputs_union import BaseInputsUnion, BaseInputsUnionTypedDict from .basereasoningconfig import BaseReasoningConfig, BaseReasoningConfigTypedDict from .codeinterpreterservertool import ( @@ -442,6 +443,8 @@ class OpenResponsesResultTypedDict(TypedDict): error_type: NotRequired[APIErrorType] r"""Canonical OpenRouter error type, stable across all API formats""" openrouter_metadata: NotRequired[OpenRouterMetadataTypedDict] + safeguard_results: NotRequired[List[ArmorSafeguardResultTypedDict]] + r"""OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.""" class OpenResponsesResult(BaseModel): @@ -530,6 +533,9 @@ class OpenResponsesResult(BaseModel): openrouter_metadata: Optional[OpenRouterMetadata] = None + safeguard_results: Optional[List[ArmorSafeguardResult]] = None + r"""OpenRouter Armor's verdict for each client tool call of this response, present whenever Armor evaluated the response (even when nothing was flagged). Independent of the `openrouter_metadata` opt-in.""" + @model_serializer(mode="wrap") def serialize_model(self, handler): optional_fields = set( @@ -554,6 +560,7 @@ def serialize_model(self, handler): "alignment", "error_type", "openrouter_metadata", + "safeguard_results", ] ) nullable_fields = set( diff --git a/src/openrouter/components/responsesrequest.py b/src/openrouter/components/responsesrequest.py index 2a62f916..dcbcb267 100644 --- a/src/openrouter/components/responsesrequest.py +++ b/src/openrouter/components/responsesrequest.py @@ -15,6 +15,7 @@ ApplyPatchServerToolOpenRouter, ApplyPatchServerToolOpenRouterTypedDict, ) +from .armorplugin import ArmorPlugin, ArmorPluginTypedDict from .autobetarouterplugin import AutoBetaRouterPlugin, AutoBetaRouterPluginTypedDict from .autorouterplugin import AutoRouterPlugin, AutoRouterPluginTypedDict from .bashservertool import BashServerTool, BashServerToolTypedDict @@ -145,6 +146,7 @@ AlignmentPluginTypedDict, FusionPluginTypedDict, AutoRouterPluginTypedDict, + ArmorPluginTypedDict, WebSearchPluginTypedDict, ], ) @@ -153,6 +155,7 @@ ResponsesRequestPlugin = Annotated[ Union[ Annotated[AlignmentPlugin, Tag("alignment")], + Annotated[ArmorPlugin, Tag("armor")], Annotated[AutoBetaRouterPlugin, Tag("auto-beta-router")], Annotated[AutoRouterPlugin, Tag("auto-router")], Annotated[ContextCompressionPlugin, Tag("context-compression")], diff --git a/uv.lock b/uv.lock index d2d80a17..25b60b0d 100644 --- a/uv.lock +++ b/uv.lock @@ -213,7 +213,7 @@ wheels = [ [[package]] name = "openrouter" -version = "1.3.50" +version = "1.3.51" source = { editable = "." } dependencies = [ { name = "httpcore" },