agentpack-cli 0.1.13__tar.gz → 0.1.14__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 (83) hide show
  1. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/PKG-INFO +1 -1
  2. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/pyproject.toml +1 -1
  3. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/__init__.py +1 -1
  4. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/application/pack_service.py +58 -1
  5. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/stats.py +40 -0
  6. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/.gitignore +0 -0
  7. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/LICENSE +0 -0
  8. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/README.md +0 -0
  9. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/adapters/__init__.py +0 -0
  10. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/adapters/antigravity.py +0 -0
  11. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/adapters/base.py +0 -0
  12. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/adapters/claude.py +0 -0
  13. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/adapters/codex.py +0 -0
  14. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/adapters/cursor.py +0 -0
  15. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/adapters/detect.py +0 -0
  16. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/adapters/generic.py +0 -0
  17. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/adapters/windsurf.py +0 -0
  18. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/analysis/__init__.py +0 -0
  19. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/analysis/dependency_graph.py +0 -0
  20. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/analysis/go_imports.py +0 -0
  21. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/analysis/java_imports.py +0 -0
  22. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/analysis/js_ts_imports.py +0 -0
  23. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/analysis/python_imports.py +0 -0
  24. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/analysis/ranking.py +0 -0
  25. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/analysis/rust_imports.py +0 -0
  26. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/analysis/symbols.py +0 -0
  27. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/analysis/tests.py +0 -0
  28. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/application/__init__.py +0 -0
  29. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/cli.py +0 -0
  30. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/__init__.py +0 -0
  31. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/_shared.py +0 -0
  32. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/benchmark.py +0 -0
  33. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/claude_cmd.py +0 -0
  34. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/diff.py +0 -0
  35. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/doctor.py +0 -0
  36. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/explain.py +0 -0
  37. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/init.py +0 -0
  38. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/install.py +0 -0
  39. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/mcp_cmd.py +0 -0
  40. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/monitor.py +0 -0
  41. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/pack.py +0 -0
  42. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/scan.py +0 -0
  43. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/status.py +0 -0
  44. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/summarize.py +0 -0
  45. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/commands/watch.py +0 -0
  46. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/__init__.py +0 -0
  47. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/bootstrap.py +0 -0
  48. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/cache.py +0 -0
  49. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/config.py +0 -0
  50. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/context_pack.py +0 -0
  51. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/diff.py +0 -0
  52. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/git.py +0 -0
  53. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/git_hooks.py +0 -0
  54. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/global_install.py +0 -0
  55. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/ignore.py +0 -0
  56. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/merkle.py +0 -0
  57. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/models.py +0 -0
  58. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/redactor.py +0 -0
  59. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/scanner.py +0 -0
  60. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/snapshot.py +0 -0
  61. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/token_estimator.py +0 -0
  62. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/core/vscode_tasks.py +0 -0
  63. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/data/agentpack.md +0 -0
  64. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/installers/__init__.py +0 -0
  65. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/installers/antigravity.py +0 -0
  66. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/installers/claude.py +0 -0
  67. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/installers/codex.py +0 -0
  68. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/installers/cursor.py +0 -0
  69. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/installers/windsurf.py +0 -0
  70. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/integrations/__init__.py +0 -0
  71. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/integrations/git_hooks.py +0 -0
  72. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/integrations/global_install.py +0 -0
  73. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/integrations/vscode_tasks.py +0 -0
  74. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/mcp_server.py +0 -0
  75. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/renderers/__init__.py +0 -0
  76. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/renderers/compact.py +0 -0
  77. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/renderers/markdown.py +0 -0
  78. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/renderers/receipts.py +0 -0
  79. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/session/__init__.py +0 -0
  80. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/session/state.py +0 -0
  81. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/summaries/__init__.py +0 -0
  82. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/summaries/base.py +0 -0
  83. {agentpack_cli-0.1.13 → agentpack_cli-0.1.14}/src/agentpack/summaries/offline.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentpack-cli
3
- Version: 0.1.13
3
+ Version: 0.1.14
4
4
  Summary: Token-aware context packing for AI coding agents — Claude, Cursor, Windsurf, and Codex
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentpack-cli"
3
- version = "0.1.13"
3
+ version = "0.1.14"
4
4
  description = "Token-aware context packing for AI coding agents — Claude, Cursor, Windsurf, and Codex"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -1,3 +1,3 @@
1
1
  """AgentPack — token-aware context packing for AI coding agents."""
2
2
 
3
- __version__ = "0.1.13"
3
+ __version__ = "0.1.14"
@@ -305,6 +305,8 @@ class PackService:
305
305
  saving_pct=saving_pct,
306
306
  selected_count=len(plan.selected),
307
307
  changed_count=len(plan.all_changed),
308
+ selected_paths=[sf.path for sf in plan.selected],
309
+ current_changed=plan.all_changed,
308
310
  )
309
311
 
