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.
- tweek/__init__.py +2 -2
- tweek/audit.py +2 -2
- tweek/cli.py +78 -6559
- tweek/cli_config.py +643 -0
- tweek/cli_configure.py +413 -0
- tweek/cli_core.py +718 -0
- tweek/cli_dry_run.py +390 -0
- tweek/cli_helpers.py +316 -0
- tweek/cli_install.py +1666 -0
- tweek/cli_logs.py +301 -0
- tweek/cli_mcp.py +148 -0
- tweek/cli_memory.py +343 -0
- tweek/cli_plugins.py +748 -0
- tweek/cli_protect.py +564 -0
- tweek/cli_proxy.py +405 -0
- tweek/cli_security.py +236 -0
- tweek/cli_skills.py +289 -0
- tweek/cli_uninstall.py +551 -0
- tweek/cli_vault.py +313 -0
- tweek/config/__init__.py +8 -0
- tweek/config/allowed_dirs.yaml +16 -17
- tweek/config/families.yaml +4 -1
- tweek/config/manager.py +49 -0
- tweek/config/models.py +307 -0
- tweek/config/patterns.yaml +29 -5
- tweek/config/templates/config.yaml.template +212 -0
- tweek/config/templates/env.template +45 -0
- tweek/config/templates/overrides.yaml.template +121 -0
- tweek/config/templates/tweek.yaml.template +20 -0
- tweek/config/templates.py +136 -0
- tweek/config/tiers.yaml +5 -4
- tweek/diagnostics.py +112 -32
- tweek/hooks/overrides.py +4 -0
- tweek/hooks/post_tool_use.py +46 -1
- tweek/hooks/pre_tool_use.py +149 -49
- tweek/integrations/openclaw.py +84 -0
- tweek/licensing.py +1 -1
- tweek/mcp/__init__.py +7 -9
- tweek/mcp/clients/chatgpt.py +2 -2
- tweek/mcp/clients/claude_desktop.py +2 -2
- tweek/mcp/clients/gemini.py +2 -2
- tweek/mcp/proxy.py +165 -1
- tweek/memory/provenance.py +438 -0
- tweek/memory/queries.py +2 -0
- tweek/memory/safety.py +23 -4
- tweek/memory/schemas.py +1 -0
- tweek/memory/store.py +101 -71
- tweek/plugins/screening/heuristic_scorer.py +1 -1
- tweek/security/integrity.py +77 -0
- tweek/security/llm_reviewer.py +162 -68
- tweek/security/local_reviewer.py +44 -2
- tweek/security/model_registry.py +73 -7
- tweek/skill_template/overrides-reference.md +1 -1
- tweek/skills/context.py +221 -0
- tweek/skills/scanner.py +2 -2
- {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/METADATA +9 -7
- {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/RECORD +62 -39
- tweek/mcp/server.py +0 -320
- {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/WHEEL +0 -0
- {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/entry_points.txt +0 -0
- {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/licenses/LICENSE +0 -0
- {tweek-0.3.0.dist-info → tweek-0.4.0.dist-info}/licenses/NOTICE +0 -0
- {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=
|
|
1
|
+
tweek/__init__.py,sha256=ObqNjfhUoPC8rXfPtT85pqrOlKoSn4_-4fKQF5cynCQ,359
|
|
2
2
|
tweek/_keygen.py,sha256=UapwIKNSwaRWdqHoJoF3hmKuiux6aIiFGe8WVskTbI8,1286
|
|
3
|
-
tweek/audit.py,sha256=
|
|
4
|
-
tweek/cli.py,sha256=
|
|
5
|
-
tweek/
|
|
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/
|
|
8
|
-
tweek/
|
|
9
|
-
tweek/
|
|
10
|
-
tweek/
|
|
11
|
-
tweek/
|
|
12
|
-
tweek/
|
|
13
|
-
tweek/
|
|
14
|
-
tweek/
|
|
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=
|
|
19
|
-
tweek/hooks/post_tool_use.py,sha256=
|
|
20
|
-
tweek/hooks/pre_tool_use.py,sha256=
|
|
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=
|
|
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=
|
|
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=
|
|
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=
|
|
36
|
-
tweek/mcp/clients/claude_desktop.py,sha256=
|
|
37
|
-
tweek/mcp/clients/gemini.py,sha256=
|
|
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/
|
|
40
|
-
tweek/memory/
|
|
41
|
-
tweek/memory/
|
|
42
|
-
tweek/memory/
|
|
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=
|
|
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=
|
|
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
|
|
97
|
-
tweek/security/model_registry.py,sha256=
|
|
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=
|
|
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=
|
|
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.
|
|
117
|
-
tweek-0.
|
|
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.
|
|
120
|
-
tweek-0.
|
|
121
|
-
tweek-0.
|
|
122
|
-
tweek-0.
|
|
123
|
-
tweek-0.
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|