Skip to content

Rename the distribution venice-ai -> venice-py (Tier A) - #36

Merged
sethbang merged 12 commits into
mainfrom
rename/venice-py-tier-a
Aug 20, 2026
Merged

Rename the distribution venice-ai -> venice-py (Tier A)#36
sethbang merged 12 commits into
mainfrom
rename/venice-py-tier-a

Conversation

@sethbang

Copy link
Copy Markdown
Owner

Renames the PyPI distribution and every user-facing surface from venice-ai to venice-py. v2.1.0 renamed the CLI binary for the same reason — Venice's official tooling owns the venice name, and a community SDK sitting on venice-ai invites people to mistake it for an official release.

The import package does not change. from venice_ai import VeniceClient still works, VENICE_API_KEY is unchanged, and the Prometheus metric names are untouched. A distribution name that differs from its import name is ordinary in Python (pillow/PIL, python-dotenv/dotenv); renaming the module would have broken every existing import for no gain.

What moves

  • Distribution venice-aivenice-py, with __version__ now looked up under the new name (see Fixed below)
  • Bundled skills venice-ai*venice-py*, and venice-py skills install sweeps superseded venice-ai* directories out of the target so both generations don't trigger against each other
  • CLI user data ~/.venice/~/.venice-py/, migrated automatically on first use. The old directory is left exactly as it was — it may hold the official CLI's data
  • User-Agent VeniceAI-Python-SDK/<v>venice-py/<v>
  • CLI self-identification--version and --help said Venice AI CLI, which is the confusion this rename exists to remove
  • Docs, README (new banner in Python's palette), examples, and both publish workflows

Fixed

__version__ resolved from importlib.metadata inside a bare except Exception falling back to a hardcoded literal — so a name mismatch would have frozen it silently, and User-Agent derives from it. A test now asserts the looked-up name and the built distribution cannot drift apart.

Release sequence

This branch is at 2.2.0rc1 deliberately: publish-testpypi.yaml refuses any version that isn't an rc/a/b pre-release. After the TestPyPI dry run and clean-room verification, a final commit on this branch reverts to 2.2.0 before merge — release.yaml refuses to publish when pyproject.version and the release tag disagree.

venice-ai is never yanked. A metadata-only bridge release follows once venice-py 2.2.0 is live on PyPI, so pip install venice-ai keeps working.

Verification

Vulture, ruff lint + format, mypy --strict, pyright, make skills-check, the 1412-test CLI suite, and the Docusaurus build under onBrokenLinks: 'throw' all pass locally. A clean-room pip install of the built wheel confirms the dist name, the venice_ai import, the version resolving from metadata, a single venice-py entry point with no bare venice, all four renamed skills, and no evals or test_support in the artifact.

🤖 Generated with Claude Code

sethbang and others added 11 commits August 20, 2026 04:19
Renames the PyPI distribution only. The import package stays `venice_ai`
and the `VENICE_` env prefix is untouched, so `import venice_ai` and
`VENICE_API_KEY` keep working for every existing user.

- pyproject: name -> venice-py, keywords gain venice-py
- install strings across README, website, examples, skills
- User-Agent: VeniceAI-Python-SDK/x -> venice-py/x
- PyPI badges, Makefile build banner, example prose

Two correctness fixes the rename surfaced:

- `__init__` looked its version up by *distribution* name inside a bare
  `except Exception`. Left as "venice-ai" it would raise
  PackageNotFoundError, get swallowed, and freeze `__version__` at the
  hardcoded fallback forever -- silently, and User-Agent is built from it.
  Adds a static guard asserting the looked-up name matches pyproject.

- Both publish workflows gated on `github.repository == 'sethbang/venice-ai'`,
  which turns into a silent no-op on any repo rename (green check, nothing
  published). Now gated on `repository_owner`, which is the part that
  actually blocks forks and is rename-proof.

Install docs drop the `>=2` floor: it existed because a bare
`pip install venice-ai` on Python <=3.13 silently resolves to v1.3.x.
venice-py has no v1 line, so pip now reports no matching distribution --
the outcome the floor was engineered to force.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Commit 0ad1988 changed the extras-install hints in src/ but not the tests
that assert on them, breaking 12 tests across 5 files. Fixes those, plus
the strings the first sweep did not reach:

- pyproject extras comments; the `venice-ai` keyword deliberately stays,
  so people searching the old name still find the package
- ci-validation install-matrix smoke print
- publish-testpypi clean-room install command (functional, not a comment)
  and the Trusted Publisher header block
- docker-compose.test.yml container and network names

Left alone deliberately:
- `@venice-ai/x402-client` is Venice's npm package, a different registry
- `venice-ai<2` pin advice and the v1.3.x migration columns: the v1 line
  exists only under the old distribution name
- `--project-name=venice-ai-docs` in docs.yml names the live Cloudflare
  Pages project; renaming the flag without renaming the project breaks
  deploys, so it belongs with the repo rename
- github.com/sethbang/venice-ai URLs, which move with the repo rename

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Renames the four bundled skill directories and everything that referred to
them: SKILL.md frontmatter names, evals skill_name fields, ~45 cross-skill
references, the tools/skills checkers and installer, and their tests.

Adds a legacy sweep to `skills install` / `uninstall`. Without it a user who
had already installed the skills would end up with both the old and new sets
in .claude/skills/ and both triggering, since uninstall only ever knew the
currently-bundled names. A directory is only removed when it is a real
directory (never a symlink), its SKILL.md frontmatter name matches, and it
carries our provenance marker -- so an unrelated user directory that happens
to share a name is left alone.

The sweep is scoped to the counterparts of the names being installed rather
than always removing all four: `skills install venice-py` should not delete
venice-ai-x402, which would strip the user's only copy of a skill whose
replacement is not being installed. A bare `skills install` still sweeps all
four.

Adds hard zero-guards to all four tools/skills checkers. They globbed on the
old prefix, so after the rename they would have matched nothing and exited 0
-- reporting success while checking no skills at all. They now exit 1 when a
glob matches nothing, which is what would have caught this class in the first
place.

Also fixes a dead link that had been shipping in the chat skill:
github.com/veniceai/venice-ai 404s; the repo is sethbang/venice-ai.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
~/.venice/ collides with the official Venice CLI (a separate Node tool
whose binary is `venice`); both can be installed side by side, so this one
moves out of the way.

The directory holds user-authored content -- hand-tuned image presets and
months of chat transcripts -- so a bare constant change would silently
orphan it. New `cli/_paths.py` owns the names and performs a one-time copy
the first time anything actually reads the directory.

- Copies only the three subpaths we own, by name, so anything the official
  CLI has since put in ~/.venice/ is left behind rather than absorbed.
- Copies rather than moves, and never touches ~/.venice/. Deleting another
  tool's data would be far worse than leaving a stale copy.
- Stages into a sibling temp dir and publishes with a single os.rename.
  Concurrent invocations race for the rename instead of interleaving
  writes; losers discard their stage and read the winner's copy. Verified
  with 8 concurrent processes: exactly one notice printed, no leftover
  staging directories. Cheaper than a lock file, which would need its own
  stale-lock recovery.
- The filesystem is the idempotency guard, so the one-time notice cannot
  repeat and there is no state to track.
- Permissions are clamped, never widened: conversations to 0700 (transcripts
  contain prompt and response text), config.yaml to 0600 (may hold a
  plaintext API key).
- A migration failure warns and continues; it is a convenience, never a
  precondition for the command the user asked for.

Hooks sit on the directory read rather than on a root callback, so
`--version` and other subcommands that never touch it pay nothing, and code
importing venice_ai.cli.presets directly still migrates. `save_config` is
hooked too: `venice-py configure` as a first-ever command would otherwise
create the new directory before any read and orphan the old data for good.

Adds an autouse fixture pointing every CLI test at a temporary home, so the
suite can neither read a developer's live API key nor create a real
~/.venice-py and thereby suppress their own migration.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Unrelated to the rename; surfaced by a full-suite run. All three predate
this branch (tests/conftest.py since v2.0.0, 50ff014).

`pytest_collection_modifyitems` called `asyncio.iscoroutinefunction`, which
is deprecated and slated for removal in Python 3.16. It fires once per
collected item, which is where ~29.9k of the suite's warnings came from --
and because it decides which tests get the asyncio marker, its removal in
3.16 would break collection outright rather than degrade quietly.

Swapped for `inspect.iscoroutinefunction`. The two differ historically:
asyncio's also returned True for generators wrapped in the `@asyncio.coroutine`
decorator, removed in 3.11. Verified equivalent here rather than assumed --
compared both across all 4984 collected items (2421 async): zero mismatches.

The two namespace-wiring tests built a loop through
`asyncio.get_event_loop_policy().new_event_loop()` -- deprecated on the same
timeline -- and never closed it, so each also leaked a loop. `asyncio.run`
closes it. Both are sync tests, so there is no running loop to conflict with.
Confirmed under `-W error::DeprecationWarning`.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The RC version is temporary: publish-testpypi.yaml refuses anything that is
not an rc/a/b pre-release. It reverts to 2.2.0 before the real release, which
release.yaml gates against the git tag.

Also moves __init__'s hardcoded version fallback to 2.2.0. It only fires in a
source tree with no installed metadata, but leaving it at 2.1.0 is the same
kind of drift the metadata lookup fix was about.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The old banner reads "Venice AI" in Venice's blues, which now points at the
wrong identity twice over: wrong name, and a palette that invites people to
read an unofficial SDK as an official one. The new one is a venice-py
wordmark in Python's own colours (#3776ab / #ffd545) -- palette only, no
official marks from either project.

PNG rather than SVG: PyPI's README renderer does not display SVG.

Text contrast is checked against the gradient it actually sits on. The
tagline renders at roughly 13px at the README's 720px display width, so it
needs the 4.5:1 AA-normal ratio rather than the 3:1 large-text one; it lands
at 5.10:1, the wordmark at 5.90:1.

venice-ai-banner.png is deliberately kept: the published PyPI page for
venice-ai 2.1.0 embeds it from main and fetches it live, so removing it
would permanently break the banner on a release that is already out.

Generator lives at .metadata/banner/make_banner.py (untracked, like the
other local tooling).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The prose is already near-unanimous: 163 uses of "SDK" across the README,
website and skills against a single "client library" -- and that one was the
pyproject description, which is the summary line on the PyPI page.

"Client library" describes a request/response wrapper around an API, which is
what openai-python and anthropic-sdk-python are. This ships a CLI with ~15
command groups, four bundled skills, pluggable rate limiting with a Redis
backend, OpenTelemetry and Prometheus observability, cost tracking, TEE
client-side E2EE and x402 wallet auth on two chains. "SDK" is the accurate
word for that, not merely the more common one in these docs.

- pyproject description (the PyPI summary line)
- banner tagline and README alt text
- package docstring, which said "the SDK provides a client library" -- an SDK
  providing a client library is circular, and it surfaces in the generated
  API reference

"SDK for Venice.ai" rather than "SDK for the Venice.ai API": an SDK targets a
platform, an API client targets an endpoint. Matches the website tagline.

Left alone: "the Prometheus client library" in _validation.py, which refers to
a different project and is correct as written.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
`venice-py --version` printed `Venice AI CLI v<version>` and `--help` opened
with `Venice AI CLI - Your AI assistant in the terminal.`

Renaming the command in v2.1.0 stopped the PATH collision with Venice's
official `venice`, but left the tool still introducing itself as Venice's —
which is the confusion the whole rename exists to remove. Someone who ran
`venice-py --version` to check which binary they had got an answer that
looked official.

Both surfaces now say `venice-py`, and `--help` states plainly that this is
the unofficial, community-maintained CLI.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The install matrix resolved its wheel with `ls dist/venice_ai-*.whl`, which
matches nothing now that the distribution builds as `venice_py-*.whl`. The
glob failing left WHEEL empty, so the job ran `pip install "[redis]"` and
died on an opaque "Expected package name" error that says nothing about the
real cause. `tools/install_matrix.sh` had the same glob.

Both now match `venice_py-*.whl` and fail loudly, naming the missing wheel
and listing dist/, rather than passing an empty string to pip.

Also formats check_skill_symbols.py — `make format-check` only covers
src/ and tests/, so tools/ had drifted.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Renaming strings in place left several passages arguing for a premise that
no longer holds.

Migration guide §0 was the worst of it. It still told readers to "pin the
major version" because "a bare `venice-ai` is how you end up back on v1",
while the code blocks beside it said `venice-py` — a name with no v1 to fall
back to. Its console sample invented a `2.0.2 Requires-Python` error for a
version never published under that name. The section now explains what is
actually true: changing the name *is* the version floor, since v1 lives only
under `venice-ai`.

The skills' trigger contexts were listed as `venice-py chat` / `venice-py
image` alongside an unconverted `venice x402`. Both forms were wrong — the
SKILL.md frontmatter triggers on natural language about Venice, not on
command names — so they are now written as the phrases a user would actually
say.

The changelog claimed in the present tense that the `venice-ai` bridge
release exists. It cannot: it depends on a `venice-py` that has to be on
PyPI first, so it necessarily ships second. Reworded, with the ordering and
the harmless gap spelled out.

Also: README H1 `Venice AI Python SDK` -> `venice-py` (with its back-to-top
anchor), an x402 skill example citing a `venice_py-2.0.0` wheel that never
existed, and the TestPyPI workflow header still describing itself as a
v2.0.0-specific dry run.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 20, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.86207% with 6 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/venice_ai/cli/commands/skills.py 92.00% 4 Missing ⚠️
src/venice_ai/cli/_paths.py 97.50% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

The branch carried 2.2.0rc1 so `publish-testpypi.yaml` would accept it — that
workflow refuses any version without an rc/a/b suffix, so a dry run is only
possible from a pre-release version.

The dry run is done and verified in a clean room: TestPyPI resolved
venice-py[all]==2.2.0rc1 with all 70 dependencies, `__version__` came from the
distribution metadata rather than the swallowed-exception fallback, the
User-Agent read venice-py/2.2.0rc1, the console script reported
`venice-py v2.2.0rc1`, only the venice-py entry point was installed, all four
skills carried their new names, and no evals shipped.

Reverting now because `release.yaml`'s version-check refuses to publish when
pyproject.version and the release tag disagree. This has to be a commit on
this branch: `main-review` requires a PR, so merging at rc1 would force a
second one.

Note that this collapses the one signal that distinguished a working metadata
lookup from a swallowed PackageNotFoundError — the fallback literal in
__init__.py is also 2.2.0. That check was meaningful only while the two
differed, and it was exercised then.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@sethbang
sethbang merged commit 2270c47 into main Aug 20, 2026
24 checks passed
@sethbang
sethbang deleted the rename/venice-py-tier-a branch August 20, 2026 17:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant