superwise-sentinel-cli 0.1.4__tar.gz → 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. superwise_sentinel_cli-0.2.0/CHANGELOG.md +6 -0
  2. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/PKG-INFO +2 -1
  3. superwise_sentinel_cli-0.2.0/build.env +1 -0
  4. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/poetry.lock +184 -3
  5. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/pyproject.toml +10 -1
  6. superwise_sentinel_cli-0.2.0/src/superwise_sentinel_cli/auth.py +166 -0
  7. superwise_sentinel_cli-0.2.0/src/superwise_sentinel_cli/cli.py +316 -0
  8. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/src/superwise_sentinel_cli/config.py +58 -5
  9. superwise_sentinel_cli-0.2.0/src/superwise_sentinel_cli/controller.py +140 -0
  10. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/src/superwise_sentinel_cli/docker_manager.py +13 -12
  11. superwise_sentinel_cli-0.2.0/src/superwise_sentinel_cli/exceptions.py +12 -0
  12. superwise_sentinel_cli-0.2.0/tests/__init__.py +0 -0
  13. superwise_sentinel_cli-0.2.0/tests/test_auth.py +518 -0
  14. superwise_sentinel_cli-0.2.0/tests/test_controller.py +299 -0
  15. superwise_sentinel_cli-0.2.0/tests/test_docker_manager.py +257 -0
  16. superwise_sentinel_cli-0.2.0/tests/test_shell_profile.py +186 -0
  17. superwise_sentinel_cli-0.1.4/build.env +0 -1
  18. superwise_sentinel_cli-0.1.4/src/superwise_sentinel_cli/auth.py +0 -29
  19. superwise_sentinel_cli-0.1.4/src/superwise_sentinel_cli/cli.py +0 -235
  20. superwise_sentinel_cli-0.1.4/src/superwise_sentinel_cli/runner.py +0 -52
  21. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/.gitignore +0 -0
  22. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/.gitlab-ci.yml +0 -0
  23. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/.pre-commit-config.yaml +0 -0
  24. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/.releaserc.json +0 -0
  25. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/CLAUDE.md +0 -0
  26. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/README.md +0 -0
  27. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/poetry.toml +0 -0
  28. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/scripts/semantic-release-cli-publish.sh +0 -0
  29. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/src/superwise_sentinel_cli/__init__.py +0 -0
  30. {superwise_sentinel_cli-0.1.4 → superwise_sentinel_cli-0.2.0}/src/superwise_sentinel_cli/shell_profile.py +0 -0
