tweek 0.3.0__py3-none-any.whl → 0.4.0__py3-none-any.whl

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 (63) hide show
  1. tweek/__init__.py +2 -2
  2. tweek/audit.py +2 -2
  3. tweek/cli.py +78 -6559
  4. tweek/cli_config.py +643 -0
  5. tweek/cli_configure.py +413 -0
  6. tweek/cli_core.py +718 -0
  7. tweek/cli_dry_run.py +390 -0
  8. tweek/cli_helpers.py +316 -0
  9. tweek/cli_install.py +1666 -0
  10. tweek/cli_logs.py +301 -0
  11. tweek/cli_mcp.py +148 -0
  12. tweek/cli_memory.py +343 -0
  13. tweek/cli_plugins.py +748 -0
  14. tweek/cli_protect.py +564 -0
  15. tweek/cli_proxy.py +405 -0
  16. tweek/cli_security.py +236 -0
  17. tweek/cli_skills.py +289 -0
  18. tweek/cli_uninstall.py +551 -0
  19. tweek/cli_vault.py +313 -0
  20. tweek/config/__init__.py +8 -0
  21. tweek/config/allowed_dirs.yaml +16 -17
  22. tweek/config/families.yaml +4 -1
  23. tweek/config/manager.py +49 -0
  24. tweek/config/models.py +307 -0
  25. tweek/config/patterns.yaml +29 -5
  26. tweek/config/templates/config.yaml.template +212 -0
  27. tweek/config/templates/env.template +45 -0
  28. tweek/config/templates/overrides.yaml.template +121 -0
  29. tweek/config/templates/tweek.yaml.template +20 -0
  30. tweek/config/templates.py +136 -0
  31. tweek/config/tiers.yaml +5 -4
  32. tweek/diagnostics.py +112 -32
  33. tweek/hooks/overrides.py +4 -0
  34. tweek/hooks/post_tool_use.py +46 -1
  35. tweek/hooks/pre_tool_use.py +149 -49
  36. tweek/integrations/openclaw.py +84 -0
  37. tweek/licensing.py +1 -1
  38. tweek/mcp/__init__.py +7 -9
  39. tweek/mcp/clients/chatgpt.py +2 -2
  40. tweek/mcp/clients/claude_desktop.py +2 -2
  41. tweek/mcp/clients/gemini.py +2 -2
  42. tweek/mcp/proxy.py +165 -1
  43. tweek/memory/provenance.py +438 -0
  44. tweek/memory/queries.py +2 -0
  45. tweek/memory/safety.py +23 -4
  46. tweek/memory/schemas.py +1 -0
  47. tweek/memory/store.py +101 -71
  48. tweek/plugins/screening/heuristic_scorer.py +1 -1
  49. tweek/security/integrity.py +77 -0
  50. tweek/security/llm_reviewer.py +162 -68
  51. tweek/security/local_reviewer.py +44 -2
  52. tweek/security/model_registry.py +73 -7
  53. tweek/skill_template/overrides-reference.md +1 -1
  54. tweek/skills/context.py +221 -0
  55. tweek/skills/scanner.py +2 -2
  56. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/METADATA +9 -7
  57. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/RECORD +62 -39
  58. tweek/mcp/server.py +0 -320
  59. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/WHEEL +0 -0
  60. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/entry_points.txt +0 -0
  61. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/licenses/LICENSE +0 -0
  62. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/licenses/NOTICE +0 -0
  63. {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/top_level.txt +0 -0
@@ -1,45 +1,66 @@
1
- tweek/__init__.py,sha256=v1mBM39Sp-MgonHi8fotmfcN7dxbow_Eh9xdbSYnjN4,360
1
+ tweek/__init__.py,sha256=ObqNjfhUoPC8rXfPtT85pqrOlKoSn4_-4fKQF5cynCQ,359
2
2
  tweek/_keygen.py,sha256=UapwIKNSwaRWdqHoJoF3hmKuiux6aIiFGe8WVskTbI8,1286
3
- tweek/audit.py,sha256=Bp4RETwdiHpT2EEi45atZa0LlJUOtALhrc3UT8MHvF8,8868
4
- tweek/cli.py,sha256=0AxYSIQ56Y2OHNVGSocNksYkiiLfUFNx5XvBUzCtZZI,254670
5
- tweek/cli_helpers.py,sha256=Q2NTOkyRTOIPNLMqY2jA5_tuzDPksAGwGXYPRK3bzoY,5538
3
+ tweek/audit.py,sha256=AzjIpy6Jc-WzTrda9lb3nZbyaR_SDWUxo04pObJP2MQ,8868
4
+ tweek/cli.py,sha256=OOZrpcrwDGbmaHxIyvBw7MoVSlEdrFNAgIwWHI56p5M,2976
5
+ tweek/cli_config.py,sha256=rSQTkw0JAqm6w02Ah2_hiJ-wIxhnrjTgvFuw2A39qfs,24525
6
+ tweek/cli_configure.py,sha256=fHm2sWxjUWFu7ulup7T-zrQ3LYiYg_1Vf-m3E5hoKd8,14603
7
+ tweek/cli_core.py,sha256=0mgcJ_ZduuloOhyIn4ecTHROMtz_pDcAdlew-E45DPk,26843
8
+ tweek/cli_dry_run.py,sha256=8DBx3qKAZHY8VA6MsbsGBs6EyDGFxKsrtmuNaHJ22C8,14335
9
+ tweek/cli_helpers.py,sha256=_8aVj8e67MrP61ao7_AaEQSi9AfJQxW3eNvnjbSWT7g,16347
10
+ tweek/cli_install.py,sha256=5AaxZmOpDk9y8Ursy_CaU8JYn4mtMPWNtIhWNpb6an8,74111
11
+ tweek/cli_logs.py,sha256=uoJBKb85EYcIQnXxNfh15w235u9UWP1he-RlwnITWuA,10776
12
+ tweek/cli_mcp.py,sha256=mIKTUqTKLlVYc9054LdjfL-maiVAabPFkb_sLtoS0Gk,4787
13
+ tweek/cli_memory.py,sha256=Sw2TOt7RGsXBoH_q13bQjUK3WyvOy49bXefZ7atoaCY,11895
6
14
  tweek/cli_model.py,sha256=iMZStFqA0Nqyzm4rxSbhD4v-AqcO6h5NI72AR7cldoY,12853
7
- tweek/diagnostics.py,sha256=KbtXQH8QrRBoyIFWumL6q9--aQQdR0tUo2GzjMhwpII,24601
8
- tweek/licensing.py,sha256=4Pt34t8Y60jaLMBYLjnmLs_0o_LUahOhGflhXeZtuPU,11703
9
- tweek/config/__init__.py,sha256=C_kQm0LqYdM67E9wNi6bsX2V7xz7GY4HiICb_XlrX8A,362
10
- tweek/config/allowed_dirs.yaml,sha256=dMF_DqKgQThzkdIEoXzDBfAjbopGrk0HTkiM7ENmBaU,788
11
- tweek/config/families.yaml,sha256=jkNO0UsmX3MFlTKC9Or3p8_MlD3ZtHM0SrQIYFqx9i8,18212
12
- tweek/config/manager.py,sha256=FTBJ4sMwnENH9tfvKB5d1SFve1R__k5j2KXb38vn1CA,39347
13
- tweek/config/patterns.yaml,sha256=8ow--0qdPJNjIY94j-vDEcrHt-TYgf9uuPCiqSMCIEQ,85376
14
- tweek/config/tiers.yaml,sha256=9hIXQ9izVKXd8ptoCsQiBo2r_XY8RvIk7VWrhWggkbc,10191
15
+ tweek/cli_plugins.py,sha256=3u8oJ0Wxb50taTc6Xofyy9voaPi62ozEfcP93VBY1oA,30059
16
+ tweek/cli_protect.py,sha256=q6VhmR2vnozdybUXJEnaofx0FVZSoQq39gWVh5xmjnc,22398
17
+ tweek/cli_proxy.py,sha256=J63CuL0bg2UVHbdavDgIcqiC1C8JS0kNG8pqHEAx9mw,14289
18
+ tweek/cli_security.py,sha256=FpPOY0YsSY5kOc9aNy8QBi9h4fpmQ7wiX3cKtRYmLzg,8482
19
+ tweek/cli_skills.py,sha256=N2D184i5gajKjrLdQuWxhdiXWGiE4NGCvPahMDZvliI,9045
20
+ tweek/cli_uninstall.py,sha256=sRDbtYxbJ9fnt-fBypEZOCR_UdTTo09RozOI_Xlo1Dc,21463
21
+ tweek/cli_vault.py,sha256=j2HUurcOCOUgObfnSiMrcJQ8k3BUs1aD-YqCNZzp98I,11457
22
+ tweek/diagnostics.py,sha256=aYtdLeTulbYF3KzIt-oqTDucYNJrBL85rsPXlPM07bg,27487
23
+ tweek/licensing.py,sha256=_t_X3wgd6F0VEoLrOags-AE2k3IZXw3WhWXFuQU4UYA,11703
24
+ tweek/config/__init__.py,sha256=ENwimeLZd2gSJXpkASMY45hbMUDn2RwM-Zl_RMvpCbQ,772
25
+ tweek/config/allowed_dirs.yaml,sha256=eHmX3QEJ-LBVdwH5tQBFeTFnlRewLvRG2jLJwBh3lOY,841
26
+ tweek/config/families.yaml,sha256=QAQD-6pnCOdiNXpXUPyeAKkYMlRcQmUpCMORkDeGA1Y,18348
27
+ tweek/config/manager.py,sha256=cs77QiAShd91RTMGxKgWUmz7qluRfQq0PogCpfxUAPA,41256
28
+ tweek/config/models.py,sha256=RbVjC2pxnkrBKanS6QGDrHwPVkmss5ouG_dqAHf_C3Q,10018
29
+ tweek/config/patterns.yaml,sha256=5HHLGGCb0KmEAEo9KPc3eja0ykYjy53x66D-u7WY6No,86749
30
+ tweek/config/templates.py,sha256=aIGD3bDfx-J6vVBKQTNZr3IIh-O9yjcddRB8l1BxZPs,4440
31
+ tweek/config/tiers.yaml,sha256=gVQ80iOqirHzlJI9YEzpi6alqqmNtNNZh1nA4DQYPPs,10298
32
+ tweek/config/templates/config.yaml.template,sha256=i3QGrIuNjF9kqJNoMJmr62mja_8Rh9gMsc-YM6YzNSE,9120
33
+ tweek/config/templates/env.template,sha256=MCnGhE6WHU5Bk9HO6dkPfBtkur2QyK69cxzHUKBWPzs,1456
34
+ tweek/config/templates/overrides.yaml.template,sha256=T9CjpPayth_1bDH-iL0mSdTTMi27GmC8cNxnBaxRNWk,4170
35
+ tweek/config/templates/tweek.yaml.template,sha256=jdSE7e3JeS9vOWEGWK2VCr66HLxSSFpOkNNUcZQQrkg,777
15
36
  tweek/hooks/__init__.py,sha256=GcgDjPdhZayxmyZ4-GfBa-ISARNtt9087RsuprRq2-s,54
16
37
  tweek/hooks/break_glass.py,sha256=GNMhCtLWPylNMlQ5QfsoUkEjgIT1Uk1Ik7HvRWeE5N8,4636
17
38
  tweek/hooks/feedback.py,sha256=uuA4opHYyBHC5sElBz-fr2Je3cg2DAv-aRHvETZcag0,6555
18
- tweek/hooks/overrides.py,sha256=1Yw_NPpZMvcFG_uyNY-ouBKSSomnxOptRedSjzkkhmE,18635
19
- tweek/hooks/post_tool_use.py,sha256=DiAnWOBd9t4vpMz1JsgUjYzToU6i-igesP2Vk83AAAc,17195
20
- tweek/hooks/pre_tool_use.py,sha256=70XbonRSGh8rYpDlI4R_Z5Ug2LwU4iLyLsS87I5xlqc,71743
39
+ tweek/hooks/overrides.py,sha256=9WfTfh5R_IstoR7SKlEIq-mgRbUTnnIiJYSTDV3_ekI,18762
40
+ tweek/hooks/post_tool_use.py,sha256=NVOgcd7wn5BL5TYQiTwvMFxy_68dWp5z6FoRYXypfaU,19195
41
+ tweek/hooks/pre_tool_use.py,sha256=qMGaRamkBUEXZFTYdiqFgmxLiTeH2ON4FHvcGKKxazg,76765
21
42
  tweek/integrations/__init__.py,sha256=sl7wFwbygmnruugX4bO2EUjoXxBlCpzTKbj-1zHuUPg,78
22
- tweek/integrations/openclaw.py,sha256=jX99__ODGI7Cq6gclSTK2pI5lsI7UGh5_iCHmq1R8RY,13798
43
+ tweek/integrations/openclaw.py,sha256=uSP_FPG5BFnk8o6Z-1PlXB8od4OX0p0nGN8xRof9XsE,16955
23
44
  tweek/integrations/openclaw_server.py,sha256=Ah7wxsxKE2lQmIdlrFINvt5jW9U_bqqERfG3X2N5Aps,12533
24
45
  tweek/logging/__init__.py,sha256=-HUdhMuDlGUwG3v2KE7xH7cClOSQ5kZIDcVO4cybVLI,228
25
46
  tweek/logging/bundle.py,sha256=eDP0Is-hna18goaHmvexXpoNAlFhmWoMG-STTLZ19_w,11911
26
47
  tweek/logging/json_logger.py,sha256=zXOsFAufj3MF0TboM5zSS7V8uNBDJea7YkJHR-uQgBA,4698
27
48
  tweek/logging/security_log.py,sha256=BwHDdrN0VCpqssStvsZdASFnyxVpANCq9xiSkFsEFFk,28486
28
- tweek/mcp/__init__.py,sha256=AOFDrzDfjOvICMcN15Hz-iNCT0Kf6oyUBB-iNEW5Vr4,791
49
+ tweek/mcp/__init__.py,sha256=UbBOrb15XrVIcyKoNLXos2N63Xw2_EeyKnaALkjfnME,610
29
50
  tweek/mcp/approval.py,sha256=WIFQi4ryXEFtgQyzQIshwgP5h_Th7Cxepx9NIhf2o_4,17885
30
51
  tweek/mcp/approval_cli.py,sha256=8WtmJF7KTLmdEF5wHqENaUJUzKEQej4CjRtFey4RcGg,11281
31
- tweek/mcp/proxy.py,sha256=0p5OEaRsFuNRcGR3rnqprkPjTdSSYgrsU_XXQiFPS8c,24819
52
+ tweek/mcp/proxy.py,sha256=aQb7FxNq1QvllL82rLAd4fyZUu5POpDPLByvRdN1bng,31073
32
53
  tweek/mcp/screening.py,sha256=ax5TK8ZSXb9uo5DFx3mxiYrBKjDBP0cTLNhA05TXb80,5421
33
- tweek/mcp/server.py,sha256=3pF3piXUNtIf2-SUJPCjGZPD42esg2KFsVXpaBXrq3E,10901
34
54
  tweek/mcp/clients/__init__.py,sha256=46tdDJRG_POVhRWLxzgeU2FjOoBKquCNf4jnHQ_FUn0,900
35
- tweek/mcp/clients/chatgpt.py,sha256=M7Mu-F1On47ijNlRj3KRb0S7tN3xkK7ZCjutAYoe8bw,3739
36
- tweek/mcp/clients/claude_desktop.py,sha256=ujkZm26l0QMlK1ectgae7VlJsl2tcOXhrWCsjyFvsdc,6624
37
- tweek/mcp/clients/gemini.py,sha256=2eKkX02gb8wuQoBeN6oo4DVmvn1R7D2mt8KGDdUFvQA,5653
55
+ tweek/mcp/clients/chatgpt.py,sha256=9nX-HODn-M9dR-39l_ltvHCjdiZfKs2i0dkb7-tSgdw,3739
56
+ tweek/mcp/clients/claude_desktop.py,sha256=c92vsomu0Ko5rqnS0157ziIpiVTO_BjaTKBxFzduyNw,6624
57
+ tweek/mcp/clients/gemini.py,sha256=IFGClXc2ytrheah0Ja7vrMLVDEhORcUdQWnEo29BOVE,5653
38
58
  tweek/memory/__init__.py,sha256=rUe3cc-Nh-8k7kEMHzF8ao2QRt-tnI9kZQAtU8GQT5M,843
39
- tweek/memory/queries.py,sha256=SdpO9VEmvuIuribJRb7W9JO_dvVC6fSdzAonaQ9kgbg,6640
40
- tweek/memory/safety.py,sha256=9nahGB5HGnOrA92X72WvcjAu8f6yTv5UE1uYk19_CBw,4586
41
- tweek/memory/schemas.py,sha256=-yTBhenL5x1w5FLiCFXVhi7ciROf5oPWgTwdz3tVslY,2045
42
- tweek/memory/store.py,sha256=d1RAgeDjRvmH6DgmQ8SopDw81K8nUxs3fNlN4-0awAc,35350
59
+ tweek/memory/provenance.py,sha256=zuVHRI9Krj4-YCEj-OJ_4P7xnmAHDelIyrN34446fhw,15628
60
+ tweek/memory/queries.py,sha256=MsUTMOai_iyVSfAmiRFcb_-E9KF2kah1WdeXOa27u-A,6712
61
+ tweek/memory/safety.py,sha256=Mv9R2bQxX2TcitIsgugY7gZmaWjxEahTyVTRTTr1ePA,5416
62
+ tweek/memory/schemas.py,sha256=WD2BIXgEYdG1rjn8MNNS1UWxc2x9bZ_7k736BkJERZg,2125
63
+ tweek/memory/store.py,sha256=Z9MwVsWkz76SncSwxaYmWT3uU4btq4CM-2JIuDkS744,36705
43
64
  tweek/platform/__init__.py,sha256=jIwiwsMU297T02JOymjAdvk7QheEJxgDspueV38pJJE,3757
44
65
  tweek/plugins/__init__.py,sha256=u2dsiOhUE2WbYArjoeyWbaaO99J0aZJU_Z_X83OzVWw,28437
45
66
  tweek/plugins/base.py,sha256=dcx-qjaYE7Dwr36JRNWQaQ1xaDZgb6-T3CTP45j3A24,33445
@@ -69,7 +90,7 @@ tweek/plugins/providers/bedrock.py,sha256=ADIdO7Kpz-kNq78Mq1pQpt8rfX9OIAR3NaMGiA
69
90
  tweek/plugins/providers/google.py,sha256=2wIt-lKXGb_vRcEz-_2zLHTyRdT_VFd3RYpEs_Vuxj0,6033
70
91
  tweek/plugins/providers/openai.py,sha256=LK3_4UIgj1XBORA2MTEI88DID67_9nXY1i8rbe3Yem0,7522
71
92
  tweek/plugins/screening/__init__.py,sha256=KijMffjrD35tbz0RBW4fb8elt36tdrNvlKBVmyeH-OA,1214
72
- tweek/plugins/screening/heuristic_scorer.py,sha256=emTYUT49-GJZhNc3wOZxjeOxJz8u7-GC7c8AVFPT7n8,17193
93
+ tweek/plugins/screening/heuristic_scorer.py,sha256=CuXR_KEoRbn9nRMdNbjzmA00WvBkp31tQTuS5E2t_sQ,17193
73
94
  tweek/plugins/screening/llm_reviewer.py,sha256=DJv4bd5iu0aXtfUyuQ5yb6UTKnyPaY0NW43JraiE90o,5135
74
95
  tweek/plugins/screening/local_model_reviewer.py,sha256=SCQDXvd5cq_w6IQP_G3RzOVDy6W2Xco0b4lKeYd14-0,5010
75
96
  tweek/plugins/screening/pattern_matcher.py,sha256=Zto8ZAJenZoN605LfHvoyNLzqYtJqJg02rH7GaAvPoo,8673
@@ -90,34 +111,36 @@ tweek/sandbox/registry.py,sha256=ZZDQYeJMNAJ0FrFEayo1KyC5r3qXSBx6Tu-JcXIMjtI,506
90
111
  tweek/screening/__init__.py,sha256=-QKzhN8TNqEOrooPunbQl_f6133LOXAszmiKyv8V07I,352
91
112
  tweek/screening/context.py,sha256=iZeD6-Fm7dNs5wlIu15MlMbIPzeTX_Pe0DUkK5xHpQ0,3030
92
113
  tweek/security/__init__.py,sha256=2qkoxVHzWeHdVWYHRYZG479Qpfodl6jNCQu_Wc3i1vM,901
114
+ tweek/security/integrity.py,sha256=QMW5Zu5PaZHC5DLwumnIq7CUOw-iqs_7AMlijLonXj4,2689
93
115
  tweek/security/language.py,sha256=690g63NoeKjwxPG0d38USa1w30QtsAohiT2SXBv-ON4,9128
94
- tweek/security/llm_reviewer.py,sha256=66DSIY1BKXWR5tamL85RpPwN6ihfCQ9PAbmXtwUoM14,49220
116
+ tweek/security/llm_reviewer.py,sha256=M9qPDx67Nj8ImlfdA57IHvuilj7JCzTaoMzxzslKvBM,53270
95
117
  tweek/security/local_model.py,sha256=fqWQOSiAcWVIM1zzy6SosXVh9hNHJbLRzTJPy9I3sFs,10451
96
- tweek/security/local_reviewer.py,sha256=-kHWDmGnMH13cSv_7DiH4n7ZTZ3uqWZoPzQgYKQKwR0,4987
97
- tweek/security/model_registry.py,sha256=XscpZcWaaJwHldX2T9C1T1zSvJ3lm0aSW4nIhwRpUzc,11022
118
+ tweek/security/local_reviewer.py,sha256=0BzFx8U42KucBL14rpUbXZ8zxsu9ALHGhVosVcj0uh0,6890
119
+ tweek/security/model_registry.py,sha256=zi0mYyTzWc6BL2W7Kd1gCLNti0N8OygKpwL94Re8Kzw,13795
98
120
  tweek/security/rate_limiter.py,sha256=bY8VIkQ-wCbNOYTLwD4MsMBoHk59zPWeZCkuE8Zntm8,24185
99
121
  tweek/security/secret_scanner.py,sha256=G-bbMwsAJD197BEOnZJdn_qphS4RNPK_wpLfkpiLuFU,18774
100
122
  tweek/security/session_analyzer.py,sha256=-Ylp583VZ_YJRkN5JZrYpaK1sVbiM6KP7ZwLBzWpiCI,24260
101
123
  tweek/skill_template/SKILL.md,sha256=gBk_Ken77scVYeCs8imm1ASnNLDpBl-C0ufgWrrkQIA,10274
102
124
  tweek/skill_template/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
103
125
  tweek/skill_template/cli-reference.md,sha256=DdXIEfTPvYn6iybVwA-r3CKkV1Mlx5Ub_sJf_lJrV2k,6913
104
- tweek/skill_template/overrides-reference.md,sha256=xlc07wXXsCOrx60wMD7LZ7fn5Z_dhLuj5Mgx04-xGQ0,4509
126
+ tweek/skill_template/overrides-reference.md,sha256=xmTIdQ_Pe0FUIhEGkUniO1rxWzsubs-XULNBElYdRlA,4509
105
127
  tweek/skill_template/scripts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
128
  tweek/skill_template/scripts/check_installed.py,sha256=-pMmfgBjdbwb5u2t9rJ0dMBz7MGYgiZM5db3tiNZgO4,5878
107
129
  tweek/skills/__init__.py,sha256=DyTvK8n5Lb-idkJhXCVytpiZjNfWveCtNkSL6o8dxHM,1209
108
130
  tweek/skills/config.py,sha256=I95wK9CBj_UiHwFuxfE8yRl7cmFiqdY0hXfF3BHP0X8,4782
131
+ tweek/skills/context.py,sha256=15wn3wh_m4n954tsWtf4p8kBdtFmwN18TxPzOaGfGlc,6672
109
132
  tweek/skills/fingerprints.py,sha256=YjPsTxqotzGlyMIgfgewSoNDTLU8_-p9fY_a44LJTjU,6027
110
133
  tweek/skills/guard.py,sha256=1g3QVFwtW2T04PPCouAAEPxgoweVGEld0WL9eCE80js,8294
111
134
  tweek/skills/isolation.py,sha256=AmGwzD8xh70HL4f5aIrvYGm_ug1hHwu8tZXSAnsKiJk,16547
112
- tweek/skills/scanner.py,sha256=PaeZNnwxLTGls2O3hQaDgBhGw9jVJThPjfKCY_05_nI,27574
135
+ tweek/skills/scanner.py,sha256=YlH-yg3_JuwmBvmnpqA4PVfWyNBHaPSjBo6d9Ncuh8k,27574
113
136
  tweek/vault/__init__.py,sha256=L408fjdRYL8-VqLEsyyHSO9PkBDhd_2mPIbrCu53YhM,980
114
137
  tweek/vault/cross_platform.py,sha256=D4UvX_7OpSo8iRx5sc2OUUWQIk8JHhgeFBYk1MbyIj4,8251
115
138
  tweek/vault/keychain.py,sha256=XL18-SUj7HwuqxLXZDViuCH81--KMu68jN9Szn1aeyw,10624
116
- tweek-0.3.0.dist-info/licenses/LICENSE,sha256=rjoDzr1vAf0bsqZglpIyekU5aewIkCk4jHZZDvVI2BE,15269
117
- tweek-0.3.0.dist-info/licenses/NOTICE,sha256=taQokyDes5UTRNEC67G-13VmqvUyTOncrrT33pCcWL0,8729
139
+ tweek-0.4.0.dist-info/licenses/LICENSE,sha256=rjoDzr1vAf0bsqZglpIyekU5aewIkCk4jHZZDvVI2BE,15269
140
+ tweek-0.4.0.dist-info/licenses/NOTICE,sha256=taQokyDes5UTRNEC67G-13VmqvUyTOncrrT33pCcWL0,8729
118
141
  tweek-openclaw-plugin/node_modules/flatted/python/flatted.py,sha256=UYburBDqkySaTfSpntPCUJRxiBGcplusJM7ECX8FEgA,3860
119
- tweek-0.3.0.dist-info/METADATA,sha256=4eLu77u_VjfeqHnZ_-sIXRthm3In7dOHRnGkAaqQy2Y,11889
120
- tweek-0.3.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
121
- tweek-0.3.0.dist-info/entry_points.txt,sha256=YXThD6UiF5XQXwqW33sphsvz-Bl4Zm6pm-xq-5wcCYE,1337
122
- tweek-0.3.0.dist-info/top_level.txt,sha256=jtNcCxjoGXN8IBqEVL0F3LHDrZD_B0S-4XF9-Ur7Pbc,28
123
- tweek-0.3.0.dist-info/RECORD,,
142
+ tweek-0.4.0.dist-info/METADATA,sha256=CIQC3olKNKfO6OmnpgLHD73kPFhQfuXbZy2eTpLPEAk,11992
143
+ tweek-0.4.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
144
+ tweek-0.4.0.dist-info/entry_points.txt,sha256=YXThD6UiF5XQXwqW33sphsvz-Bl4Zm6pm-xq-5wcCYE,1337
145
+ tweek-0.4.0.dist-info/top_level.txt,sha256=jtNcCxjoGXN8IBqEVL0F3LHDrZD_B0S-4XF9-Ur7Pbc,28
146
+ tweek-0.4.0.dist-info/RECORD,,
tweek/mcp/server.py DELETED
@@ -1,320 +0,0 @@
1
- #!/usr/bin/env python3
2
- """
3
- Tweek MCP Gateway Server
4
-
5
- Minimal MCP server exposing only tools that add genuinely new capabilities
6
- not available as built-in desktop client tools:
7
- - tweek_vault: Secure keychain credential retrieval
8
- - tweek_status: Security status and activity reporting
9
-
10
- Desktop clients' built-in tools (Bash, Read, Write, etc.) cannot be
11
- intercepted via MCP. For upstream MCP server interception, use the
12
- proxy mode: tweek mcp proxy
13
-
14
- Usage:
15
- tweek mcp serve # stdio mode (desktop clients)
16
- """
17
- from __future__ import annotations
18
-
19
- import json
20
- import logging
21
- import os
22
- from typing import Any, Dict, Optional
23
-
24
- try:
25
- from mcp.server import Server
26
- from mcp.server.stdio import stdio_server
27
- from mcp.types import (
28
- TextContent,
29
- Tool,
30
- )
31
- MCP_AVAILABLE = True
32
- except ImportError:
33
- MCP_AVAILABLE = False
34
-
35
- from tweek.screening.context import ScreeningContext
36
-
37
- logger = logging.getLogger(__name__)
38
-
39
- # Version for MCP server identification
40
- MCP_SERVER_VERSION = "0.2.0"
41
-
42
-
43
- def _check_mcp_available():
44
- """Raise RuntimeError if MCP SDK is not installed."""
45
- if not MCP_AVAILABLE:
46
- raise RuntimeError(
47
- "MCP SDK not installed. Install with: pip install 'tweek[mcp]' "
48
- "or pip install mcp"
49
- )
50
-
51
-
52
- class TweekMCPServer:
53
- """
54
- Tweek MCP Gateway.
55
-
56
- Exposes vault and status tools via MCP. These are genuinely new
57
- capabilities not available as built-in desktop client tools.
58
-
59
- For intercepting upstream MCP server tool calls, use TweekMCPProxy
60
- from tweek.mcp.proxy instead.
61
- """
62
-
63
- def __init__(self, config: Optional[Dict[str, Any]] = None):
64
- _check_mcp_available()
65
- self.config = config or {}
66
- self.server = Server("tweek-security")
67
- self._setup_handlers()
68
- self._request_count = 0
69
- self._blocked_count = 0
70
-
71
- def _setup_handlers(self):
72
- """Register MCP protocol handlers."""
73
-
74
- @self.server.list_tools()
75
- async def list_tools() -> list[Tool]:
76
- """Return the list of tools this server provides."""
77
- tools = []
78
-
79
- tool_configs = self.config.get("mcp", {}).get("gateway", {}).get("tools", {})
80
-
81
- if tool_configs.get("vault", True):
82
- tools.append(Tool(
83
- name="tweek_vault",
84
- description=(
85
- "Retrieve a credential from Tweek's secure vault. "
86
- "Credentials are stored in the system keychain, not in .env files. "
87
- "Use this instead of reading .env files or hardcoding secrets."
88
- ),
89
- inputSchema={
90
- "type": "object",
91
- "properties": {
92
- "skill": {
93
- "type": "string",
94
- "description": "Skill namespace for the credential",
95
- },
96
- "key": {
97
- "type": "string",
98
- "description": "Credential key name",
99
- },
100
- },
101
- "required": ["skill", "key"],
102
- },
103
- ))
104
-
105
- if tool_configs.get("status", True):
106
- tools.append(Tool(
107
- name="tweek_status",
108
- description=(
109
- "Show Tweek security status including active plugins, "
110
- "recent activity, threat summary, and proxy statistics."
111
- ),
112
- inputSchema={
113
- "type": "object",
114
- "properties": {
115
- "detail": {
116
- "type": "string",
117
- "enum": ["summary", "plugins", "activity", "threats"],
118
- "description": "Level of detail (default: summary)",
119
- },
120
- },
121
- },
122
- ))
123
-
124
- return tools
125
-
126
- @self.server.call_tool()
127
- async def call_tool(name: str, arguments: dict) -> list[TextContent]:
128
- """Handle tool calls."""
129
- self._request_count += 1
130
-
131
- handler_map = {
132
- "tweek_vault": self._handle_vault,
133
- "tweek_status": self._handle_status,
134
- }
135
-
136
- handler = handler_map.get(name)
137
- if handler is None:
138
- return [TextContent(
139
- type="text",
140
- text=json.dumps({
141
- "error": f"Unknown tool: {name}",
142
- "available_tools": list(handler_map.keys()),
143
- }),
144
- )]
145
-
146
- try:
147
- result = await handler(arguments)
148
- return [TextContent(type="text", text=result)]
149
- except Exception as e:
150
- logger.error(f"Tool {name} failed: {e}")
151
- return [TextContent(
152
- type="text",
153
- text=json.dumps({"error": str(e), "tool": name}),
154
- )]
155
-
156
- def _build_context(
157
- self,
158
- tool_name: str,
159
- content: str,
160
- tool_input: Optional[Dict[str, Any]] = None,
161
- ) -> ScreeningContext:
162
- """Build a ScreeningContext for MCP tool calls."""
163
- return ScreeningContext(
164
- tool_name=tool_name,
165
- content=content,
166
- tier="default",
167
- working_dir=os.getcwd(),
168
- source="mcp",
169
- client_name=self.config.get("client_name"),
170
- tool_input=tool_input,
171
- )
172
-
173
- def _run_screening(self, context: ScreeningContext) -> Dict[str, Any]:
174
- """
175
- Run the shared screening pipeline.
176
-
177
- In gateway mode, should_prompt is converted to blocked
178
- since there is no interactive user to confirm.
179
- """
180
- from tweek.mcp.screening import run_mcp_screening
181
-
182
- result = run_mcp_screening(context)
183
-
184
- if result.get("should_prompt"):
185
- self._blocked_count += 1
186
- return {
187
- "allowed": False,
188
- "blocked": True,
189
- "reason": f"Requires user confirmation: {result.get('reason', '')}",
190
- "findings": result.get("findings", []),
191
- }
192
-
193
- if result.get("blocked"):
194
- self._blocked_count += 1
195
-
196
- return {
197
- "allowed": result.get("allowed", False),
198
- "blocked": result.get("blocked", False),
199
- "reason": result.get("reason"),
200
- "findings": result.get("findings", []),
201
- }
202
-
203
- async def _handle_vault(self, arguments: Dict[str, Any]) -> str:
204
- """Handle tweek_vault tool call."""
205
- skill = arguments.get("skill", "")
206
- key = arguments.get("key", "")
207
-
208
- # Screen vault access
209
- context = self._build_context("Vault", f"vault:{skill}/{key}", arguments)
210
- screening = self._run_screening(context)
211
-
212
- if screening["blocked"]:
213
- return json.dumps({
214
- "blocked": True,
215
- "reason": screening["reason"],
216
- })
217
-
218
- try:
219
- from tweek.vault.cross_platform import CrossPlatformVault
220
-
221
- vault = CrossPlatformVault()
222
- value = vault.get(skill, key)
223
-
224
- if value is None:
225
- return json.dumps({
226
- "error": f"Credential not found: {skill}/{key}",
227
- "available": False,
228
- })
229
-
230
- return json.dumps({
231
- "value": value,
232
- "skill": skill,
233
- "key": key,
234
- })
235
-
236
- except Exception as e:
237
- # Don't leak internal details across trust boundary
238
- logger.error(f"Vault operation failed: {e}")
239
- return json.dumps({"error": "Vault operation failed"})
240
-
241
- async def _handle_status(self, arguments: Dict[str, Any]) -> str:
242
- """Handle tweek_status tool call."""
243
- detail = arguments.get("detail", "summary")
244
-
245
- try:
246
- status = {
247
- "version": MCP_SERVER_VERSION,
248
- "source": "mcp",
249
- "mode": "gateway",
250
- "gateway_requests": self._request_count,
251
- "gateway_blocked": self._blocked_count,
252
- }
253
-
254
- if detail in ("summary", "plugins"):
255
- try:
256
- from tweek.plugins import get_registry
257
- registry = get_registry()
258
- stats = registry.get_stats()
259
- status["plugins"] = stats
260
- except ImportError:
261
- status["plugins"] = {"error": "Plugin system not available"}
262
-
263
- if detail in ("summary", "activity"):
264
- try:
265
- from tweek.logging.security_log import get_logger as get_sec_logger
266
- sec_logger = get_sec_logger()
267
- recent = sec_logger.get_recent(limit=10)
268
- status["recent_activity"] = [
269
- {
270
- "timestamp": str(e.timestamp),
271
- "event_type": e.event_type.value,
272
- "tool": e.tool_name,
273
- "decision": e.decision,
274
- }
275
- for e in recent
276
- ] if recent else []
277
- except (ImportError, Exception):
278
- status["recent_activity"] = []
279
-
280
- # Include approval queue stats if available
281
- try:
282
- from tweek.mcp.approval import ApprovalQueue
283
- queue = ApprovalQueue()
284
- status["approval_queue"] = queue.get_stats()
285
- except Exception:
286
- pass
287
-
288
- return json.dumps(status, indent=2)
289
-
290
- except Exception as e:
291
- return json.dumps({"error": str(e)})
292
-
293
-
294
- async def run_server(config: Optional[Dict[str, Any]] = None):
295
- """
296
- Run the Tweek MCP gateway server on stdio transport.
297
-
298
- Exposes tweek_vault and tweek_status tools. For upstream MCP
299
- server interception, use run_proxy() instead.
300
- """
301
- _check_mcp_available()
302
-
303
- server = TweekMCPServer(config=config)
304
-
305
- logger.info("Starting Tweek MCP Gateway...")
306
- logger.info(f"Version: {MCP_SERVER_VERSION}")
307
- logger.info("Tools: tweek_vault, tweek_status")
308
- logger.info("For upstream MCP interception, use: tweek mcp proxy")
309
-
310
- async with stdio_server() as (read_stream, write_stream):
311
- await server.server.run(
312
- read_stream,
313
- write_stream,
314
- server.server.create_initialization_options(),
315
- )
316
-
317
-
318
- def create_server(config: Optional[Dict[str, Any]] = None) -> "TweekMCPServer":
319
- """Create a TweekMCPServer instance for programmatic use."""
320
- return TweekMCPServer(config=config)
File without changes