agentpack-cli 0.3.25__tar.gz → 0.3.28__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.3.25 → agentpack_cli-0.3.28}/PKG-INFO +2 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/README.md +1 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/pyproject.toml +1 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/__init__.py +1 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/application/pack_service.py +7 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/benchmark.py +20 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/doctor.py +38 -5
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/next_cmd.py +4 -3
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/pack.py +3 -2
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/start_cmd.py +2 -3
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/status.py +2 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/task_cmd.py +3 -2
- agentpack_cli-0.3.28/src/agentpack/commands/upgrade.py +93 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/workflow_cmd.py +5 -3
- agentpack_cli-0.3.28/src/agentpack/core/command_surface.py +136 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/context_pack.py +12 -1
- agentpack_cli-0.3.28/src/agentpack/core/e2e_benchmark.py +75 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/data/agentpack.md +7 -7
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/data/codex_plugin/.codex-plugin/plugin.json +1 -1
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/data/codex_plugin/skills/agentpack-refresh.md +3 -3
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/installers/antigravity.py +21 -9
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/installers/claude.py +25 -9
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/installers/codex.py +21 -9
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/installers/cursor.py +24 -25
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/installers/windsurf.py +21 -10
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/integrations/agents.py +11 -9
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/integrations/vscode_tasks.py +5 -2
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/mcp_server.py +56 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/renderers/markdown.py +14 -3
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/router/models.py +8 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/router/prompt_builder.py +34 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/router/scoring.py +24 -3
- agentpack_cli-0.3.28/src/agentpack/router/service.py +611 -0
- agentpack_cli-0.3.25/src/agentpack/commands/upgrade.py +0 -38
- agentpack_cli-0.3.25/src/agentpack/router/service.py +0 -258
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/.gitignore +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/LICENSE +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/adapters/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/adapters/antigravity.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/adapters/base.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/adapters/claude.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/adapters/codex.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/adapters/cursor.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/adapters/detect.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/adapters/generic.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/adapters/windsurf.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/dependency_graph.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/go_imports.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/java_imports.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/js_ts_imports.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/monorepo.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/naming_signals.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/python_ast.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/python_imports.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/ranking.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/repo_map.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/role_inference.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/rust_imports.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/symbols.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/task_classifier.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/analysis/tests.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/application/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/cli.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/_shared.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/ci_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/claude_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/compress_output.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/dashboard.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/dev_check.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/diagnose_selection.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/diff.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/eval_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/explain.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/guard.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/hook_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/ignore_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/init.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/install.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/learn.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/mcp_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/memory.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/migrate.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/monitor.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/perf.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/quickstart.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/release_check.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/release_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/repair.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/retrieve.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/route.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/scan.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/skills.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/state_cmd.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/stats.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/summarize.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/threads.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/tune.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/verify_wheel.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/watch.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/commands/wrap.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/bootstrap.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/cache.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/changed_paths.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/config.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/diff.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/evals.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/execution_state.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/git.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/git_hooks.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/global_install.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/ignore.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/loop_protocol.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/merkle.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/models.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/modes.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/pack_registry.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/redactor.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/scanner.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/snapshot.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/task_freshness.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/thread_context.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/token_estimator.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/core/vscode_tasks.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/dashboard/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/dashboard/collectors.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/dashboard/models.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/dashboard/renderers.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/data/codex_plugin/skills/agentpack-pack.md +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/data/codex_plugin/skills/agentpack-review.md +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/data/codex_plugin/skills/agentpack-route.md +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/data/codex_plugin/skills/agentpack.md +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/installers/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/integrations/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/integrations/git_hooks.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/integrations/global_install.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/integrations/platform.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/learning/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/learning/collector.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/learning/extractor.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/learning/feedback.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/learning/lesson_ranker.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/learning/models.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/learning/provider.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/learning/quality.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/learning/renderers.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/learning/skill_map.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/output_compression/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/output_compression/core.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/renderers/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/renderers/compact.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/renderers/receipts.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/router/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/router/discovery.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/router/parser.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/router/skills_index.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/session/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/session/events.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/session/state.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/summaries/__init__.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/src/agentpack/summaries/base.py +0 -0
- {agentpack_cli-0.3.25 → agentpack_cli-0.3.28}/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.3.
|
|
3
|
+
Version: 0.3.28
|
|
4
4
|
Summary: Local context engine for AI coding agents that ranks relevant repo files and builds compact task-focused context packs for Claude Code, Codex, Cursor, Windsurf, MCP, and CI workflows.
|
|
5
5
|
Project-URL: Homepage, https://github.com/vishal2612200/agentpack
|
|
6
6
|
Project-URL: Documentation, https://vishal2612200.github.io/agentpack/
|
|
@@ -60,6 +60,7 @@ Description-Content-Type: text/markdown
|
|
|
60
60
|
</p>
|
|
61
61
|
|
|
62
62
|
<p align="center">
|
|
63
|
+
<a href="https://deepwiki.com/vishal2612200/agentpack"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
63
64
|
<a href="https://pypi.org/project/agentpack-cli/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/agentpack-cli.svg"></a>
|
|
64
65
|
<a href="https://pepy.tech/projects/agentpack-cli"><img alt="PyPI downloads" src="https://static.pepy.tech/personalized-badge/agentpack-cli?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads"></a>
|
|
65
66
|
<a href="https://www.npmjs.com/package/@vishal2612200/agentpack"><img alt="npm version" src="https://img.shields.io/npm/v/@vishal2612200/agentpack.svg"></a>
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
</p>
|
|
14
14
|
|
|
15
15
|
<p align="center">
|
|
16
|
+
<a href="https://deepwiki.com/vishal2612200/agentpack"><img src="https://deepwiki.com/badge.svg" alt="Ask DeepWiki"></a>
|
|
16
17
|
<a href="https://pypi.org/project/agentpack-cli/"><img alt="PyPI version" src="https://img.shields.io/pypi/v/agentpack-cli.svg"></a>
|
|
17
18
|
<a href="https://pepy.tech/projects/agentpack-cli"><img alt="PyPI downloads" src="https://static.pepy.tech/personalized-badge/agentpack-cli?period=total&units=INTERNATIONAL_SYSTEM&left_color=BLACK&right_color=GREEN&left_text=downloads"></a>
|
|
18
19
|
<a href="https://www.npmjs.com/package/@vishal2612200/agentpack"><img alt="npm version" src="https://img.shields.io/npm/v/@vishal2612200/agentpack.svg"></a>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "agentpack-cli"
|
|
3
|
-
version = "0.3.
|
|
3
|
+
version = "0.3.28"
|
|
4
4
|
description = "Local context engine for AI coding agents that ranks relevant repo files and builds compact task-focused context packs for Claude Code, Codex, Cursor, Windsurf, MCP, and CI workflows."
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
requires-python = ">=3.10"
|
|
@@ -9,6 +9,7 @@ from datetime import datetime, timezone
|
|
|
9
9
|
from pathlib import Path
|
|
10
10
|
from typing import Any
|
|
11
11
|
|
|
12
|
+
from agentpack import __version__
|
|
12
13
|
from agentpack.core.config import load_config
|
|
13
14
|
from agentpack.core.changed_paths import clear_changed_paths, read_changed_paths
|
|
14
15
|
from agentpack.core.ignore import DEFAULT_AGENTIGNORE, load_spec
|
|
@@ -16,6 +17,7 @@ from agentpack.core.scanner import scan, scan_incremental
|
|
|
16
17
|
from agentpack.core.snapshot import build_snapshot, save_snapshot, load_snapshot
|
|
17
18
|
from agentpack.core.diff import diff_snapshots
|
|
18
19
|
from agentpack.core import git
|
|
20
|
+
from agentpack.core.command_surface import refresh_commands
|
|
19
21
|
from agentpack.core.context_pack import enrich_call_site_scores, select_files, save_pack_metadata, load_pack_metadata
|
|
20
22
|
from agentpack.core.execution_state import build_execution_state, compact_execution_state
|
|
21
23
|
from agentpack.core.models import (
|
|
@@ -1575,7 +1577,12 @@ def _build_freshness_metadata(
|
|
|
1575
1577
|
) -> dict[str, Any]:
|
|
1576
1578
|
dirty = git.dirty_files(root) if git.is_git_repo(root) else set()
|
|
1577
1579
|
metadata: dict[str, Any] = {
|
|
1580
|
+
"agentpack_version": __version__,
|
|
1578
1581
|
"generated_at": datetime.now(timezone.utc).isoformat(),
|
|
1582
|
+
"cwd": str(Path.cwd()),
|
|
1583
|
+
"git_root": str(root),
|
|
1584
|
+
"worktree_path": str(root),
|
|
1585
|
+
"source_command": refresh_commands(request.agent).primary,
|
|
1579
1586
|
"task_source": request.task_source,
|
|
1580
1587
|
"changed_files_source": plan.changed_files_source,
|
|
1581
1588
|
"snapshot_root_hash": snapshot_root_hash,
|
|
@@ -166,6 +166,7 @@ class E2EResult:
|
|
|
166
166
|
expected_files_touched: list[str]
|
|
167
167
|
missing_expected_edits: list[str]
|
|
168
168
|
unexpected_files_touched: list[str]
|
|
169
|
+
agentpack_noise: list[str]
|
|
169
170
|
agent_log_path: str
|
|
170
171
|
test_log_path: str
|
|
171
172
|
workdir: str
|
|
@@ -3226,6 +3227,7 @@ def _e2e_strategy_metrics(records: list[dict[str, Any]], strategy: str) -> dict[
|
|
|
3226
3227
|
return {
|
|
3227
3228
|
"runs": float(len(subset)),
|
|
3228
3229
|
"success_rate": sum(1 for row in subset if row.get("passed")) / len(subset),
|
|
3230
|
+
"noise_rate": sum(1 for row in subset if row.get("agentpack_noise")) / len(subset),
|
|
3229
3231
|
"expected_touch_rate": expected_touch_rate,
|
|
3230
3232
|
"avg_input_tokens": avg("input_tokens"),
|
|
3231
3233
|
"avg_output_tokens": avg("agent_output_tokens"),
|
|
@@ -3285,6 +3287,7 @@ def _print_e2e_ab_table(
|
|
|
3285
3287
|
table.add_row("runs", f"{base['runs']:.0f}", f"{treat['runs']:.0f}", "-")
|
|
3286
3288
|
table.add_row("task success", f"{base['success_rate']:.0%}", f"{treat['success_rate']:.0%}", f"{deltas['success_rate_pp']:+.1f} pp")
|
|
3287
3289
|
table.add_row("expected file touched", f"{base['expected_touch_rate']:.0%}", f"{treat['expected_touch_rate']:.0%}", "-")
|
|
3290
|
+
table.add_row("AgentPack noise cases", f"{base['noise_rate']:.0%}", f"{treat['noise_rate']:.0%}", "-")
|
|
3288
3291
|
table.add_row("tool calls", f"{base['avg_tool_calls']:.1f}", f"{treat['avg_tool_calls']:.1f}", f"{deltas['tool_calls_saved']:+.1f}")
|
|
3289
3292
|
table.add_row("tokens", f"{base['avg_total_tokens']:,.0f}", f"{treat['avg_total_tokens']:,.0f}", f"{deltas['tokens_saved']:+,.0f}")
|
|
3290
3293
|
table.add_row("cost", f"${base['avg_total_cost_usd']:.4f}", f"${treat['avg_total_cost_usd']:.4f}", _fmt_signed_usd(deltas["token_cost_saved_usd"]))
|
|
@@ -3317,6 +3320,7 @@ def _e2e_ab_markdown(
|
|
|
3317
3320
|
f"| runs | {base['runs']:.0f} | {treat['runs']:.0f} | - |",
|
|
3318
3321
|
f"| task success | {base['success_rate']:.0%} | {treat['success_rate']:.0%} | {deltas['success_rate_pp']:+.1f} pp |",
|
|
3319
3322
|
f"| expected file touched | {base['expected_touch_rate']:.0%} | {treat['expected_touch_rate']:.0%} | - |",
|
|
3323
|
+
f"| AgentPack noise cases | {base['noise_rate']:.0%} | {treat['noise_rate']:.0%} | - |",
|
|
3320
3324
|
f"| tool calls | {base['avg_tool_calls']:.1f} | {treat['avg_tool_calls']:.1f} | {deltas['tool_calls_saved']:+.1f} |",
|
|
3321
3325
|
f"| tokens | {base['avg_total_tokens']:,.0f} | {treat['avg_total_tokens']:,.0f} | {deltas['tokens_saved']:+,.0f} |",
|
|
3322
3326
|
f"| token cost | ${base['avg_total_cost_usd']:.4f} | ${treat['avg_total_cost_usd']:.4f} | {_fmt_signed_usd(deltas['token_cost_saved_usd'])} |",
|
|
@@ -3410,6 +3414,7 @@ def _run_e2e_case(
|
|
|
3410
3414
|
expected_touched = _expected_files_touched(public_changed, case.expected_edit_paths)
|
|
3411
3415
|
missing_expected = sorted(set(case.expected_edit_paths) - set(expected_touched))
|
|
3412
3416
|
unexpected_touched = _unexpected_files_touched(public_changed, case.expected_edit_paths)
|
|
3417
|
+
agentpack_noise = _agentpack_noise(strategy, unexpected_touched, missing_expected, public_changed)
|
|
3413
3418
|
time_to_first_expected_file = _time_to_first_expected_file(repo, expected_touched, agent_start_epoch)
|
|
3414
3419
|
tool_calls = _estimate_agent_tool_calls(agent)
|
|
3415
3420
|
duration = time.perf_counter() - start
|
|
@@ -3442,6 +3447,7 @@ def _run_e2e_case(
|
|
|
3442
3447
|
expected_files_touched=expected_touched,
|
|
3443
3448
|
missing_expected_edits=missing_expected,
|
|
3444
3449
|
unexpected_files_touched=unexpected_touched,
|
|
3450
|
+
agentpack_noise=agentpack_noise,
|
|
3445
3451
|
agent_log_path=str(agent_log_path),
|
|
3446
3452
|
test_log_path=str(test_log_path),
|
|
3447
3453
|
workdir=str(work_root),
|
|
@@ -3495,6 +3501,20 @@ def _unexpected_files_touched(changed: list[str], expected_edit_paths: list[str]
|
|
|
3495
3501
|
return sorted(path for path in changed if path not in expected)
|
|
3496
3502
|
|
|
3497
3503
|
|
|
3504
|
+
def _agentpack_noise(strategy: str, unexpected: list[str], missing_expected: list[str], changed: list[str]) -> list[str]:
|
|
3505
|
+
if "agentpack" not in strategy:
|
|
3506
|
+
return []
|
|
3507
|
+
noise: list[str] = []
|
|
3508
|
+
if unexpected:
|
|
3509
|
+
noise.append(f"unexpected edits: {', '.join(unexpected[:5])}")
|
|
3510
|
+
if missing_expected:
|
|
3511
|
+
noise.append(f"missed expected files: {', '.join(missing_expected[:5])}")
|
|
3512
|
+
generated = [path for path in changed if _is_generated_e2e_path(path)]
|
|
3513
|
+
if generated:
|
|
3514
|
+
noise.append(f"generated AgentPack files changed: {', '.join(generated[:5])}")
|
|
3515
|
+
return noise
|
|
3516
|
+
|
|
3517
|
+
|
|
3498
3518
|
def _process_output_tokens(result: subprocess.CompletedProcess[str]) -> int:
|
|
3499
3519
|
return estimate_tokens("\n".join(part for part in (result.stdout, result.stderr) if part))
|
|
3500
3520
|
|
|
@@ -17,6 +17,7 @@ from agentpack.integrations.global_install import (
|
|
|
17
17
|
_detect_rc_file,
|
|
18
18
|
)
|
|
19
19
|
from agentpack.commands._shared import console, _root
|
|
20
|
+
from agentpack.core.command_surface import available_cli_commands, installed_cli_status, refresh_commands
|
|
20
21
|
from agentpack.core.context_pack import load_pack_metadata
|
|
21
22
|
from agentpack.core.ignore import agentignore_sync_status, format_import_summary
|
|
22
23
|
from agentpack.core.task_freshness import task_freshness
|
|
@@ -45,7 +46,12 @@ def register(app: typer.Typer) -> None:
|
|
|
45
46
|
|
|
46
47
|
# --- CLI binary ---
|
|
47
48
|
console.print("[bold]CLI[/]")
|
|
48
|
-
|
|
49
|
+
cli_status = installed_cli_status()
|
|
50
|
+
binary = cli_status.get("binary") or shutil.which("agentpack")
|
|
51
|
+
console.print(f" [green]✓[/] importable AgentPack version: {cli_status.get('agentpack_version')}")
|
|
52
|
+
importable = cli_status.get("importable_commands") or []
|
|
53
|
+
if importable:
|
|
54
|
+
console.print(f" [green]✓[/] importable commands: {', '.join(str(cmd) for cmd in importable)}")
|
|
49
55
|
if binary:
|
|
50
56
|
try:
|
|
51
57
|
result = subprocess.run(["agentpack", "--version"], capture_output=True, text=True)
|
|
@@ -56,6 +62,15 @@ def register(app: typer.Typer) -> None:
|
|
|
56
62
|
else:
|
|
57
63
|
console.print(" [red]✗[/] agentpack not on PATH — run: pipx install agentpack-cli")
|
|
58
64
|
ok = False
|
|
65
|
+
help_commands = cli_status.get("help_commands") or []
|
|
66
|
+
if help_commands:
|
|
67
|
+
console.print(f" [green]✓[/] installed CLI commands: {', '.join(str(cmd) for cmd in help_commands)}")
|
|
68
|
+
if binary and "guard" not in set(str(cmd) for cmd in help_commands) and "guard" in set(available_cli_commands()):
|
|
69
|
+
console.print(
|
|
70
|
+
" [yellow]![/] installed CLI command surface may be stale; "
|
|
71
|
+
f"exact repair: {cli_status.get('repair_command')}"
|
|
72
|
+
)
|
|
73
|
+
ok = False
|
|
59
74
|
|
|
60
75
|
try:
|
|
61
76
|
root = _root()
|
|
@@ -147,8 +162,19 @@ def register(app: typer.Typer) -> None:
|
|
|
147
162
|
"MCP get_context auto-refreshes this, or run: agentpack pack --task auto"
|
|
148
163
|
)
|
|
149
164
|
ok = False
|
|
165
|
+
meta = load_pack_metadata(root) or {}
|
|
166
|
+
freshness = meta.get("freshness") or {}
|
|
167
|
+
if freshness:
|
|
168
|
+
console.print(
|
|
169
|
+
" [green]✓[/] context provenance: "
|
|
170
|
+
f"task_source={freshness.get('task_source', 'unknown')}, "
|
|
171
|
+
f"git_root={freshness.get('git_root', root)}, "
|
|
172
|
+
f"worktree={freshness.get('worktree_path', root)}, "
|
|
173
|
+
f"branch={freshness.get('git_branch', 'unknown')}, "
|
|
174
|
+
f"generated={freshness.get('generated_at', 'unknown')}"
|
|
175
|
+
)
|
|
150
176
|
else:
|
|
151
|
-
console.print(" [yellow]![/] No context pack yet — write .agentpack/task.md, then run:
|
|
177
|
+
console.print(f" [yellow]![/] No context pack yet — write .agentpack/task.md, then run: {refresh_commands(agent).context_missing}")
|
|
152
178
|
|
|
153
179
|
# --- Agent-specific config ---
|
|
154
180
|
console.print("\n[bold]Agent config[/]")
|
|
@@ -249,6 +275,14 @@ def register(app: typer.Typer) -> None:
|
|
|
249
275
|
pass
|
|
250
276
|
if not _local_has_mcp and not _global_has_mcp:
|
|
251
277
|
console.print(" [yellow]![/] MCP server not registered — mcp__agentpack__* tools unavailable")
|
|
278
|
+
console.print(" [yellow]![/] exact repair: agentpack install --agent claude")
|
|
279
|
+
ok = False
|
|
280
|
+
else:
|
|
281
|
+
console.print(
|
|
282
|
+
" [green]✓[/] expected MCP tools: "
|
|
283
|
+
"readiness, route_task, pack_context, get_context, refresh, get_stats"
|
|
284
|
+
)
|
|
285
|
+
console.print(" [green]✓[/] live exposure proof: call MCP tool `readiness` from the agent host")
|
|
252
286
|
|
|
253
287
|
# --- Agent integration matrix ---
|
|
254
288
|
console.print("\n[bold]Agent integration audit[/]")
|
|
@@ -268,8 +302,7 @@ def register(app: typer.Typer) -> None:
|
|
|
268
302
|
ok = False
|
|
269
303
|
if not selected_ok:
|
|
270
304
|
console.print(
|
|
271
|
-
f" [yellow]![/]
|
|
272
|
-
f"agentpack guard --agent {selected} --repair-stale --refresh-context"
|
|
305
|
+
f" [yellow]![/] exact repair: {refresh_commands(selected).repair}"
|
|
273
306
|
)
|
|
274
307
|
|
|
275
308
|
# --- Concurrent threads ---
|
|
@@ -288,7 +321,7 @@ def register(app: typer.Typer) -> None:
|
|
|
288
321
|
if findings:
|
|
289
322
|
for finding in findings:
|
|
290
323
|
console.print(f" [yellow]![/] {finding}")
|
|
291
|
-
|
|
324
|
+
console.print(" [dim]warning only; keep these out of commits/releases.[/]")
|
|
292
325
|
else:
|
|
293
326
|
console.print(" [green]✓[/] no generated release-noise files staged or untracked")
|
|
294
327
|
|
|
@@ -7,6 +7,7 @@ import typer
|
|
|
7
7
|
from agentpack.commands._shared import console, _root, run_refresh
|
|
8
8
|
from agentpack.commands.diagnose_selection import build_selection_diagnosis, _markdown_report
|
|
9
9
|
from agentpack.commands.guard import _context_is_fresh
|
|
10
|
+
from agentpack.core.command_surface import refresh_commands
|
|
10
11
|
from agentpack.core.config import load_config
|
|
11
12
|
from agentpack.core.context_pack import load_pack_metadata
|
|
12
13
|
from agentpack.core.loop_protocol import load_loop_state
|
|
@@ -34,7 +35,7 @@ def register(app: typer.Typer) -> None:
|
|
|
34
35
|
stats = run_refresh(root, "auto", "balanced", 0)
|
|
35
36
|
if stats:
|
|
36
37
|
recommendations = [{"kind": "fixed", "command": "agentpack next", "reason": "refreshed stale context"}]
|
|
37
|
-
fixes.append({"kind": "stale_context", "command": "
|
|
38
|
+
fixes.append({"kind": "stale_context", "command": refresh_commands("auto").repair, "returncode": 0})
|
|
38
39
|
payload = {"recommendations": recommendations, "fixes": fixes, "ok": not recommendations}
|
|
39
40
|
if json_output:
|
|
40
41
|
typer.echo(json.dumps(payload, indent=2, sort_keys=True))
|
|
@@ -58,7 +59,7 @@ def _recommendations(root) -> list[dict[str, str]]:
|
|
|
58
59
|
items.append({"kind": "missing_task", "command": 'agentpack start "describe the task"', "reason": "no concrete task is set"})
|
|
59
60
|
fresh, reason = _context_is_fresh(root)
|
|
60
61
|
if not fresh:
|
|
61
|
-
items.append({"kind": "stale_context", "command": "
|
|
62
|
+
items.append({"kind": "stale_context", "command": refresh_commands("auto").repair, "reason": reason})
|
|
62
63
|
if _has_thread_conflicts(root):
|
|
63
64
|
items.append({"kind": "thread_conflict", "command": "agentpack threads --conflicts", "reason": "active threads overlap on this branch/worktree"})
|
|
64
65
|
if _pack_looks_noisy(root):
|
|
@@ -138,7 +139,7 @@ def _fix_all_safe(root, recommendations: list[dict[str, str]]) -> tuple[list[dic
|
|
|
138
139
|
stats = run_refresh(root, "auto", "balanced", 0)
|
|
139
140
|
fixes.append({
|
|
140
141
|
"kind": "stale_context",
|
|
141
|
-
"command": "
|
|
142
|
+
"command": refresh_commands("auto").repair,
|
|
142
143
|
"returncode": 0 if stats else 1,
|
|
143
144
|
})
|
|
144
145
|
recommendations = _recommendations(root)
|
|
@@ -17,6 +17,7 @@ from agentpack.analysis.ranking import suggest_task_rewrite
|
|
|
17
17
|
from agentpack.application.pack_service import PackRequest, PackService, PackResult
|
|
18
18
|
from agentpack.commands._shared import console, _root, _file_hash, _now_iso
|
|
19
19
|
from agentpack.core.changed_paths import record_changed_paths
|
|
20
|
+
from agentpack.core.command_surface import refresh_commands
|
|
20
21
|
from agentpack.core.modes import MODE_HELP, invalid_mode_message, is_requested_mode
|
|
21
22
|
from agentpack.integrations.agents import check_agent_integration, install_agent_integration
|
|
22
23
|
from agentpack.session.state import TASK_FILE, load_session, save_session, log_activity
|
|
@@ -314,7 +315,7 @@ def _agent_integration_warnings(result: PackResult) -> list[str]:
|
|
|
314
315
|
if not failing:
|
|
315
316
|
return []
|
|
316
317
|
return [
|
|
317
|
-
f"Agent integration needs repair ({agent}); run `
|
|
318
|
+
f"Agent integration needs repair ({agent}); run `{refresh_commands(agent).repair}`."
|
|
318
319
|
]
|
|
319
320
|
|
|
320
321
|
|
|
@@ -337,7 +338,7 @@ def _auto_repair_stale_agent_rules(agent: str) -> None:
|
|
|
337
338
|
except Exception as exc:
|
|
338
339
|
console.print(
|
|
339
340
|
f"[yellow]Stale AgentPack integration detected for {agent}; "
|
|
340
|
-
f"run `
|
|
341
|
+
f"run `{refresh_commands(agent).repair}`. ({exc})[/]"
|
|
341
342
|
)
|
|
342
343
|
|
|
343
344
|
|
|
@@ -6,6 +6,7 @@ from pathlib import Path
|
|
|
6
6
|
import typer
|
|
7
7
|
|
|
8
8
|
from agentpack.commands._shared import console, _root
|
|
9
|
+
from agentpack.core.command_surface import refresh_command_args
|
|
9
10
|
from agentpack.core.context_pack import load_pack_metadata
|
|
10
11
|
from agentpack.core.thread_context import resolve_thread_option, thread_paths
|
|
11
12
|
from agentpack.integrations.platform import cli_module_argv
|
|
@@ -42,9 +43,7 @@ def register(app: typer.Typer) -> None:
|
|
|
42
43
|
if workspace:
|
|
43
44
|
argv.extend(["--workspace", workspace])
|
|
44
45
|
else:
|
|
45
|
-
argv = cli_module_argv(
|
|
46
|
-
if budget:
|
|
47
|
-
argv.extend(["--budget", str(budget)])
|
|
46
|
+
argv = cli_module_argv(*refresh_command_args(agent, mode, budget))
|
|
48
47
|
if thread_id:
|
|
49
48
|
argv.extend(["--thread", thread_id])
|
|
50
49
|
result = subprocess.run(argv, cwd=root)
|
|
@@ -4,6 +4,7 @@ import typer
|
|
|
4
4
|
import shutil
|
|
5
5
|
|
|
6
6
|
from agentpack.core.config import load_config
|
|
7
|
+
from agentpack.core.command_surface import refresh_commands
|
|
7
8
|
from agentpack.core.ignore import load_spec
|
|
8
9
|
from agentpack.core.scanner import scan
|
|
9
10
|
from agentpack.core.snapshot import build_snapshot
|
|
@@ -98,4 +99,4 @@ def _print_deep_health(root, meta: dict | None) -> None:
|
|
|
98
99
|
if not check.ok:
|
|
99
100
|
failing.append(check)
|
|
100
101
|
if failing:
|
|
101
|
-
console.print(f" [yellow]![/]
|
|
102
|
+
console.print(f" [yellow]![/] Repair: {refresh_commands(agent).repair}")
|
|
@@ -7,6 +7,7 @@ from pathlib import Path
|
|
|
7
7
|
import typer
|
|
8
8
|
|
|
9
9
|
from agentpack.commands._shared import console, _root
|
|
10
|
+
from agentpack.core.command_surface import refresh_command_args
|
|
10
11
|
from agentpack.core.thread_context import resolve_thread_option, thread_paths
|
|
11
12
|
from agentpack.integrations.platform import cli_module_argv
|
|
12
13
|
from agentpack.session.state import TASK_FILE
|
|
@@ -47,7 +48,7 @@ def set_task(
|
|
|
47
48
|
task_text: str = typer.Argument(..., help="Task text to write."),
|
|
48
49
|
thread: str = typer.Option("", "--thread", help="Use thread-scoped task state."),
|
|
49
50
|
pack: bool = typer.Option(False, "--pack", help="Run agentpack pack after writing the task."),
|
|
50
|
-
guard: bool = typer.Option(False, "--guard", help="Run
|
|
51
|
+
guard: bool = typer.Option(False, "--guard", help="Run the installed refresh/repair command after writing."),
|
|
51
52
|
agent: str = typer.Option("auto", "--agent", help="Agent to pass to pack/guard."),
|
|
52
53
|
mode: str = typer.Option("balanced", "--mode", help="Pack/guard mode."),
|
|
53
54
|
) -> None:
|
|
@@ -63,7 +64,7 @@ def set_task(
|
|
|
63
64
|
|
|
64
65
|
thread_id = _thread_id(root, thread)
|
|
65
66
|
if guard:
|
|
66
|
-
_run_cli(
|
|
67
|
+
_run_cli(refresh_command_args(agent, mode), thread_id=thread_id)
|
|
67
68
|
elif pack:
|
|
68
69
|
_run_cli(["pack", "--agent", agent, "--task", "auto", "--mode", mode], thread_id=thread_id)
|
|
69
70
|
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import subprocess
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
|
|
7
|
+
from agentpack.commands._shared import console, _root
|
|
8
|
+
from agentpack.commands.install import (
|
|
9
|
+
_install_slash_command,
|
|
10
|
+
_print_global_template_results,
|
|
11
|
+
_print_install_results,
|
|
12
|
+
)
|
|
13
|
+
from agentpack.integrations import global_install as global_hooks
|
|
14
|
+
from agentpack.integrations.agents import SUPPORTED_AGENTS, expand_agents, install_agent_integration
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def register(app: typer.Typer) -> None:
|
|
18
|
+
@app.command()
|
|
19
|
+
def upgrade(
|
|
20
|
+
agent: str = typer.Option(
|
|
21
|
+
"auto",
|
|
22
|
+
"--agent",
|
|
23
|
+
help=f"Agent integration to refresh after package upgrade ({' | '.join(SUPPORTED_AGENTS)}).",
|
|
24
|
+
),
|
|
25
|
+
repair_existing_global_hooks: bool = typer.Option(
|
|
26
|
+
True,
|
|
27
|
+
"--repair-existing-global-hooks/--no-repair-existing-global-hooks",
|
|
28
|
+
help="Refresh already-installed global git/shell hooks after upgrading AgentPack.",
|
|
29
|
+
),
|
|
30
|
+
) -> None:
|
|
31
|
+
"""Refresh existing AgentPack repo/global integration surfaces after a package upgrade."""
|
|
32
|
+
root = _root()
|
|
33
|
+
if agent not in SUPPORTED_AGENTS:
|
|
34
|
+
console.print(f"[yellow]Unknown agent: {agent}. Supported: {', '.join(SUPPORTED_AGENTS)}[/]")
|
|
35
|
+
raise typer.Exit(1)
|
|
36
|
+
|
|
37
|
+
agents = expand_agents(agent, root)
|
|
38
|
+
if agent == "auto":
|
|
39
|
+
console.print(f"[dim]Auto-detected agent: {agents[0]}[/]")
|
|
40
|
+
|
|
41
|
+
for selected in agents:
|
|
42
|
+
console.print(f"\n[bold]{selected}[/]")
|
|
43
|
+
results = install_agent_integration(
|
|
44
|
+
root,
|
|
45
|
+
selected,
|
|
46
|
+
install_slash_command=_install_slash_command,
|
|
47
|
+
)
|
|
48
|
+
_print_install_results(selected, results)
|
|
49
|
+
|
|
50
|
+
if repair_existing_global_hooks:
|
|
51
|
+
_repair_existing_global_hooks()
|
|
52
|
+
|
|
53
|
+
console.print("\n[bold green]Upgrade integration refresh complete.[/]")
|
|
54
|
+
console.print(f" Verify with: [bold]agentpack doctor --agent {agent}[/]")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def _repair_existing_global_hooks() -> None:
|
|
58
|
+
repaired = False
|
|
59
|
+
if _global_git_templates_are_installed():
|
|
60
|
+
repaired = True
|
|
61
|
+
console.print("\n[bold]Refreshing existing global git template hooks...[/]")
|
|
62
|
+
hook_results = global_hooks.install_git_template_hooks()
|
|
63
|
+
_print_global_template_results(hook_results)
|
|
64
|
+
git_cfg_action = global_hooks.configure_git_template_dir(dry_run=False)
|
|
65
|
+
console.print(f"[green]git config --global init.templateDir {git_cfg_action}.[/]")
|
|
66
|
+
|
|
67
|
+
rc_file = global_hooks._detect_rc_file()
|
|
68
|
+
if rc_file is not None and rc_file.exists() and global_hooks._SHELL_MARKER_START in rc_file.read_text(encoding="utf-8"):
|
|
69
|
+
repaired = True
|
|
70
|
+
console.print("\n[bold]Refreshing existing shell cd hook...[/]")
|
|
71
|
+
action, path = global_hooks.install_shell_hook(rc_file)
|
|
72
|
+
if path is not None:
|
|
73
|
+
console.print(f"[green]{path} {action}.[/]")
|
|
74
|
+
|
|
75
|
+
if not repaired:
|
|
76
|
+
console.print("\n[dim]No existing global AgentPack hooks found to refresh.[/]")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _global_git_templates_are_installed() -> bool:
|
|
80
|
+
hooks_dir = global_hooks._GIT_TEMPLATE_DIR / "hooks"
|
|
81
|
+
for name in global_hooks._HOOK_SCRIPTS:
|
|
82
|
+
hook_path = hooks_dir / name
|
|
83
|
+
if hook_path.exists() and global_hooks._AGENTPACK_MARKER in hook_path.read_text(encoding="utf-8"):
|
|
84
|
+
return True
|
|
85
|
+
try:
|
|
86
|
+
result = subprocess.run(
|
|
87
|
+
["git", "config", "--global", "init.templateDir"],
|
|
88
|
+
capture_output=True,
|
|
89
|
+
text=True,
|
|
90
|
+
)
|
|
91
|
+
except Exception:
|
|
92
|
+
return False
|
|
93
|
+
return result.stdout.strip() == str(global_hooks._GIT_TEMPLATE_DIR)
|
|
@@ -10,6 +10,7 @@ import typer
|
|
|
10
10
|
|
|
11
11
|
from agentpack.commands._shared import console, _root, run_refresh
|
|
12
12
|
from agentpack.commands.guard import _context_is_fresh
|
|
13
|
+
from agentpack.core.command_surface import refresh_commands
|
|
13
14
|
from agentpack.core.config import load_config
|
|
14
15
|
from agentpack.core.loop_protocol import (
|
|
15
16
|
LoopCommandResult,
|
|
@@ -317,7 +318,7 @@ def _loop_finish_blockers(
|
|
|
317
318
|
{
|
|
318
319
|
"kind": "stale_context",
|
|
319
320
|
"message": f"Context is stale: {reason}",
|
|
320
|
-
"command": "
|
|
321
|
+
"command": refresh_commands("auto").repair,
|
|
321
322
|
}
|
|
322
323
|
)
|
|
323
324
|
return blockers
|
|
@@ -434,6 +435,7 @@ def _read_task(root: Path, thread: str) -> str:
|
|
|
434
435
|
|
|
435
436
|
def _refresh_loop_context(root: Path, agent: str, mode: str, budget: int, thread_id: str | None) -> LoopCommandResult:
|
|
436
437
|
stats = run_refresh(root, agent, mode, budget, thread_id=thread_id)
|
|
438
|
+
command = refresh_commands(agent).primary
|
|
437
439
|
if stats is None:
|
|
438
|
-
return LoopCommandResult(command=
|
|
439
|
-
return LoopCommandResult(command=
|
|
440
|
+
return LoopCommandResult(command=command, returncode=1, output_excerpt="context refresh failed")
|
|
441
|
+
return LoopCommandResult(command=command, returncode=0, output_excerpt=json.dumps(stats, sort_keys=True))
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import shutil
|
|
4
|
+
import subprocess
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
from typing import Iterable
|
|
7
|
+
|
|
8
|
+
from agentpack import __version__
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class RefreshCommands:
|
|
13
|
+
primary: str
|
|
14
|
+
context_missing: str
|
|
15
|
+
thread_auto: str | None
|
|
16
|
+
repair: str
|
|
17
|
+
used_guard: bool
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def available_cli_commands() -> tuple[str, ...]:
|
|
21
|
+
"""Return command names registered by the importable AgentPack CLI."""
|
|
22
|
+
try:
|
|
23
|
+
import typer.main
|
|
24
|
+
|
|
25
|
+
from agentpack.cli import app
|
|
26
|
+
|
|
27
|
+
click_cmd = typer.main.get_command(app)
|
|
28
|
+
return tuple(sorted(click_cmd.commands))
|
|
29
|
+
except Exception:
|
|
30
|
+
return ()
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def has_cli_command(command: str) -> bool:
|
|
34
|
+
return command in available_cli_commands()
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def refresh_commands(agent: str = "auto") -> RefreshCommands:
|
|
38
|
+
if has_cli_command("guard"):
|
|
39
|
+
base = f"agentpack guard --agent {agent} --repair-stale --refresh-context"
|
|
40
|
+
return RefreshCommands(
|
|
41
|
+
primary=base,
|
|
42
|
+
context_missing=base,
|
|
43
|
+
thread_auto=f"AGENTPACK_THREAD_ID=<stable-id> {base} --thread auto",
|
|
44
|
+
repair=base,
|
|
45
|
+
used_guard=True,
|
|
46
|
+
)
|
|
47
|
+
pack = f"agentpack pack --agent {agent} --task auto"
|
|
48
|
+
return RefreshCommands(
|
|
49
|
+
primary=pack,
|
|
50
|
+
context_missing='printf "%s\\n" "<task>" > .agentpack/task.md && ' + pack,
|
|
51
|
+
thread_auto=None,
|
|
52
|
+
repair="agentpack repair --agent " + agent if has_cli_command("repair") else pack,
|
|
53
|
+
used_guard=False,
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def refresh_command_args(agent: str = "auto", mode: str = "balanced", budget: int = 0) -> list[str]:
|
|
58
|
+
"""Return CLI argv parts for refreshing context with the current command surface."""
|
|
59
|
+
if has_cli_command("guard"):
|
|
60
|
+
args = ["guard", "--agent", agent, "--repair-stale", "--refresh-context", "--mode", mode]
|
|
61
|
+
else:
|
|
62
|
+
args = ["pack", "--agent", agent, "--task", "auto", "--mode", mode]
|
|
63
|
+
if budget:
|
|
64
|
+
args.extend(["--budget", str(budget)])
|
|
65
|
+
return args
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def fallback_agent_guidance() -> str:
|
|
69
|
+
return (
|
|
70
|
+
"If AgentPack tools are unavailable or context looks stale/wrong-worktree, "
|
|
71
|
+
"do not trust old pack output. Use direct `rg`, PR diff inspection, and target-file reads, "
|
|
72
|
+
"then run focused validation."
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def prompt_quality_guidance() -> str:
|
|
77
|
+
return (
|
|
78
|
+
"Prompt hygiene: for agent-mode coding work, prefer `Task`, `Files`, "
|
|
79
|
+
"`Acceptance criteria`, `Constraints`, `Validation`, and `Output` sections. "
|
|
80
|
+
"For short/simple questions, use Ask/Chat mode instead of agent mode. "
|
|
81
|
+
"Keep routine responses concise unless the user asks for detail."
|
|
82
|
+
)
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def installed_cli_status() -> dict[str, object]:
|
|
86
|
+
binary = shutil.which("agentpack")
|
|
87
|
+
status: dict[str, object] = {
|
|
88
|
+
"agentpack_version": __version__,
|
|
89
|
+
"binary": binary,
|
|
90
|
+
"importable_commands": list(available_cli_commands()),
|
|
91
|
+
}
|
|
92
|
+
if not binary:
|
|
93
|
+
status["available"] = False
|
|
94
|
+
status["repair_command"] = "pipx install agentpack-cli"
|
|
95
|
+
return status
|
|
96
|
+
try:
|
|
97
|
+
version = subprocess.run(
|
|
98
|
+
[binary, "--version"],
|
|
99
|
+
capture_output=True,
|
|
100
|
+
text=True,
|
|
101
|
+
timeout=5,
|
|
102
|
+
)
|
|
103
|
+
help_result = subprocess.run(
|
|
104
|
+
[binary, "--help"],
|
|
105
|
+
capture_output=True,
|
|
106
|
+
text=True,
|
|
107
|
+
timeout=5,
|
|
108
|
+
)
|
|
109
|
+
except (OSError, subprocess.TimeoutExpired) as exc:
|
|
110
|
+
status["available"] = False
|
|
111
|
+
status["error"] = str(exc)
|
|
112
|
+
status["repair_command"] = "pipx upgrade agentpack-cli"
|
|
113
|
+
return status
|
|
114
|
+
status["available"] = version.returncode == 0
|
|
115
|
+
status["installed_version"] = (version.stdout.strip() or version.stderr.strip())
|
|
116
|
+
status["help_commands"] = _commands_from_help(help_result.stdout + "\n" + help_result.stderr)
|
|
117
|
+
status["repair_command"] = "pipx upgrade agentpack-cli"
|
|
118
|
+
return status
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def _commands_from_help(text: str) -> list[str]:
|
|
122
|
+
commands: set[str] = set()
|
|
123
|
+
known = set(available_cli_commands())
|
|
124
|
+
for line in text.splitlines():
|
|
125
|
+
stripped = line.strip().strip("│").strip()
|
|
126
|
+
if not stripped:
|
|
127
|
+
continue
|
|
128
|
+
first = stripped.split()[0].strip("`")
|
|
129
|
+
if first in known:
|
|
130
|
+
commands.add(first)
|
|
131
|
+
return sorted(commands)
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def missing_commands(commands: Iterable[str]) -> list[str]:
|
|
135
|
+
available = set(available_cli_commands())
|
|
136
|
+
return sorted({cmd for cmd in commands if cmd and cmd not in available})
|
|
@@ -91,7 +91,18 @@ def save_pack_metadata(
|
|
|
91
91
|
"concurrent_context": concurrent_context or {},
|
|
92
92
|
}
|
|
93
93
|
if freshness:
|
|
94
|
-
for key in (
|
|
94
|
+
for key in (
|
|
95
|
+
"agentpack_version",
|
|
96
|
+
"source_command",
|
|
97
|
+
"cwd",
|
|
98
|
+
"git_root",
|
|
99
|
+
"worktree_path",
|
|
100
|
+
"git_sha",
|
|
101
|
+
"git_branch",
|
|
102
|
+
"task_source",
|
|
103
|
+
"changed_files_source",
|
|
104
|
+
"task_class",
|
|
105
|
+
):
|
|
95
106
|
if key in freshness:
|
|
96
107
|
meta[key] = freshness[key]
|
|
97
108
|
path = metadata_path or _metadata_path(root)
|