nanoPyCodeAgent 0.1.0__tar.gz → 0.3.0__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.
- nanopycodeagent-0.3.0/.agents/skills/land-pr/SKILL.md +85 -0
- nanopycodeagent-0.3.0/.agents/skills/release/SKILL.md +89 -0
- nanopycodeagent-0.3.0/.agents/skills/release/scripts/verify-release.sh +71 -0
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/.github/workflows/release.yml +7 -3
- nanopycodeagent-0.3.0/AGENTS.md +73 -0
- nanopycodeagent-0.3.0/CLAUDE.md +1 -0
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/PKG-INFO +32 -1
- nanopycodeagent-0.3.0/README.md +82 -0
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/README.zh-CN.md +29 -0
- nanopycodeagent-0.3.0/docs/RELEASING.md +33 -0
- nanopycodeagent-0.3.0/docs/changelogs/0.1.x.md +32 -0
- nanopycodeagent-0.3.0/docs/changelogs/0.2.x.md +23 -0
- nanopycodeagent-0.3.0/docs/changelogs/0.3.x.md +22 -0
- nanopycodeagent-0.3.0/docs/dev_notes/en/0.2.x.md +24 -0
- nanopycodeagent-0.3.0/docs/dev_notes/en/0.3.x.md +49 -0
- nanopycodeagent-0.3.0/docs/dev_notes/zh-CN/0.2.x.md +24 -0
- nanopycodeagent-0.3.0/docs/dev_notes/zh-CN/0.3.x.md +49 -0
- nanopycodeagent-0.3.0/docs/superpowers/plans/2026-06-21-release-skills.md +661 -0
- nanopycodeagent-0.3.0/docs/superpowers/specs/2026-06-21-release-skill-design.md +240 -0
- nanopycodeagent-0.3.0/docs/superpowers/specs/2026-06-29-config-file-support-design.md +124 -0
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/pyproject.toml +11 -1
- nanopycodeagent-0.3.0/src/nanopycodeagent/__init__.py +5 -0
- nanopycodeagent-0.3.0/src/nanopycodeagent/agent.py +181 -0
- nanopycodeagent-0.3.0/tests/test_agent.py +512 -0
- nanopycodeagent-0.3.0/uv.lock +350 -0
- nanopycodeagent-0.1.0/README.md +0 -52
- nanopycodeagent-0.1.0/docs/changelogs/0.1.x.md +0 -25
- nanopycodeagent-0.1.0/src/nanopycodeagent/__init__.py +0 -2
- nanopycodeagent-0.1.0/uv.lock +0 -7
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/.gitignore +0 -0
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/.python-version +0 -0
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/LICENSE +0 -0
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/docs/changelogs/README.md +0 -0
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/docs/dev_notes/README.md +0 -0
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/docs/dev_notes/en/0.1.x.md +0 -0
- {nanopycodeagent-0.1.0 → nanopycodeagent-0.3.0}/docs/dev_notes/zh-CN/0.1.x.md +0 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: land-pr
|
|
3
|
+
description: >
|
|
4
|
+
Use when merging a feature/bugfix PR into main — the everyday, no-release flow.
|
|
5
|
+
Makes the PR self-contained: rewrites the PR description from the PR's own
|
|
6
|
+
contents, appends a changelog [Unreleased] entry when warranted, regenerates the
|
|
7
|
+
English dev notes from the Chinese source when touched, and keeps the bilingual
|
|
8
|
+
README in sync. Then — only after explicit maintainer confirmation — merges the
|
|
9
|
+
PR. Does NOT tag or publish. Triggers on
|
|
10
|
+
"合并 PR / land PR / 合并这个 PR / merge this PR".
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Land a PR
|
|
14
|
+
|
|
15
|
+
Merge a feature/bugfix PR into `main`, making the PR **self-contained** first:
|
|
16
|
+
its code, changelog entry, dev notes (zh + en), and README (zh + en) all in sync
|
|
17
|
+
within the PR. This skill never tags or publishes — that is the `release` skill's job.
|
|
18
|
+
|
|
19
|
+
## Prerequisites
|
|
20
|
+
|
|
21
|
+
`git` and `gh` (authenticated). See `docs/RELEASING.md`.
|
|
22
|
+
|
|
23
|
+
## Steps
|
|
24
|
+
|
|
25
|
+
Work on the PR's feature branch (not `main`). `<series>` is the current series
|
|
26
|
+
file, e.g. `docs/changelogs/0.1.x.md` / `docs/dev_notes/{zh-CN,en}/0.1.x.md`.
|
|
27
|
+
|
|
28
|
+
### 1. Preflight — stop if any check fails
|
|
29
|
+
- `command -v git gh` — present.
|
|
30
|
+
- `gh auth status` — authenticated.
|
|
31
|
+
- `git status --porcelain` — empty (clean tree).
|
|
32
|
+
- current branch is **not** `main` (`git branch --show-current`).
|
|
33
|
+
|
|
34
|
+
### 2. Ensure a PR exists
|
|
35
|
+
```bash
|
|
36
|
+
gh pr view --json number,url 2>/dev/null || gh pr create --fill
|
|
37
|
+
```
|
|
38
|
+
Note the PR number for later steps.
|
|
39
|
+
|
|
40
|
+
### 3. Append a changelog entry (when warranted)
|
|
41
|
+
Inspect `git diff main...HEAD`. If the changes are worth recording for users, add
|
|
42
|
+
an entry under `## [Unreleased]` in `<series>` (changelogs) in the right group
|
|
43
|
+
(Added / Changed / Fixed / Removed). Purely internal/tooling changes may need
|
|
44
|
+
**no** entry — decide, and surface the decision at the gate.
|
|
45
|
+
|
|
46
|
+
### 4. Sync English dev notes (if the Chinese source changed)
|
|
47
|
+
If this PR modified `docs/dev_notes/zh-CN/<series>.md`, regenerate the whole
|
|
48
|
+
`docs/dev_notes/en/<series>.md` by translating the Chinese source. The English
|
|
49
|
+
file is generated — do not hand-edit beyond this regeneration.
|
|
50
|
+
|
|
51
|
+
### 5. Keep the bilingual README in sync
|
|
52
|
+
If this PR changed only one of `README.md` / `README.zh-CN.md`, mirror the change
|
|
53
|
+
into the other (translate/align) so the pair stays consistent. Both READMEs are
|
|
54
|
+
hand-written sources — propose the synced change and let the maintainer adjust the
|
|
55
|
+
wording at the gate; do not blindly overwrite. If both were already changed, skip.
|
|
56
|
+
|
|
57
|
+
### 6. Commit and push the sync changes
|
|
58
|
+
Commit any changes from steps 3–5 to the feature branch and push:
|
|
59
|
+
```bash
|
|
60
|
+
git commit -am "docs: sync changelog/dev-notes/README for this PR"
|
|
61
|
+
git push
|
|
62
|
+
```
|
|
63
|
+
(Skip if steps 3–5 produced no changes.)
|
|
64
|
+
|
|
65
|
+
### 7. Rewrite the PR description from scratch
|
|
66
|
+
Build the description **only** from the PR's actual contents — commits, changed
|
|
67
|
+
files, `gh pr diff`. **Do not read or extend the old description** (it may be
|
|
68
|
+
stale). Update via the GitHub API (`gh pr edit` can fail on deprecated Projects
|
|
69
|
+
Classic):
|
|
70
|
+
```bash
|
|
71
|
+
gh api repos/{owner}/{repo}/pulls/{number} -X PATCH -f body="..." --silent
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### 8. ⛔ Confirmation gate (mandatory)
|
|
75
|
+
Present to the maintainer: the rewritten **PR description**, the **changelog
|
|
76
|
+
entry** added (or "none, because …"), and any **dev notes / README sync** done
|
|
77
|
+
(or a README drift warning). **Wait for explicit confirmation** (e.g. "确认 / go").
|
|
78
|
+
Do not merge until approved.
|
|
79
|
+
|
|
80
|
+
### 9. Merge
|
|
81
|
+
```bash
|
|
82
|
+
gh pr merge --merge
|
|
83
|
+
```
|
|
84
|
+
Use the project's existing convention (merge commit; `--squash` only if asked).
|
|
85
|
+
Done — do **not** tag or publish.
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: release
|
|
3
|
+
description: >
|
|
4
|
+
Use when cutting a new release of nanoPyCodeAgent (low-frequency). Does release
|
|
5
|
+
work only — assumes dev notes and README were already kept in sync per-PR by
|
|
6
|
+
land-pr. Picks the next version from the changelog [Unreleased], cuts the
|
|
7
|
+
changelog, then — only after explicit maintainer confirmation — commits the
|
|
8
|
+
changelog straight to main, pushes the vX.Y.Z tag (which triggers the PyPI +
|
|
9
|
+
GitHub Release CI), and verifies the published artifacts via uvx. Triggers on
|
|
10
|
+
"发布 / 发版 / cut a release / publish a release / 打 tag 发版".
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Release
|
|
14
|
+
|
|
15
|
+
Cut and publish a new release of **nanoPyCodeAgent**. This skill does release
|
|
16
|
+
work only; per-PR docs (dev notes, README) are kept in sync by the `land-pr`
|
|
17
|
+
skill, not here.
|
|
18
|
+
|
|
19
|
+
The version is derived from the git tag by `hatch-vcs` — **the tag is the source
|
|
20
|
+
of truth**. Pushing a `v*` tag triggers `.github/workflows/release.yml`
|
|
21
|
+
(`build` → `publish-to-pypi` → `github-release`).
|
|
22
|
+
|
|
23
|
+
## Prerequisites
|
|
24
|
+
|
|
25
|
+
`git`, `gh` (authenticated), and `uv` installed. See `docs/RELEASING.md`.
|
|
26
|
+
|
|
27
|
+
## Steps
|
|
28
|
+
|
|
29
|
+
Work entirely on `main`. `<series>` is the current series changelog file,
|
|
30
|
+
e.g. `docs/changelogs/0.1.x.md`.
|
|
31
|
+
|
|
32
|
+
### 1. Preflight — stop if any check fails
|
|
33
|
+
- `command -v git gh uv` — all present.
|
|
34
|
+
- `gh auth status` — authenticated.
|
|
35
|
+
- `git status --porcelain` — empty (clean tree).
|
|
36
|
+
- `<series>` has entries under `## [Unreleased]`. If empty, there is nothing to
|
|
37
|
+
release — stop.
|
|
38
|
+
|
|
39
|
+
### 2. Switch to main and update
|
|
40
|
+
```bash
|
|
41
|
+
git checkout main && git pull --ff-only
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### 3. Decide the version
|
|
45
|
+
Read the entries under `## [Unreleased]` and propose the next semver `X.Y.Z`:
|
|
46
|
+
- a `Removed`/breaking entry → major
|
|
47
|
+
- an `Added` entry → minor
|
|
48
|
+
- only `Fixed` → patch
|
|
49
|
+
|
|
50
|
+
**0.x caveat:** on `0.y.z` a minor may still contain breaking changes; treat the
|
|
51
|
+
proposal as a suggestion. The maintainer makes the final call at the gate (step 5).
|
|
52
|
+
|
|
53
|
+
### 4. Cut the changelog
|
|
54
|
+
In `<series>`:
|
|
55
|
+
- rename `## [Unreleased]` to `## [X.Y.Z] - <today YYYY-MM-DD>`, keeping its entries;
|
|
56
|
+
- add a fresh empty `## [Unreleased]` section above it.
|
|
57
|
+
|
|
58
|
+
Touch no other file — dev notes and README were synced per-PR by `land-pr`.
|
|
59
|
+
|
|
60
|
+
### 5. ⛔ Confirmation gate (mandatory)
|
|
61
|
+
Present to the maintainer: the proposed **version** `X.Y.Z` and the **changelog
|
|
62
|
+
diff** (`git diff <series>`). **Wait for explicit confirmation** (e.g. "确认 / go").
|
|
63
|
+
Do not commit, push, or tag until approved. If the version changes, redo step 4.
|
|
64
|
+
|
|
65
|
+
### 6. Commit and push to main
|
|
66
|
+
```bash
|
|
67
|
+
git commit -am "Release vX.Y.Z"
|
|
68
|
+
git push origin main
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 7. Tag and push (triggers the release workflow)
|
|
72
|
+
```bash
|
|
73
|
+
git tag vX.Y.Z
|
|
74
|
+
git push origin vX.Y.Z
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### 8. Watch the release workflow
|
|
78
|
+
```bash
|
|
79
|
+
gh run watch
|
|
80
|
+
```
|
|
81
|
+
Confirm `build` → `publish-to-pypi` → `github-release` succeed. Publish steps are
|
|
82
|
+
idempotent (`--check-url`, `gh release view || create`); a failed run is safe to re-run.
|
|
83
|
+
|
|
84
|
+
### 9. Verify and report
|
|
85
|
+
```bash
|
|
86
|
+
.agents/skills/release/scripts/verify-release.sh vX.Y.Z
|
|
87
|
+
```
|
|
88
|
+
Polls official PyPI for the version, checks the GitHub Release has wheel + sdist,
|
|
89
|
+
and runs a `uvx` smoke test. Report success, or surface the failure verbatim.
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# verify-release.sh — verify a published nanoPyCodeAgent release.
|
|
3
|
+
#
|
|
4
|
+
# Against the OFFICIAL PyPI index (bypassing any local mirror lag) it checks:
|
|
5
|
+
# 1. the version is present on PyPI
|
|
6
|
+
# 2. a GitHub Release exists for the tag with wheel + sdist assets
|
|
7
|
+
# 3. `uvx ...@VERSION` runs the console entry point (smoke test)
|
|
8
|
+
#
|
|
9
|
+
# Usage: verify-release.sh <version|vVERSION> e.g. verify-release.sh 0.1.1
|
|
10
|
+
#
|
|
11
|
+
# Smoke test runs the entry point with no args (currently side-effect-free).
|
|
12
|
+
# If the entry point ever gains required args/interaction, adjust step 3.
|
|
13
|
+
set -euo pipefail
|
|
14
|
+
|
|
15
|
+
PACKAGE="nanoPyCodeAgent"
|
|
16
|
+
PYPI_JSON="https://pypi.org/pypi/${PACKAGE}/json"
|
|
17
|
+
PYPI_INDEX="https://pypi.org/simple/"
|
|
18
|
+
POLL_TIMEOUT="${VERIFY_TIMEOUT:-300}" # seconds budget per polling stage
|
|
19
|
+
POLL_INTERVAL="${VERIFY_INTERVAL:-15}" # seconds between polls
|
|
20
|
+
|
|
21
|
+
usage() {
|
|
22
|
+
cat <<'EOF'
|
|
23
|
+
Usage: verify-release.sh <version|vVERSION>
|
|
24
|
+
|
|
25
|
+
Verifies a published release against official PyPI + GitHub Release:
|
|
26
|
+
1. version present on PyPI (pinned to pypi.org, ignores mirrors)
|
|
27
|
+
2. GitHub Release for the tag has wheel + sdist assets
|
|
28
|
+
3. uvx smoke test runs the published artifact
|
|
29
|
+
|
|
30
|
+
Env overrides:
|
|
31
|
+
VERIFY_TIMEOUT seconds to wait per polling stage (default 300)
|
|
32
|
+
VERIFY_INTERVAL seconds between polls (default 15)
|
|
33
|
+
EOF
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if [[ $# -ne 1 ]]; then usage; exit 1; fi
|
|
37
|
+
if [[ "$1" == "-h" || "$1" == "--help" ]]; then usage; exit 0; fi
|
|
38
|
+
|
|
39
|
+
version="${1#v}" # strip leading v -> 0.1.1
|
|
40
|
+
tag="v${version}" # normalized tag -> v0.1.1
|
|
41
|
+
|
|
42
|
+
log() { printf '\n=== %s ===\n' "$*"; }
|
|
43
|
+
fail() { printf 'ERROR: %s\n' "$*" >&2; exit 1; }
|
|
44
|
+
|
|
45
|
+
# 1. PyPI presence (poll, pinned to official index) -----------------------
|
|
46
|
+
log "Checking PyPI for ${PACKAGE} ${version}"
|
|
47
|
+
deadline=$(( $(date +%s) + POLL_TIMEOUT ))
|
|
48
|
+
until curl -fsSL "$PYPI_JSON" | grep -q "\"${version}\""; do
|
|
49
|
+
(( $(date +%s) >= deadline )) && fail "version ${version} not on PyPI after ${POLL_TIMEOUT}s"
|
|
50
|
+
printf 'not on PyPI yet; retrying in %ss...\n' "$POLL_INTERVAL"; sleep "$POLL_INTERVAL"
|
|
51
|
+
done
|
|
52
|
+
printf 'OK: %s %s is on PyPI\n' "$PACKAGE" "$version"
|
|
53
|
+
|
|
54
|
+
# 2. GitHub Release + assets ----------------------------------------------
|
|
55
|
+
log "Checking GitHub Release ${tag}"
|
|
56
|
+
gh release view "$tag" >/dev/null 2>&1 || fail "no GitHub Release for ${tag}"
|
|
57
|
+
assets="$(gh release view "$tag" --json assets --jq '.assets[].name')"
|
|
58
|
+
grep -q '\.whl$' <<<"$assets" || fail "Release ${tag} missing a wheel (.whl) asset"
|
|
59
|
+
grep -q '\.tar\.gz$' <<<"$assets" || fail "Release ${tag} missing an sdist (.tar.gz) asset"
|
|
60
|
+
printf 'OK: GitHub Release %s has wheel + sdist\n' "$tag"
|
|
61
|
+
|
|
62
|
+
# 3. uvx smoke test (official index, with retries) ------------------------
|
|
63
|
+
log "Smoke-testing uvx ${PACKAGE}@${version}"
|
|
64
|
+
deadline=$(( $(date +%s) + POLL_TIMEOUT ))
|
|
65
|
+
until uvx --index "$PYPI_INDEX" --from "${PACKAGE}@${version}" "$PACKAGE" >/dev/null 2>&1; do
|
|
66
|
+
(( $(date +%s) >= deadline )) && fail "uvx smoke test failed for ${PACKAGE}@${version} after ${POLL_TIMEOUT}s"
|
|
67
|
+
printf 'uvx not ready (index propagation?); retrying in %ss...\n' "$POLL_INTERVAL"; sleep "$POLL_INTERVAL"
|
|
68
|
+
done
|
|
69
|
+
printf 'OK: uvx smoke test passed for %s@%s\n' "$PACKAGE" "$version"
|
|
70
|
+
|
|
71
|
+
log "Release ${tag} verified ✔"
|
|
@@ -33,7 +33,7 @@ jobs:
|
|
|
33
33
|
- name: Check distribution metadata
|
|
34
34
|
run: uvx twine check dist/*
|
|
35
35
|
- name: Upload artifacts
|
|
36
|
-
uses: actions/upload-artifact@
|
|
36
|
+
uses: actions/upload-artifact@v7
|
|
37
37
|
with:
|
|
38
38
|
name: dist
|
|
39
39
|
path: dist/
|
|
@@ -46,12 +46,16 @@ jobs:
|
|
|
46
46
|
id-token: write # required for Trusted Publishing (OIDC)
|
|
47
47
|
steps:
|
|
48
48
|
- name: Download artifacts
|
|
49
|
-
uses: actions/download-artifact@
|
|
49
|
+
uses: actions/download-artifact@v8
|
|
50
50
|
with:
|
|
51
51
|
name: dist
|
|
52
52
|
path: dist/
|
|
53
53
|
- name: Install uv
|
|
54
54
|
uses: astral-sh/setup-uv@08807647e7069bb48b6ef5acd8ec9567f424441b # v8.1.0
|
|
55
|
+
with:
|
|
56
|
+
# No checkout in this job, so the cache-dependency glob (pyproject.toml,
|
|
57
|
+
# uv.lock) matches nothing; uv publish needs no resolved-dep cache anyway.
|
|
58
|
+
enable-cache: false
|
|
55
59
|
- name: Publish to PyPI
|
|
56
60
|
# --check-url makes re-runs idempotent: files already on the index are
|
|
57
61
|
# skipped instead of failing the job on "file already exists".
|
|
@@ -65,7 +69,7 @@ jobs:
|
|
|
65
69
|
contents: write # required to create the release and upload assets
|
|
66
70
|
steps:
|
|
67
71
|
- name: Download artifacts
|
|
68
|
-
uses: actions/download-artifact@
|
|
72
|
+
uses: actions/download-artifact@v8
|
|
69
73
|
with:
|
|
70
74
|
name: dist
|
|
71
75
|
path: dist/
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
nanoPyCodeAgent — a nano code agent built from scratch in pure Python.
|
|
4
|
+
|
|
5
|
+
This is the shared project instruction file for coding agents. Codex reads
|
|
6
|
+
`AGENTS.md`; Claude Code reads `CLAUDE.md`, a symlink to this file.
|
|
7
|
+
|
|
8
|
+
## Skills
|
|
9
|
+
|
|
10
|
+
Project skills live in `.agents/skills/` and are auto-discovered by Codex and pi
|
|
11
|
+
(`.agents/skills/**/SKILL.md`); Claude Code discovers them via `.claude/skills`
|
|
12
|
+
(a symlink to `.agents/skills`). Use a skill by stating intent — the agent loads
|
|
13
|
+
the matching one:
|
|
14
|
+
|
|
15
|
+
- **Landing a PR** (everyday, no release) — merge a feature/bugfix PR into `main`:
|
|
16
|
+
`.agents/skills/land-pr/SKILL.md`
|
|
17
|
+
- **Releasing** (cut a version, publish to PyPI + GitHub):
|
|
18
|
+
`.agents/skills/release/SKILL.md`
|
|
19
|
+
|
|
20
|
+
See `docs/RELEASING.md` for the release process and prerequisites.
|
|
21
|
+
|
|
22
|
+
## Language
|
|
23
|
+
|
|
24
|
+
Write everything in **English** by default — source code (identifiers,
|
|
25
|
+
comments, string literals), commit messages, PR titles/descriptions, changelog
|
|
26
|
+
entries, and Markdown documentation.
|
|
27
|
+
|
|
28
|
+
The **only** exception is documentation explicitly designated as Chinese:
|
|
29
|
+
|
|
30
|
+
- `README.zh-CN.md` and any other `*.zh-CN.*` file.
|
|
31
|
+
- Files under a `zh-CN/` directory (e.g. `docs/dev_notes/zh-CN/`).
|
|
32
|
+
- Design specs under `docs/superpowers/specs/` — the prose may be Chinese for
|
|
33
|
+
review convenience, but the deliverables the spec produces (code under
|
|
34
|
+
`src/`, tests, and any English documentation) remain English.
|
|
35
|
+
- Any document with an explicit requirement to be written in Chinese.
|
|
36
|
+
|
|
37
|
+
Everything outside that list — including code under `src/`, this file, and all
|
|
38
|
+
other docs — is English.
|
|
39
|
+
|
|
40
|
+
## Commits & PRs
|
|
41
|
+
|
|
42
|
+
All agents working in this repo MUST follow
|
|
43
|
+
[Conventional Commits 1.0.0](https://www.conventionalcommits.org/en/v1.0.0/)
|
|
44
|
+
for **commit messages** and **PR titles** (squash-merge often uses the PR
|
|
45
|
+
title as the commit subject).
|
|
46
|
+
|
|
47
|
+
**Format:**
|
|
48
|
+
|
|
49
|
+
```
|
|
50
|
+
<type>[optional scope][!]: <description>
|
|
51
|
+
|
|
52
|
+
[optional body]
|
|
53
|
+
|
|
54
|
+
[optional footer(s)]
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
**Allowed types:** `feat`, `fix`, `docs`, `style`, `refactor`, `perf`,
|
|
58
|
+
`test`, `build`, `ci`, `chore`, `revert`.
|
|
59
|
+
|
|
60
|
+
**Rules:**
|
|
61
|
+
|
|
62
|
+
- Description: imperative mood, lowercase, no trailing period.
|
|
63
|
+
- Breaking changes: add `!` after the type/scope and/or include a
|
|
64
|
+
`BREAKING CHANGE:` footer.
|
|
65
|
+
- Separate the optional body and footer(s) from the description with a
|
|
66
|
+
blank line.
|
|
67
|
+
|
|
68
|
+
**Examples:**
|
|
69
|
+
|
|
70
|
+
- `feat: add streaming output to the agent loop`
|
|
71
|
+
- `fix(parser): handle empty tool-call arguments`
|
|
72
|
+
- `docs: require Conventional Commits in AGENTS.md`
|
|
73
|
+
- `refactor!: drop Python 3.9 support` (breaking change)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
AGENTS.md
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: nanoPyCodeAgent
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: A nano code agent built from scratch in pure Python.
|
|
5
5
|
Project-URL: Homepage, https://github.com/minixalpha/nanoPyCodeAgent
|
|
6
6
|
Project-URL: Repository, https://github.com/minixalpha/nanoPyCodeAgent
|
|
@@ -13,6 +13,7 @@ Classifier: Intended Audience :: Developers
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.13
|
|
15
15
|
Requires-Python: >=3.13
|
|
16
|
+
Requires-Dist: anthropic>=0.112.0
|
|
16
17
|
Description-Content-Type: text/markdown
|
|
17
18
|
|
|
18
19
|
# nanoPyCodeAgent
|
|
@@ -60,6 +61,32 @@ uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@main" nanoPyCodeAg
|
|
|
60
61
|
uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@v0.1.0" nanoPyCodeAgent
|
|
61
62
|
```
|
|
62
63
|
|
|
64
|
+
### Configuration
|
|
65
|
+
|
|
66
|
+
Credentials and the model come from two sources: **environment variables** and
|
|
67
|
+
an optional user-level config file at `~/.nanoPyCodeAgent/settings.json`.
|
|
68
|
+
Environment variables take precedence — the config file only fills in keys you
|
|
69
|
+
have not set in the environment.
|
|
70
|
+
|
|
71
|
+
The config file mirrors [Claude Code's settings](https://code.claude.com/docs/en/settings):
|
|
72
|
+
put the values under an `env` object. Empty or whitespace-only values are ignored.
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"env": {
|
|
77
|
+
"ANTHROPIC_API_KEY": "",
|
|
78
|
+
"ANTHROPIC_BASE_URL": "",
|
|
79
|
+
"ANTHROPIC_MODEL": ""
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
| Variable | Required | Default | Description |
|
|
85
|
+
| --- | --- | --- | --- |
|
|
86
|
+
| `ANTHROPIC_API_KEY` | Yes | — | Your Anthropic API key, or the key for a third-party / proxy service. |
|
|
87
|
+
| `ANTHROPIC_BASE_URL` | No | `https://api.anthropic.com` | Point the SDK at a non-official / proxy endpoint. Leave it unset to use the official API — an empty value breaks requests. |
|
|
88
|
+
| `ANTHROPIC_MODEL` | No | `claude-sonnet-4-6` | Override the model. An empty or whitespace-only value falls back to the default. |
|
|
89
|
+
|
|
63
90
|
### How to Update
|
|
64
91
|
|
|
65
92
|
Upgrade an installed tool to the latest release:
|
|
@@ -67,3 +94,7 @@ Upgrade an installed tool to the latest release:
|
|
|
67
94
|
```bash
|
|
68
95
|
uv tool upgrade nanoPyCodeAgent # or: pipx upgrade nanoPyCodeAgent
|
|
69
96
|
```
|
|
97
|
+
|
|
98
|
+
## Releasing
|
|
99
|
+
|
|
100
|
+
For maintainers: see [docs/RELEASING.md](docs/RELEASING.md) for the release process and prerequisites.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# nanoPyCodeAgent
|
|
2
|
+
|
|
3
|
+
[English](README.md) | [简体中文](README.zh-CN.md)
|
|
4
|
+
|
|
5
|
+
A nano code agent built in pure Python.
|
|
6
|
+
|
|
7
|
+
> "What I cannot create, I do not understand." — Richard Feynman, 1988
|
|
8
|
+
|
|
9
|
+
## Usage
|
|
10
|
+
|
|
11
|
+
nanoPyCodeAgent requires Python 3.13 or newer.
|
|
12
|
+
|
|
13
|
+
### How to Run
|
|
14
|
+
|
|
15
|
+
There are a few ways to run it — pick whichever fits your workflow.
|
|
16
|
+
|
|
17
|
+
#### Run without installing
|
|
18
|
+
|
|
19
|
+
Use `uvx` to run the latest release without installing anything:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
uvx nanoPyCodeAgent
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
#### Run after installing
|
|
26
|
+
|
|
27
|
+
Install it as a persistent command-line tool, then run it from anywhere:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
uv tool install nanoPyCodeAgent # or: pipx install nanoPyCodeAgent
|
|
31
|
+
nanoPyCodeAgent
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
#### Run a branch or tagged version
|
|
35
|
+
|
|
36
|
+
Run an unreleased branch or a specific release tag straight from GitHub:
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# latest commit on a branch
|
|
40
|
+
uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@main" nanoPyCodeAgent
|
|
41
|
+
|
|
42
|
+
# a specific tag
|
|
43
|
+
uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@v0.1.0" nanoPyCodeAgent
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Configuration
|
|
47
|
+
|
|
48
|
+
Credentials and the model come from two sources: **environment variables** and
|
|
49
|
+
an optional user-level config file at `~/.nanoPyCodeAgent/settings.json`.
|
|
50
|
+
Environment variables take precedence — the config file only fills in keys you
|
|
51
|
+
have not set in the environment.
|
|
52
|
+
|
|
53
|
+
The config file mirrors [Claude Code's settings](https://code.claude.com/docs/en/settings):
|
|
54
|
+
put the values under an `env` object. Empty or whitespace-only values are ignored.
|
|
55
|
+
|
|
56
|
+
```json
|
|
57
|
+
{
|
|
58
|
+
"env": {
|
|
59
|
+
"ANTHROPIC_API_KEY": "",
|
|
60
|
+
"ANTHROPIC_BASE_URL": "",
|
|
61
|
+
"ANTHROPIC_MODEL": ""
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
| Variable | Required | Default | Description |
|
|
67
|
+
| --- | --- | --- | --- |
|
|
68
|
+
| `ANTHROPIC_API_KEY` | Yes | — | Your Anthropic API key, or the key for a third-party / proxy service. |
|
|
69
|
+
| `ANTHROPIC_BASE_URL` | No | `https://api.anthropic.com` | Point the SDK at a non-official / proxy endpoint. Leave it unset to use the official API — an empty value breaks requests. |
|
|
70
|
+
| `ANTHROPIC_MODEL` | No | `claude-sonnet-4-6` | Override the model. An empty or whitespace-only value falls back to the default. |
|
|
71
|
+
|
|
72
|
+
### How to Update
|
|
73
|
+
|
|
74
|
+
Upgrade an installed tool to the latest release:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
uv tool upgrade nanoPyCodeAgent # or: pipx upgrade nanoPyCodeAgent
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Releasing
|
|
81
|
+
|
|
82
|
+
For maintainers: see [docs/RELEASING.md](docs/RELEASING.md) for the release process and prerequisites.
|
|
@@ -43,6 +43,31 @@ uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@main" nanoPyCodeAg
|
|
|
43
43
|
uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@v0.1.0" nanoPyCodeAgent
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
+
### 配置
|
|
47
|
+
|
|
48
|
+
凭据与模型有两种配置来源:**环境变量**,以及可选的用户级配置文件
|
|
49
|
+
`~/.nanoPyCodeAgent/settings.json`。环境变量优先级更高——配置文件只用于填补你
|
|
50
|
+
未在环境变量中设置的键。
|
|
51
|
+
|
|
52
|
+
配置文件写法与 [Claude Code settings](https://code.claude.com/docs/en/settings)
|
|
53
|
+
一致:把值放在 `env` 对象下。空值或纯空白会被忽略。
|
|
54
|
+
|
|
55
|
+
```json
|
|
56
|
+
{
|
|
57
|
+
"env": {
|
|
58
|
+
"ANTHROPIC_API_KEY": "",
|
|
59
|
+
"ANTHROPIC_BASE_URL": "",
|
|
60
|
+
"ANTHROPIC_MODEL": ""
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
| 变量 | 是否必填 | 默认值 | 说明 |
|
|
66
|
+
| --- | --- | --- | --- |
|
|
67
|
+
| `ANTHROPIC_API_KEY` | 是 | 无 | 你的 Anthropic API key,或第三方/代理服务的 key。 |
|
|
68
|
+
| `ANTHROPIC_BASE_URL` | 否 | `https://api.anthropic.com` | 将 SDK 指向非官方/代理 endpoint。使用官方 API 时保持不设置;留空值会导致请求失败。 |
|
|
69
|
+
| `ANTHROPIC_MODEL` | 否 | `claude-sonnet-4-6` | 覆盖默认模型。空值或纯空白会回退到默认值。 |
|
|
70
|
+
|
|
46
71
|
### 如何更新
|
|
47
72
|
|
|
48
73
|
将已安装的工具升级到最新发布版:
|
|
@@ -50,3 +75,7 @@ uvx --from "git+https://github.com/minixalpha/nanoPyCodeAgent@v0.1.0" nanoPyCode
|
|
|
50
75
|
```bash
|
|
51
76
|
uv tool upgrade nanoPyCodeAgent # 或: pipx upgrade nanoPyCodeAgent
|
|
52
77
|
```
|
|
78
|
+
|
|
79
|
+
## 发布
|
|
80
|
+
|
|
81
|
+
维护者请参阅 [docs/RELEASING.md](docs/RELEASING.md) 了解发布流程与前置条件。
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Releasing
|
|
2
|
+
|
|
3
|
+
How nanoPyCodeAgent is maintained and released. Two agent skills drive the flow;
|
|
4
|
+
this document is the human reference.
|
|
5
|
+
|
|
6
|
+
## Prerequisites (maintainers)
|
|
7
|
+
|
|
8
|
+
- **`uv`** — build / publish / run (`uvx`).
|
|
9
|
+
- **`gh`** — GitHub CLI, authenticated (`gh auth status`).
|
|
10
|
+
- **`git`**.
|
|
11
|
+
- One-time: PyPI Trusted Publishing must be configured for this repo (see the
|
|
12
|
+
header comment in `.github/workflows/release.yml`).
|
|
13
|
+
|
|
14
|
+
## Two skills
|
|
15
|
+
|
|
16
|
+
| Skill | When | What it does | Publishes? |
|
|
17
|
+
|-------|------|--------------|------------|
|
|
18
|
+
| `land-pr` | Every feature/bugfix PR | Rewrites the PR description, appends a changelog `[Unreleased]` entry when warranted, syncs dev notes (zh→en) and the bilingual README, then merges after confirmation. | No |
|
|
19
|
+
| `release` | Cutting a version | Picks the next version from `[Unreleased]`, cuts the changelog, commits to `main`, pushes the `vX.Y.Z` tag (triggering CI), and verifies PyPI + GitHub Release. | Yes |
|
|
20
|
+
|
|
21
|
+
The changelog flows across both: `land-pr` accumulates entries under
|
|
22
|
+
`[Unreleased]`; `release` turns `[Unreleased]` into a dated version section.
|
|
23
|
+
|
|
24
|
+
## How it publishes
|
|
25
|
+
|
|
26
|
+
Pushing a `v*` tag triggers `.github/workflows/release.yml`:
|
|
27
|
+
`build` → `publish-to-pypi` (PyPI Trusted Publishing / OIDC) → `github-release`.
|
|
28
|
+
The version is derived from the git tag by `hatch-vcs`.
|
|
29
|
+
|
|
30
|
+
## Triggering the skills
|
|
31
|
+
|
|
32
|
+
State intent to your agent — "land this PR" / "合并 PR", or "cut a release" /
|
|
33
|
+
"发布". The agent loads the matching skill from `.agents/skills/`.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Changelog — 0.1.x
|
|
2
|
+
|
|
3
|
+
All notable changes in the **0.1.x** release series are documented here.
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- Project-level agent skills `land-pr` and `release` (in `.agents/skills/`, cross-agent: Claude Code / Codex / pi), with a `verify-release.sh` post-publish check, a root `AGENTS.md`, and `docs/RELEASING.md`.
|
|
9
|
+
- Contributing convention: all agents must follow Conventional Commits 1.0.0 for commit messages and PR titles (documented in `AGENTS.md`).
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
- CI: upgrade the release workflow's artifact actions off the deprecated Node 20 runtime — `actions/upload-artifact` v4 → v7 and `actions/download-artifact` v4 → v8 — and disable the unused `setup-uv` cache in the `publish-to-pypi` job, which has no checkout so its cache-dependency glob matched nothing (#3).
|
|
13
|
+
|
|
14
|
+
## [0.1.0] - 2026-06-20
|
|
15
|
+
|
|
16
|
+
### Added
|
|
17
|
+
- uv-managed project with the console-script entry point `nanoPyCodeAgent`.
|
|
18
|
+
- Tag-driven release pipeline: PyPI Trusted Publishing + GitHub Release.
|
|
19
|
+
- Bilingual README (English / 简体中文).
|
|
20
|
+
- changelogs and dev notes
|
|
21
|
+
|
|
22
|
+
<!--
|
|
23
|
+
When cutting a release, copy the relevant items from [Unreleased] into a new
|
|
24
|
+
version section above it, e.g.:
|
|
25
|
+
|
|
26
|
+
## [0.1.1] - YYYY-MM-DD
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
### Changed
|
|
30
|
+
### Fixed
|
|
31
|
+
### Removed
|
|
32
|
+
-->
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# Changelog — 0.2.x
|
|
2
|
+
|
|
3
|
+
All notable changes in the **0.2.x** release series are documented here.
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.2.0] - 2026-07-09
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
- Interactive agent loop: a multi-turn chatbot built on the Anthropic Python SDK that keeps the full conversation in memory for context and quits on `/exit`.
|
|
11
|
+
- Configurable endpoint, API key, and model via environment variables (`ANTHROPIC_API_KEY` / `ANTHROPIC_BASE_URL` / `ANTHROPIC_MODEL`) and an optional user-level config file `~/.nanoPyCodeAgent/settings.json`, whose `env` object mirrors [Claude Code's settings](https://code.claude.com/docs/en/settings). Environment variables take precedence; only `ANTHROPIC_*` keys are read, and empty / whitespace-only values are ignored. A missing, unreadable, or malformed config file never blocks startup, and Ctrl-C quits cleanly.
|
|
12
|
+
|
|
13
|
+
<!--
|
|
14
|
+
When cutting a release, copy the relevant items from [Unreleased] into a new
|
|
15
|
+
version section above it, e.g.:
|
|
16
|
+
|
|
17
|
+
## [0.2.0] - YYYY-MM-DD
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
### Changed
|
|
21
|
+
### Fixed
|
|
22
|
+
### Removed
|
|
23
|
+
-->
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Changelog — 0.3.x
|
|
2
|
+
|
|
3
|
+
All notable changes in the **0.3.x** release series are documented here.
|
|
4
|
+
|
|
5
|
+
## [Unreleased]
|
|
6
|
+
|
|
7
|
+
## [0.3.0] - 2026-07-10
|
|
8
|
+
|
|
9
|
+
### Changed
|
|
10
|
+
- Agent replies now stream to the terminal as they are generated, instead of appearing all at once after the full response is ready.
|
|
11
|
+
|
|
12
|
+
<!--
|
|
13
|
+
When cutting a release, copy the relevant items from [Unreleased] into a new
|
|
14
|
+
version section above it, e.g.:
|
|
15
|
+
|
|
16
|
+
## [0.3.0] - YYYY-MM-DD
|
|
17
|
+
|
|
18
|
+
### Added
|
|
19
|
+
### Changed
|
|
20
|
+
### Fixed
|
|
21
|
+
### Removed
|
|
22
|
+
-->
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Development Notes — 0.2.x
|
|
2
|
+
|
|
3
|
+
> Generated from the Chinese source [`../zh-CN/0.2.x.md`](../zh-CN/0.2.x.md). Do not edit by hand.
|
|
4
|
+
|
|
5
|
+
## 0.2.0 - 2026.06.29
|
|
6
|
+
|
|
7
|
+
This release implements a minimally functional chatbot that holds a multi-turn conversation with the LLM through the [Messages](https://platform.claude.com/docs/en/api/python/messages/create) API.
|
|
8
|
+
|
|
9
|
+
The LLM's endpoint, key, and model can be configured in two ways:
|
|
10
|
+
|
|
11
|
+
- **Environment variables**: the variable names follow [Claude Code's environment variables](https://code.claude.com/docs/en/env-vars); the three common ones are `ANTHROPIC_API_KEY`, `ANTHROPIC_BASE_URL`, and `ANTHROPIC_MODEL`.
|
|
12
|
+
- **Config file**: located at `~/.nanoPyCodeAgent/settings.json`, with values placed under its `env` field, using the same convention as the `env` field in [Claude Code's settings](https://code.claude.com/docs/en/settings). Example:
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"env": {
|
|
17
|
+
"ANTHROPIC_API_KEY": "",
|
|
18
|
+
"ANTHROPIC_BASE_URL": "",
|
|
19
|
+
"ANTHROPIC_MODEL": ""
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
The two can be mixed, and **environment variables take precedence over the config file**: when a key is already set in the environment, the config file's value for that same key is ignored; the config file only fills in keys the environment leaves unset. The empty strings in the example are placeholders — empty values (empty or whitespace-only) are skipped.
|