feat(adk): overhaul ADK backend to align with v1.0.0 store#400
Merged
Conversation
Adds test_converters.py (39 tests) and test_service.py (13 tests) for Chapter 1 of the ADK Clean-Break Overhaul. Tests are written against the new contract and will fail until the production code is updated.
Parametrized smoke test covering all 28 shipped ADK store classes (session and memory, async and sync). Asserts __abstractmethods__ is empty so any store missing a required base-class method is caught immediately. Several stores are expected to fail today — the test documents that problem ahead of the Ch1 clean-break overhaul that will fix them.
- split_scoped_state returns (app, user, session) not (session, app, user) - merge_scoped_state has optional app_state/user_state params - event_json uses model_dump() (dict) not model_dump_json() (str) - record_to_event uses model_validate() not model_validate_json() - session_to_record calls filter_temp_state - create_session calls filter_temp_state - revert extract_content_text to original format - xfail test for extra fields (Event has extra='forbid')
BigQuery has correctness bugs (JSON_VALUE flattening, unsafe bytes encoding) and is architecturally mismatched for ADK session storage (high latency query jobs, eventual consistency, per-query cost model). - Delete sqlspec/adapters/bigquery/adk/ directory - Remove BigQuery from ADK backends docs table - Remove BigQuery ADK entries from store instantiation tests - Base BigQuery adapter (sqlspec.adapters.bigquery) is preserved
Rebuild DuckdbADKStore for the clean-break 5-column EventRecord: - Events table now uses (session_id, invocation_id, author, timestamp, event_json) instead of 17+ decomposed columns - Implement create_event_and_update_state() for atomic event+state writes - Update create_event() to build event_json blob from legacy parameters - Update list_events() to return new 5-key EventRecord shape - Use TIMESTAMPTZ instead of TIMESTAMP for timezone-aware storage Fix DuckdbADKMemoryStore FTS bugs: - Replace wrong @@ operator with match_bm25() for BM25-ranked search - Move FTS index refresh from search to post-insert/delete only - Add stemmer, stopwords, strip_accents config to FTS index creation
Rebuild the Spanner session/event stores for the clean-break EventRecord (5 keys: session_id, invocation_id, author, timestamp, event_json). Changes: - Events table DDL reduced to 5 columns with event_json as JSON type - Implement create_event_and_update_state() for atomic event+state writes - Update list_events/create_event to use new EventRecord shape - Add ORDER BY update_time DESC to list_sessions - Add _get_drop_memory_table_sql to SpannerSyncADKMemoryStore - Remove bytes_to_spanner/spanner_to_bytes imports (no more actions column) - Keep FARM_FINGERPRINT sharding and commit timestamp support
Update ADBC ADK store to use the new 5-column EventRecord contract (session_id, invocation_id, author, timestamp, event_json). All dialect DDL branches use appropriate JSON types: JSONB for PostgreSQL, JSON for DuckDB, VARIANT for Snowflake, TEXT for SQLite and generic fallback. Adds create_event_and_update_state for atomic event+state persistence.
Rebuild asyncmy, pymysql, and mysqlconnector ADK session/event stores for the clean-break EventRecord contract (5 columns: session_id, invocation_id, author, timestamp, event_json as native JSON). - Events table DDL reduced from 17 columns + BLOB to 5 columns + JSON - Async stores implement append_event_and_update_state() for atomic event+state persistence in a single transaction - Sync stores implement create_event(), create_event_and_update_state(), and list_events() to satisfy BaseSyncADKStore abstract methods - mysqlconnector extracts shared DDL helpers (_mysql_sessions_ddl, _mysql_events_ddl) to reduce duplication between async and sync stores - All adapters use %s parameter style consistently - Memory stores left unchanged
Implement Chapter 11 (artifact-service) of the ADK Clean-Break Overhaul.
Adds SQLSpecArtifactService implementing all 7 BaseArtifactService methods
(save_artifact, load_artifact, list_artifact_keys, delete_artifact,
list_versions, list_artifact_versions, get_artifact_version) by composing
SQL-backed metadata storage with sqlspec/storage/ content backends.
Architecture:
- Metadata (version, filename, mime_type, custom_metadata, canonical_uri)
stored in a SQL table via BaseAsync/SyncADKArtifactStore
- Content bytes stored in object storage (S3, GCS, Azure, local filesystem)
via StorageRegistry, addressed by canonical URI
- URI pattern: {base}/apps/{app}/users/{user}/[sessions/{sid}/]artifacts/{file}/v{ver}
- Versioning is append-only (0-based, monotonically increasing)
- Content written first, metadata second (fail-fast ordering)
- Delete removes metadata first, content cleanup is best-effort
New files:
- sqlspec/extensions/adk/artifact/__init__.py (package exports)
- sqlspec/extensions/adk/artifact/_types.py (ArtifactRecord TypedDict)
- sqlspec/extensions/adk/artifact/store.py (BaseAsync/SyncADKArtifactStore ABCs)
- sqlspec/extensions/adk/artifact/service.py (SQLSpecArtifactService)
Also adds artifact_table and artifact_storage_uri fields to ADKConfig.
Update all ADK integration tests to work with the new 5-column EventRecord (session_id, invocation_id, author, timestamp, event_json) instead of the old 17-column decomposed schema. Changes per adapter: - asyncmy: Replace old event dicts with 5-key EventRecord for append_event; update schema verification to check new columns - mysqlconnector: Same as asyncmy - duckdb: Remove get_event calls (method removed), update event assertions to check event_json instead of top-level columns - oracledb: Replace 17-column EventRecord literals with 5-key records; remove old boolean/LOB column-specific tests - spanner: Update event content assertions to read from event_json - adbc: Update all event operation tests to verify 5-key shape; update DDL tests to check for event_json column types instead of old BLOB/BOOLEAN/INTEGER columns No BigQuery ADK tests exist (already removed in prior chapter).
….async_() Convert all sync ADK session and memory stores from BaseSyncADKStore/ BaseSyncADKMemoryStore to BaseAsyncADKStore/BaseAsyncADKMemoryStore. Each sync store now: - Extends the async base class instead of the sync base class - Has private sync methods (e.g., _create_session, _get_session) - Has public async wrappers using async_() from sync_tools - Maps create_event_and_update_state -> append_event_and_update_state - Maps list_events -> get_events (with after_timestamp/limit params) - Adds append_event method - Drops legacy create_event method Stores converted (session + memory): - DuckDB, ADBC, Psycopg (sync), CockroachDB Psycopg (sync), MySQL Connector (sync), PyMySQL, Oracle (sync), Spanner (sync), SQLite (memory store only) The SQLite session store was already using this pattern and served as the reference implementation.
- Change EventRecord.event_json type from str to dict[str, Any] to match actual usage (model_dump returns dict, stores deserialize from DB to dict) - Fix sync _create_tables methods calling async DDL methods without await by using run_() wrapper consistently across all sync stores - Fix sync _create_session methods calling async get_session by using sync _get_session instead - Add missing datetime import in pymysql store - Fix Oracle/ADBC/DuckDB stores to deserialize event_json from str to dict when reading from database
…RI configuration.
…it` parameters across adapters, and refactor event insertion logic.
…andling, refining Spanner JSON serialization, and adding session creation error checks.
…and enhance migration configuration documentation.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Improved ADK integration based on upstream improvements since initial implementation.
EventRecordwith 5-column model (session_id,invocation_id,author,timestamp,event_json). Eliminates column drift with upstream ADK — new Event fields are captured automatically without schema changes.append_event()now persists session state atomically with the event viaappend_event_and_update_state(). Previously, state mutations fromevent.actions.state_deltawere lost on reload.temp:keys stripped before persistence,app:/user:split/merge helpers for future cross-session state sharing.BaseAsyncADKStoreand wrap sync operations viasqlspec.utils.sync_tools.async_().SQLSpecArtifactServicecomposing SQL metadata tables withsqlspec/storage/content backends (S3, GCS, Azure, local filesystem).add_events_to_memory()andadd_memory()implemented (ADK v1.25+ contract).ADKConfigexpanded withfts_language,artifact_storage_uri,schema_version, partitioning, retention, compression, and SQLite optimization sections.