agentpack-cli 0.1.1__tar.gz → 0.1.2__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.
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/PKG-INFO +2 -2
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/README.md +1 -1
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/pyproject.toml +1 -1
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/application/pack_service.py +6 -3
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/scanner.py +27 -3
- agentpack_cli-0.1.2/src/agentpack/core/token_estimator.py +40 -0
- agentpack_cli-0.1.1/src/agentpack/core/token_estimator.py +0 -26
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/.gitignore +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/LICENSE +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/adapters/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/adapters/base.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/adapters/claude.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/adapters/codex.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/adapters/cursor.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/adapters/generic.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/adapters/windsurf.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/analysis/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/analysis/dependency_graph.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/analysis/go_imports.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/analysis/java_imports.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/analysis/js_ts_imports.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/analysis/python_imports.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/analysis/ranking.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/analysis/rust_imports.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/analysis/symbols.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/analysis/tests.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/application/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/cli.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/_shared.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/benchmark.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/claude_cmd.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/diff.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/doctor.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/explain.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/init.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/install.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/monitor.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/pack.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/scan.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/session.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/stats.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/status.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/summarize.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/commands/watch.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/bootstrap.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/cache.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/config.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/context_pack.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/diff.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/git.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/git_hooks.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/global_install.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/ignore.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/merkle.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/models.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/redactor.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/snapshot.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/core/vscode_tasks.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/data/agentpack.md +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/installers/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/installers/claude.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/installers/codex.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/installers/cursor.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/installers/windsurf.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/integrations/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/integrations/git_hooks.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/integrations/global_install.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/integrations/vscode_tasks.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/renderers/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/renderers/compact.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/renderers/markdown.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/renderers/receipts.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/session/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/session/state.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/summaries/__init__.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/summaries/base.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/src/agentpack/summaries/llm.py +0 -0
- {agentpack_cli-0.1.1 → agentpack_cli-0.1.2}/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.
|
|
3
|
+
Version: 0.1.2
|
|
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
|
|
@@ -43,7 +43,7 @@ Description-Content-Type: text/markdown
|
|
|
43
43
|
[](https://opensource.org/licenses/MIT)
|
|
44
44
|
[](https://github.com/vishal2612200/agentpack/actions/workflows/ci.yml)
|
|
45
45
|
|
|
46
|
-
> **Status: alpha (v0.1.
|
|
46
|
+
> **Status: alpha (v0.1.2).** Works, tested, used in real sessions. Python and JavaScript/TypeScript are the best-supported languages. Not yet validated across a wide range of repos. API may change before 1.0.
|
|
47
47
|
>
|
|
48
48
|
> **Platform note:** macOS and Linux are fully supported. Windows support is not yet implemented (git hooks use POSIX shell; the Claude Code session hooks use `python3`/`rm -f`). Contributions welcome.
|
|
49
49
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
[](https://opensource.org/licenses/MIT)
|
|
6
6
|
[](https://github.com/vishal2612200/agentpack/actions/workflows/ci.yml)
|
|
7
7
|
|
|
8
|
-
> **Status: alpha (v0.1.
|
|
8
|
+
> **Status: alpha (v0.1.2).** Works, tested, used in real sessions. Python and JavaScript/TypeScript are the best-supported languages. Not yet validated across a wide range of repos. API may change before 1.0.
|
|
9
9
|
>
|
|
10
10
|
> **Platform note:** macOS and Linux are fully supported. Windows support is not yet implemented (git hooks use POSIX shell; the Claude Code session hooks use `python3`/`rm -f`). Contributions welcome.
|
|
11
11
|
|
|
@@ -90,9 +90,11 @@ class ChangeDetector:
|
|
|
90
90
|
packable: list[FileInfo],
|
|
91
91
|
root: Path,
|
|
92
92
|
since: str | None,
|
|
93
|
+
previous_snap: dict | None = None,
|
|
93
94
|
) -> ChangeSet:
|
|
94
95
|
current_snap = build_snapshot(packable)
|
|
95
|
-
previous_snap
|
|
96
|
+
if previous_snap is None:
|
|
97
|
+
previous_snap = load_snapshot(root)
|
|
96
98
|
snap_diff = diff_snapshots(previous_snap, current_snap)
|
|
97
99
|
changed_from_snap: set[str] = set(snap_diff.added + snap_diff.modified)
|
|
98
100
|
|
|
@@ -160,7 +162,8 @@ class PackPlanner:
|
|
|
160
162
|
phase_times: dict[str, float] = {}
|
|
161
163
|
|
|
162
164
|
t0 = time.perf_counter()
|
|
163
|
-
|
|
165
|
+
previous_snap = load_snapshot(root)
|
|
166
|
+
scan_result = scan(root, ignore_spec, cfg.context.max_file_tokens, previous_snapshot=previous_snap)
|
|
164
167
|
phase_times["scan"] = time.perf_counter() - t0
|
|
165
168
|
|
|
166
169
|
packable = scan_result.packable
|
|
@@ -175,7 +178,7 @@ class PackPlanner:
|
|
|
175
178
|
phase_times["deps"] = time.perf_counter() - t0
|
|
176
179
|
|
|
177
180
|
t0 = time.perf_counter()
|
|
178
|
-
changes = ChangeDetector().detect(packable, root, request.since)
|
|
181
|
+
changes = ChangeDetector().detect(packable, root, request.since, previous_snap=previous_snap)
|
|
179
182
|
phase_times["changes"] = time.perf_counter() - t0
|
|
180
183
|
|
|
181
184
|
t0 = time.perf_counter()
|
|
@@ -7,7 +7,7 @@ import pathspec
|
|
|
7
7
|
|
|
8
8
|
from agentpack.core.ignore import load_spec, is_ignored
|
|
9
9
|
from agentpack.core.models import FileInfo, ScanResult
|
|
10
|
-
from agentpack.core.token_estimator import estimate_tokens
|
|
10
|
+
from agentpack.core.token_estimator import estimate_tokens, estimate_tokens_bytes
|
|
11
11
|
|
|
12
12
|
BINARY_EXTENSIONS = {
|
|
13
13
|
".png", ".jpg", ".jpeg", ".gif", ".bmp", ".ico", ".svg",
|
|
@@ -54,7 +54,7 @@ LANGUAGE_MAP: dict[str, str] = {
|
|
|
54
54
|
".xml": "xml",
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
ALWAYS_SKIP = {".git", ".agentpack"}
|
|
57
|
+
ALWAYS_SKIP = {".git", ".agentpack", ".claude"}
|
|
58
58
|
|
|
59
59
|
|
|
60
60
|
def file_hash(path: Path) -> str:
|
|
@@ -79,11 +79,14 @@ def scan(
|
|
|
79
79
|
root: Path,
|
|
80
80
|
ignore_spec: pathspec.PathSpec,
|
|
81
81
|
max_file_tokens: int = 4000,
|
|
82
|
+
previous_snapshot: dict | None = None,
|
|
82
83
|
) -> ScanResult:
|
|
83
84
|
packable: list[FileInfo] = []
|
|
84
85
|
ignored: list[FileInfo] = []
|
|
85
86
|
binary: list[FileInfo] = []
|
|
86
87
|
|
|
88
|
+
prev_files: dict[str, dict] = (previous_snapshot or {}).get("files", {})
|
|
89
|
+
|
|
87
90
|
for abs_path in root.rglob("*"):
|
|
88
91
|
if not abs_path.is_file():
|
|
89
92
|
continue
|
|
@@ -125,6 +128,27 @@ def scan(
|
|
|
125
128
|
|
|
126
129
|
size = abs_path.stat().st_size
|
|
127
130
|
lang = LANGUAGE_MAP.get(abs_path.suffix.lower())
|
|
131
|
+
fhash = file_hash(abs_path)
|
|
132
|
+
|
|
133
|
+
# Unchanged file: reuse cached token count, skip content read.
|
|
134
|
+
# Content is loaded lazily by context_pack.select_files() when needed.
|
|
135
|
+
prev = prev_files.get(rel_str)
|
|
136
|
+
if prev and prev.get("hash") == fhash:
|
|
137
|
+
cached_tokens = prev.get("estimated_tokens", estimate_tokens_bytes(size))
|
|
138
|
+
too_large = cached_tokens > max_file_tokens
|
|
139
|
+
packable.append(
|
|
140
|
+
FileInfo(
|
|
141
|
+
path=rel_str,
|
|
142
|
+
abs_path=abs_path,
|
|
143
|
+
language=lang,
|
|
144
|
+
size_bytes=size,
|
|
145
|
+
estimated_tokens=cached_tokens,
|
|
146
|
+
hash=fhash,
|
|
147
|
+
too_large=too_large,
|
|
148
|
+
content=None,
|
|
149
|
+
)
|
|
150
|
+
)
|
|
151
|
+
continue
|
|
128
152
|
|
|
129
153
|
try:
|
|
130
154
|
text = abs_path.read_text(errors="replace")
|
|
@@ -141,7 +165,7 @@ def scan(
|
|
|
141
165
|
language=lang,
|
|
142
166
|
size_bytes=size,
|
|
143
167
|
estimated_tokens=tokens,
|
|
144
|
-
hash=
|
|
168
|
+
hash=fhash,
|
|
145
169
|
too_large=too_large,
|
|
146
170
|
content=text,
|
|
147
171
|
)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import os
|
|
4
|
+
|
|
5
|
+
_encoder = None
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def _get_encoder():
|
|
9
|
+
global _encoder
|
|
10
|
+
if _encoder is None:
|
|
11
|
+
try:
|
|
12
|
+
import tiktoken
|
|
13
|
+
# Only load tiktoken if its vocab cache already exists — avoids
|
|
14
|
+
# a blocking network download when running inside git hooks.
|
|
15
|
+
cache_dir = os.environ.get(
|
|
16
|
+
"TIKTOKEN_CACHE_DIR",
|
|
17
|
+
os.path.join(os.path.expanduser("~"), ".cache", "huggingface", "hub"),
|
|
18
|
+
)
|
|
19
|
+
tiktoken_cache = os.path.join(os.path.expanduser("~"), ".cache", "tiktoken")
|
|
20
|
+
cache_warm = os.path.isdir(tiktoken_cache) and any(
|
|
21
|
+
True for _ in os.scandir(tiktoken_cache)
|
|
22
|
+
) if os.path.isdir(tiktoken_cache) else False
|
|
23
|
+
if cache_warm or os.environ.get("AGENTPACK_FORCE_TIKTOKEN"):
|
|
24
|
+
_encoder = tiktoken.get_encoding("cl100k_base")
|
|
25
|
+
else:
|
|
26
|
+
_encoder = False
|
|
27
|
+
except ImportError:
|
|
28
|
+
_encoder = False
|
|
29
|
+
return _encoder
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def estimate_tokens(text: str) -> int:
|
|
33
|
+
enc = _get_encoder()
|
|
34
|
+
if enc:
|
|
35
|
+
return max(1, len(enc.encode(text, disallowed_special=())))
|
|
36
|
+
return max(1, len(text) // 4)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def estimate_tokens_bytes(size_bytes: int) -> int:
|
|
40
|
+
return max(1, size_bytes // 4)
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
_encoder = None
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
def _get_encoder():
|
|
7
|
-
global _encoder
|
|
8
|
-
if _encoder is None:
|
|
9
|
-
try:
|
|
10
|
-
import tiktoken
|
|
11
|
-
_encoder = tiktoken.get_encoding("cl100k_base")
|
|
12
|
-
except ImportError:
|
|
13
|
-
_encoder = False
|
|
14
|
-
return _encoder
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def estimate_tokens(text: str) -> int:
|
|
18
|
-
enc = _get_encoder()
|
|
19
|
-
if enc:
|
|
20
|
-
return max(1, len(enc.encode(text, disallowed_special=())))
|
|
21
|
-
return max(1, len(text) // 4)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def estimate_tokens_bytes(size_bytes: int) -> int:
|
|
25
|
-
# byte-level fallback when text is unavailable
|
|
26
|
-
return max(1, size_bytes // 4)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|