agentpack-cli 0.1.25__tar.gz → 0.1.26__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.25 → agentpack_cli-0.1.26}/PKG-INFO +10 -6
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/README.md +9 -5
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/pyproject.toml +1 -1
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/__init__.py +1 -1
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/hook_cmd.py +116 -7
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/stats.py +4 -1
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/status.py +27 -2
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/config.py +12 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/data/agentpack.md +5 -4
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/installers/antigravity.py +8 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/installers/codex.py +2 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/installers/cursor.py +9 -4
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/installers/windsurf.py +4 -2
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/renderers/markdown.py +3 -2
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/.gitignore +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/LICENSE +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/adapters/__init__.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/adapters/antigravity.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/adapters/base.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/adapters/claude.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/adapters/codex.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/adapters/cursor.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/adapters/detect.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/adapters/generic.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/adapters/windsurf.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/analysis/__init__.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/analysis/dependency_graph.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/analysis/go_imports.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/analysis/java_imports.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/analysis/js_ts_imports.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/analysis/python_imports.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/analysis/ranking.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/analysis/rust_imports.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/analysis/symbols.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/analysis/tests.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/application/__init__.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/application/pack_service.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/cli.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/__init__.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/_shared.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/benchmark.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/claude_cmd.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/diff.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/doctor.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/explain.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/init.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/install.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/mcp_cmd.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/monitor.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/pack.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/quickstart.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/scan.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/summarize.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/commands/watch.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/__init__.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/bootstrap.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/cache.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/context_pack.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/diff.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/git.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/git_hooks.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/global_install.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/ignore.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/merkle.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/models.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/redactor.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/scanner.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/snapshot.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/token_estimator.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/core/vscode_tasks.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/installers/__init__.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/installers/claude.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/integrations/__init__.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/integrations/git_hooks.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/integrations/global_install.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/integrations/vscode_tasks.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/mcp_server.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/renderers/__init__.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/renderers/compact.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/renderers/receipts.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/session/__init__.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/session/state.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/summaries/__init__.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/src/agentpack/summaries/base.py +0 -0
- {agentpack_cli-0.1.25 → agentpack_cli-0.1.26}/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.26
|
|
4
4
|
Summary: Task-aware context packing for AI coding agents — Claude, Cursor, Windsurf, Codex, and Antigravity
|
|
5
5
|
License: MIT
|
|
6
6
|
License-File: LICENSE
|
|
@@ -377,7 +377,7 @@ Configures:
|
|
|
377
377
|
- `CLAUDE.md` — tells Claude to read the context pack before each task
|
|
378
378
|
- `.claude/settings.json` — two hooks:
|
|
379
379
|
- `SessionStart`: clears injection sentinel so first prompt gets context
|
|
380
|
-
- `UserPromptSubmit`: runs `agentpack hook` — detects repo changes via `root_hash`, triggers background repack using your prompt as task. With MCP: emits Option-B hint (~100 tokens, task + top files). Without MCP: emits capped fallback (top 8 files, ≤3k chars)
|
|
380
|
+
- `UserPromptSubmit`: runs `agentpack hook` — detects repo changes via `root_hash`, detects clear task switches, updates `.agentpack/task.md`, and triggers background repack using your prompt as task. With MCP: emits Option-B hint (~100 tokens, task + top files). Without MCP: emits capped fallback (top 8 files, ≤3k chars)
|
|
381
381
|
|
|
382
382
|
After this, context is injected automatically into every Claude Code session. No `/agentpack` command needed — it just happens.
|
|
383
383
|
|
|
@@ -388,7 +388,7 @@ agentpack install --agent cursor
|
|
|
388
388
|
```
|
|
389
389
|
|
|
390
390
|
Configures:
|
|
391
|
-
- `.cursorrules` — rule: read `.agentpack/context.md`
|
|
391
|
+
- `.cursorrules` — rule: write current task, run `agentpack pack --task auto`, then read `.agentpack/context.md`
|
|
392
392
|
- `.cursor/rules/agentpack.mdc` — `alwaysApply: true` rule (Cursor v0.43+)
|
|
393
393
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
394
394
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
@@ -400,7 +400,7 @@ agentpack install --agent windsurf
|
|
|
400
400
|
```
|
|
401
401
|
|
|
402
402
|
Configures:
|
|
403
|
-
- `.windsurfrules` — rule: read `.agentpack/context.md`
|
|
403
|
+
- `.windsurfrules` — rule: write current task, run `agentpack pack --task auto`, then read `.agentpack/context.md`
|
|
404
404
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
405
405
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
406
406
|
|
|
@@ -411,7 +411,7 @@ agentpack install --agent codex
|
|
|
411
411
|
```
|
|
412
412
|
|
|
413
413
|
Configures:
|
|
414
|
-
- `AGENTS.md` — tells Codex to read the context pack before each task
|
|
414
|
+
- `AGENTS.md` — tells Codex to write current task, repack, and read the context pack before each task
|
|
415
415
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
416
416
|
|
|
417
417
|
### Antigravity
|
|
@@ -422,7 +422,7 @@ agentpack install --agent antigravity
|
|
|
422
422
|
|
|
423
423
|
Configures:
|
|
424
424
|
- `.agent/skills/agentpack/SKILL.md` — AgentPack context as a Skill; Antigravity activates it automatically for coding tasks
|
|
425
|
-
- `GEMINI.md` — registers the agentpack skill reference
|
|
425
|
+
- `GEMINI.md` — registers the agentpack skill reference and task-switch protocol
|
|
426
426
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
427
427
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
428
428
|
|
|
@@ -1063,6 +1063,10 @@ include_tests = true
|
|
|
1063
1063
|
include_configs = true
|
|
1064
1064
|
include_receipts = true
|
|
1065
1065
|
|
|
1066
|
+
[hooks]
|
|
1067
|
+
task_switch_detection = true
|
|
1068
|
+
task_switch_min_terms = 1
|
|
1069
|
+
|
|
1066
1070
|
[agents.claude]
|
|
1067
1071
|
output = ".agentpack/context.claude.md"
|
|
1068
1072
|
patch_claude_md = true
|
|
@@ -338,7 +338,7 @@ Configures:
|
|
|
338
338
|
- `CLAUDE.md` — tells Claude to read the context pack before each task
|
|
339
339
|
- `.claude/settings.json` — two hooks:
|
|
340
340
|
- `SessionStart`: clears injection sentinel so first prompt gets context
|
|
341
|
-
- `UserPromptSubmit`: runs `agentpack hook` — detects repo changes via `root_hash`, triggers background repack using your prompt as task. With MCP: emits Option-B hint (~100 tokens, task + top files). Without MCP: emits capped fallback (top 8 files, ≤3k chars)
|
|
341
|
+
- `UserPromptSubmit`: runs `agentpack hook` — detects repo changes via `root_hash`, detects clear task switches, updates `.agentpack/task.md`, and triggers background repack using your prompt as task. With MCP: emits Option-B hint (~100 tokens, task + top files). Without MCP: emits capped fallback (top 8 files, ≤3k chars)
|
|
342
342
|
|
|
343
343
|
After this, context is injected automatically into every Claude Code session. No `/agentpack` command needed — it just happens.
|
|
344
344
|
|
|
@@ -349,7 +349,7 @@ agentpack install --agent cursor
|
|
|
349
349
|
```
|
|
350
350
|
|
|
351
351
|
Configures:
|
|
352
|
-
- `.cursorrules` — rule: read `.agentpack/context.md`
|
|
352
|
+
- `.cursorrules` — rule: write current task, run `agentpack pack --task auto`, then read `.agentpack/context.md`
|
|
353
353
|
- `.cursor/rules/agentpack.mdc` — `alwaysApply: true` rule (Cursor v0.43+)
|
|
354
354
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
355
355
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
@@ -361,7 +361,7 @@ agentpack install --agent windsurf
|
|
|
361
361
|
```
|
|
362
362
|
|
|
363
363
|
Configures:
|
|
364
|
-
- `.windsurfrules` — rule: read `.agentpack/context.md`
|
|
364
|
+
- `.windsurfrules` — rule: write current task, run `agentpack pack --task auto`, then read `.agentpack/context.md`
|
|
365
365
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
366
366
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
367
367
|
|
|
@@ -372,7 +372,7 @@ agentpack install --agent codex
|
|
|
372
372
|
```
|
|
373
373
|
|
|
374
374
|
Configures:
|
|
375
|
-
- `AGENTS.md` — tells Codex to read the context pack before each task
|
|
375
|
+
- `AGENTS.md` — tells Codex to write current task, repack, and read the context pack before each task
|
|
376
376
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
377
377
|
|
|
378
378
|
### Antigravity
|
|
@@ -383,7 +383,7 @@ agentpack install --agent antigravity
|
|
|
383
383
|
|
|
384
384
|
Configures:
|
|
385
385
|
- `.agent/skills/agentpack/SKILL.md` — AgentPack context as a Skill; Antigravity activates it automatically for coding tasks
|
|
386
|
-
- `GEMINI.md` — registers the agentpack skill reference
|
|
386
|
+
- `GEMINI.md` — registers the agentpack skill reference and task-switch protocol
|
|
387
387
|
- `.git/hooks/post-commit`, `post-merge`, `post-checkout` — background repack on tree change
|
|
388
388
|
- `.vscode/tasks.json` — "AgentPack: Repack context" in Command Palette + `runOn: folderOpen`
|
|
389
389
|
|
|
@@ -1024,6 +1024,10 @@ include_tests = true
|
|
|
1024
1024
|
include_configs = true
|
|
1025
1025
|
include_receipts = true
|
|
1026
1026
|
|
|
1027
|
+
[hooks]
|
|
1028
|
+
task_switch_detection = true
|
|
1029
|
+
task_switch_min_terms = 1
|
|
1030
|
+
|
|
1027
1031
|
[agents.claude]
|
|
1028
1032
|
output = ".agentpack/context.claude.md"
|
|
1029
1033
|
patch_claude_md = true
|
|
@@ -10,6 +10,7 @@ import typer
|
|
|
10
10
|
|
|
11
11
|
from agentpack.commands._shared import _root
|
|
12
12
|
from agentpack.core import git as _git
|
|
13
|
+
from agentpack.core.config import load_config
|
|
13
14
|
|
|
14
15
|
_TASK_FILE = ".agentpack/task.md"
|
|
15
16
|
_TASK_FILE_DEFAULT_MARKER = "Write or update the current coding task here."
|
|
@@ -17,6 +18,37 @@ _CODING_PROMPT_RE = re.compile(
|
|
|
17
18
|
r"(?:fix|add|refactor|impl|implement|update|write|debug|test|build|migrate|remove|delete|rename|optimize)\b",
|
|
18
19
|
re.IGNORECASE,
|
|
19
20
|
)
|
|
21
|
+
_TASK_STOPWORDS = {
|
|
22
|
+
"add",
|
|
23
|
+
"all",
|
|
24
|
+
"and",
|
|
25
|
+
"bug",
|
|
26
|
+
"build",
|
|
27
|
+
"can",
|
|
28
|
+
"change",
|
|
29
|
+
"changes",
|
|
30
|
+
"code",
|
|
31
|
+
"delete",
|
|
32
|
+
"fix",
|
|
33
|
+
"for",
|
|
34
|
+
"implement",
|
|
35
|
+
"improve",
|
|
36
|
+
"make",
|
|
37
|
+
"please",
|
|
38
|
+
"refactor",
|
|
39
|
+
"remove",
|
|
40
|
+
"task",
|
|
41
|
+
"test",
|
|
42
|
+
"that",
|
|
43
|
+
"the",
|
|
44
|
+
"these",
|
|
45
|
+
"this",
|
|
46
|
+
"update",
|
|
47
|
+
"with",
|
|
48
|
+
"work",
|
|
49
|
+
"write",
|
|
50
|
+
"you",
|
|
51
|
+
}
|
|
20
52
|
|
|
21
53
|
|
|
22
54
|
def register(app: typer.Typer) -> None:
|
|
@@ -83,13 +115,66 @@ def _looks_like_coding_prompt(prompt: str) -> bool:
|
|
|
83
115
|
return bool(_CODING_PROMPT_RE.search(stripped))
|
|
84
116
|
|
|
85
117
|
|
|
86
|
-
def
|
|
118
|
+
def _prompt_task(prompt: str) -> str:
|
|
119
|
+
if not prompt or not _looks_like_coding_prompt(prompt):
|
|
120
|
+
return ""
|
|
121
|
+
task = " ".join(prompt.strip().split())[:200]
|
|
122
|
+
if not _task_terms(task):
|
|
123
|
+
return ""
|
|
124
|
+
return task
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def _task_terms(text: str) -> set[str]:
|
|
128
|
+
terms: set[str] = set()
|
|
129
|
+
for raw in re.findall(r"[A-Za-z0-9][A-Za-z0-9_-]*", text.lower()):
|
|
130
|
+
for part in re.split(r"[-_]", raw):
|
|
131
|
+
if len(part) >= 3 and part not in _TASK_STOPWORDS:
|
|
132
|
+
terms.add(part)
|
|
133
|
+
return terms
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def _looks_like_task_switch(current_task: str, prompt: str, min_terms: int = 1) -> bool:
|
|
137
|
+
"""Heuristic: a coding prompt with disjoint concrete terms likely starts a new task."""
|
|
138
|
+
prompt_task = _prompt_task(prompt)
|
|
139
|
+
if not current_task or not prompt_task:
|
|
140
|
+
return False
|
|
141
|
+
if current_task.strip().lower() == prompt_task.lower():
|
|
142
|
+
return False
|
|
143
|
+
current_terms = _task_terms(current_task)
|
|
144
|
+
prompt_terms = _task_terms(prompt_task)
|
|
145
|
+
required_terms = max(1, min_terms)
|
|
146
|
+
if len(current_terms) < required_terms or len(prompt_terms) < required_terms:
|
|
147
|
+
return False
|
|
148
|
+
return bool(current_terms and prompt_terms and current_terms.isdisjoint(prompt_terms))
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def _write_task_md(root: Path, task: str) -> None:
|
|
152
|
+
task_path = root / _TASK_FILE
|
|
153
|
+
task_path.parent.mkdir(parents=True, exist_ok=True)
|
|
154
|
+
task_path.write_text(task.strip() + "\n", encoding="utf-8")
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
def _resolve_task(
|
|
158
|
+
root: Path,
|
|
159
|
+
prompt: str,
|
|
160
|
+
*,
|
|
161
|
+
task_switch_detection: bool = True,
|
|
162
|
+
task_switch_min_terms: int = 1,
|
|
163
|
+
) -> str:
|
|
87
164
|
"""Merge task.md + prompt into best task description for repack."""
|
|
88
165
|
task_md = _load_task_md(root)
|
|
166
|
+
prompt_task = _prompt_task(prompt)
|
|
167
|
+
if (
|
|
168
|
+
task_switch_detection
|
|
169
|
+
and task_md
|
|
170
|
+
and prompt_task
|
|
171
|
+
and _looks_like_task_switch(task_md, prompt_task, min_terms=task_switch_min_terms)
|
|
172
|
+
):
|
|
173
|
+
return prompt_task
|
|
89
174
|
if task_md:
|
|
90
175
|
return task_md
|
|
91
|
-
if
|
|
92
|
-
return
|
|
176
|
+
if prompt_task:
|
|
177
|
+
return prompt_task
|
|
93
178
|
return "auto"
|
|
94
179
|
|
|
95
180
|
|
|
@@ -177,13 +262,37 @@ def _run_user_prompt_submit(root: Path) -> None:
|
|
|
177
262
|
except Exception:
|
|
178
263
|
prompt = ""
|
|
179
264
|
|
|
180
|
-
|
|
265
|
+
cfg = load_config(root)
|
|
266
|
+
task_md = _load_task_md(root)
|
|
267
|
+
task_switched = bool(
|
|
268
|
+
cfg.hooks.task_switch_detection
|
|
269
|
+
and _looks_like_task_switch(
|
|
270
|
+
task_md,
|
|
271
|
+
prompt,
|
|
272
|
+
min_terms=cfg.hooks.task_switch_min_terms,
|
|
273
|
+
)
|
|
274
|
+
)
|
|
275
|
+
task = _resolve_task(
|
|
276
|
+
root,
|
|
277
|
+
prompt,
|
|
278
|
+
task_switch_detection=cfg.hooks.task_switch_detection,
|
|
279
|
+
task_switch_min_terms=cfg.hooks.task_switch_min_terms,
|
|
280
|
+
)
|
|
281
|
+
if task_switched and task != "auto":
|
|
282
|
+
try:
|
|
283
|
+
_write_task_md(root, task)
|
|
284
|
+
except Exception:
|
|
285
|
+
pass
|
|
181
286
|
|
|
182
287
|
current_hash = _current_root_hash(root)
|
|
183
288
|
reminded_hash = snap_sentinel.read_text().strip() if snap_sentinel.exists() else None
|
|
184
289
|
repo_changed = current_hash != reminded_hash
|
|
290
|
+
packed_task = _load_pack_task(root)
|
|
291
|
+
pack_task_changed = bool(task != "auto" and packed_task and packed_task != task)
|
|
292
|
+
|
|
293
|
+
should_repack = repo_changed or task_switched or pack_task_changed
|
|
185
294
|
|
|
186
|
-
if
|
|
295
|
+
if should_repack:
|
|
187
296
|
subprocess.Popen(
|
|
188
297
|
["agentpack", "pack", "--task", task, "--mode", "balanced", "--since", "HEAD~1"],
|
|
189
298
|
stdout=subprocess.DEVNULL,
|
|
@@ -203,7 +312,7 @@ def _run_user_prompt_submit(root: Path) -> None:
|
|
|
203
312
|
f" - {h['path']}" + (f" — {h['why']}" if h.get("why") else "")
|
|
204
313
|
for h in hints
|
|
205
314
|
)
|
|
206
|
-
status_note = "(repacking — call pack_context for fresh results)" if
|
|
315
|
+
status_note = "(repacking — call pack_context for fresh results)" if should_repack else "(index fresh)"
|
|
207
316
|
current_task = _load_task_md(root) or _infer_live_task(root)
|
|
208
317
|
msg = (
|
|
209
318
|
f"AgentPack {status_note}\n"
|
|
@@ -224,7 +333,7 @@ def _run_user_prompt_submit(root: Path) -> None:
|
|
|
224
333
|
f" - {h['path']}" + (f" — {h['why']}" if h.get("why") else "")
|
|
225
334
|
for h in hints
|
|
226
335
|
)
|
|
227
|
-
changed_note = " (repacking in background)" if
|
|
336
|
+
changed_note = " (repacking in background)" if should_repack else ""
|
|
228
337
|
msg = (
|
|
229
338
|
f"AgentPack context{changed_note}\n"
|
|
230
339
|
f"task: {current_task}\n"
|
|
@@ -245,7 +245,10 @@ def _freshness_diagnostics(
|
|
|
245
245
|
|
|
246
246
|
task_md = _task_md_body(root)
|
|
247
247
|
if task_md and task_md != meta.get("task"):
|
|
248
|
-
diagnostics.append(
|
|
248
|
+
diagnostics.append(
|
|
249
|
+
".agentpack/task.md differs from the latest packed task "
|
|
250
|
+
f"(packed: {meta.get('task')}; current: {task_md})."
|
|
251
|
+
)
|
|
249
252
|
|
|
250
253
|
if meta.get("snapshot_root_hash") and meta.get("snapshot_root_hash") != current_root_hash:
|
|
251
254
|
diagnostics.append("Files changed since the latest pack; refresh before trusting top included files.")
|
|
@@ -11,6 +11,24 @@ from agentpack.application.pack_service import AdapterRegistry
|
|
|
11
11
|
from agentpack.commands._shared import console, _root
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
def _task_md_body(root) -> str:
|
|
15
|
+
path = root / ".agentpack" / "task.md"
|
|
16
|
+
if not path.exists():
|
|
17
|
+
return ""
|
|
18
|
+
try:
|
|
19
|
+
lines = [
|
|
20
|
+
line.strip()
|
|
21
|
+
for line in path.read_text(encoding="utf-8").splitlines()
|
|
22
|
+
if line.strip() and not line.startswith("#")
|
|
23
|
+
]
|
|
24
|
+
except OSError:
|
|
25
|
+
return ""
|
|
26
|
+
body = lines[0] if lines else ""
|
|
27
|
+
if "Write or update the current coding task here." in body:
|
|
28
|
+
return ""
|
|
29
|
+
return body
|
|
30
|
+
|
|
31
|
+
|
|
14
32
|
def register(app: typer.Typer) -> None:
|
|
15
33
|
@app.command()
|
|
16
34
|
def status() -> None:
|
|
@@ -32,12 +50,19 @@ def register(app: typer.Typer) -> None:
|
|
|
32
50
|
)
|
|
33
51
|
current = build_snapshot(scan_result.packable)
|
|
34
52
|
|
|
35
|
-
|
|
53
|
+
task_md = _task_md_body(root)
|
|
54
|
+
task_changed = bool(task_md and task_md != meta.get("task"))
|
|
55
|
+
if current["root_hash"] == meta.get("snapshot_root_hash") and not task_changed:
|
|
36
56
|
console.print("[green]Context pack is up to date.[/]")
|
|
37
57
|
console.print(f" Task: {meta.get('task')}")
|
|
38
58
|
console.print(f" Generated: {meta.get('generated_at')}")
|
|
39
59
|
else:
|
|
40
|
-
|
|
60
|
+
if task_changed:
|
|
61
|
+
console.print("[yellow]Context pack is STALE.[/] .agentpack/task.md changed since last pack.")
|
|
62
|
+
console.print(f" Packed task: {meta.get('task')}")
|
|
63
|
+
console.print(f" Current task: {task_md}")
|
|
64
|
+
else:
|
|
65
|
+
console.print("[yellow]Context pack is STALE.[/] Files changed since last pack.")
|
|
41
66
|
console.print(f" Last generated: {meta.get('generated_at')}")
|
|
42
67
|
console.print(" Run [bold]agentpack pack[/] to refresh.")
|
|
43
68
|
raise typer.Exit(1)
|
|
@@ -36,6 +36,11 @@ class SummaryConfig(BaseModel):
|
|
|
36
36
|
schema_version: int = 1
|
|
37
37
|
|
|
38
38
|
|
|
39
|
+
class HooksConfig(BaseModel):
|
|
40
|
+
task_switch_detection: bool = True
|
|
41
|
+
task_switch_min_terms: int = 1
|
|
42
|
+
|
|
43
|
+
|
|
39
44
|
class AgentConfig(BaseModel):
|
|
40
45
|
output: str
|
|
41
46
|
patch_claude_md: bool = False
|
|
@@ -78,6 +83,7 @@ class Config(BaseModel):
|
|
|
78
83
|
project: ProjectConfig = Field(default_factory=ProjectConfig)
|
|
79
84
|
context: ContextConfig = Field(default_factory=ContextConfig)
|
|
80
85
|
summary: SummaryConfig = Field(default_factory=SummaryConfig)
|
|
86
|
+
hooks: HooksConfig = Field(default_factory=HooksConfig)
|
|
81
87
|
agents: AgentsConfig = Field(default_factory=AgentsConfig)
|
|
82
88
|
scoring: ScoringWeights = Field(default_factory=ScoringWeights)
|
|
83
89
|
|
|
@@ -105,6 +111,12 @@ include_tests = true
|
|
|
105
111
|
include_configs = true
|
|
106
112
|
include_receipts = true
|
|
107
113
|
|
|
114
|
+
[hooks]
|
|
115
|
+
# Claude UserPromptSubmit can detect a clearly different coding prompt,
|
|
116
|
+
# update .agentpack/task.md, and repack even if files did not change.
|
|
117
|
+
task_switch_detection = true
|
|
118
|
+
task_switch_min_terms = 1
|
|
119
|
+
|
|
108
120
|
[scoring]
|
|
109
121
|
# Scoring weights — higher wins budget allocation.
|
|
110
122
|
# Tune these to make agentpack favour your team's file layout.
|
|
@@ -33,9 +33,9 @@ Pack repo context and immediately start working on the task.
|
|
|
33
33
|
|
|
34
34
|
If a session is already running (`.agentpack/session.json` exists and `"active": true`):
|
|
35
35
|
|
|
36
|
-
1.
|
|
37
|
-
2.
|
|
38
|
-
3.
|
|
36
|
+
1. If the user gives a new coding task, write a one-line summary to `.agentpack/task.md`.
|
|
37
|
+
2. Run `agentpack pack --task auto` unless watch mode already refreshed after the task write.
|
|
38
|
+
3. Read `.agentpack/context.md` — context now matches the current task.
|
|
39
39
|
4. Proceed with the task using the context you just read.
|
|
40
40
|
|
|
41
41
|
To start a session:
|
|
@@ -95,8 +95,9 @@ test -f .agentpack/config.toml || agentpack init --yes
|
|
|
95
95
|
### Step 3: Determine workflow
|
|
96
96
|
|
|
97
97
|
**Session active** (`.agentpack/session.json` exists, `"active": true`):
|
|
98
|
-
- Read `.agentpack/context.md`
|
|
99
98
|
- Update `.agentpack/task.md` if task changed
|
|
99
|
+
- Run `agentpack pack --task auto` unless watch already refreshed it
|
|
100
|
+
- Read `.agentpack/context.md`
|
|
100
101
|
- Proceed immediately
|
|
101
102
|
|
|
102
103
|
**No session**:
|
|
@@ -10,6 +10,14 @@ _GEMINI_BLOCK = """\
|
|
|
10
10
|
<!-- agentpack:block:start -->
|
|
11
11
|
skills:
|
|
12
12
|
- agentpack
|
|
13
|
+
|
|
14
|
+
At the start of every coding task:
|
|
15
|
+
1. Write a one-line task summary to `.agentpack/task.md` (overwrite the whole file).
|
|
16
|
+
2. Run `agentpack pack --task auto` to refresh context for that task.
|
|
17
|
+
3. Read `.agent/skills/agentpack/SKILL.md`.
|
|
18
|
+
4. Use files listed in context as starting points, but verify with actual code before editing.
|
|
19
|
+
|
|
20
|
+
When the user switches to a different coding task, repeat steps 1-3 before editing.
|
|
13
21
|
<!-- agentpack:block:end -->"""
|
|
14
22
|
|
|
15
23
|
_BLOCK_RE = re.compile(
|
|
@@ -15,6 +15,8 @@ At the start of every coding task:
|
|
|
15
15
|
2. Run `agentpack pack --task auto` to refresh context.
|
|
16
16
|
3. Read `.agentpack/context.md` — it lists the files most relevant to your task.
|
|
17
17
|
4. Use those files as starting points, but verify with actual code before editing.
|
|
18
|
+
|
|
19
|
+
When the user switches to a different coding task, repeat steps 1-3 before editing.
|
|
18
20
|
<!-- agentpack:end -->"""
|
|
19
21
|
|
|
20
22
|
_BLOCK_RE = re.compile(
|
|
@@ -10,8 +10,10 @@ _CURSOR_RULE = """\
|
|
|
10
10
|
<!-- agentpack:rule:start -->
|
|
11
11
|
At the start of every coding task:
|
|
12
12
|
1. Write a one-line task summary to `.agentpack/task.md` (overwrite the whole file).
|
|
13
|
-
2.
|
|
14
|
-
3.
|
|
13
|
+
2. Run `agentpack pack --task auto` to refresh context for that task.
|
|
14
|
+
3. Read `.agentpack/context.md`.
|
|
15
|
+
4. Use files listed in context as starting points, but verify with actual code before editing.
|
|
16
|
+
When the user switches to a different coding task, repeat steps 1-3 before editing.
|
|
15
17
|
If context is missing: `agentpack pack --agent cursor --task "<task>"`
|
|
16
18
|
<!-- agentpack:rule:end -->"""
|
|
17
19
|
|
|
@@ -58,8 +60,11 @@ alwaysApply: true
|
|
|
58
60
|
At the start of every coding task:
|
|
59
61
|
|
|
60
62
|
1. Write a one-line task summary to `.agentpack/task.md` (overwrite the whole file).
|
|
61
|
-
2.
|
|
62
|
-
3.
|
|
63
|
+
2. Run `agentpack pack --task auto` to refresh context for that task.
|
|
64
|
+
3. Read `.agentpack/context.md`.
|
|
65
|
+
4. Use files listed in context as starting points, but verify with actual code before editing.
|
|
66
|
+
|
|
67
|
+
When the user switches to a different coding task, repeat steps 1-3 before editing.
|
|
63
68
|
|
|
64
69
|
If context is missing: `agentpack pack --agent cursor --task "<task>"`
|
|
65
70
|
"""
|
|
@@ -10,8 +10,10 @@ _WINDSURF_RULE = """\
|
|
|
10
10
|
<!-- agentpack:rule:start -->
|
|
11
11
|
At the start of every coding task:
|
|
12
12
|
1. Write a one-line task summary to `.agentpack/task.md` (overwrite the whole file).
|
|
13
|
-
2.
|
|
14
|
-
3.
|
|
13
|
+
2. Run `agentpack pack --task auto` to refresh context for that task.
|
|
14
|
+
3. Read `.agentpack/context.md`.
|
|
15
|
+
4. Use files listed in context as starting points, but verify with actual code before editing.
|
|
16
|
+
When the user switches to a different coding task, repeat steps 1-3 before editing.
|
|
15
17
|
If context is missing: `agentpack pack --agent windsurf --task "<task>"`
|
|
16
18
|
<!-- agentpack:rule:end -->"""
|
|
17
19
|
|
|
@@ -104,8 +104,9 @@ def render_claude(pack: ContextPack) -> str:
|
|
|
104
104
|
"Priority order: changed files → keyword-matched files → dependencies → summaries.\n"
|
|
105
105
|
"Files marked `full` contain complete source. Files marked `symbols` contain relevant "
|
|
106
106
|
"function/class bodies. Files marked `summary` are unchanged context.\n"
|
|
107
|
-
"If
|
|
108
|
-
"
|
|
107
|
+
"If this pack's task does not match the user's current task, write the new task to "
|
|
108
|
+
"`.agentpack/task.md`, run `agentpack pack --task auto`, re-read the context, then proceed. "
|
|
109
|
+
"If the pack looks stale (changed files list is empty but you expect changes), refresh the pack before editing."
|
|
109
110
|
)
|
|
110
111
|
sections.append("")
|
|
111
112
|
|
|
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
|