aicp-cli 0.3.0__tar.gz → 0.3.1__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.
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/CHANGELOG.md +16 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/PKG-INFO +14 -19
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/README.md +13 -18
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/pyproject.toml +1 -1
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/menu.py +10 -1
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_menu.py +10 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/uv.lock +1 -1
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/.github/workflows/ci.yml +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/.github/workflows/release.yml +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/.gitignore +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/LICENSE +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/TODO.md +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/config.example.json +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/docs/images/aicp-run.png +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/skills/commit.md +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/skills/safe-git-push/SKILL.md +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/skills/safe-git-push/scripts/safe_push.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/__init__.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/_keyreader.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/_utils.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/budget.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/cli.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/config.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/contracts.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/gitflow.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/i18n.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/notify.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/present.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/quota.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/runner.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/secrets.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/skills.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/src/aicp/timing.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/conftest.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_budget.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_cli.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_config.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_cross_platform.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_gitflow.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_i18n.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_menu_skills.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_notify.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_present.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_quota.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_runner.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_secrets.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_skills.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_timing.py +0 -0
- {aicp_cli-0.3.0 → aicp_cli-0.3.1}/tests/test_undo.py +0 -0
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
## [0.3.1] - 2026-09-14
|
|
2
|
+
|
|
3
|
+
### 🐛 Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **menu:** Stop config panel resizing on row selection
|
|
6
|
+
|
|
7
|
+
### 📚 Documentation
|
|
8
|
+
|
|
9
|
+
- **readme:** Document releasing and the wheel version check
|
|
10
|
+
- Remove CI section from README.md
|
|
11
|
+
- Add uv requirement note to README.md
|
|
1
12
|
## [0.3.0] - 2026-09-14
|
|
2
13
|
|
|
3
14
|
### 🐛 Bug Fixes
|
|
@@ -16,8 +27,13 @@
|
|
|
16
27
|
|
|
17
28
|
- **release:** Publish wheels to PyPI via trusted publishing
|
|
18
29
|
- Assert the built wheel reports the right version
|
|
30
|
+
- **release:** V0.3.0
|
|
19
31
|
## [0.2.1] - 2026-09-13
|
|
20
32
|
|
|
33
|
+
### 📚 Documentation
|
|
34
|
+
|
|
35
|
+
- **changelog:** Release v0.2.1
|
|
36
|
+
|
|
21
37
|
### ⚙️ Miscellaneous Tasks
|
|
22
38
|
|
|
23
39
|
- Refresh uv lockfile for v0.2.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: aicp-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.1
|
|
4
4
|
Summary: AI commit + push, with a git-verified result summary
|
|
5
5
|
Project-URL: Repository, https://github.com/weskao/aicp
|
|
6
6
|
Project-URL: Issues, https://github.com/weskao/aicp/issues
|
|
@@ -36,6 +36,7 @@ push that never reached the remote.
|
|
|
36
36
|
## Requirements
|
|
37
37
|
|
|
38
38
|
- Python 3.10 or newer
|
|
39
|
+
- [`uv`](https://docs.astral.sh/uv/) — the install path below
|
|
39
40
|
- `git`
|
|
40
41
|
- At least one of the six AI CLIs above on `PATH`
|
|
41
42
|
|
|
@@ -178,27 +179,21 @@ that, and even then the original is moved aside to `<name>.bak` (numbered
|
|
|
178
179
|
`.bak.1`, `.bak.2`, … so a second forced install never clobbers the first
|
|
179
180
|
backup) before aicp writes its own copy.
|
|
180
181
|
|
|
181
|
-
###
|
|
182
|
+
### Releasing
|
|
182
183
|
|
|
183
|
-
`.github/workflows/
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
184
|
+
`.github/workflows/release.yml` runs on a `v*` tag. It repeats the full
|
|
185
|
+
lint/test/build pass, installs the wheel into a throwaway venv, and refuses to
|
|
186
|
+
upload unless that wheel reports the version being tagged — so a tag that
|
|
187
|
+
disagrees with `pyproject.toml` fails before anything reaches PyPI. It then
|
|
188
|
+
publishes with Trusted Publishing (OIDC — there is no API token stored in this
|
|
189
|
+
repo) and attaches the wheel, sdist and `SHA256SUMS` to the GitHub release.
|
|
187
190
|
|
|
188
|
-
|
|
189
|
-
|
|
191
|
+
Checksums are generated *after* publishing on purpose: `uv publish` uploads
|
|
192
|
+
everything in `dist/`, and `SHA256SUMS` is not a distribution.
|
|
190
193
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
```sh
|
|
196
|
-
gh secret set TELEGRAM_BOT_TOKEN -R <owner>/<repo> # paste the bot token
|
|
197
|
-
gh secret set TELEGRAM_CHAT_ID -R <owner>/<repo> # paste the chat id
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
Verify with `gh secret list -R <owner>/<repo>` — GitHub shows the names and
|
|
201
|
-
timestamps only; secret values can never be read back, by you or by CI logs.
|
|
194
|
+
A tag runs the workflow file **as it existed at that tag**, so a release that
|
|
195
|
+
failed to publish can't be repaired by re-running the old tag — the fix isn't
|
|
196
|
+
in that tree. Bump the version and tag again.
|
|
202
197
|
|
|
203
198
|
## Configuration
|
|
204
199
|
|
|
@@ -24,6 +24,7 @@ push that never reached the remote.
|
|
|
24
24
|
## Requirements
|
|
25
25
|
|
|
26
26
|
- Python 3.10 or newer
|
|
27
|
+
- [`uv`](https://docs.astral.sh/uv/) — the install path below
|
|
27
28
|
- `git`
|
|
28
29
|
- At least one of the six AI CLIs above on `PATH`
|
|
29
30
|
|
|
@@ -166,27 +167,21 @@ that, and even then the original is moved aside to `<name>.bak` (numbered
|
|
|
166
167
|
`.bak.1`, `.bak.2`, … so a second forced install never clobbers the first
|
|
167
168
|
backup) before aicp writes its own copy.
|
|
168
169
|
|
|
169
|
-
###
|
|
170
|
+
### Releasing
|
|
170
171
|
|
|
171
|
-
`.github/workflows/
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
172
|
+
`.github/workflows/release.yml` runs on a `v*` tag. It repeats the full
|
|
173
|
+
lint/test/build pass, installs the wheel into a throwaway venv, and refuses to
|
|
174
|
+
upload unless that wheel reports the version being tagged — so a tag that
|
|
175
|
+
disagrees with `pyproject.toml` fails before anything reaches PyPI. It then
|
|
176
|
+
publishes with Trusted Publishing (OIDC — there is no API token stored in this
|
|
177
|
+
repo) and attaches the wheel, sdist and `SHA256SUMS` to the GitHub release.
|
|
175
178
|
|
|
176
|
-
|
|
177
|
-
|
|
179
|
+
Checksums are generated *after* publishing on purpose: `uv publish` uploads
|
|
180
|
+
everything in `dist/`, and `SHA256SUMS` is not a distribution.
|
|
178
181
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
```sh
|
|
184
|
-
gh secret set TELEGRAM_BOT_TOKEN -R <owner>/<repo> # paste the bot token
|
|
185
|
-
gh secret set TELEGRAM_CHAT_ID -R <owner>/<repo> # paste the chat id
|
|
186
|
-
```
|
|
187
|
-
|
|
188
|
-
Verify with `gh secret list -R <owner>/<repo>` — GitHub shows the names and
|
|
189
|
-
timestamps only; secret values can never be read back, by you or by CI logs.
|
|
182
|
+
A tag runs the workflow file **as it existed at that tag**, so a release that
|
|
183
|
+
failed to publish can't be repaired by re-running the old tag — the fix isn't
|
|
184
|
+
in that tree. Bump the version and tag again.
|
|
190
185
|
|
|
191
186
|
## Configuration
|
|
192
187
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# PyPI distribution name only — the `aicp` name was taken in 2021 by an
|
|
3
3
|
# unrelated project. The command, import path and repo stay `aicp`.
|
|
4
4
|
name = "aicp-cli"
|
|
5
|
-
version = "0.3.
|
|
5
|
+
version = "0.3.1"
|
|
6
6
|
description = "AI commit + push, with a git-verified result summary"
|
|
7
7
|
readme = "README.md"
|
|
8
8
|
requires-python = ">=3.10"
|
|
@@ -653,8 +653,17 @@ def _panel(
|
|
|
653
653
|
)
|
|
654
654
|
title = f"{_t(state.lang, 'config_title', 'aicp config')} (v{__version__})"
|
|
655
655
|
if selected is not None:
|
|
656
|
+
# Reserve the widest help line ANY row can show, not just the selected
|
|
657
|
+
# one's — otherwise the frame narrows and widens as the cursor moves
|
|
658
|
+
# across rows with shorter and longer help text (render_panel sizes
|
|
659
|
+
# its own width off the notes it is handed).
|
|
660
|
+
help_budget = frame_columns - 4
|
|
661
|
+
fitted_help = [_fit(_t(state.lang, *row.help), help_budget) for row in ROWS]
|
|
662
|
+
reserve = max(width(h) for h in fitted_help)
|
|
663
|
+
help_line = fitted_help[selected - 1]
|
|
664
|
+
help_line += " " * (reserve - width(help_line))
|
|
656
665
|
texts = [
|
|
657
|
-
|
|
666
|
+
help_line,
|
|
658
667
|
"",
|
|
659
668
|
_t(state.lang, "config_keys_tui", "↑↓ select · ←→ change · ⏎ change/run · q/Ctrl-C quit · saves as you go"),
|
|
660
669
|
]
|
|
@@ -146,6 +146,16 @@ def test_cli_order_motion_runs_the_other_way_too():
|
|
|
146
146
|
assert _plain(frames[-1]) == " → ".join(after)
|
|
147
147
|
|
|
148
148
|
|
|
149
|
+
def test_selecting_a_different_row_does_not_resize_the_panel():
|
|
150
|
+
"""Rows carry help text of very different lengths — the box must be sized
|
|
151
|
+
for the longest one up front, not reflow as the cursor passes each row."""
|
|
152
|
+
state = MenuState(Path("menu.aicprc"), True, True, "en", list(ROSTER_NAMES))
|
|
153
|
+
|
|
154
|
+
widths = {width(_panel(state, selected=i)[0]) for i in range(1, len(ROWS) + 1)}
|
|
155
|
+
|
|
156
|
+
assert len(widths) == 1, "the frame width changed when a different row was selected"
|
|
157
|
+
|
|
158
|
+
|
|
149
159
|
@pytest.mark.parametrize("columns, lines", [(80, 24), (100, 24), (60, 24), (100, 14)])
|
|
150
160
|
def test_the_panel_fits_the_terminal_it_draws_on(columns, lines, monkeypatch):
|
|
151
161
|
"""Every line inside the terminal, in both languages.
|
|
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
|