Skip to content

0.2.20

Choose a tag to compare

@DEENUU1 DEENUU1 released this 06 Oct 12:31
9006efd

Added

  • --llm-provider openai_compatible: any OpenAI-compatible gateway or
    server
    — model routers and LLM gateways (LiteLLM, Requesty, OrcaRouter,
    Portkey) and self-hosted servers (vLLM, llama.cpp, LM Studio, Ollama), reached
    by OPENAI_COMPATIBLE_BASE_URL, with AI_MODEL named as the endpoint names
    it and an optional OPENAI_COMPATIBLE_API_KEY (OPENAI_API_KEY is never sent
    there). Pydantic AI and Pydantic Deep Agents projects; OpenAI embeddings for
    RAG go to the same endpoint; Pydantic Deep Agents projects need
    pydantic-deep 0.3.50, which also compacts long conversations on that endpoint.
    One provider instead of a named one per gateway (#141, #156)

  • --memory: persistent per-user agent memory (Pydantic AI + PostgreSQL) —
    the assistant keeps a Markdown notebook per user with the
    pydantic-ai-harness Memory capability, reads it back at the start of
    every conversation, and gets write_memory / read_memory /
    delete_memory / search_memory tools, each rendered as a chat card. Users
    inspect, edit and delete every file on Settings → Memory
    (/api/v1/me/memory, optimistic-concurrency versions). With --teams each
    organisation gets its own notebook, so nothing learned in one is injected
    into another; channel bots use memory only in one-to-one chats; deleting a
    user deletes their memory; a notebook holds at most 100 files. Stored in the
    harness's own agent_memory* tables, which Alembic autogenerate now leaves
    alone (as it does the TODO planner's todos). Activated at runtime with
    ENABLE_MEMORY=true. Contributed by @OchnikBartek (#133)

Changed

  • Generated projects run Valkey instead of Redis —
    valkey/valkey:9-alpine in the compose files, the GitHub Actions and GitLab
    CI services, and valkey-server / valkey-cli for the prod command and
    health checks. Redis 8 is licensed RSALv2/SSPLv1/AGPLv3; Valkey is the
    BSD-licensed fork and speaks the same protocol, so the redis client,
    REDIS_* settings and the redis service name are unchanged. Existing
    projects:
    Valkey cannot load an RDB written by Redis 7.4 (Can't handle RDB format version 12); the template keeps only cache, broker and rate-limit
    data there, so move /data/dump.rdb aside (or recreate the redis_data
    volume) before the first start. The prod health check gained a
    start_period, so a restarted container is not judged on its stale status
  • Renovate no longer proposes Postgres or Milvus major updates: a new major
    changes the on-disk format of existing projects' volumes (Postgres needs
    pg_upgrade), so each will be done deliberately, with a migration note

Fixed

Generated projects had drifted from the libraries they resolve to: main's CI
failed in 13 jobs, and several breakages were runtime-only.

  • Every PostgreSQL project failed to run Alembic and SQLAdmin — SQLAlchemy
    2.1 maps a bare postgresql:// URL to psycopg 3, which the template does not
    install. DATABASE_URL_SYNC now names postgresql+psycopg2://, which also
    holds under SQLAlchemy 2.0 (pinned by SQLModel); the deep-research TODO pool
    strips the driver back off for asyncpg
  • Tool results crashed every PydanticAI and PydanticDeep chat turn —
    Pydantic AI 2.0 replaced FunctionToolResultEvent.result with .part, and the
    agent session still read .result, which ty could not see through an
    untyped event. The pydantic-ai-slim floor is now 2.0.0
  • PydanticDeep projects could not build their agent — pydantic-deep 0.3.45
    moved to Pydantic AI workspaces: the assistant now uses StateWorkspace, or
    DaytonaWorkspace with the Daytona sandbox backend (which now installs the daytona
    extra instead of silently falling back to in-memory), and uploads go through
    DeepAgentDeps.upload_file. Since pydantic-deep installs pydantic-ai-slim,
    the selected provider's SDK is now declared, as for PydanticAI projects
  • The project-scoped PydanticDeep chat WebSocket could never have worked —
    it called get_agent(context=...), which takes no such argument, and a
    stream_events() method that does not exist. It now streams
    run_stream_events()
  • MCP connections failed on mcp 2.x — the streamable-HTTP transport is
    streamable_http_client with headers on an httpx2 client, and the OAuth
    discovery helpers return httpx2 requests that an httpx client cannot
    send. Both ported; mcp>=2.0.0 is now declared
  • Code execution and skills broke on new majors — pydantic-monty 1.0
    renamed max_duration_secs to max_feed_duration_secs, and
    pydantic-ai-skills 2.0 removed SkillsToolset for SkillsCapability
    (skills now load through load_capability)
  • OpenAI embeddings relied on another package's dependency — openai is
    now declared whenever OpenAI embeddings are selected, so a non-OpenAI
    provider no longer leaves the embedding service without its SDK
  • docker-compose.prod.yml was rejected outright for Celery and Taskiq
    projects
    — celery_worker and taskiq_worker run replicas: 2 and also set
    container_name, which has to be unique, so Compose v2 refused the whole
    project (can't set container_name and celery_worker as container name must be unique). The two workers no longer name their containers
  • A PydanticDeep chat forgot the conversation on every turn — the template
    assumed pydantic-deep kept history between runs; it keeps none
    (history_messages_path is only an archive for searching compacted history).
    The chat session now carries the conversation's messages from turn to turn,
    and its in-memory workspace documents too, so files written in one turn are
    there in the next; another conversation starts afresh. The project chat
    socket and channel bots replay their history as well (#175)
  • Channel bots handed the model the new message twice — the message was
    stored before the conversation history was loaded, so it arrived as the
    prompt and again at the end of the history; it is now loaded first, for every
    framework
  • Skill cards rendered as generic tool calls — since pydantic-ai-skills
    2.0 a skill loads through load_capability(id) and returns its instructions,
    but the chat, the demo replay and the step captions still looked for 1.x's
    load_skill / list_skills and an XML result. They now recognise
    load_capability and show the skill's name and the start of its
    instructions (#177)

Security

  • Any signed-in user could write into another user's conversation — the
    REST POST /conversations/{id}/messages never passed the caller to
    ConversationService.add_message, so neither ownership nor a share was
    checked, and a read-only (view) share recipient could append too. Over the
    chat WebSocket, persist_user_turn logged a refused conversation as a failed
    write and carried on: the turn ran, and the agent's reply was saved into a
    conversation the user could only read, or could not see at all. add_message
    now requires the owner or an edit share, and the WebSocket refuses such a
    turn with an error event before the agent runs. Reported by
    @failsafesecurity (#143)
  • Upgraded the generator's locked aiohttp, anyio, multidict, pyjwt,
    urllib3 and virtualenv past the advisories pip-audit reports