tweek 0.4.2__py3-none-any.whl → 0.4.3__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 CHANGED
@@ -10,7 +10,7 @@ Tweek provides:
10
10
  - Per-skill/per-tool security policies
11
11
  """
12
12
 
13
- __version__ = "0.4.2"
13
+ __version__ = "0.4.3"
14
14
  __author__ = "Tommy Mancino"
15
15
 
16
16
  # "TOO MUCH PRESSURE!" - Tweek Tweak
tweek/cli_install.py CHANGED
@@ -234,6 +234,8 @@ def parse_env_keys(env_path: Path) -> List[str]:
234
234
  def _ensure_local_model_deps() -> bool:
235
235
  """Install onnxruntime, tokenizers, numpy if missing.
236
236
 
237
+ Tries pip first, then uv pip (for uv-managed venvs that lack pip).
238
+
237
239
  Returns True if deps are available after this call.
238
240
  """
239
241
  try:
@@ -244,26 +246,54 @@ def _ensure_local_model_deps() -> bool:
244
246
  except ImportError:
245
247
  pass
246
248
 
247
- console.print("\n[cyan]Installing local model dependencies...[/cyan]")
249
+ import subprocess
250
+ import shutil
251
+
252
+ deps = ["onnxruntime>=1.16.0", "tokenizers>=0.15.0", "numpy>=1.24.0"]
253
+ console.print("\n[bold cyan]Installing classifier dependencies[/bold cyan]")
254
+ console.print(" [white]onnxruntime, tokenizers, numpy[/white]")
255
+ console.print()
256
+
257
+ # Method 1: Try pip (works for pip/pipx installs)
248
258
  try:
249
- import subprocess
250
259
  result = subprocess.run(
251
- [sys.executable, "-m", "pip", "install", "onnxruntime>=1.16.0", "tokenizers>=0.15.0", "numpy>=1.24.0"],
260
+ [sys.executable, "-m", "pip", "install", *deps],
252
261
  capture_output=True,
253
262
  text=True,
254
263
  timeout=300,
255
264
  )
256
265
  if result.returncode == 0:
257
- console.print("[green]\u2713[/green] Local model dependencies installed")
266
+ console.print("[green]\u2713[/green] Classifier dependencies installed")
258
267
  return True
259
- else:
260
- console.print(f"[yellow]\u26a0[/yellow] Could not install dependencies: {result.stderr.strip()[:200]}")
261
- console.print(" [white]Install manually with: pip install tweek[local-models][/white]")
262
- return False
263
- except Exception as e:
264
- console.print(f"[yellow]\u26a0[/yellow] Could not install dependencies: {e}")
265
- console.print(" [white]Install manually with: pip install tweek[local-models][/white]")
266
- return False
268
+ except Exception:
269
+ pass
270
+
271
+ # Method 2: Try uv pip (works for uv tool installs where pip is absent)
272
+ uv_cmd = shutil.which("uv")
273
+ if uv_cmd:
274
+ console.print(" [white]pip not available in this environment, trying uv...[/white]")
275
+ try:
276
+ result = subprocess.run(
277
+ [uv_cmd, "pip", "install", "--python", sys.executable, *deps],
278
+ capture_output=True,
279
+ text=True,
280
+ timeout=300,
281
+ )
282
+ if result.returncode == 0:
283
+ console.print("[green]\u2713[/green] Classifier dependencies installed (via uv)")
284
+ return True
285
+ else:
286
+ console.print(f"[yellow]\u26a0[/yellow] uv pip install failed: {result.stderr.strip()[:200]}")
287
+ except Exception as e:
288
+ console.print(f"[yellow]\u26a0[/yellow] uv pip install failed: {e}")
289
+
290
+ console.print("[yellow]\u26a0[/yellow] Could not install classifier dependencies automatically")
291
+ console.print(" [white]Install manually:[/white]")
292
+ if uv_cmd:
293
+ console.print(f" uv pip install --python {sys.executable} tweek[local-models]")
294
+ else:
295
+ console.print(" pip install tweek[local-models]")
296
+ return False
267
297
 
268
298
 
269
299
  def _download_local_model(quick: bool) -> bool:
@@ -293,7 +323,12 @@ def _download_local_model(quick: bool) -> bool:
293
323
  console.print("\n[white]Local model module not available — skipping model download[/white]")
294
324
  return False
295
325
 
296
- # Auto-install deps if missing (onnxruntime, tokenizers, numpy)
326
+ console.print("\n[bold cyan]Local Classifier Setup[/bold cyan]")
327
+ console.print(" [white]The on-device classifier detects prompt injection without any API key.[/white]")
328
+ console.print()
329
+
330
+ # Step A: Ensure deps are installed
331
+ console.print(" [bold]1/2 Dependencies[/bold]")
297
332
  deps_available = _ensure_local_model_deps()
298
333
  if not deps_available:
299
334
  return False
@@ -306,34 +341,37 @@ def _download_local_model(quick: bool) -> bool:
306
341
 
307
342
  if not LOCAL_MODEL_AVAILABLE:
308
343
  if not quick:
309
- console.print("\n[yellow]\u26a0[/yellow] Local model dependencies not fully functional after install")
344
+ console.print(" [yellow]\u26a0[/yellow] Dependencies installed but not functional restart may be needed")
310
345
  return False
311
346
 
347
+ # Step B: Download model
348
+ console.print()
349
+ console.print(" [bold]2/2 Model Download[/bold]")
350
+
312
351
  default_name = get_default_model_name()
313
352
 
314
353
  if is_model_installed(default_name):
315
- console.print(f"\n[green]\u2713[/green] Local classifier model already installed ({default_name})")
354
+ console.print(f" [green]\u2713[/green] Already installed ({default_name})")
316
355
  return True
317
356
 
318
357
  definition = get_model_definition(default_name)
319
358
  if definition is None:
320
359
  return False
321
360
 
322
- if not quick:
323
- console.print(f"\n[bold]Downloading local classifier model[/bold]")
324
- console.print(f" Model: {definition.display_name}")
325
- console.print(f" Size: ~{definition.size_mb:.0f} MB")
326
- console.print(f" License: {definition.license}")
327
- console.print(f" [white]This enables on-device prompt injection detection (no API key needed)[/white]")
328
- console.print()
361
+ console.print(f" Model: {definition.display_name}")
362
+ console.print(f" Size: ~{definition.size_mb:.0f} MB")
363
+ console.print(f" License: {definition.license}")
364
+ console.print()
329
365
 
330
- from rich.progress import Progress, BarColumn, DownloadColumn, TransferSpeedColumn
366
+ from rich.progress import Progress, BarColumn, DownloadColumn, TransferSpeedColumn, TimeRemainingColumn
331
367
 
332
368
  progress = Progress(
333
369
  "[progress.description]{task.description}",
334
370
  BarColumn(),
371
+ "[progress.percentage]{task.percentage:>3.0f}%",
335
372
  DownloadColumn(),
336
373
  TransferSpeedColumn(),
374
+ TimeRemainingColumn(),
337
375
  console=console,
338
376
  )
339
377
 
@@ -350,16 +388,16 @@ def _download_local_model(quick: bool) -> bool:
350
388
  with progress:
351
389
  download_model(default_name, progress_callback=progress_callback)
352
390
 
353
- console.print(f"[green]\u2713[/green] Local classifier model downloaded ({default_name})")
391
+ console.print(f" [green]\u2713[/green] Classifier model ready ({default_name})")
354
392
  return True
355
393
 
356
394
  except ModelDownloadError as e:
357
- console.print(f"\n[yellow]\u26a0[/yellow] Could not download local model: {e}")
358
- console.print(" [white]You can download it later with: tweek model download[/white]")
395
+ console.print(f"\n [yellow]\u26a0[/yellow] Could not download model: {e}")
396
+ console.print(" [white]Download later with: tweek model download[/white]")
359
397
  return False
360
398
  except Exception as e:
361
- console.print(f"\n[yellow]\u26a0[/yellow] Model download failed: {e}")
362
- console.print(" [white]You can download it later with: tweek model download[/white]")
399
+ console.print(f"\n [yellow]\u26a0[/yellow] Model download failed: {e}")
400
+ console.print(" [white]Download later with: tweek model download[/white]")
363
401
  return False
364
402
 
365
403
 
@@ -404,6 +442,12 @@ def _install_claude_code_hooks(install_global: bool, dev_test: bool, backup: boo
404
442
  "proxy": False,
405
443
  }
406
444
 
445
+ # ═══════════════════════════════════════════════════════════════
446
+ # PHASE 1: Environment Detection
447
+ # ═══════════════════════════════════════════════════════════════
448
+ console.print("[bold cyan]Phase 1/4: Environment Detection[/bold cyan]")
449
+ console.print()
450
+
407
451
  # ─────────────────────────────────────────────────────────────
408
452
  # Step 1: Detect Claude Code CLI
409
453
  # ─────────────────────────────────────────────────────────────
@@ -567,6 +611,13 @@ def _install_claude_code_hooks(install_global: bool, dev_test: bool, backup: boo
567
611
  except Exception as e:
568
612
  console.print(f"[white]Warning: Could not check for proxy conflicts: {e}[/white]")
569
613
 
614
+ # ═══════════════════════════════════════════════════════════════
615
+ # PHASE 2: Hook & Skill Installation
616
+ # ═══════════════════════════════════════════════════════════════
617
+ console.print()
618
+ console.print("[bold cyan]Phase 2/4: Hook & Skill Installation[/bold cyan]")
619
+ console.print()
620
+
570
621
  # ─────────────────────────────────────────────────────────────
571
622
  # Step 5: Install hooks into settings.json
572
623
  # ─────────────────────────────────────────────────────────────
@@ -730,6 +781,12 @@ def _install_claude_code_hooks(install_global: bool, dev_test: bool, backup: boo
730
781
  console.print(f"[white]Tweek skill source not found \u2014 skill not installed[/white]")
731
782
  console.print(f" [white]Skill can be installed manually from the tweek repository[/white]")
732
783
 
784
+ # ═══════════════════════════════════════════════════════════════
785
+ # PHASE 3: Classifier & Security
786
+ # ═══════════════════════════════════════════════════════════════
787
+ console.print()
788
+ console.print("[bold cyan]Phase 3/4: Classifier & Security Configuration[/bold cyan]")
789
+
733
790
  # ─────────────────────────────────────────────────────────────
734
791
  # Step 7: Download local classifier model
735
792
  # ─────────────────────────────────────────────────────────────
@@ -1013,6 +1070,13 @@ def _install_claude_code_hooks(install_global: bool, dev_test: bool, backup: boo
1013
1070
  except Exception as e:
1014
1071
  console.print(f"\n[yellow]Warning: Could not save proxy config: {e}[/yellow]")
1015
1072
 
1073
+ # ═══════════════════════════════════════════════════════════════
1074
+ # PHASE 4: Verification & Summary
1075
+ # ═══════════════════════════════════════════════════════════════
1076
+ console.print()
1077
+ console.print("[bold cyan]Phase 4/4: Verification & Summary[/bold cyan]")
1078
+ console.print()
1079
+
1016
1080
  # ─────────────────────────────────────────────────────────────
1017
1081
  # Step 13: Post-install verification and summary
1018
1082
  # ─────────────────────────────────────────────────────────────
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tweek
3
- Version: 0.4.2
3
+ Version: 0.4.3
4
4
  Summary: Defense-in-depth security for AI coding assistants - protect credentials, code, and system from prompt injection attacks
5
5
  Author: Tommy Mancino
6
6
  License-Expression: Apache-2.0
@@ -1,4 +1,4 @@
1
- tweek/__init__.py,sha256=t1KCgD0YKKLEBTFoWw7b7BKP6w2BJ7Oq1vtoXokj2R8,359
1
+ tweek/__init__.py,sha256=UIwNpJC_gnvm1PUxLmQpu9t5ZrlDpSn_-ehenv2ztt8,359
2
2
  tweek/_keygen.py,sha256=UapwIKNSwaRWdqHoJoF3hmKuiux6aIiFGe8WVskTbI8,1286
3
3
  tweek/audit.py,sha256=AzjIpy6Jc-WzTrda9lb3nZbyaR_SDWUxo04pObJP2MQ,8868
4
4
  tweek/cli.py,sha256=OOZrpcrwDGbmaHxIyvBw7MoVSlEdrFNAgIwWHI56p5M,2976
@@ -7,7 +7,7 @@ tweek/cli_configure.py,sha256=fHm2sWxjUWFu7ulup7T-zrQ3LYiYg_1Vf-m3E5hoKd8,14603
7
7
  tweek/cli_core.py,sha256=sq-zIX_rrDB3KsaLcehsYHKUsAQrqHwsAvHgxN7iHiQ,27643
8
8
  tweek/cli_dry_run.py,sha256=8DBx3qKAZHY8VA6MsbsGBs6EyDGFxKsrtmuNaHJ22C8,14335
9
9
  tweek/cli_helpers.py,sha256=_8aVj8e67MrP61ao7_AaEQSi9AfJQxW3eNvnjbSWT7g,16347
10
- tweek/cli_install.py,sha256=k0apx-yJIsepaPncvKVc2OZWAbKg_ElEvKJ5L2Hb0f4,85019
10
+ tweek/cli_install.py,sha256=Xip9eH45J-OFRcUPFowf6LEb4DZ6eDw5FyuVj6MED8U,88377
11
11
  tweek/cli_logs.py,sha256=uoJBKb85EYcIQnXxNfh15w235u9UWP1he-RlwnITWuA,10776
12
12
  tweek/cli_mcp.py,sha256=mIKTUqTKLlVYc9054LdjfL-maiVAabPFkb_sLtoS0Gk,4787
13
13
  tweek/cli_memory.py,sha256=Sw2TOt7RGsXBoH_q13bQjUK3WyvOy49bXefZ7atoaCY,11895
@@ -139,11 +139,11 @@ tweek/skills/scanner.py,sha256=YlH-yg3_JuwmBvmnpqA4PVfWyNBHaPSjBo6d9Ncuh8k,27574
139
139
  tweek/vault/__init__.py,sha256=L408fjdRYL8-VqLEsyyHSO9PkBDhd_2mPIbrCu53YhM,980
140
140
  tweek/vault/cross_platform.py,sha256=D4UvX_7OpSo8iRx5sc2OUUWQIk8JHhgeFBYk1MbyIj4,8251
141
141
  tweek/vault/keychain.py,sha256=XL18-SUj7HwuqxLXZDViuCH81--KMu68jN9Szn1aeyw,10624
142
- tweek-0.4.2.dist-info/licenses/LICENSE,sha256=rjoDzr1vAf0bsqZglpIyekU5aewIkCk4jHZZDvVI2BE,15269
143
- tweek-0.4.2.dist-info/licenses/NOTICE,sha256=taQokyDes5UTRNEC67G-13VmqvUyTOncrrT33pCcWL0,8729
142
+ tweek-0.4.3.dist-info/licenses/LICENSE,sha256=rjoDzr1vAf0bsqZglpIyekU5aewIkCk4jHZZDvVI2BE,15269
143
+ tweek-0.4.3.dist-info/licenses/NOTICE,sha256=taQokyDes5UTRNEC67G-13VmqvUyTOncrrT33pCcWL0,8729
144
144
  tweek-openclaw-plugin/node_modules/flatted/python/flatted.py,sha256=UYburBDqkySaTfSpntPCUJRxiBGcplusJM7ECX8FEgA,3860
145
- tweek-0.4.2.dist-info/METADATA,sha256=zxSNhepswO-jyvEwLeo6NC9I-X-_qL2Do1DUK-FKB20,11992
146
- tweek-0.4.2.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
147
- tweek-0.4.2.dist-info/entry_points.txt,sha256=YXThD6UiF5XQXwqW33sphsvz-Bl4Zm6pm-xq-5wcCYE,1337
148
- tweek-0.4.2.dist-info/top_level.txt,sha256=jtNcCxjoGXN8IBqEVL0F3LHDrZD_B0S-4XF9-Ur7Pbc,28
149
- tweek-0.4.2.dist-info/RECORD,,
145
+ tweek-0.4.3.dist-info/METADATA,sha256=ynxe3BBnGBznFuUF6LpjjFuwyZ5yA4G70aKIf61-6a8,11992
146
+ tweek-0.4.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
147
+ tweek-0.4.3.dist-info/entry_points.txt,sha256=YXThD6UiF5XQXwqW33sphsvz-Bl4Zm6pm-xq-5wcCYE,1337
148
+ tweek-0.4.3.dist-info/top_level.txt,sha256=jtNcCxjoGXN8IBqEVL0F3LHDrZD_B0S-4XF9-Ur7Pbc,28
149
+ tweek-0.4.3.dist-info/RECORD,,
File without changes