astra-cli-agent 0.1.2__tar.gz → 0.1.3__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.
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/.env.example +7 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/HANDOFF.md +298 -135
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/PKG-INFO +59 -3
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/README.md +58 -2
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/pyproject.toml +1 -1
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/git_agent.py +6 -2
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/cli/setup.py +86 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/git/backend.py +3 -2
- astra_cli_agent-0.1.3/src/astra/tools/git/github_backend.py +305 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/git/tools.py +61 -1
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_git_backend.py +42 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_git_tools.py +22 -1
- astra_cli_agent-0.1.3/tests/unit/test_github_backend.py +212 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_setup.py +112 -1
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/.github/workflows/ci.yml +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/.github/workflows/release.yml +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/.gitignore +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/LICENSE +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/docs/ARCHITECTURE.md +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/base.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/coder_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/debug_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/docker_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/documentation_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/file_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/kubernetes_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/mcp_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/memory_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/planner_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/research_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/retrieve_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/agents/reviewer_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/cli/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/cli/app.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/cli/chat.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/cli/ingest.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/cli/mcp.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/cli/memory.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/cli/rendering.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/cli/single.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/config/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/config/defaults.yaml +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/config/profiles/.gitkeep +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/core/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/core/confirm.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/core/events.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/core/exceptions.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/core/graph.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/core/json_stream.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/core/onboarding.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/core/settings.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/core/state.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/llm/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/llm/cost.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/llm/litellm_client.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/llm/ollama_client.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/llm/provider.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/llm/router.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/memory/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/memory/chunking.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/memory/embeddings.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/memory/models.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/memory/retriever.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/memory/store.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/memory/vector_store.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/models/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/models/tool_result.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/prompts/.gitkeep +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/code/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/code/backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/code/tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/docker/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/docker/backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/docker/tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/filesystem/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/filesystem/backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/filesystem/tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/git/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/kubernetes/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/kubernetes/backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/kubernetes/tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/mcp/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/mcp/backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/mcp/client.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/mcp/discovery.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/registry.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/shell/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/shell/backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/shell/tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/web/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/web/backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/tools/web/tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/utils/__init__.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/src/astra/utils/logging.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/e2e/.gitkeep +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/e2e/test_e2e_live_groq.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/fixtures/mcp_fixture_server.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/integration/.gitkeep +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/integration/_helpers.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/integration/conftest.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/integration/test_cli_ask.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/integration/test_cli_confirm_gate.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/integration/test_cli_ingest_and_retrieval.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/integration/test_cli_mcp.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/integration/test_cli_run_pipeline.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/.gitkeep +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/conftest.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_agents.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_chat.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_chunking.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_cli.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_code_backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_code_tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_docker_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_docker_backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_docker_tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_file_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_filesystem_backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_filesystem_tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_git_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_graph.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_json_stream.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_kubernetes_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_kubernetes_backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_kubernetes_tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_llm_adapters.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_llm_cost.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_llm_router.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_llm_router_streaming.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_mcp_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_mcp_backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_mcp_client.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_mcp_discovery.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_mcp_http_transport.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_memory_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_memory_store.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_onboarding.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_rag_e2e.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_research_agent.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_shell_backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_shell_tools.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_vector_store.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_web_backend.py +0 -0
- {astra_cli_agent-0.1.2 → astra_cli_agent-0.1.3}/tests/unit/test_web_tools.py +0 -0
|
@@ -9,6 +9,13 @@ GROQ_API_KEY=
|
|
|
9
9
|
# Local Ollama server (optional last-resort fallback)
|
|
10
10
|
OLLAMA_HOST=http://localhost:11434
|
|
11
11
|
|
|
12
|
+
# Optional GitHub API access (the git agent's github_* tools: create/delete repos, issues,
|
|
13
|
+
# pull requests, and authenticated push/pull against private repos). Generate a fine-grained
|
|
14
|
+
# personal access token at https://github.com/settings/tokens with repo scope. Leaving
|
|
15
|
+
# GITHUB_TOKEN unset simply disables these tools; local git operations (status/diff/commit/
|
|
16
|
+
# push to a public or already-authenticated remote/etc.) work without it.
|
|
17
|
+
GITHUB_TOKEN=
|
|
18
|
+
|
|
12
19
|
# Optional general web search (the research agent's `web_search_general` tool). Uses SerpApi
|
|
13
20
|
# (https://serpapi.com) to run a real Google search. Leaving SERPAPI_KEY unset simply disables
|
|
14
21
|
# `web_search_general`; the GitHub/StackOverflow/fetch tools work without it.
|
|
@@ -6,9 +6,14 @@ The living architecture doc is [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) —
|
|
|
6
6
|
too for the full target design. This file is the "where are we right now" companion.
|
|
7
7
|
|
|
8
8
|
Last updated: 2026-07-11, end of Phase 18 + a post-18 hardening pass (see §7) that closed
|
|
9
|
-
six of the "known simplifications" from §3,
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
six of the "known simplifications" from §3, a post-18 addendum (see §9) that verified CI is
|
|
10
|
+
actually live on GitHub, resolved a PyPI naming collision (renamed to `astra-cli-agent`),
|
|
11
|
+
and added first-run `astra setup` provider onboarding, and a public-release pass (see §10)
|
|
12
|
+
that actually published `astra-cli-agent` to PyPI (v0.1.0–v0.1.2), stood up a public
|
|
13
|
+
README-only GitHub repo, and gave the CLI a real ASCII-logo presence. **The project is
|
|
14
|
+
fully shipped and installable** (`pip install astra-cli-agent`) — everything left open is
|
|
15
|
+
either a nice-to-have (LangSmith tracing needs a working key) or infra the user owns
|
|
16
|
+
(kubernetes cluster for a handful of skipped tests).
|
|
12
17
|
|
|
13
18
|
---
|
|
14
19
|
|
|
@@ -1388,138 +1393,9 @@ running on every future `pytest -q`, whereas the manual checks in Phases 3–16
|
|
|
1388
1393
|
~~17. Full test pass — integration + e2e tests (`tests/integration/`, `tests/e2e/`).~~ —
|
|
1389
1394
|
**done, see Phase 17 above.**
|
|
1390
1395
|
~~18. Packaging/CI/CD — GitHub Actions (`.github/workflows/`), PyPI trusted-publishing release
|
|
1391
|
-
automation.~~ — **code-complete
|
|
1392
|
-
infrastructure
|
|
1393
|
-
|
|
1394
|
-
---
|
|
1395
|
-
|
|
1396
|
-
## 5. Post-Phase-18 addendum (2026-07-11): CI verified live, PyPI rename, first-run onboarding
|
|
1397
|
-
|
|
1398
|
-
This session found Phase 18's "known gap" note (§4 above, "CI never run on real GitHub
|
|
1399
|
-
infrastructure") was **stale** — a remote had since been added and pushed outside of a
|
|
1400
|
-
tracked phase. Checked directly: `git remote -v` shows `origin` →
|
|
1401
|
-
`github.com/Subharjun/astra-cli` (private), `git log` shows two commits already pushed to
|
|
1402
|
-
`main`, and `gh run list` shows both pushes triggered a real `CI` workflow run on GitHub's
|
|
1403
|
-
infrastructure — both green. **Nothing left to do for CI itself.** Whoever picks this up
|
|
1404
|
-
next should open PRs against `main` going forward rather than pushing directly, now that
|
|
1405
|
-
CI is live and would actually gate them.
|
|
1406
|
-
|
|
1407
|
-
**PyPI blocker found and resolved**: `astra-cli` (the name Phase 18 assumed would be
|
|
1408
|
-
registered) is already taken on PyPI by an unrelated project (a different "Astra agent
|
|
1409
|
-
framework" CLI, owned by a different PyPI user). Confirmed via `curl
|
|
1410
|
-
https://pypi.org/pypi/astra-cli/json` returning a real, different project's metadata, not
|
|
1411
|
-
a 404. **Renamed the PyPI distribution name to `astra-cli-agent`** (confirmed available via
|
|
1412
|
-
a 404 check first) in `pyproject.toml`'s `[project].name` — **the installed console command
|
|
1413
|
-
stays `astra`** (`[project.scripts]` unchanged), so this is a packaging-metadata-only
|
|
1414
|
-
rename, not a UX change. `docs/ARCHITECTURE.md`'s install-target line and `README.md`
|
|
1415
|
-
updated to match; `.github/workflows/release.yml` needed no changes since it reads the name
|
|
1416
|
-
from `pyproject.toml` rather than hardcoding it. **Still needs a human**: registering
|
|
1417
|
-
`astra-cli-agent` on PyPI, adding the trusted-publisher entry (repo + `release.yml` +
|
|
1418
|
-
`pypi` environment name), and creating the `pypi` GitHub Environment — none of that is
|
|
1419
|
-
executable from inside a coding session. Step-by-step instructions for that are now in
|
|
1420
|
-
README.md's "Releasing (maintainers)" section.
|
|
1421
|
-
|
|
1422
|
-
**New: `astra setup` — first-run provider onboarding**, the same "prompt for what's needed
|
|
1423
|
-
before doing anything else" pattern other terminal AI CLIs use, since Astra previously just
|
|
1424
|
-
failed with a raw `AllProvidersFailedError` if no `.env` had been hand-edited yet.
|
|
1425
|
-
- `core/onboarding.py`: `configured_providers()` (which of `GROQ_API_KEY`/
|
|
1426
|
-
`ANTHROPIC_API_KEY`/`OPENAI_API_KEY` are non-empty in the environment) and
|
|
1427
|
-
`is_provider_configured()`. Ollama needs no key, so a completed wizard run always writes
|
|
1428
|
-
an `ASTRA_SETUP_COMPLETE=true` marker to `~/.astra/.env` regardless of which provider was
|
|
1429
|
-
chosen — otherwise an Ollama-only setup would trigger onboarding forever.
|
|
1430
|
-
- `cli/setup.py`: `astra setup` — an interactive loop over Groq/Anthropic/OpenAI/Ollama.
|
|
1431
|
-
For a cloud provider, the key is tested with one real, cheap completion call
|
|
1432
|
-
(`temperature=0, max_tokens=5`, "reply with exactly: ok") **before** being saved, using
|
|
1433
|
-
the same `LiteLLMClient`/`OllamaClient` adapters the real router uses — not a separate
|
|
1434
|
-
validation path that could drift from what actually works. A failed test doesn't silently
|
|
1435
|
-
discard the key; the user is asked whether to save it anyway (e.g. a transient network
|
|
1436
|
-
blip). `_write_env_vars()` updates `~/.astra/.env` in place, preserving unrelated lines
|
|
1437
|
-
and replacing an existing key rather than duplicating it, and applies the same values to
|
|
1438
|
-
`os.environ` immediately so the rest of that process sees them with no restart needed.
|
|
1439
|
-
Loops until the user declines "configure another provider" (recommended, since
|
|
1440
|
-
`FallbackRouter` only has something to fall back to if more than one is configured).
|
|
1441
|
-
- `ensure_provider_or_prompt()` is called at the top of `ask`, `run` (i.e. `astra
|
|
1442
|
-
"<prompt>"`), and `chat` — the three commands that actually make an LLM call — before
|
|
1443
|
-
they touch the graph/router at all. If nothing is configured, it offers to run the wizard
|
|
1444
|
-
right there (`typer.confirm`, default yes); declining prints how to run `astra setup`
|
|
1445
|
-
later and exits cleanly (code 1) instead of a raw provider-chain stack trace. `hello`
|
|
1446
|
-
deliberately does **not** force this (it's meant to stay a side-effect-free sanity check)
|
|
1447
|
-
— it now just reports provider status passively (`LLM provider configured: groq` or a
|
|
1448
|
-
yellow "run astra setup" nudge).
|
|
1449
|
-
- `"setup"` added to `cli/app.py`'s `_KNOWN_COMMANDS` (same manual-upkeep gotcha flagged in
|
|
1450
|
-
§3 — every new top-level command needs an entry here or `resolve_argv` mis-rewrites it).
|
|
1451
|
-
|
|
1452
|
-
Tests: `tests/unit/test_onboarding.py` (5, pure env-var logic), `tests/unit/test_setup.py`
|
|
1453
|
-
(12, `monkeypatch`-injected fake `LiteLLMClient`/`OllamaClient` + a `typer.prompt`/
|
|
1454
|
-
`typer.confirm` fake-queue harness + a `tmp_path`-redirected `USER_CONFIG_DIR` — covering
|
|
1455
|
-
the env-file write/preserve/replace behavior, a working-key save, a bad-key decline, a
|
|
1456
|
-
bad-key "save anyway", Ollama configuration, an empty-key skip, the full wizard's
|
|
1457
|
-
save-marker-after-one-provider path, and all three `ensure_provider_or_prompt` branches),
|
|
1458
|
-
plus one new case in `tests/unit/test_cli.py` (`setup` recognized by `resolve_argv`). Full
|
|
1459
|
-
suite: 289 passed + 36 skipped (unchanged kubernetes-cluster skip count), `ruff check .` and
|
|
1460
|
-
`mypy src` (strict) both clean.
|
|
1461
|
-
|
|
1462
|
-
**Verified live** (real Groq calls, two disposable `$HOME` sandboxes, never touching the
|
|
1463
|
-
real `~/.astra`): direct call to `_test_cloud_provider("groq", ...)` with the real key from
|
|
1464
|
-
this repo's `.env` → genuine `'ok'` response, proving the wizard's key-test path itself
|
|
1465
|
-
works against the real API, not just mocked tests. Full interactive wizard end-to-end via a
|
|
1466
|
-
piped-stdin `astra setup` run against a real Groq key in a fresh sandbox `$HOME` → real
|
|
1467
|
-
`✓ got a real response from groq/llama-3.3-70b-versatile: 'ok'`, key + completion marker
|
|
1468
|
-
written to that sandbox's `~/.astra/.env`. Separately, `astra ask "hello"` in a **different**
|
|
1469
|
-
fresh sandbox `$HOME` with zero providers configured → the auto-prompt fired
|
|
1470
|
-
("No LLM provider is configured yet... Run the setup wizard now?"), walked through the full
|
|
1471
|
-
wizard with a deliberately invalid key, correctly reported the real Groq `invalid_api_key`
|
|
1472
|
-
error, saved it anyway on user confirmation, then proceeded to actually attempt the real
|
|
1473
|
-
request — which failed for the expected reason (bad key) with the real
|
|
1474
|
-
`AllProvidersFailedError` chain, proving `ensure_provider_or_prompt()` actually gates the
|
|
1475
|
-
call rather than just running cosmetically. `astra hello` confirmed to report
|
|
1476
|
-
`LLM provider configured: groq` correctly in this repo's own already-configured environment
|
|
1477
|
-
without prompting (passive path).
|
|
1478
|
-
|
|
1479
|
-
**Caught by real CI, not by local testing**: pushing the onboarding change broke 8 of the
|
|
1480
|
-
10 `tests/integration/` tests on GitHub's runner (green locally beforehand) —
|
|
1481
|
-
`ensure_provider_or_prompt()` only checks provider API-key env vars, so it didn't know
|
|
1482
|
-
`patch_router()` (the integration suite's helper for swapping in a `FakeRouter`) had
|
|
1483
|
-
already made the pipeline fully working; it blocked on a real `typer.confirm` prompt with
|
|
1484
|
-
no piped stdin and aborted. Invisible locally because this repo's own `.env` (real Groq
|
|
1485
|
-
key, gitignored) always made `is_provider_configured()` true regardless of the bug —
|
|
1486
|
-
GitHub's runner has no such file, by design (§4 item 15/CI notes: no `GROQ_API_KEY` secret
|
|
1487
|
-
configured, deliberately, so CI never spends real API money). Fixed by having
|
|
1488
|
-
`tests/integration/_helpers.py`'s `patch_router()` also `monkeypatch.setenv("GROQ_API_KEY",
|
|
1489
|
-
"test-fake-key")` — it's already simulating a working provider, so the gate should see one
|
|
1490
|
-
too. Reverified **the actual failure mode**, not just the fix, by temporarily moving this
|
|
1491
|
-
repo's real `.env` aside and re-running `tests/integration/` in a fresh `$HOME`: all 10
|
|
1492
|
-
failed the same way pre-fix, all 10 passed post-fix — then pushed again and confirmed the
|
|
1493
|
-
real GitHub Actions run went green. This is exactly the kind of gap `tests/integration/`
|
|
1494
|
-
(Phase 17) exists to catch and mostly did — except a gate that behaves differently based on
|
|
1495
|
-
ambient env state needs either a credential-free CI runner (which this repo already has) or
|
|
1496
|
-
a local repro with the same env, and this session's first local check used the wrong one.
|
|
1497
|
-
|
|
1498
|
-
⚠️ **Unrelated pre-existing issue noticed, not fixed (out of scope for this session)**:
|
|
1499
|
-
during the bad-key live test above, the fallback chain's `anthropic` attempt failed with
|
|
1500
|
-
`litellm.UnsupportedParamsError: claude-sonnet-5 does not support temperature=0.2. Only
|
|
1501
|
-
temperature=1 is supported.` — `defaults.yaml`'s `llm.temperature: 0.2` default is
|
|
1502
|
-
incompatible with the `claude-sonnet-5` model name in the same file's fallback chain.
|
|
1503
|
-
Whoever next touches `llm/router.py` or `config/defaults.yaml` should either drop
|
|
1504
|
-
`temperature` for Anthropic calls or pin a different default model — flagging here so it
|
|
1505
|
-
isn't mistaken for something this session broke.
|
|
1506
|
-
|
|
1507
|
-
All 18 phases from the architecture doc's phase list are now built. What's left:
|
|
1508
|
-
1. ~~**Prove `ci.yml` actually runs**~~ — **closed in §8**: a GitHub remote now exists
|
|
1509
|
-
(`https://github.com/Subharjun/astra-cli`, private), pushed, and the push-triggered `ci.yml`
|
|
1510
|
-
run went fully green on real GitHub-hosted infrastructure (checkout → Python 3.12 → `uv`
|
|
1511
|
-
install → ruff → mypy → pytest, 3m32s). See §8 for the run details.
|
|
1512
|
-
2. **Prove `release.yml` actually publishes**: register `astra-cli` as a PyPI project, add a
|
|
1513
|
-
trusted publisher entry pointing at this repo (see Phase 18's section above for the exact
|
|
1514
|
-
fields needed), create the `pypi` GitHub Environment, then cut a real `v0.1.0` GitHub Release
|
|
1515
|
-
and confirm the package actually lands on PyPI.
|
|
1516
|
-
3. **Live-verify Phase 15's LangSmith tracing** if a working `lsv2_...` key turns up — both keys
|
|
1517
|
-
tried in that session were rejected with `403 Forbidden`, so this is still only code-complete,
|
|
1518
|
-
not confirmed working end-to-end.
|
|
1519
|
-
|
|
1520
|
-
Neither remaining item blocks calling the project "done" in the sense the original 18-phase plan
|
|
1521
|
-
meant — they're external-account-setup steps (PyPI trusted-publisher registration, a valid
|
|
1522
|
-
LangSmith key) that fall outside what a coding session alone can complete.
|
|
1396
|
+
automation.~~ — **fully proven, not just code-complete — see §8 (CI verified live on real
|
|
1397
|
+
GitHub infrastructure) and §9/§10 (PyPI package actually published and installable as
|
|
1398
|
+
`astra-cli-agent`, real GitHub Releases cut for v0.1.0/v0.1.1/v0.1.2).**
|
|
1523
1399
|
|
|
1524
1400
|
---
|
|
1525
1401
|
|
|
@@ -1750,3 +1626,290 @@ credential-blocked live search test now passes for real instead of skipping), `r
|
|
|
1750
1626
|
|
|
1751
1627
|
**Verified live**: `gh run list` / `gh run watch` against the real run — every step (`Ruff`,
|
|
1752
1628
|
`Mypy`, `Pytest`) shows a genuine ✓ from the GitHub-hosted runner.
|
|
1629
|
+
|
|
1630
|
+
---
|
|
1631
|
+
|
|
1632
|
+
## 9. Post-Phase-18 addendum (2026-07-11): CI verified live, PyPI rename, first-run onboarding
|
|
1633
|
+
|
|
1634
|
+
This session found Phase 18's "known gap" note (§4 above, "CI never run on real GitHub
|
|
1635
|
+
infrastructure") was **stale** — a remote had since been added and pushed outside of a
|
|
1636
|
+
tracked phase. Checked directly: `git remote -v` shows `origin` →
|
|
1637
|
+
`github.com/Subharjun/astra-cli` (private), `git log` shows two commits already pushed to
|
|
1638
|
+
`main`, and `gh run list` shows both pushes triggered a real `CI` workflow run on GitHub's
|
|
1639
|
+
infrastructure — both green. **Nothing left to do for CI itself.** Whoever picks this up
|
|
1640
|
+
next should open PRs against `main` going forward rather than pushing directly, now that
|
|
1641
|
+
CI is live and would actually gate them.
|
|
1642
|
+
|
|
1643
|
+
**PyPI blocker found and resolved**: `astra-cli` (the name Phase 18 assumed would be
|
|
1644
|
+
registered) is already taken on PyPI by an unrelated project (a different "Astra agent
|
|
1645
|
+
framework" CLI, owned by a different PyPI user). Confirmed via `curl
|
|
1646
|
+
https://pypi.org/pypi/astra-cli/json` returning a real, different project's metadata, not
|
|
1647
|
+
a 404. **Renamed the PyPI distribution name to `astra-cli-agent`** (confirmed available via
|
|
1648
|
+
a 404 check first) in `pyproject.toml`'s `[project].name` — **the installed console command
|
|
1649
|
+
stays `astra`** (`[project.scripts]` unchanged), so this is a packaging-metadata-only
|
|
1650
|
+
rename, not a UX change. `docs/ARCHITECTURE.md`'s install-target line and `README.md`
|
|
1651
|
+
updated to match; `.github/workflows/release.yml` needed no changes since it reads the name
|
|
1652
|
+
from `pyproject.toml` rather than hardcoding it. **Still needs a human**: registering
|
|
1653
|
+
`astra-cli-agent` on PyPI, adding the trusted-publisher entry (repo + `release.yml` +
|
|
1654
|
+
`pypi` environment name), and creating the `pypi` GitHub Environment — none of that is
|
|
1655
|
+
executable from inside a coding session. Step-by-step instructions for that are now in
|
|
1656
|
+
README.md's "Releasing (maintainers)" section.
|
|
1657
|
+
|
|
1658
|
+
**New: `astra setup` — first-run provider onboarding**, the same "prompt for what's needed
|
|
1659
|
+
before doing anything else" pattern other terminal AI CLIs use, since Astra previously just
|
|
1660
|
+
failed with a raw `AllProvidersFailedError` if no `.env` had been hand-edited yet.
|
|
1661
|
+
- `core/onboarding.py`: `configured_providers()` (which of `GROQ_API_KEY`/
|
|
1662
|
+
`ANTHROPIC_API_KEY`/`OPENAI_API_KEY` are non-empty in the environment) and
|
|
1663
|
+
`is_provider_configured()`. Ollama needs no key, so a completed wizard run always writes
|
|
1664
|
+
an `ASTRA_SETUP_COMPLETE=true` marker to `~/.astra/.env` regardless of which provider was
|
|
1665
|
+
chosen — otherwise an Ollama-only setup would trigger onboarding forever.
|
|
1666
|
+
- `cli/setup.py`: `astra setup` — an interactive loop over Groq/Anthropic/OpenAI/Ollama.
|
|
1667
|
+
For a cloud provider, the key is tested with one real, cheap completion call
|
|
1668
|
+
(`temperature=0, max_tokens=5`, "reply with exactly: ok") **before** being saved, using
|
|
1669
|
+
the same `LiteLLMClient`/`OllamaClient` adapters the real router uses — not a separate
|
|
1670
|
+
validation path that could drift from what actually works. A failed test doesn't silently
|
|
1671
|
+
discard the key; the user is asked whether to save it anyway (e.g. a transient network
|
|
1672
|
+
blip). `_write_env_vars()` updates `~/.astra/.env` in place, preserving unrelated lines
|
|
1673
|
+
and replacing an existing key rather than duplicating it, and applies the same values to
|
|
1674
|
+
`os.environ` immediately so the rest of that process sees them with no restart needed.
|
|
1675
|
+
Loops until the user declines "configure another provider" (recommended, since
|
|
1676
|
+
`FallbackRouter` only has something to fall back to if more than one is configured).
|
|
1677
|
+
- `ensure_provider_or_prompt()` is called at the top of `ask`, `run` (i.e. `astra
|
|
1678
|
+
"<prompt>"`), and `chat` — the three commands that actually make an LLM call — before
|
|
1679
|
+
they touch the graph/router at all. If nothing is configured, it offers to run the wizard
|
|
1680
|
+
right there (`typer.confirm`, default yes); declining prints how to run `astra setup`
|
|
1681
|
+
later and exits cleanly (code 1) instead of a raw provider-chain stack trace. `hello`
|
|
1682
|
+
deliberately does **not** force this (it's meant to stay a side-effect-free sanity check)
|
|
1683
|
+
— it now just reports provider status passively (`LLM provider configured: groq` or a
|
|
1684
|
+
yellow "run astra setup" nudge).
|
|
1685
|
+
- `"setup"` added to `cli/app.py`'s `_KNOWN_COMMANDS` (same manual-upkeep gotcha flagged in
|
|
1686
|
+
§3 — every new top-level command needs an entry here or `resolve_argv` mis-rewrites it).
|
|
1687
|
+
|
|
1688
|
+
Tests: `tests/unit/test_onboarding.py` (5, pure env-var logic), `tests/unit/test_setup.py`
|
|
1689
|
+
(12, `monkeypatch`-injected fake `LiteLLMClient`/`OllamaClient` + a `typer.prompt`/
|
|
1690
|
+
`typer.confirm` fake-queue harness + a `tmp_path`-redirected `USER_CONFIG_DIR` — covering
|
|
1691
|
+
the env-file write/preserve/replace behavior, a working-key save, a bad-key decline, a
|
|
1692
|
+
bad-key "save anyway", Ollama configuration, an empty-key skip, the full wizard's
|
|
1693
|
+
save-marker-after-one-provider path, and all three `ensure_provider_or_prompt` branches),
|
|
1694
|
+
plus one new case in `tests/unit/test_cli.py` (`setup` recognized by `resolve_argv`). Full
|
|
1695
|
+
suite: 289 passed + 36 skipped (unchanged kubernetes-cluster skip count), `ruff check .` and
|
|
1696
|
+
`mypy src` (strict) both clean.
|
|
1697
|
+
|
|
1698
|
+
**Verified live** (real Groq calls, two disposable `$HOME` sandboxes, never touching the
|
|
1699
|
+
real `~/.astra`): direct call to `_test_cloud_provider("groq", ...)` with the real key from
|
|
1700
|
+
this repo's `.env` → genuine `'ok'` response, proving the wizard's key-test path itself
|
|
1701
|
+
works against the real API, not just mocked tests. Full interactive wizard end-to-end via a
|
|
1702
|
+
piped-stdin `astra setup` run against a real Groq key in a fresh sandbox `$HOME` → real
|
|
1703
|
+
`✓ got a real response from groq/llama-3.3-70b-versatile: 'ok'`, key + completion marker
|
|
1704
|
+
written to that sandbox's `~/.astra/.env`. Separately, `astra ask "hello"` in a **different**
|
|
1705
|
+
fresh sandbox `$HOME` with zero providers configured → the auto-prompt fired
|
|
1706
|
+
("No LLM provider is configured yet... Run the setup wizard now?"), walked through the full
|
|
1707
|
+
wizard with a deliberately invalid key, correctly reported the real Groq `invalid_api_key`
|
|
1708
|
+
error, saved it anyway on user confirmation, then proceeded to actually attempt the real
|
|
1709
|
+
request — which failed for the expected reason (bad key) with the real
|
|
1710
|
+
`AllProvidersFailedError` chain, proving `ensure_provider_or_prompt()` actually gates the
|
|
1711
|
+
call rather than just running cosmetically. `astra hello` confirmed to report
|
|
1712
|
+
`LLM provider configured: groq` correctly in this repo's own already-configured environment
|
|
1713
|
+
without prompting (passive path).
|
|
1714
|
+
|
|
1715
|
+
**Caught by real CI, not by local testing**: pushing the onboarding change broke 8 of the
|
|
1716
|
+
10 `tests/integration/` tests on GitHub's runner (green locally beforehand) —
|
|
1717
|
+
`ensure_provider_or_prompt()` only checks provider API-key env vars, so it didn't know
|
|
1718
|
+
`patch_router()` (the integration suite's helper for swapping in a `FakeRouter`) had
|
|
1719
|
+
already made the pipeline fully working; it blocked on a real `typer.confirm` prompt with
|
|
1720
|
+
no piped stdin and aborted. Invisible locally because this repo's own `.env` (real Groq
|
|
1721
|
+
key, gitignored) always made `is_provider_configured()` true regardless of the bug —
|
|
1722
|
+
GitHub's runner has no such file, by design (§4 item 15/CI notes: no `GROQ_API_KEY` secret
|
|
1723
|
+
configured, deliberately, so CI never spends real API money). Fixed by having
|
|
1724
|
+
`tests/integration/_helpers.py`'s `patch_router()` also `monkeypatch.setenv("GROQ_API_KEY",
|
|
1725
|
+
"test-fake-key")` — it's already simulating a working provider, so the gate should see one
|
|
1726
|
+
too. Reverified **the actual failure mode**, not just the fix, by temporarily moving this
|
|
1727
|
+
repo's real `.env` aside and re-running `tests/integration/` in a fresh `$HOME`: all 10
|
|
1728
|
+
failed the same way pre-fix, all 10 passed post-fix — then pushed again and confirmed the
|
|
1729
|
+
real GitHub Actions run went green. This is exactly the kind of gap `tests/integration/`
|
|
1730
|
+
(Phase 17) exists to catch and mostly did — except a gate that behaves differently based on
|
|
1731
|
+
ambient env state needs either a credential-free CI runner (which this repo already has) or
|
|
1732
|
+
a local repro with the same env, and this session's first local check used the wrong one.
|
|
1733
|
+
|
|
1734
|
+
⚠️ **Unrelated pre-existing issue noticed, not fixed (out of scope for this session)**:
|
|
1735
|
+
during the bad-key live test above, the fallback chain's `anthropic` attempt failed with
|
|
1736
|
+
`litellm.UnsupportedParamsError: claude-sonnet-5 does not support temperature=0.2. Only
|
|
1737
|
+
temperature=1 is supported.` — `defaults.yaml`'s `llm.temperature: 0.2` default is
|
|
1738
|
+
incompatible with the `claude-sonnet-5` model name in the same file's fallback chain.
|
|
1739
|
+
Whoever next touches `llm/router.py` or `config/defaults.yaml` should either drop
|
|
1740
|
+
`temperature` for Anthropic calls or pin a different default model — flagging here so it
|
|
1741
|
+
isn't mistaken for something this session broke.
|
|
1742
|
+
|
|
1743
|
+
All 18 phases from the architecture doc's phase list are now built. What's left:
|
|
1744
|
+
1. ~~**Prove `ci.yml` actually runs**~~ — **closed in §8**: a GitHub remote now exists
|
|
1745
|
+
(`https://github.com/Subharjun/astra-cli`, private), pushed, and the push-triggered `ci.yml`
|
|
1746
|
+
run went fully green on real GitHub-hosted infrastructure (checkout → Python 3.12 → `uv`
|
|
1747
|
+
install → ruff → mypy → pytest, 3m32s). See §8 for the run details.
|
|
1748
|
+
2. ~~**Prove `release.yml` actually publishes**~~ — **closed in §10**: the user registered
|
|
1749
|
+
`astra-cli-agent` (not `astra-cli` — see the PyPI-blocker paragraph above) as a PyPI pending
|
|
1750
|
+
publisher and created the `pypi` GitHub Environment; `v0.1.0` was tagged and released, and
|
|
1751
|
+
the package landed on PyPI for real, confirmed via a fresh-venv `pip install`. See §10.
|
|
1752
|
+
3. **Live-verify Phase 15's LangSmith tracing** if a working `lsv2_...` key turns up — both keys
|
|
1753
|
+
tried in that session were rejected with `403 Forbidden`, so this is still only code-complete,
|
|
1754
|
+
not confirmed working end-to-end. **Still open** as of §10.
|
|
1755
|
+
|
|
1756
|
+
Neither remaining item blocks calling the project "done" in the sense the original 18-phase plan
|
|
1757
|
+
meant — they're external-account-setup steps (PyPI trusted-publisher registration, a valid
|
|
1758
|
+
LangSmith key) that fall outside what a coding session alone can complete.
|
|
1759
|
+
|
|
1760
|
+
---
|
|
1761
|
+
|
|
1762
|
+
## 10. Public release (2026-07-11): PyPI v0.1.0–v0.1.2 shipped, public README repo, big banner
|
|
1763
|
+
|
|
1764
|
+
Continuation of §9 in the same calling session. §9 left two things pending on the user: register
|
|
1765
|
+
`astra-cli-agent` as a PyPI pending publisher, and create the `pypi` GitHub Environment. Both
|
|
1766
|
+
confirmed done — `gh api repos/Subharjun/astra-cli/environments` showed a real `pypi` environment
|
|
1767
|
+
(created `2026-07-11T11:57:25Z`, no protection rules).
|
|
1768
|
+
|
|
1769
|
+
### v0.1.0: first real PyPI publish
|
|
1770
|
+
|
|
1771
|
+
- Tagged `v0.1.0`, pushed the tag, `gh release create v0.1.0 --generate-notes` — publishing that
|
|
1772
|
+
Release fired `release.yml` for real. Green on the first try (`build` → sdist+wheel →
|
|
1773
|
+
`publish` via PyPI trusted-publishing/OIDC, no token anywhere in the repo).
|
|
1774
|
+
- **Verified live, not just "the workflow said success"**: fresh `python3 -m venv` +
|
|
1775
|
+
`pip install astra-cli-agent` from the real public index, `astra version` → `astra 0.1.0`,
|
|
1776
|
+
`astra hello`, `astra --help` all worked, including the onboarding nudge
|
|
1777
|
+
("No LLM provider configured yet. Run astra setup to get started.") firing correctly for a
|
|
1778
|
+
genuinely fresh install.
|
|
1779
|
+
- Downloaded the actual published wheel from `files.pythonhosted.org` and grepped its contents
|
|
1780
|
+
for `.env`/secret/key patterns — zero matches, confirming no credentials ship in the package
|
|
1781
|
+
(the user asked directly whether this was possible; answered from direct inspection, not
|
|
1782
|
+
inference).
|
|
1783
|
+
|
|
1784
|
+
### Public-repo privacy discussion, and what actually got built
|
|
1785
|
+
|
|
1786
|
+
The user wants the source private but still wants a public, installable package. Clarified for
|
|
1787
|
+
the record: the private GitHub repo (`Subharjun/astra-cli`) staying private does **not** make the
|
|
1788
|
+
PyPI package private — PyPI is a public index, and the wheel/sdist contain full `.py` source
|
|
1789
|
+
regardless of GitHub visibility, since Python isn't compiled/obfuscated. There is no "private
|
|
1790
|
+
PyPI project with public `pip install`" without a separate private index (Gemfury/Cloudsmith/
|
|
1791
|
+
self-hosted devpi) or installing straight from the private GitHub repo via `pip install
|
|
1792
|
+
git+https://...`. Presented these options; **user chose to publish to PyPI anyway** (source
|
|
1793
|
+
downloadable via `pip download`/wheel inspection is an accepted tradeoff) but wanted the
|
|
1794
|
+
**GitHub side to show a separate public repo containing only usage instructions, not source**.
|
|
1795
|
+
|
|
1796
|
+
- Created `Subharjun/astra-cli-agent` as a new public GitHub repo (separate from the private
|
|
1797
|
+
`Subharjun/astra-cli`, which stays the real working repo and stays private).
|
|
1798
|
+
- **First attempt was wrong and had to be corrected**: initially pushed the *entire* private
|
|
1799
|
+
repo's history (all source, all commits, the `v0.1.0` tag) to the new public repo — a
|
|
1800
|
+
misreading of "public repo" as "public mirror." User corrected explicitly: *"no no public repo
|
|
1801
|
+
just readme.md file no other just instructions."*
|
|
1802
|
+
- **Fix**: deleted the `v0.1.0` tag from the public repo. Attempted `gh repo delete` to start
|
|
1803
|
+
clean, but `gh`'s token lacks the `delete_repo` scope, and granting it requires an interactive
|
|
1804
|
+
browser OAuth step this non-interactive session can't complete (`gh auth refresh -h github.com
|
|
1805
|
+
-s delete_repo` needs a device-code confirmation in a browser). Instead, sanitized the existing
|
|
1806
|
+
repo: built a fresh orphan git history (`git init` in a scratch dir, one commit containing only
|
|
1807
|
+
`README.md`) and `git push --force` to replace `main` entirely. Verified after the fact via the
|
|
1808
|
+
GitHub API: `main` has exactly 1 commit, `contents/` lists only `README.md`, zero other
|
|
1809
|
+
branches, zero tags. ⚠️ **Known residual caveat, disclosed to the user**: force-replacing history
|
|
1810
|
+
makes the old source-containing commit unreachable from any ref (so it won't appear anywhere in
|
|
1811
|
+
GitHub's UI/history), but without the `delete_repo`+recreate path there's no hard guarantee
|
|
1812
|
+
GitHub has garbage-collected the underlying git objects yet — a direct-SHA lookup could
|
|
1813
|
+
theoretically still resolve for some window. Full delete+recreate remains the only airtight fix,
|
|
1814
|
+
and needs the user (or a session with `delete_repo` scope granted interactively) to do it.
|
|
1815
|
+
- The public repo's `README.md` is a trimmed variant of the main README: badges (PyPI version +
|
|
1816
|
+
Python version only — no CI badge, since no workflow lives in this repo; no license badge/file,
|
|
1817
|
+
since "no other files" was explicit), the same feature table, install/quickstart/config/MCP
|
|
1818
|
+
sections, no "Contributing/development" section (there's no source here to clone/build).
|
|
1819
|
+
|
|
1820
|
+
### README beautification + LICENSE + pyproject metadata (private repo)
|
|
1821
|
+
|
|
1822
|
+
- `README.md` (private repo) rewritten: leads with badges (PyPI version, Python version, CI
|
|
1823
|
+
status, MIT license), a feature table per agent domain (git/filesystem/shell/docker/k8s/web/
|
|
1824
|
+
debug/docs/MCP), a proper quickstart walking through `astra setup` → example commands → the
|
|
1825
|
+
confirmation-gate behavior, an MCP-server config example, and a "Contributing/development"
|
|
1826
|
+
section — replacing the old stub that just said "early scaffold" and listed two commands.
|
|
1827
|
+
- Added `LICENSE` (MIT) — `pyproject.toml` had declared `license = { text = "MIT" }` since Phase 2
|
|
1828
|
+
but no `LICENSE` file had ever actually been created; added now that the project has real public
|
|
1829
|
+
surface area.
|
|
1830
|
+
- Added `[project.urls]` (`Homepage`, `Issues`) to `pyproject.toml`, pointing at the new public
|
|
1831
|
+
`astra-cli-agent` GitHub repo — no `Repository` key, since that repo is README-only and calling
|
|
1832
|
+
it "the repository" would be misleading about where the source actually lives.
|
|
1833
|
+
- **Real build-breaking bug caught by CI, not locally**: the first `[project.urls]` edit placed
|
|
1834
|
+
the table header *before* the existing `dependencies = [...]` list inside `[project]` — in TOML,
|
|
1835
|
+
a table header ends the previous table, so `dependencies` silently became a key under
|
|
1836
|
+
`[project.urls]` instead of `[project]`. `hatchling` rejected this outright at build time
|
|
1837
|
+
(`TypeError: URL 'dependencies' of field 'project.urls' must be a string`), breaking `pip
|
|
1838
|
+
install`/`uv pip install -e .` entirely. Invisible locally because the dev venv already had the
|
|
1839
|
+
package installed from before the bad edit — first surfaced when CI ran `uv pip install --system
|
|
1840
|
+
-e ".[dev]"` from scratch on the newly-created public-repo push and failed at the install step.
|
|
1841
|
+
Fixed by moving `[project.urls]` after `[project.optional-dependencies]`; reverified with a real
|
|
1842
|
+
`uv pip install -e ".[dev]"` from scratch plus the full test suite before pushing again.
|
|
1843
|
+
|
|
1844
|
+
### Big ASCII banner (user-requested: "make it appear big... typer or rich")
|
|
1845
|
+
|
|
1846
|
+
User feedback: the CLI's presence "doesn't feel like Claude" and asked for something bigger, using
|
|
1847
|
+
Typer or Rich. `print_banner()` previously wrapped the word "Astra" in a one-line-tall bordered
|
|
1848
|
+
`Panel` — replaced with a real figlet wordmark:
|
|
1849
|
+
|
|
1850
|
+
- New runtime dependency `pyfiglet` (pure Python, zero transitive deps) — lazy-imported inside
|
|
1851
|
+
`print_banner()`, same "pay for it only where it's used" convention `litellm`/
|
|
1852
|
+
`sentence-transformers`/`mcp` already follow, since only three interactive commands need it.
|
|
1853
|
+
- `cli/rendering.py`: `print_banner()` now renders `pyfiglet.figlet_format("ASTRA", font="slant")`
|
|
1854
|
+
as a Rich `Text`, coloring each line with a fixed cyan→violet gradient (`_BANNER_GRADIENT`,
|
|
1855
|
+
5 hex stops, purely cosmetic — no meaning attached to the specific colors), followed by the
|
|
1856
|
+
"your terminal AI developer assistant" tagline in dim italic.
|
|
1857
|
+
- Wired into `hello` and `setup` (already had the old banner) and **newly into `cli/chat.py`'s
|
|
1858
|
+
`run_chat()`** startup, which previously printed only a plain one-line `"Astra chat"` label with
|
|
1859
|
+
no banner at all.
|
|
1860
|
+
- Deliberately **not** added to `ask`/`run` (`astra "<prompt>"`) — those are also used
|
|
1861
|
+
non-interactively/scripted/piped, and a multi-line ASCII banner on every scripted invocation
|
|
1862
|
+
would be noise, not polish.
|
|
1863
|
+
|
|
1864
|
+
### Shipped as v0.1.1 — then a real bug found in production, fixed as v0.1.2
|
|
1865
|
+
|
|
1866
|
+
- Bumped `pyproject.toml` to `0.1.1`, tagged, released — `release.yml` published it for real.
|
|
1867
|
+
- **Live-verified in a fresh venv, and this is what caught the bug**: `astra hello` showed the new
|
|
1868
|
+
banner correctly, but `astra version` printed `astra 0.1.0` — one version behind what was just
|
|
1869
|
+
explicitly installed (`pip install astra-cli-agent==0.1.1`).
|
|
1870
|
+
- **Root cause**: `src/astra/__init__.py`'s `__version__` was a hardcoded string literal,
|
|
1871
|
+
completely disconnected from `pyproject.toml`'s `version` field — nothing had ever wired them
|
|
1872
|
+
together, all the way back to Phase 2. It happened to read `"0.1.0"` and nobody had bumped it
|
|
1873
|
+
during any of the version changes this session, since local dev testing via `pip install -e .`
|
|
1874
|
+
never surfaces the mismatch the way a real "install a specific released version and check what
|
|
1875
|
+
it reports" test does.
|
|
1876
|
+
- **Fixed properly, not just patched for this one instance**: `__version__` now resolves via
|
|
1877
|
+
`importlib.metadata.version("astra-cli-agent")` at import time (falls back to a hardcoded
|
|
1878
|
+
constant only if run from a source checkout with no installed distribution metadata at all,
|
|
1879
|
+
which shouldn't happen via any normal install path). This makes future drift structurally
|
|
1880
|
+
impossible for anyone who installs the package normally — `astra version` will always match
|
|
1881
|
+
whatever's actually installed.
|
|
1882
|
+
- Bumped to `0.1.2`, tagged, released, published. **Live-verified again** in a completely fresh
|
|
1883
|
+
venv (`pip install astra-cli-agent==0.1.2`): `astra version` → `astra 0.1.2` correctly, banner
|
|
1884
|
+
renders correctly. This is the version currently live and correct on PyPI.
|
|
1885
|
+
|
|
1886
|
+
### Verification discipline held throughout
|
|
1887
|
+
|
|
1888
|
+
Every step in this section (banner change, LICENSE/README/pyproject edits, the TOML bug fix, the
|
|
1889
|
+
`__version__` fix) went through the same loop before being pushed: local `ruff check .` + `mypy
|
|
1890
|
+
src` (strict) + `pytest -q` all green (**289 passed, 36 skipped**, unchanged kubernetes-cluster
|
|
1891
|
+
skip count throughout), push, wait for real GitHub Actions CI to go green, *then* proceed — never
|
|
1892
|
+
assumed a fix worked from local state alone once a real CI failure had already been observed once
|
|
1893
|
+
this session (the `[project.urls]` TOML bug). Every PyPI publish was confirmed with a genuinely
|
|
1894
|
+
fresh `python3 -m venv` + `pip install` from the real index, not just "the release workflow
|
|
1895
|
+
reported success."
|
|
1896
|
+
|
|
1897
|
+
### Housekeeping: this document's own section numbering
|
|
1898
|
+
|
|
1899
|
+
This session found a pre-existing numbering collision in this very file: an earlier addendum had
|
|
1900
|
+
been inserted as "## 5. Post-Phase-18 addendum," directly colliding with an already-existing,
|
|
1901
|
+
differently-scoped "## 5. Environment state" section further down (itself part of an older
|
|
1902
|
+
5→6→7→8 sequence: Environment state, Working agreements, the post-18 hardening pass, and the
|
|
1903
|
+
web-search/GitHub-push section). Fixed by relocating that addendum to become **§9** (after §8,
|
|
1904
|
+
where it chronologically belongs — it discovered/confirmed work §8 had already done), and this
|
|
1905
|
+
section is **§10**. `§1`–`§8`'s existing numbers and every cross-reference to them elsewhere in
|
|
1906
|
+
this document were left untouched to avoid a much larger, riskier rewrite across ~1700 lines;
|
|
1907
|
+
only the previously-misnumbered/misplaced section was moved and renumbered.
|
|
1908
|
+
|
|
1909
|
+
**Final state as of this section**: all 18 phases built (§2), all known simplifications tracked
|
|
1910
|
+
(§3) with six closed in §7 and more in §9/§10, CI proven live on real GitHub infrastructure (§8),
|
|
1911
|
+
`astra-cli-agent` actually published and installable from PyPI at `v0.1.2` (this section),
|
|
1912
|
+
first-run provider onboarding shipped (§9), and a real ASCII-logo presence shipped (this
|
|
1913
|
+
section). Remaining open items are genuinely external: a working LangSmith key (§9 item 3) and,
|
|
1914
|
+
per §5's environment notes, a local kubernetes cluster to un-skip a handful of tests — neither
|
|
1915
|
+
blocks calling this project done and publicly usable.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: astra-cli-agent
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.3
|
|
4
4
|
Summary: Astra — a terminal AI assistant that understands natural language and drives your dev tools.
|
|
5
5
|
Project-URL: Homepage, https://github.com/Subharjun/astra-cli-agent
|
|
6
6
|
Project-URL: Issues, https://github.com/Subharjun/astra-cli-agent/issues
|
|
@@ -63,7 +63,7 @@ wrapping a shell call.
|
|
|
63
63
|
|
|
64
64
|
| Domain | Agent | Capabilities |
|
|
65
65
|
|---|---|---|
|
|
66
|
-
| Git | `GitAgent` | status, diff, log, blame, branch, commit (auto-generates messages), push, merge, checkout, stash |
|
|
66
|
+
| Git | `GitAgent` | status, diff, log, blame, branch, commit (auto-generates messages), push, merge, checkout, stash, plus GitHub API: create/delete repos, issues, pull requests (needs `GITHUB_TOKEN`) |
|
|
67
67
|
| Filesystem & code | `FileAgent` | read/write/move/delete files, lint & format (`ruff`), run tests (`pytest`), symbol search |
|
|
68
68
|
| Shell | `FileAgent` | runs arbitrary commands behind a hard denylist + confirmation gate |
|
|
69
69
|
| Docker | `DockerAgent` | ps, images, build, run, logs, exec, inspect, rm/rmi, prune |
|
|
@@ -73,6 +73,27 @@ wrapping a shell call.
|
|
|
73
73
|
| Documentation | `DocumentationAgent` | writes docstrings, README sections, usage guides |
|
|
74
74
|
| MCP | `MCPAgent` | connects to any configured MCP server (stdio, HTTP, or SSE) and discovers/calls its tools |
|
|
75
75
|
|
|
76
|
+
**Example prompts by domain** — every one of these routes automatically, no flags needed
|
|
77
|
+
beyond `--yes` for anything risky:
|
|
78
|
+
|
|
79
|
+
| Domain | Example prompt |
|
|
80
|
+
|---|---|
|
|
81
|
+
| Git | `astra "what's the git status here, and diff the uncommitted changes"` |
|
|
82
|
+
| Git | `astra "commit my staged changes with a good message" --yes` |
|
|
83
|
+
| Git | `astra "list the open issues on this github repo"` (needs `GITHUB_TOKEN`) |
|
|
84
|
+
| Filesystem & code | `astra "create a file called notes.md with a todo list"` |
|
|
85
|
+
| Filesystem & code | `astra "run the linter and the test suite on this project"` |
|
|
86
|
+
| Shell | `astra "run df -h and tell me how much disk space is free" --yes` |
|
|
87
|
+
| Docker | `astra "list all running docker containers"` |
|
|
88
|
+
| Docker | `astra "build a docker image from the Dockerfile in this directory" --yes` |
|
|
89
|
+
| Kubernetes | `astra "list the pods in the default namespace"` |
|
|
90
|
+
| Kubernetes | `astra "scale the api deployment to 3 replicas" --yes` |
|
|
91
|
+
| Web research | `astra "search stack overflow for how to fix a detached HEAD in git"` |
|
|
92
|
+
| Web research | `astra "find github repos for a python rate limiter library"` |
|
|
93
|
+
| Debugging | `astra "here's a stack trace, find the root cause and propose a fix: <paste>"` |
|
|
94
|
+
| Documentation | `astra "write a README section documenting the config file format"` |
|
|
95
|
+
| MCP | `astra "list the tools available from my configured MCP servers"` |
|
|
96
|
+
|
|
76
97
|
Also included:
|
|
77
98
|
|
|
78
99
|
- **Safety by default** — risky operations (`git push`, file delete, shell, container/exec
|
|
@@ -88,7 +109,9 @@ Also included:
|
|
|
88
109
|
- **Cost/token tracking** — `astra memory costs` shows a real per-provider/per-model
|
|
89
110
|
breakdown and daily spend trend, no external service required.
|
|
90
111
|
- **First-run onboarding** — `astra setup` walks you through picking a provider and tests
|
|
91
|
-
your key with a real request before saving it.
|
|
112
|
+
your key with a real request before saving it. Optionally continues into GitHub API
|
|
113
|
+
(`GITHUB_TOKEN`) and general web search (`SERPAPI_KEY`) setup, same real-tested-before-saved
|
|
114
|
+
flow.
|
|
92
115
|
|
|
93
116
|
See [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) for the full design and
|
|
94
117
|
[HANDOFF.md](HANDOFF.md) for exactly what's built, what's tested, and what's left.
|
|
@@ -131,6 +154,11 @@ is the fastest way to try Astra.
|
|
|
131
154
|
If you skip this step, the first command that actually needs an LLM (`ask`, a bare prompt,
|
|
132
155
|
or `chat`) will offer to run the wizard for you automatically.
|
|
133
156
|
|
|
157
|
+
The wizard then offers an optional second stage for feature-unlocking keys — a GitHub
|
|
158
|
+
personal access token (`GITHUB_TOKEN`, for the `github_*` tools) and a SerpApi key
|
|
159
|
+
(`SERPAPI_KEY`, for general web search) — same real-request-before-saving flow, skippable,
|
|
160
|
+
default no. Run `astra setup` again any time to add these later.
|
|
161
|
+
|
|
134
162
|
Then just talk to it — **from inside whatever project directory you want it to act on**,
|
|
135
163
|
since every tool call is scoped to your current working directory:
|
|
136
164
|
|
|
@@ -185,6 +213,34 @@ mcp:
|
|
|
185
213
|
|
|
186
214
|
`astra mcp tools` lists everything discovered from your configured servers.
|
|
187
215
|
|
|
216
|
+
## All commands
|
|
217
|
+
|
|
218
|
+
Beyond natural-language prompts, every subcommand below is a direct, non-LLM entrypoint:
|
|
219
|
+
|
|
220
|
+
```bash
|
|
221
|
+
astra hello # install/config/provider sanity check
|
|
222
|
+
astra version # print the installed version
|
|
223
|
+
astra setup # interactive onboarding wizard (LLM provider + optional integrations)
|
|
224
|
+
astra ask "<prompt>" # one-shot LLM call, bypasses the agent pipeline
|
|
225
|
+
astra chat # interactive REPL with streaming + history
|
|
226
|
+
astra ingest [path] # index a codebase for retrieval (defaults to .)
|
|
227
|
+
|
|
228
|
+
astra memory history [-n N] # recent conversation history
|
|
229
|
+
astra memory clear # wipe conversation history
|
|
230
|
+
astra memory costs # per-provider/per-model cost & token breakdown
|
|
231
|
+
astra memory projects # list ingested (RAG-indexed) projects
|
|
232
|
+
astra memory search "<query>" # test retrieval directly against an ingested project
|
|
233
|
+
astra memory prefs set <k> <v> # store a preference
|
|
234
|
+
astra memory prefs get <k> # read a preference
|
|
235
|
+
astra memory prefs list # list all preferences
|
|
236
|
+
|
|
237
|
+
astra mcp servers # list configured MCP servers
|
|
238
|
+
astra mcp tools # list tools discovered from configured MCP servers
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Any bare prompt (`astra "..."`) or `astra run "<prompt>"` triggers the full
|
|
242
|
+
router→planner→execute→reviewer→memory pipeline described above.
|
|
243
|
+
|
|
188
244
|
## Contributing / development
|
|
189
245
|
|
|
190
246
|
```bash
|