Add opt-in default CPT conversation store (closes #235)#242
Merged
Conversation
Ships a WordPress-native default conversation store inside canonical, dormant behind a single filter, resolving the zero-store cold-start gap from #235 without imposing a session post type on installs that don't ask for it. Enable with: add_filter( 'agents_api_enable_default_conversation_store', '__return_true' ); When enabled, WP_Agent_Cpt_Conversation_Store registers the agents_api_session CPT and provides itself as a fallback on wp_agent_conversation_store at low priority (5) — any host store at the default priority still wins. When not enabled, nothing registers and a vanilla install is unchanged, preserving the contracts-only default and the WP-core landing path: an off-by-default dormant class is not a mandatory post type. The store is wp_posts + wp_postmeta backed (no custom tables), generalized from the openclawp reference. It implements WP_Agent_Principal_Conversation_Store (and therefore WP_Agent_Conversation_Store) plus WP_Agent_Conversation_Lock; ownership is keyed by (owner_type, owner_key) so audience/token principals are first-class, with the int-user methods delegating to the _for_owner variants. Also updates the no-store error to point at the opt-in filter and records the decision in docs/default-stores-companion.md (superseding the earlier separate companion-package direction per maintainer consensus: easier to consume, no second package to maintain). Adds tests/cpt-conversation-store-smoke.php: 38 assertions against the canonical interfaces via an in-memory WP shim — full CRUD round-trip, user/audience owner isolation, pending-session dedup, and lock acquire/release/CAS reclaim. Closes #235. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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
Ships a WordPress-native default conversation store inside canonical, dormant behind a single filter, resolving the zero-store cold-start friction from #235.
Enable it with one line:
When enabled,
WP_Agent_Cpt_Conversation_Storeregisters theagents_api_sessionCPT and provides itself as a fallback onwp_agent_conversation_storeat low priority (5) — any host store at the default priority still wins. When not enabled, nothing registers and a vanilla install is unchanged.Why in canonical behind a flag (not a separate package)
This supersedes the earlier separate-companion direction, per maintainer consensus (@chubes4, @lezama) on the #235 thread:
composer require wordpress/agents-api+ one filter, instead of installing and version-tracking a second tiny plugin.The store
WP_Agent_Cpt_Conversation_Store—wp_posts+wp_postmetabacked (no custom tables), generalized from the openclawp reference. ImplementsWP_Agent_Principal_Conversation_Store(and thereforeWP_Agent_Conversation_Store) plusWP_Agent_Conversation_Lock. Ownership is keyed by(owner_type, owner_key)so audience/token principals are first-class; the int-user methods delegate to the_for_ownervariants. Messages JSON inpost_content, ownership/workspace/provider-continuity/context in meta, title inpost_title. Single-writer lock via atomicadd_post_meta($unique)+ compare-and-swap reclaim.Retention is intentionally not shipped — it stays a consumer responsibility so the substrate doesn't become a product runtime.
Changes
src/Transcripts/class-wp-agent-cpt-conversation-store.php— the store.src/Transcripts/register-default-conversation-store.php— opt-in registration (CPT on init + filter fallback, both gated onagents_api_enable_default_conversation_store).agents-api.php— require both.register-agents-conversation-session-abilities.php— no-store error now points at the opt-in filter.docs/default-stores-companion.md— records the decision, marks the separate-package direction superseded.tests/cpt-conversation-store-smoke.php— 38 assertions via an in-memory WP shim.Test plan
php tests/cpt-conversation-store-smoke.php— 38 assertions: contract implementation, full CRUD round-trip, user/audience owner isolation, pending-session dedup, lock acquire/release/contention/CAS reclaim.composer test— full suite green (incl. bootstrap source-tree + no-product-prose checks).meta_query/date_querylist + dedup paths is worth doing before relying on it in production, since the smoke shimsWP_Query.Closes #235.