ai-push-hooks 0.1.13 → 0.1.15
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.
package/README.md
CHANGED
|
@@ -24,9 +24,9 @@ pnpm add -D ai-push-hooks
|
|
|
24
24
|
|
|
25
25
|
Requirements:
|
|
26
26
|
|
|
27
|
-
- Python 3.10+ (`python3` or `python`) is required, including npm installs.
|
|
28
|
-
-
|
|
29
|
-
- `gh` is required only if you use PR creation via `gh_pr_create`.
|
|
27
|
+
- [Python 3.10+](https://www.python.org/downloads/) (`python3` or `python`) is required, including npm installs.
|
|
28
|
+
- [OpenCode CLI](https://github.com/sst/opencode) is required for `llm` and `apply` steps. The expected executable is `opencode`; `opencode-cli` is also accepted for compatibility.
|
|
29
|
+
- [GitHub CLI (`gh`)](https://cli.github.com/manual/installation) is required only if you use PR creation via `gh_pr_create`.
|
|
30
30
|
|
|
31
31
|
## Quick start
|
|
32
32
|
|
|
@@ -53,12 +53,12 @@ Requirements:
|
|
|
53
53
|
| Command | What it does |
|
|
54
54
|
| --- | --- |
|
|
55
55
|
| `ai-push-hooks hook <remote-name> <remote-url>` | Runs the configured pre-push workflow. |
|
|
56
|
-
| `ai-push-hooks init --template minimal-docs` | Writes
|
|
56
|
+
| `ai-push-hooks init --template minimal-docs` | Writes `ai-push-hooks.toml` starter config. |
|
|
57
57
|
| `ai-push-hooks init --template minimal-docs --force` | Overwrites an existing config file. |
|
|
58
58
|
|
|
59
59
|
## Configuration overview
|
|
60
60
|
|
|
61
|
-
- Config file lookup order:
|
|
61
|
+
- Config file lookup order: `ai-push-hooks.toml`, then `.ai-push-hooks.toml` (legacy).
|
|
62
62
|
- If no config file is present, built-in defaults are used.
|
|
63
63
|
- File values are deep-merged over defaults.
|
|
64
64
|
- Prompt resolution precedence for `llm` and `apply` steps:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-push-hooks",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "Modular AI push-hook workflow runner",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"run.sh",
|
|
21
21
|
"pyproject.toml",
|
|
22
22
|
"LICENSE",
|
|
23
|
-
"
|
|
23
|
+
"ai-push-hooks.toml"
|
|
24
24
|
],
|
|
25
25
|
"engines": {
|
|
26
26
|
"node": ">=18"
|
package/pyproject.toml
CHANGED
package/src/ai_push_hooks/cli.py
CHANGED
|
@@ -27,9 +27,11 @@ def init_config(template: str, force: bool, cwd: pathlib.Path | None = None) ->
|
|
|
27
27
|
if template != "minimal-docs":
|
|
28
28
|
raise HookError("Only `minimal-docs` is supported")
|
|
29
29
|
target_dir = cwd or pathlib.Path.cwd()
|
|
30
|
-
config_path = target_dir / "
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
config_path = target_dir / "ai-push-hooks.toml"
|
|
31
|
+
legacy_path = target_dir / ".ai-push-hooks.toml"
|
|
32
|
+
existing_path = config_path if config_path.exists() else legacy_path if legacy_path.exists() else None
|
|
33
|
+
if existing_path is not None and not force:
|
|
34
|
+
raise HookError(f"Refusing to overwrite existing config without --force: {existing_path}")
|
|
33
35
|
config_path.write_text(MINIMAL_DOCS_TEMPLATE, encoding="utf-8")
|
|
34
36
|
sys.stdout.write(str(config_path) + "\n")
|
|
35
37
|
return 0
|
|
@@ -318,7 +318,7 @@ def _apply_env_overrides(config: HookConfig) -> HookConfig:
|
|
|
318
318
|
def load_config(repo_root: pathlib.Path) -> tuple[HookConfig, pathlib.Path | None]:
|
|
319
319
|
config_path: pathlib.Path | None = None
|
|
320
320
|
raw = copy.deepcopy(DEFAULT_CONFIG_RAW)
|
|
321
|
-
for candidate in [repo_root / "
|
|
321
|
+
for candidate in [repo_root / "ai-push-hooks.toml", repo_root / ".ai-push-hooks.toml"]:
|
|
322
322
|
if candidate.exists():
|
|
323
323
|
config_path = candidate
|
|
324
324
|
text = candidate.read_text(encoding="utf-8")
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
3
|
import json
|
|
4
|
-
import os
|
|
5
4
|
import pathlib
|
|
6
5
|
import re
|
|
7
6
|
import shutil
|
|
@@ -26,24 +25,14 @@ def sanitize_filename_component(value: str) -> str:
|
|
|
26
25
|
return cleaned.strip("-") or "value"
|
|
27
26
|
|
|
28
27
|
|
|
29
|
-
def prefer_opencode_cli_candidate(candidate: str) -> str:
|
|
30
|
-
path = pathlib.Path(candidate)
|
|
31
|
-
if path.name != "opencode":
|
|
32
|
-
return candidate
|
|
33
|
-
sibling = path.with_name("opencode-cli")
|
|
34
|
-
if sibling.exists() and os.access(sibling, os.X_OK):
|
|
35
|
-
return str(sibling)
|
|
36
|
-
return candidate
|
|
37
|
-
|
|
38
|
-
|
|
39
28
|
def resolve_opencode_executable() -> str:
|
|
29
|
+
opencode_path = shutil.which("opencode")
|
|
30
|
+
if opencode_path:
|
|
31
|
+
return opencode_path
|
|
40
32
|
cli_path = shutil.which("opencode-cli")
|
|
41
33
|
if cli_path:
|
|
42
34
|
return cli_path
|
|
43
|
-
|
|
44
|
-
if opencode_path:
|
|
45
|
-
return prefer_opencode_cli_candidate(opencode_path)
|
|
46
|
-
raise HookError("opencode is required but not installed")
|
|
35
|
+
raise HookError("opencode (or opencode-cli) is required but not installed")
|
|
47
36
|
|
|
48
37
|
|
|
49
38
|
def parse_opencode_json_run_output(raw: str) -> tuple[str | None, str]:
|
|
File without changes
|