310
312
  return PackResult(
@@ -331,6 +333,56 @@ def _sf_tokens(sf: SelectedFile) -> int:
331
333
  return estimate_tokens("\n".join(parts)) if parts else 50
332
334
 
333
335
 
336
+ def _load_last_record(metrics_path: Path) -> dict[str, Any] | None:
337
+ """Return the most recent metrics record that has selected_paths."""
338
+ if not metrics_path.exists():
339
+ return None
340
+ try:
341
+ lines = metrics_path.read_text(encoding="utf-8").splitlines()
342
+ for line in reversed(lines):
343
+ line = line.strip()
344
+ if not line:
345
+ continue
346
+ rec = json.loads(line)
347
+ if rec.get("selected_paths"):
348
+ return rec
349
+ except Exception:
350
+ pass
351
+ return None
352
+
353
+
354
+ def _compute_selection_accuracy(
355
+ root: Path,
356
+ metrics_path: Path,
357
+ current_selected: list[str],
358
+ current_changed: set[str],
359
+ ) -> dict[str, float]:
360
+ """Compare previous pack's selected_paths vs files actually changed since then.
361
+
362
+ recall = |predicted ∩ actual_changed| / |actual_changed|
363
+ precision = |predicted ∩ actual_changed| / |predicted|
364
+ """
365
+ prev = _load_last_record(metrics_path)
366
+ if prev is None:
367
+ return {}
368
+
369
+ prev_selected: set[str] = set(prev["selected_paths"])
370
+ # actual_changed = files changed since the previous pack (current git diff)
371
+ actual_changed: set[str] = current_changed
372
+ if not actual_changed or not prev_selected:
373
+ return {}
374
+
375
+ hits = prev_selected & actual_changed
376
+ recall = len(hits) / len(actual_changed)
377
+ precision = len(hits) / len(prev_selected)
378
+ f1 = (2 * precision * recall / (precision + recall)) if (precision + recall) > 0 else 0.0
379
+ return {
380
+ "selection_recall": round(recall, 3),
381
+ "selection_precision": round(precision, 3),
382
+ "selection_f1": round(f1, 3),
383
+ }
384
+
385
+
334
386
  def _record_metrics(
335
387
  root: Path,
336
388
  *,
@@ -342,9 +394,12 @@ def _record_metrics(
342
394
  saving_pct: float,
343
395
  selected_count: int,
344
396
  changed_count: int,
397
+ selected_paths: list[str],
398
+ current_changed: set[str],
345
399
  ) -> None:
346
400
  metrics_path = root / ".agentpack" / "metrics.jsonl"
347
- record = {
401
+ accuracy = _compute_selection_accuracy(root, metrics_path, selected_paths, current_changed)
402
+ record: dict[str, Any] = {
348
403
  "ts": datetime.now(timezone.utc).isoformat(),
349
404
  "task": task,
350
405
  "mode": mode,
@@ -353,9 +408,11 @@ def _record_metrics(
353
408
  "saving_pct": round(saving_pct, 1),
354
409
  "selected_files": selected_count,
355
410
  "changed_files": changed_count,
411
+ "selected_paths": selected_paths,
356
412
  "phases": {k: round(v, 3) for k, v in phase_times.items()},
357
413
  "total_s": round(sum(phase_times.values()), 3),
358
414
  }
415
+ record.update(accuracy)
359
416
  try:
360
417
  with metrics_path.open("a") as fh:
361
418
  fh.write(json.dumps(record) + "\n")
@@ -109,9 +109,49 @@ def register(app: typer.Typer) -> None:
109
109
  top_tbl.add_row(str(i), path, mode, why)
110
110
  console.print(top_tbl)
111
111
 
112
+ # --- Selection accuracy (last 10 runs) ---
113
+ accuracy_rows = _load_accuracy_rows(metrics_path, n=10)
114
+ if accuracy_rows:
115
+ avg_recall = sum(r["selection_recall"] for r in accuracy_rows) / len(accuracy_rows)
116
+ avg_precision = sum(r["selection_precision"] for r in accuracy_rows) / len(accuracy_rows)
117
+ avg_f1 = sum(r["selection_f1"] for r in accuracy_rows) / len(accuracy_rows)
118
+ console.print()
119
+ acc_tbl = Table(title=f"Selection Accuracy (last {len(accuracy_rows)} runs)", box=box.SIMPLE, show_header=False, padding=(0, 2))
120
+ acc_tbl.add_column(style="dim")
121
+ acc_tbl.add_column(justify="right", style="bold")
122
+ acc_tbl.add_row("avg recall", f"{avg_recall:.1%}")
123
+ acc_tbl.add_row("avg precision", f"{avg_precision:.1%}")
124
+ acc_tbl.add_row("avg F1", f"{avg_f1:.1%}")
125
+ console.print(acc_tbl)
126
+ console.print("[dim]recall = how many changed files were in the previous pack[/]")
127
+
112
128
  console.print("[dim]'manual' = hand-picking 20 most relevant full files[/]")
113
129
 
114
130
 
131
+ def _load_accuracy_rows(metrics_path: Path, n: int = 10) -> list[dict]:
132
+ """Return up to n most recent metrics records that have accuracy fields."""
133
+ if not metrics_path.exists():
134
+ return []
135
+ try:
136
+ lines = metrics_path.read_text(encoding="utf-8").splitlines()
137
+ rows = []
138
+ for line in reversed(lines):
139
+ line = line.strip()
140
+ if not line:
141
+ continue
142
+ try:
143
+ rec = json.loads(line)
144
+ except Exception:
145
+ continue
146
+ if "selection_recall" in rec:
147
+ rows.append(rec)
148
+ if len(rows) >= n:
149
+ break
150
+ return rows
151
+ except Exception:
152
+ return []
153
+
154
+
115
155
  def _parse_top_files(context_path: Path) -> list[tuple[str, str, str]]:
116
156
  """Parse top selected files from context.md. Returns list of (path, mode, why)."""
117
157
  results: list[tuple[str, str, str]] = []
File without changes
File without changes