Changelog
Notable changes since the AutoGen → A2A migration. Each entry is
keyed by the merging pull request; full diffs live in
git log and on GitHub.
Unreleased
- Documentation overhaul: split detailed reference material into
docs/, tightenedREADME.md, and aligned both with the current code surface. - Documentation format: migrated the
docs/reference set from Markdown to static HTML pages with a shared local stylesheet and.htmlinternal links. - Maintenance: refreshed code comments and docstrings so they emphasize security, concurrency, configuration precedence, and persistence invariants without restating obvious code behavior.
0.2.0 (PR #9 — 17112b6)
P0 review follow-ups closing the last batch of API hardening items.
- Timestamps:
AgentSession.created_at/last_active, eachagents[*].created_at, and every executor history entry are now Unix wall-clock seconds viatime.time(). Clients can correlate session metadata with individual message timestamps. - Error responses: every unhandled exception is
logged with
logger.exception(...)and surfaces a generic{ "detail": "Internal server error" }to clients. Exception text is no longer echoed in HTTP responses. - API-key comparison:
verify_api_keyiterates the full allow-list without short-circuiting, usingsecrets.compare_digeston every entry. Empty headers are rejected outright. API_ALLOWED_KEYSparsing: blank entries from trailing commas or double commas are filtered, so a stray separator can no longer admit an empty key.- Repo metadata: added
.gitnexus/to.gitignore; appended GitNexus guidance toCLAUDE.md.
PR #8 — 96baf48
Runtime config and persona persistence hardening.
- LLM credential cascade:
load_configreadsdefault_modelfirst, then loadsapi_key/api_basefrom the matchingmodel_configsentry, with environment overrides winning. A global file-levelapi_keyno longer overrides a per-model key. save_personare-validation:Persona.save_personare-checks the ID regex and rejects path-traversal patterns (..,/,\, null bytes) before touching the filesystem, even though the model’s Pydantic validator already constrains the same field.- Tests: added
tests/test_review_fixes.pycovering the new config and persistence paths.
PR #7 — 3fa9e14
A2A executor await fixes, path-traversal hardening, and broader security tightening.
- Awaitable event queue: every
event_queue.enqueue_event(...)call is awaited. Status updates that previously dropped silently now reach clients. - Shared
chat()entry point: the legacy_run_llm_loopwas promoted to a publicchat(context_id, user_text)method. RESTsend_messageand the A2Aexecutepath both call it, so behavior cannot diverge. - Tool-iteration cap fallback: when
MAX_TOOL_ITERATIONS = 10is exceeded, the executor forces a final completion withtool_choice="none". Earlier versions stripped prior tool messages in a way that broke strict OpenAI-compatible providers. - Per-context concurrency: each
context_idis now serialized by anasyncio.Lock. Concurrent A2A or REST calls on the same conversation cannot interleave history writes. Histories are stored in an LRUOrderedDictcapped at 200 contexts; the corresponding lock is evicted with the history. - Persona ID safety:
Persona.idis constrained by^[a-z0-9_-]{1,64}$at the Pydantic layer and re-checked on save and delete. The loader sanitizes legacy IDs in place (with a warning) so pre-existing files keep loading. - Networking defaults: server binds to
127.0.0.1by default; CORSallow_credentialsis forced off whenallowed_originscontains*(with a warning). - Auth dependency: introduced
make_api_key_dependency(config)producing a FastAPI dependency that enforces the configured header. - Pydantic v2: replaced every
.dict()with.model_dump(). - Tests: added
test_auth.py,test_executor.py,test_persona_id_security.py.
PR #6 — d580a6e
Documentation pass after the A2A migration.
- Removed stale AutoGen references from
README.mdand docstrings.
PR #5 — bba117b
Migrated from AutoGen 0.4 to the Google A2A protocol.
- Removed:
src/persona_agent/core/persona_agent.py,core/agent_factory.py, and the AutoGen dependency. - Added:
a2a/executor.py,a2a/agent_card.py,llm/client.py,mcp/direct_mcp.py. Each persona is now an independent A2A ASGI sub-app built via the SDK’s publicA2AFastAPIApplication.build()API. - Shared infrastructure: REST routes and the A2A
executor share a single
LLMClientandDirectMCPManagerviaAgentFactory. - Net change: ~-2000 lines.