@@ -0,0 +1,6 @@
1
+ ## [0.1.4](https://gitlab.com/askboss/product/superwise/platform/sentinel-cli/compare/0.1.3...0.1.4) (2026-07-01)
2
+
3
+
4
+ ### <!-- 2. -->:bug: Bug Fixes
5
+
6
+ * update provider config ([b9d249a](https://gitlab.com/askboss/product/superwise/platform/sentinel-cli/commit/b9d249a28302f8fdd295fcd07d86da2ca989777e))
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: superwise-sentinel-cli
3
- Version: 0.1.4
3
+ Version: 0.2.0
4
4
  Summary: Sentinel is an LLM proxy that intercepts traffic, enabling you to monitor, secure, and optimize your AI usage. This CLI tool helps you quickly set up traffic interception on this machine
5
5
  Requires-Python: <4.0,>=3.11
6
6
  Requires-Dist: click>=8.1
7
7
  Requires-Dist: docker>=7.0
8
8
  Requires-Dist: pydantic-settings>=2.3
9
9
  Requires-Dist: pydantic>=2.0
10
+ Requires-Dist: requests>=2.28
@@ -0,0 +1 @@
1
+ RELEASED_VERSION=0.2.0
@@ -184,12 +184,116 @@ version = "0.4.6"
184
184
  description = "Cross-platform colored terminal text."
185
185
  optional = false
186
186
  python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
187
- groups = ["main"]
188
- markers = "platform_system == \"Windows\""
187
+ groups = ["main", "test"]
189
188
  files = [
190
189
  {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
191
190
  {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
192
191
  ]
192
+ markers = {main = "platform_system == \"Windows\"", test = "sys_platform == \"win32\""}
193
+
194
+ [[package]]
195
+ name = "coverage"
196
+ version = "7.15.0"
197
+ description = "Code coverage measurement for Python"
198
+ optional = false
199
+ python-versions = ">=3.10"
200
+ groups = ["test"]
201
+ files = [
202
+ {file = "coverage-7.15.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:50913d4bf5ddafa6ca3693da5e4dd833dd1b772e0283c99ca7f7d287db67331a"},
203
+ {file = "coverage-7.15.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:359e141ccd33893ce3f1ad5525f8b96083003677c82182e5907d62d4ea5799fc"},
204
+ {file = "coverage-7.15.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3200b6204935f928c64b2ca1f923ab8c1acb7c9de45ec61569711b34d25cccaf"},
205
+ {file = "coverage-7.15.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:be616bf61346883b2cfdc5178669647e03531d81ab761a7e378558b7e8bcb628"},
206
+ {file = "coverage-7.15.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc7bafc3fe1059463a8fdd97ca79972d6e2bf819d775c7d54991b5b1971201d6"},
207
+ {file = "coverage-7.15.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:b713aa7fcf325a01d4184d848acb46fd84f78fdb0978470c636b23a06a753d91"},
208
+ {file = "coverage-7.15.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:e38e6fba2d56652fdfaf0231f8f78aeb805234a912de25dc291ee5cce5b8faa4"},
209
+ {file = "coverage-7.15.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:884499f42e382675be80770391983b90e0c0c774d87dbeeebf5f991cf6612b20"},
210
+ {file = "coverage-7.15.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:840481b12e083dbcbafab14794a8781a958edf327c8d3d70b4eee42f9b8253aa"},
211
+ {file = "coverage-7.15.0-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:276646e9481703d09f854f3b2f018f24e19fd7049ae670a92570043eb97203b1"},
212
+ {file = "coverage-7.15.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:4de4b4d3f5545aa6c60dc4efd9c63b5b5dcc3bf00fe83146b2bdfffb8f6613bd"},
213
+ {file = "coverage-7.15.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5c504097b2a89b1e85bc6070d920df77daec701337e3aeef2c17775a5dd0ca90"},
214
+ {file = "coverage-7.15.0-cp310-cp310-win32.whl", hash = "sha256:f6e80ed91f98316e86b9c137206b04b2bcfbffccbdff49bd2eb09dddb1cf14e0"},
215
+ {file = "coverage-7.15.0-cp310-cp310-win_amd64.whl", hash = "sha256:b3b3e22030f3f6f5e01a5ce69936552a5c0f6992b7698777377b99041961031f"},
216
+ {file = "coverage-7.15.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:003fff99412ea848c0aaebcc78ed2b6ce7d8a1227ed17e68470672770b78a02a"},
217
+ {file = "coverage-7.15.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5cbd804bf2784ce7b45114516050f346ecd50f960c4bb630a7ee9e1d78fa2118"},
218
+ {file = "coverage-7.15.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:8773e15c23305b58882a4611fb9b2755977eae0dc2e515366a1b6c98866cc4c2"},
219
+ {file = "coverage-7.15.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f50e40081494c1dc4239ebb202014cbcc3306ea96fb6302a34c8cc0967fc5ae8"},
220
+ {file = "coverage-7.15.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:daf96f37f5fc3a7b6c6da862eb4aee61c426bd63da236ed4a73ef0e503b4bca5"},
221
+ {file = "coverage-7.15.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:51aa20f6ae2788fd197747766edf4cd8234fd9423309b934257fa6b21a592723"},
222
+ {file = "coverage-7.15.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:03d1f922757662eb7af586e77834792274cff776bc7b1d1a0b66a49ea9d84735"},
223
+ {file = "coverage-7.15.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a6d6acc9a7666245e6133dd15144ca038a85a9cd5026bb06d6bbae9e77440dc9"},
224
+ {file = "coverage-7.15.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:1ac2c4c27c7df851dc9a017c2d7de00b69147e84ba3d96f37a530b0b6fb51035"},
225
+ {file = "coverage-7.15.0-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:b761a1d504fd4bd1f20f418753964dca9f5862a511fc854dac58296b3b223671"},
226
+ {file = "coverage-7.15.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:e43b045e11c16e897895758ae90e4a90cf99e93d58549e2f90c0e2272e155695"},
227
+ {file = "coverage-7.15.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:589b54513e901739f4b4582c705ce96b80c96f57641b1464607e2367a270e540"},
228
+ {file = "coverage-7.15.0-cp311-cp311-win32.whl", hash = "sha256:106781b8482749162d0b47056937ba0933508e5d9447f65a5e7d5c422f0d6bb4"},
229
+ {file = "coverage-7.15.0-cp311-cp311-win_amd64.whl", hash = "sha256:821e92b3631d762a339695824cadbbc73020354eba2a23a551a99ad34938fbe6"},
230
+ {file = "coverage-7.15.0-cp311-cp311-win_arm64.whl", hash = "sha256:309990eb5fb8014b9f67cb211f7fd41876ec8a88a88d3ae76de0ed1d611e3640"},
231
+ {file = "coverage-7.15.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:b75ee5e8cb7575636ac598719b4307ac529ec8fcd79608a35c3cd4d4dada812d"},
232
+ {file = "coverage-7.15.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffb31267816b93b075302248cc1737506081b4f163df4401e9df1a6424aafabe"},
233
+ {file = "coverage-7.15.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e4d0bb73455bf97ab243a8f12c37c686ccf1c13bb614b7b85f1d062f06f42b2c"},
234
+ {file = "coverage-7.15.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:20d9ccc4ebd0edc434d86dfd2a1dd2a8efa6b6b3073d0485a394fee86459ebb4"},
235
+ {file = "coverage-7.15.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:20c8a976c365c8cb12f0cbd099508772ea41fb5fa80657a8506df0e11bd278c5"},
236
+ {file = "coverage-7.15.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:f948fd5ba1b9cbca91f0ae08b4c1ce2b139509149a435e2585d056d57d70bf01"},
237
+ {file = "coverage-7.15.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:f58185f06edf6ad68ec9fb155d63ef650c82f3fbd7e1770e2867751fb13158f4"},
238
+ {file = "coverage-7.15.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:02adc79a920c73c647c5d117f55747df7f2de94571884758ce8bc58e04f0a796"},
239
+ {file = "coverage-7.15.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:6eb7c300fbed667fd6e3588eba71c1904cdb06110ca6fdf908c26bdd88b8e382"},
240
+ {file = "coverage-7.15.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b5fb23fa2de9dce1f5c36c09066d8fcda16cd96e8e26686caa2d7cb9b567d65c"},
241
+ {file = "coverage-7.15.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:cec79341dbe6281484024979976d0c7f22beae08b4a254655decd25d42cbe766"},
242
+ {file = "coverage-7.15.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:6c664c5444b1d970b1b2a450e21fb19ee5c9cfdf151ded2dda37260031cca0da"},
243
+ {file = "coverage-7.15.0-cp312-cp312-win32.whl", hash = "sha256:5f764a3fa339bde6b3aa97657f5a6a3a9451e4a5b4ea98a2892c773a43525f77"},
244
+ {file = "coverage-7.15.0-cp312-cp312-win_amd64.whl", hash = "sha256:52f9a4d2c4c56c8848bc2f524916698354b0211488b38c49ad9ae54f6cafbff6"},
245
+ {file = "coverage-7.15.0-cp312-cp312-win_arm64.whl", hash = "sha256:31e5c3e70c85307ea35a12964e2e40f56ca2ee4b1c8c721ccf4609d17071080b"},
246
+ {file = "coverage-7.15.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5be4caf3b28836f078abe700f8944dac4a65d78f16d6c600c89cb624e5535782"},
247
+ {file = "coverage-7.15.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:dd58ad1404704303ca8d4f4b8a1095e7cbc7040ef17a66df1e6619aa10176430"},
248
+ {file = "coverage-7.15.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bbcbb317c2e5ded5b21104af81c29f391be2af98d065693ffbe8d23949b948e5"},
249
+ {file = "coverage-7.15.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:27f31ecb458da3f859aab3f15ada871eb7a7768807d88df4a9f186bb17737970"},
250
+ {file = "coverage-7.15.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13fb759be317fdc62e0f56bffdf61cfcb45c7761ad6b71e3e583e71a67ae753c"},
251
+ {file = "coverage-7.15.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:d5cf007add5ab4bb8fa9f4c77e3732127c9e6cad501d7db43355fbfafca0be84"},
252
+ {file = "coverage-7.15.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:cc78d9843bd576fbe2118248258d485e968dc535f95ed504a7b0867ba9b51389"},
253
+ {file = "coverage-7.15.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a263060f1de0b4b74b4e089c2a70b8003b3781c733329a9c8fd54995328f9950"},
254
+ {file = "coverage-7.15.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c48decf16e0dfd5b049c7d5e82200c23c08126719142998d4f172444e3d0529e"},
255
+ {file = "coverage-7.15.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:08fb028000ed0aaa0a4cbdfbb98be7cb42f370db973fbbb469733505ab20e13e"},
256
+ {file = "coverage-7.15.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:fb7dc0c3b7d8a1077abea0b8546ebc5e26d6ef6ecefc2f0f5ad2b8a53bdad837"},
257
+ {file = "coverage-7.15.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6cb3602054ccbe9f0d8c2dc04bbeba90d5719236e2cd06e042ddd6d3fc7b6e37"},
258
+ {file = "coverage-7.15.0-cp313-cp313-win32.whl", hash = "sha256:0bf781da64326b677be344df505171435b6f58716108606621d5d27d964fff8b"},
259
+ {file = "coverage-7.15.0-cp313-cp313-win_amd64.whl", hash = "sha256:2c57a275078ee3fa185f83e400f765bc764a549de66d99b47881645cbd4ea629"},
260
+ {file = "coverage-7.15.0-cp313-cp313-win_arm64.whl", hash = "sha256:3812c61afc6685c7999b39320779ab8f43b7a3081fdb0def39976e56fbdb9a21"},
261
+ {file = "coverage-7.15.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:41cb79af843222e11da87127ad0ecbfa878abadd0f770a4a99391a27d3887324"},
262
+ {file = "coverage-7.15.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7d2008989ef8fe54188d3f3bfa2e3099b025af11e90a6a1b9e7dc433d04263d8"},
263
+ {file = "coverage-7.15.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:769e8ece11a596315ebf5aa7ec383aeeed016c091d2bf6363ffb996d41529092"},
264
+ {file = "coverage-7.15.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:65a6b6164ee5c39e2f3803f314292d6c61a607ba7fee253d1e03c42dc3903502"},
265
+ {file = "coverage-7.15.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:75128817f95a5c45bb01d65fd2d8b9cb54bbe03d81608fb70e3e14b437ad56c2"},
266
+ {file = "coverage-7.15.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:9887bb428fe2d4cd4bee89bac1a6c9932f484afd5b36fbd4ff6ea5f825bb1f5e"},
267
+ {file = "coverage-7.15.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:0bfc0be1f702042207a93a00523b1065ee1fe951e96edf311581c0bbc2e34888"},
268
+ {file = "coverage-7.15.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f64627d55def5a43282d70e08396672692f77e4da610a5bb8bb4060b432b6859"},
269
+ {file = "coverage-7.15.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:2c6f0fa473003905c6d5bac328ee4eba9fbea654f15bc24b8a3274b23363fa99"},
270
+ {file = "coverage-7.15.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:2bcf9afaf064172c6ec3c58a325a9957ad1178c05dd934e25f253321776e0676"},
271
+ {file = "coverage-7.15.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:baf06bc987115d6fb938d403f7eab684a057766c490367999a2b71a6883110c6"},
272
+ {file = "coverage-7.15.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f0405f2ff97b1c4c0e782cb32e02f32369bcf2e6b618b591d67e1ea754575dfe"},
273
+ {file = "coverage-7.15.0-cp314-cp314-win32.whl", hash = "sha256:ab282853ed5fbd64bbb162f19cb8fcb7087187508a6374b4f9c34ec1577c4e8f"},
274
+ {file = "coverage-7.15.0-cp314-cp314-win_amd64.whl", hash = "sha256:3bb3040e9f4bbe26fcb0cd7cc85ac63e630d3f3a9c74f027abf4caa27e706663"},
275
+ {file = "coverage-7.15.0-cp314-cp314-win_arm64.whl", hash = "sha256:346771144d34f7fa84ec28386f78e0f31653f33cf35e19d253d5b35f9e8201da"},
276
+ {file = "coverage-7.15.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:d34a010905fb6401324ba016b5da03d574967f7b21ce48ea41e66f0f1f95f641"},
277
+ {file = "coverage-7.15.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:bb25d825d885ca8036795dacfc3924d33091fc76d71ebc99420c6b79e77d96fa"},
278
+ {file = "coverage-7.15.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:94c9686bfe8a9a6810297aecbd99beaa3445f9e8dc2f80b1382cca0d86b64461"},
279
+ {file = "coverage-7.15.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:9bd671c25f9d85f09d7ec481d0e43d5139f486c06a37139847a7ce569788af72"},
280
+ {file = "coverage-7.15.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:110cbdf8d2e216577312cf06ccf85539c0e5a5420ef747e4a4719b5e483c88cd"},
281
+ {file = "coverage-7.15.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2c5d4619214f1d9993e7b00a8600d14614b7e9d84e89507460b126aa5e6559e5"},
282
+ {file = "coverage-7.15.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:781a704516e2d8346fbbd5be6c6f3412dd824785146528b3a01816f26c081007"},
283
+ {file = "coverage-7.15.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:bd4a1b44bcb65ee29e947ac92bbee04956df3a6bfc6143641bb6cae7ede00fc9"},
284
+ {file = "coverage-7.15.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:0e4950c9d6d3e39c64c991814ff315e2d0b9cb8152363594212c9e55208c0a8f"},
285
+ {file = "coverage-7.15.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:fe9c87ff42e5472d80d21704972e1f96e104a0a599d77c5e35db5a3c562e2571"},
286
+ {file = "coverage-7.15.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:f00d5ae1dd2fe13fb8186e3e7d37bcbd8b25c0d764ff7d1b32cef9be058510a8"},
287
+ {file = "coverage-7.15.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:363ab38cc78b615f11c9cac3cf1d7eef950c18b9fdedfb9066f59461dcf84d68"},
288
+ {file = "coverage-7.15.0-cp314-cp314t-win32.whl", hash = "sha256:54fd9c53a5fafff509195f1b6a3f9be615d8e8362a3629ff1de23d270c03c86b"},
289
+ {file = "coverage-7.15.0-cp314-cp314t-win_amd64.whl", hash = "sha256:87b47553097ba185ed964866078e7e63adea9f5f51b5f39691c34f30afd21080"},
290
+ {file = "coverage-7.15.0-cp314-cp314t-win_arm64.whl", hash = "sha256:aeefb2dd178fe7eee79f0ad25d75855cb35ee9ed472db2c5ea06f5b4fd00cec5"},
291
+ {file = "coverage-7.15.0-py3-none-any.whl", hash = "sha256:56da6a4cbe8f7e9e80bd072ca9cefe67d7106a440a7ec06519ec6507ac94ad19"},
292
+ {file = "coverage-7.15.0.tar.gz", hash = "sha256:9ac3fe7a1435986463eaa8ee253ae2f2a268709ba4ae5c7dd1f52a05391ad78f"},
293
+ ]
294
+
295
+ [package.extras]
296
+ toml = ["tomli ; python_full_version <= \"3.11.0a6\""]
193
297
 
194
298
  [[package]]
195
299
  name = "docker"
@@ -229,6 +333,46 @@ files = [
229
333
  [package.extras]
230
334
  all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"]
231
335
 
336
+ [[package]]
337
+ name = "iniconfig"
338
+ version = "2.3.0"
339
+ description = "brain-dead simple config-ini parsing"
340
+ optional = false
341
+ python-versions = ">=3.10"
342
+ groups = ["test"]
343
+ files = [
344
+ {file = "iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12"},
345
+ {file = "iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730"},
346
+ ]
347
+
348
+ [[package]]
349
+ name = "packaging"
350
+ version = "26.2"
351
+ description = "Core utilities for Python packages"
352
+ optional = false
353
+ python-versions = ">=3.8"
354
+ groups = ["test"]
355
+ files = [
356
+ {file = "packaging-26.2-py3-none-any.whl", hash = "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e"},
357
+ {file = "packaging-26.2.tar.gz", hash = "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661"},
358
+ ]
359
+
360
+ [[package]]
361
+ name = "pluggy"
362
+ version = "1.6.0"
363
+ description = "plugin and hook calling mechanisms for python"
364
+ optional = false
365
+ python-versions = ">=3.9"
366
+ groups = ["test"]
367
+ files = [
368
+ {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"},
369
+ {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"},
370
+ ]
371
+
372
+ [package.extras]
373
+ dev = ["pre-commit", "tox"]
374
+ testing = ["coverage", "pytest", "pytest-benchmark"]
375
+
232
376
  [[package]]
233
377
  name = "pydantic"
234
378
  version = "2.13.4"
@@ -408,6 +552,43 @@ gcp-secret-manager = ["google-cloud-secret-manager (>=2.23.1)"]
408
552
  toml = ["tomli (>=2.0.1)"]
409
553
  yaml = ["pyyaml (>=6.0.1)"]
410
554
 
555
+ [[package]]
556
+ name = "pygments"
557
+ version = "2.20.0"
558
+ description = "Pygments is a syntax highlighting package written in Python."
559
+ optional = false
560
+ python-versions = ">=3.9"
561
+ groups = ["test"]
562
+ files = [
563
+ {file = "pygments-2.20.0-py3-none-any.whl", hash = "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176"},
564
+ {file = "pygments-2.20.0.tar.gz", hash = "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f"},
565
+ ]
566
+
567
+ [package.extras]
568
+ windows-terminal = ["colorama (>=0.4.6)"]
569
+
570
+ [[package]]
571
+ name = "pytest"
572
+ version = "9.1.1"
573
+ description = "pytest: simple powerful testing with Python"
574
+ optional = false
575
+ python-versions = ">=3.10"
576
+ groups = ["test"]
577
+ files = [
578
+ {file = "pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c"},
579
+ {file = "pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313"},
580
+ ]
581
+
582
+ [package.dependencies]
583
+ colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""}
584
+ iniconfig = ">=1.0.1"
585
+ packaging = ">=22"
586
+ pluggy = ">=1.5,<2"
587
+ pygments = ">=2.7.2"
588
+
589
+ [package.extras]
590
+ dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"]
591
+
411
592
  [[package]]
412
593
  name = "python-dotenv"
413
594
  version = "1.2.2"
@@ -525,4 +706,4 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""]
525
706
  [metadata]
526
707
  lock-version = "2.1"
527
708
  python-versions = ">=3.11, <4.0"
528
- content-hash = "45499291d0b76e80992028bb365de21217a830932d52ecbe6584652efa5efba7"
709
+ content-hash = "b2291011b34a3b81b2f9f32bc8d7fcc77aeeff74dc5ffd66b6bc16161dc97663"
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "superwise-sentinel-cli"
7
- version = "0.1.4"
7
+ version = "0.2.0"
8
8
  description = "Sentinel is an LLM proxy that intercepts traffic, enabling you to monitor, secure, and optimize your AI usage. This CLI tool helps you quickly set up traffic interception on this machine"
9
9
  requires-python = ">=3.11, <4.0"
10
10
  dependencies = [
@@ -12,6 +12,7 @@ dependencies = [
12
12
  "docker>=7.0",
13
13
  "pydantic>=2.0",
14
14
  "pydantic-settings>=2.3",
15
+ "requests>=2.28",
15
16
  ]
16
17
 
17
18
  [project.scripts]
@@ -19,3 +20,11 @@ sentinel = "superwise_sentinel_cli.cli:main"
19
20
 
20
21
  [tool.hatch.build.targets.wheel]
21
22
  packages = ["src/superwise_sentinel_cli"]
23
+
24
+ [tool.poetry.group.test.dependencies]
25
+ pytest = "^9.1.1"
26
+ coverage = "^7.15.0"
27
+
28
+ [tool.pytest.ini_options]
29
+ testpaths = ["tests"]
30
+ pythonpath = ["src"]
@@ -0,0 +1,166 @@
1
+ from __future__ import annotations
2
+
3
+ import time
4
+
5
+ import requests
6
+ from superwise_sentinel_cli.config import AppConfig
7
+ from superwise_sentinel_cli.config import CONFIG_DIR
8
+ from superwise_sentinel_cli.exceptions import AuthenticationError
9
+ from superwise_sentinel_cli.exceptions import BaseCLIException
10
+
11
+ _TOKEN_FILE = CONFIG_DIR / "token"
12
+ _REFRESH_TOKEN_FILE = CONFIG_DIR / "refresh_token"
13
+
14
+ _TERMINAL_DEVICE_ERRORS = {"access_denied", "expired_token", "invalid_grant"}
15
+
16
+
17
+ def _save_tokens(access_token: str, refresh_token: str | None = None) -> None:
18
+ CONFIG_DIR.mkdir(parents=True, exist_ok=True)
19
+ _TOKEN_FILE.write_text(access_token)
20
+ if refresh_token is not None:
21
+ _REFRESH_TOKEN_FILE.write_text(refresh_token)
22
+
23
+
24
+ def device_authorize() -> dict:
25
+ cfg = AppConfig.load()
26
+ client_id = cfg.FRONTEGG_APP_CLIENT_ID
27
+ auth_host = cfg.sw_auth_host
28
+ response = requests.post(
29
+ auth_host + "/oauth/device/authorize",
30
+ headers={"content-type": "application/json"},
31
+ json={"client_id": client_id},
32
+ timeout=10,
33
+ )
34
+ response.raise_for_status()
35
+ return response.json()
36
+
37
+
38
+ def device_poll(device_code: str, poll_interval: int = 5, expires_in: int = 900) -> str:
39
+ cfg = AppConfig.load()
40
+ client_id = cfg.FRONTEGG_APP_CLIENT_ID
41
+ auth_host = cfg.sw_auth_host
42
+ url = auth_host + "/oauth/token"
43
+ body = {
44
+ "grant_type": "urn:ietf:params:oauth:grant-type:device_code",
45
+ "device_code": device_code,
46
+ "client_id": client_id,
47
+ }
48
+ deadline = time.monotonic() + expires_in
49
+
50
+ while time.monotonic() < deadline:
51
+ time.sleep(poll_interval)
52
+ response = requests.post(
53
+ url,
54
+ headers={"content-type": "application/json"},
55
+ json=body,
56
+ timeout=10,
57
+ )
58
+ if response.status_code == 200:
59
+ data = response.json()
60
+ _save_tokens(data["access_token"], data["refresh_token"])
61
+ return data["access_token"]
62
+
63
+ if response.status_code == 400:
64
+ error = response.json().get("error", "")
65
+ if error == "authorization_pending":
66
+ continue
67
+ elif error == "slow_down":
68
+ poll_interval += 5
69
+ continue
70
+ elif error in _TERMINAL_DEVICE_ERRORS:
71
+ raise BaseCLIException(f"Device authorization failed: {error}")
72
+ try:
73
+ response.raise_for_status()
74
+ except Exception:
75
+ raise BaseCLIException("Device authorization failed. Please try again later.")
76
+
77
+ raise BaseCLIException("Device authorization timed out. Run 'sentinel auth' again.")
78
+
79
+
80
+ def refresh_access_token(auth_host: str) -> str:
81
+ stored = _REFRESH_TOKEN_FILE.read_text().strip()
82
+ if not stored:
83
+ raise RuntimeError("Cached refresh token is empty.")
84
+ response = requests.post(
85
+ auth_host + "/oauth/token",
86
+ headers={"content-type": "application/json"},
87
+ json={
88
+ "grant_type": "refresh_token",
89
+ "refresh_token": stored,
90
+ "client_id": AppConfig.load().FRONTEGG_APP_CLIENT_ID,
91
+ },
92
+ timeout=10,
93
+ )
94
+ response.raise_for_status()
95
+ data = response.json()
96
+ new_access = data["access_token"]
97
+ _save_tokens(new_access, data.get("refresh_token", stored))
98
+ return new_access
99
+
100
+
101
+ def authenticate_machine_credentials(
102
+ client_id: str | None = None,
103
+ client_secret: str | None = None,
104
+ auth_host: str | None = None,
105
+ force: bool = False,
106
+ ) -> str:
107
+ if not force and _TOKEN_FILE.exists():
108
+ return _TOKEN_FILE.read_text()
109
+
110
+ cfg = AppConfig.load()
111
+ url = (auth_host or cfg.sw_auth_host) + "/identity/resources/auth/v1/api-token"
112
+ headers = {"accept": "application/json", "content-type": "application/json"}
113
+ body = {"clientId": client_id or cfg.superwise_client_id, "secret": client_secret or cfg.superwise_client_secret}
114
+ response = requests.post(url, headers=headers, json=body, timeout=10)
115
+ if response.status_code == 401:
116
+ raise AuthenticationError("Invalid credentials.")
117
+ else:
118
+ response.raise_for_status()
119
+ token = response.json()["accessToken"]
120
+ _save_tokens(token)
121
+ return token
122
+
123
+
124
+ def authenticate(
125
+ client_id: str | None = None,
126
+ client_secret: str | None = None,
127
+ force: bool = False,
128
+ ) -> str:
129
+ cfg = AppConfig.load()
130
+ resolved_host = cfg.sw_auth_host
131
+
132
+ if not force and _TOKEN_FILE.exists():
133
+ return _TOKEN_FILE.read_text()
134
+
135
+ if not (client_id or client_secret) and _REFRESH_TOKEN_FILE.exists():
136
+ try:
137
+ return refresh_access_token(resolved_host)
138
+ except Exception:
139
+ pass
140
+
141
+ effective_id = client_id or cfg.superwise_client_id
142
+ effective_secret = client_secret or cfg.superwise_client_secret
143
+ if effective_id and effective_secret:
144
+ return authenticate_machine_credentials(
145
+ client_id=effective_id,
146
+ client_secret=effective_secret,
147
+ auth_host=resolved_host,
148
+ force=True,
149
+ )
150
+
151
+ raise AuthenticationError("Not authenticated. Run 'sentinel auth' to log in.")
152
+
153
+
154
+ def create_api_token(access_token: str) -> None:
155
+ cfg = AppConfig.load()
156
+ response = requests.post(
157
+ cfg.sw_auth_host + "/identity/resources/users/api-tokens/v1",
158
+ headers={"Authorization": f"Bearer {access_token}", "Content-Type": "application/json"},
159
+ json={"description": "cli-token"},
160
+ timeout=10,
161
+ )
162
+ response.raise_for_status()
163
+ data = response.json()
164
+ cfg.superwise_client_id = data["clientId"]
165
+ cfg.superwise_client_secret = data["secret"]
166
+ cfg.save()