agentpack-cli 0.1.12__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.12 → agentpack_cli-0.1.14}/PKG-INFO +1 -1
  2. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/pyproject.toml +1 -1
  3. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/__init__.py +1 -1
  4. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/application/pack_service.py +58 -1
  5. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/stats.py +40 -0
  6. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/watch.py +22 -1
  7. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/.gitignore +0 -0
  8. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/LICENSE +0 -0
  9. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/README.md +0 -0
  10. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/adapters/__init__.py +0 -0
  11. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/adapters/antigravity.py +0 -0
  12. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/adapters/base.py +0 -0
  13. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/adapters/claude.py +0 -0
  14. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/adapters/codex.py +0 -0
  15. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/adapters/cursor.py +0 -0
  16. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/adapters/detect.py +0 -0
  17. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/adapters/generic.py +0 -0
  18. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/adapters/windsurf.py +0 -0
  19. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/analysis/__init__.py +0 -0
  20. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/analysis/dependency_graph.py +0 -0
  21. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/analysis/go_imports.py +0 -0
  22. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/analysis/java_imports.py +0 -0
  23. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/analysis/js_ts_imports.py +0 -0
  24. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/analysis/python_imports.py +0 -0
  25. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/analysis/ranking.py +0 -0
  26. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/analysis/rust_imports.py +0 -0
  27. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/analysis/symbols.py +0 -0
  28. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/analysis/tests.py +0 -0
  29. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/application/__init__.py +0 -0
  30. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/cli.py +0 -0
  31. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/__init__.py +0 -0
  32. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/_shared.py +0 -0
  33. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/benchmark.py +0 -0
  34. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/claude_cmd.py +0 -0
  35. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/diff.py +0 -0
  36. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/doctor.py +0 -0
  37. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/explain.py +0 -0
  38. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/init.py +0 -0
  39. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/install.py +0 -0
  40. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/mcp_cmd.py +0 -0
  41. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/monitor.py +0 -0
  42. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/pack.py +0 -0
  43. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/scan.py +0 -0
  44. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/status.py +0 -0
  45. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/commands/summarize.py +0 -0
  46. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/__init__.py +0 -0
  47. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/bootstrap.py +0 -0
  48. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/cache.py +0 -0
  49. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/config.py +0 -0
  50. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/context_pack.py +0 -0
  51. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/diff.py +0 -0
  52. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/git.py +0 -0
  53. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/git_hooks.py +0 -0
  54. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/global_install.py +0 -0
  55. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/ignore.py +0 -0
  56. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/merkle.py +0 -0
  57. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/models.py +0 -0
  58. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/redactor.py +0 -0
  59. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/scanner.py +0 -0
  60. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/snapshot.py +0 -0
  61. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/token_estimator.py +0 -0
  62. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/core/vscode_tasks.py +0 -0
  63. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/data/agentpack.md +0 -0
  64. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/installers/__init__.py +0 -0
  65. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/installers/antigravity.py +0 -0
  66. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/installers/claude.py +0 -0
  67. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/installers/codex.py +0 -0
  68. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/installers/cursor.py +0 -0
  69. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/installers/windsurf.py +0 -0
  70. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/integrations/__init__.py +0 -0
  71. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/integrations/git_hooks.py +0 -0
  72. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/integrations/global_install.py +0 -0
  73. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/integrations/vscode_tasks.py +0 -0
  74. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/mcp_server.py +0 -0
  75. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/renderers/__init__.py +0 -0
  76. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/renderers/compact.py +0 -0
  77. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/renderers/markdown.py +0 -0
  78. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/renderers/receipts.py +0 -0
  79. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/session/__init__.py +0 -0
  80. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/session/state.py +0 -0
  81. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/summaries/__init__.py +0 -0
  82. {agentpack_cli-0.1.12 → agentpack_cli-0.1.14}/src/agentpack/summaries/base.py +0 -0
  83. {agentpack_cli-0.1.12 → 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.12
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.12"
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.12"
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]] = []
@@ -19,6 +19,7 @@ _IGNORE_DIRS = {
19
19
  ".vscode", ".idea", ".fleet",
20
20
  }
21
21
  _IGNORE_NAMES = {"context.md", "context.compact.md"}
22
+ _IGNORE_SUFFIXES = {".tsbuildinfo"} # TypeScript incremental build artifacts
22
23
  # Ignore all .agentpack/ generated files; task.md is the sole exception (user-edited, triggers refresh)
23
24
 
24
25
  # Adapter output paths written outside .agentpack/ (e.g. antigravity writes .agent/skills/agentpack/SKILL.md).
@@ -81,6 +82,8 @@ def _should_ignore(path: str) -> bool:
81
82
  name = Path(path).name
82
83
  if name in _IGNORE_NAMES:
83
84
  return True
85
+ if any(name.endswith(suf) for suf in _IGNORE_SUFFIXES):
86
+ return True
84
87
  norm = path.replace("\\", "/")
85
88
  # Ignore everything under .agentpack/ except task.md
86
89
  if norm.startswith(".agentpack/") and norm != TASK_FILE:
@@ -139,7 +142,7 @@ def _watch_with_watchdog(
139
142
  _run_refresh(root, agent, mode, budget)
140
143
 
141
144
  class Handler(FileSystemEventHandler):
142
- def on_any_event(self, event): # type: ignore[override]
145
+ def _handle(self, event) -> None: # type: ignore[override]
143
146
  if event.is_directory:
144
147
  return
145
148
  try:
@@ -152,6 +155,24 @@ def _watch_with_watchdog(
152
155
  console.print(f"[dim][{_ts()}][/] task changed")
153
156
  _pending[0] = True
154
157
 
158
+ # Only react to mutations — not reads (avoids inotify IN_ACCESS loop on Linux)
159
+ on_created = _handle
160
+ on_modified = _handle
161
+ on_deleted = _handle
162
+
163
+ def on_moved(self, event) -> None: # type: ignore[override]
164
+ if event.is_directory:
165
+ return
166
+ # Check both src (rename from) and dest (rename to)
167
+ for raw in (event.src_path, event.dest_path):
168
+ try:
169
+ path = str(Path(raw).relative_to(root))
170
+ except ValueError:
171
+ continue
172
+ if not _should_ignore(path):
173
+ _pending[0] = True
174
+ return
175
+
155
176
  observer = Observer()
156
177
  try:
157
178
  observer.schedule(Handler(), str(root), recursive=True)
File without changes
File without changes