Skip to content

Commit 396bb85

Browse files
gibrownrobfelty
andauthored
Jetpack Search AI Answers: add dashboard and front end ui. (#48592)
* Jetpack Search AI Answers - add dashboard and front end ui. This is a squashed commit from developing the feature and multiple experiments with the interface. It also includes the original plan for building the feature. This was merged with the new experience selection logic from #48500 * Add search tests to improve test coverage. * Further improve test coverage and clean up the changelog file. * Clean up old planning and design docs from the branch. Update the roadmap. * Address PR feedback: clean up css, some minor oversights, and punt on a few things. * Fix mistake with the changelogs. * Updated REST API calls to use new combined workflow * Addressed possible security concern * No longer requiring Gutenberg Rebased from trunk * Fixed tests * fixed tests * static analysis fix * Getting rid of unnecessary token * Fixed issue with saving personality * fixed personality settings * another attempt at fixing saving personality --------- Co-authored-by: Robert Felty <robfelty@gmail.com>
1 parent a43fa54 commit 396bb85

51 files changed

Lines changed: 4314 additions & 490 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

pnpm-lock.yaml

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

projects/packages/search/AGENTS.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
# Jetpack Search
2+
3+
## UI Components
4+
5+
**Always use existing design system components instead of writing custom ones.**
6+
7+
The Jetpack Search dashboard is actively migrating to standard WordPress components. When building UI, follow this priority order:
8+
9+
### Priority 1: `@wordpress/ui`
10+
The primary component library for new Jetpack work. Use for:
11+
- `Button`, `Link`
12+
- `Notice.Root` / `Notice.Title` / `Notice.Description`
13+
- Tabs, dialogs, and layout primitives
14+
15+
### Priority 2: `@wordpress/components`
16+
Fallback for anything not yet in `@wordpress/ui`:
17+
- `ToggleControl`, `TextareaControl`, `SelectControl`
18+
- `Tabs`, `TabPanel`
19+
- `Notice` (legacy)
20+
21+
### Priority 3: `@automattic/jetpack-components`
22+
Jetpack-specific components (upsell cards, plan badges, etc.).
23+
24+
### Never reinvent
25+
Do **not** create custom implementations of:
26+
- Tab bars → use `@wordpress/components` `Tabs` or `@wordpress/ui`
27+
- Buttons → use `@wordpress/ui` `Button`
28+
- Notices/alerts → use `@wordpress/ui` `Notice`
29+
- Toggles/checkboxes → use `@wordpress/components` `ToggleControl`
30+
31+
When unsure which component to use, the `@wordpress/design-system-mcp` MCP is configured for this project — use it to look up the right component before building a custom one.
32+
33+
## Data access
34+
35+
- `@automattic/jetpack-shared-extension-utils``getSiteFragment()` for site domain
36+
- `@automattic/jetpack-script-data``isWpcomPlatformSite()` for WP.com detection
37+
- Store selectors via `useSelect( select => select( STORE_ID ).selectorName(), [] )` — always include `[]` dependency array
38+
39+
## Testing
40+
41+
Always run all three suites when changing search code:
42+
43+
```bash
44+
# JS tests (from projects/packages/search/)
45+
pnpm test-scripts
46+
47+
# Search PHP tests
48+
jetpack test php packages/search -v
49+
50+
# Sync PHP tests — search changes often affect the sync whitelist
51+
jetpack test php packages/sync -v
52+
```
53+
54+
- Mock external packages in tests; mock custom hooks (`hooks/use-*`) rather than their internals
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Significance: major
2+
Type: added
3+
4+
Search: AI Answers — add streaming ai answers panel in the instant-search overlay. The AI can be customized from a new AI Answers dashboard. The feature is availabe for all paid plans.
Lines changed: 309 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,309 @@
1+
# Local Testing Setup — Jetpack Search AI Answers
2+
3+
A checklist to verify your local environment can run tests and test the AI Answers feature end-to-end, including live calls to a WPcom sandbox.
4+
5+
---
6+
7+
## 1. Prerequisites
8+
9+
- [x ] Docker Desktop is installed and running (`docker info` returns no error)
10+
- [x ] `jetpack` CLI is installed and on PATH:
11+
```bash
12+
jetpack --version
13+
# If missing: npm install -g @automattic/jetpack-cli (or pnpm add -g)
14+
```
15+
- [x ] Node and pnpm are available:
16+
```bash
17+
node --version # 20+
18+
pnpm --version # 9+
19+
```
20+
- [x ] PHP and Composer are available:
21+
```bash
22+
php --version # 8.0+
23+
composer --version
24+
```
25+
- [x ] You're on the right branch:
26+
```bash
27+
git branch # should be jps3-answers-plan
28+
```
29+
30+
---
31+
32+
## 2. Install Monorepo Dependencies
33+
34+
- [x ] Install all JS and PHP dependencies from the monorepo root:
35+
```bash
36+
pnpm install
37+
composer install
38+
```
39+
This only needs to be done once (or after a `git pull` that changes lockfiles).
40+
41+
---
42+
43+
## 3. Run Unit Tests Without Docker
44+
45+
The PHP unit tests for the Search and Sync packages use WorDBless (no WordPress needed) and run locally without Docker.
46+
47+
- [x ] Run Search package PHP tests:
48+
```bash
49+
jetpack test php packages/search -v
50+
```
51+
Expected: all tests pass (including `AI_Answers_Test` once Task 1 is implemented).
52+
53+
- [x ] Run Sync package PHP tests:
54+
```bash
55+
jetpack test php packages/sync -v
56+
```
57+
Expected: all tests pass (including the CPT sync tests once Task 2 is implemented).
58+
59+
- [x ] Run Search package JS tests:
60+
```bash
61+
cd projects/packages/search
62+
pnpm test-scripts
63+
```
64+
Expected: all tests pass.
65+
66+
---
67+
68+
## 4. Build the Search Package
69+
70+
Build is required before the Docker site can serve the updated JS bundle.
71+
72+
- [x ] Build all Search JS bundles:
73+
```bash
74+
cd projects/packages/search
75+
pnpm build
76+
```
77+
Expected: `build/` directory updated with no errors.
78+
79+
- [ ] For active development, use watch mode instead:
80+
```bash
81+
pnpm watch
82+
```
83+
Leave this running while you work — it rebuilds on file save.
84+
85+
---
86+
87+
## 5. Start Docker WordPress Environment
88+
89+
- [x ] Start containers (first time or after `jetpack docker clean`):
90+
```bash
91+
jetpack docker up -d
92+
jetpack docker install
93+
```
94+
WordPress is now at [http://localhost](http://localhost).
95+
Default credentials: `jp_docker_acct` / `jp_docker_pass`
96+
97+
- [x ] If containers were already installed previously, just start them:
98+
```bash
99+
jetpack docker up -d
100+
```
101+
102+
- [x ] Verify WordPress is reachable:
103+
```bash
104+
open http://localhost/wp-admin
105+
```
106+
You should see the WP login page.
107+
108+
- [x ] Verify Jetpack plugin is active (it's auto-linked from the monorepo):
109+
```bash
110+
jetpack docker wp plugin list | grep jetpack
111+
```
112+
Expected: `jetpack` shows as `active`.
113+
114+
---
115+
116+
## 6. Connect Jetpack to WordPress.com via Tunnel
117+
118+
Jetpack requires a publicly accessible URL to handshake with WPcom.
119+
120+
**If you're an Automattician**, use Jurassic Tube (preferred):
121+
122+
- [ ] Follow the setup instructions at PCYsg-GJ2-p2 to install and configure Jurassic Tube if you haven't already.
123+
- [ ] Start the tunnel:
124+
```bash
125+
jetpack docker up --jurassic-tube
126+
```
127+
Note your assigned domain (e.g. `yourname.jurassictube.example`).
128+
129+
**Alternative**: Use ngrok (requires a paid account for a stable subdomain):
130+
- [ ] Start with ngrok:
131+
```bash
132+
jetpack docker up --ngrok
133+
```
134+
135+
- [ ] Once the tunnel is running, re-install WordPress with the tunnel domain:
136+
```bash
137+
jetpack docker install
138+
```
139+
(This updates `WP_SITEURL` and `WP_HOME` to the tunnel domain.)
140+
141+
- [ ] Go to **Jetpack → Dashboard** in wp-admin and complete the WPcom connection flow. Sign in with your WPcom account.
142+
143+
- [ ] Verify connection:
144+
```bash
145+
jetpack docker wp jetpack status
146+
```
147+
Expected: `Jetpack is connected to WordPress.com`.
148+
149+
---
150+
151+
## 7. Enable Instant Search
152+
153+
Instant Search must be enabled for the overlay and AI Answers panel to appear.
154+
155+
- [ ] Enable the Search module and Instant Search:
156+
```bash
157+
jetpack docker wp option update jetpack_active_modules '["search"]' --format=json
158+
jetpack docker wp option update instant_search_enabled 1
159+
```
160+
161+
- [ ] Verify in wp-admin: **Jetpack → Search** should show the Search dashboard with "Instant Search" toggled on.
162+
163+
---
164+
165+
## 8. Enable the AI Answers Feature Flag
166+
167+
- [ ] Enable the AI Answers feature:
168+
```bash
169+
jetpack docker wp option update jetpack_search_ai_answers_enabled 1
170+
```
171+
172+
- [ ] Verify the **Behavior** and **Topics** tabs appear at **Jetpack → Search**.
173+
174+
- [ ] Add a test behavior post via the Behavior tab (type any text, click Save).
175+
176+
- [ ] Add a test topic via **Jetpack → Search → Topics → Add Topic**.
177+
Use this post content as a starting point:
178+
```
179+
This topic covers questions about resetting passwords and account access.
180+
181+
Example questions:
182+
- How do I reset my password?
183+
- I forgot my login email.
184+
- My account is locked.
185+
186+
Guidelines:
187+
Direct users to the account recovery page. Do not speculate about lock durations.
188+
```
189+
190+
---
191+
192+
## 9. Point PHP→WPcom Calls to a Sandbox
193+
194+
This routes Jetpack's server-side API calls (JWT issuance, sync, REST proxy) through your WPcom sandbox instead of production.
195+
196+
- [ ] Create a mu-plugin file for sandbox config:
197+
```bash
198+
cat > tools/docker/mu-plugins/sandbox.php << 'EOF'
199+
<?php
200+
// Route Jetpack server-side WPcom calls to sandbox.
201+
// Replace YOUR_SANDBOX with your actual sandbox hostname (e.g. myname.wordpress.com).
202+
define( 'JETPACK__SANDBOX_DOMAIN', 'YOUR_SANDBOX.wordpress.com' );
203+
EOF
204+
```
205+
206+
- [ ] Restart containers to pick up the mu-plugin:
207+
```bash
208+
jetpack docker down && jetpack docker up -d
209+
```
210+
211+
- [ ] Verify the sandbox constant is loaded:
212+
```bash
213+
jetpack docker wp eval "echo JETPACK__SANDBOX_DOMAIN;"
214+
```
215+
Expected: prints your sandbox hostname.
216+
217+
**What this affects**: sync calls, JWT token issuance, REST proxy calls made by PHP. It does NOT redirect browser-to-wpcom calls (the overlay search query and the AI answers SSE call).
218+
219+
---
220+
221+
## 10. Point Browser→WPcom Calls to a Sandbox
222+
223+
The instant-search overlay and AI Answers SSE call go directly from the browser to `public-api.wordpress.com`. To test against a sandbox, you need to intercept these at the network level.
224+
225+
### Option A: Proxyman (macOS, recommended)
226+
227+
- [ ] Install [Proxyman](https://proxyman.io) (free tier is sufficient).
228+
- [ ] Enable SSL proxying for `public-api.wordpress.com`.
229+
- [ ] Add a **Map Remote** rule:
230+
- Match: `https://public-api.wordpress.com/*`
231+
- Replace host with: `YOUR_SANDBOX.wordpress.com`
232+
- [ ] Enable the rule and keep Proxyman running while testing.
233+
234+
### Option B: /etc/hosts entry (only works if sandbox has a stable IP)
235+
236+
- [ ] Add to `/etc/hosts`:
237+
```
238+
SANDBOX_IP public-api.wordpress.com
239+
```
240+
- [ ] Flush DNS cache:
241+
```bash
242+
sudo dscacheutil -flushcache && sudo killall -HUP mDNSResponder
243+
```
244+
- [ ] Remove the entry when done to restore normal operation.
245+
246+
### Option C: Hardcode in mu-plugin (no proxy needed, test only)
247+
248+
If you just want to test with a different base URL, add an override filter in your sandbox mu-plugin. The search overlay reads `JetpackInstantSearchOptions.apiRoot` for WP REST calls; for the AI answers endpoint you can override via a filter on `generate_initial_javascript_state()`:
249+
250+
```php
251+
add_filter( 'jetpack_instant_search_options', function( $options ) {
252+
// Override the AI answers endpoint base for sandbox testing.
253+
$options['aiAnswersBaseUrl'] = 'https://YOUR_SANDBOX.wordpress.com/wpcom/v2';
254+
return $options;
255+
} );
256+
```
257+
258+
This requires a small code change in `answers-panel`'s SSE URL construction to read `aiAnswersBaseUrl` from `JetpackInstantSearchOptions` with a fallback to `https://public-api.wordpress.com/wpcom/v2`. Add that fallback when implementing Task 8.
259+
260+
---
261+
262+
## 11. Verify End-to-End in the Browser
263+
264+
Once the wpcom AI agent endpoint is live on your sandbox:
265+
266+
- [ ] Open the site frontend in a browser (via the tunnel URL or localhost).
267+
- [ ] Click the Search icon or start typing in the search box to open the overlay.
268+
- [ ] Type a query that matches your test topic (e.g. "reset password") — at least 3 characters.
269+
- [ ] Verify: **loading spinner** appears above the results ("Finding an answer…").
270+
- [ ] Verify: **streamed tokens** appear and the answer text builds up progressively.
271+
- [ ] Verify: **citations** appear below the answer when the stream completes.
272+
- [ ] Verify: standard search results still appear below the citations.
273+
- [ ] Type a query with no matching topic or search results — verify the panel shows a graceful "I couldn't find relevant content" response (or hides silently on error).
274+
- [ ] Disable the feature flag and verify the panel disappears:
275+
```bash
276+
jetpack docker wp option update jetpack_search_ai_answers_enabled 0
277+
```
278+
Refresh the page — no AI panel should appear.
279+
280+
---
281+
282+
## 12. Verify Sync is Wiring Up (Optional — requires WPcom sandbox)
283+
284+
To verify that CPT posts are reaching the sandbox's shadow replicastore:
285+
286+
- [ ] Create a topic post via the Topics tab.
287+
- [ ] Force a sync:
288+
```bash
289+
jetpack docker wp jetpack sync start
290+
```
291+
- [ ] Check sync queue is draining:
292+
```bash
293+
jetpack docker wp jetpack sync status
294+
```
295+
- [ ] On your WPcom sandbox, use the Jetpack Debug page (`jptools.wordpress.com/debug`) or the WPcom REST API to verify the `jetpack_search_topic` post arrived.
296+
297+
---
298+
299+
## Troubleshooting
300+
301+
| Problem | Fix |
302+
|---------|-----|
303+
| `jetpack docker up` fails | Make sure Docker Desktop is running and you have at least 4 GB RAM allocated |
304+
| Jetpack won't connect | Confirm the tunnel is active and the tunnel URL matches `WP_SITEURL` — run `jetpack docker install` after starting the tunnel |
305+
| Instant Search overlay doesn't appear | Check `instant_search_enabled` is `1` and the Jetpack Search module is active; try a hard refresh |
306+
| AI panel doesn't appear | Check `jetpack_search_ai_answers_enabled` is `1`; open browser dev tools and look for console errors from the SSE connection |
307+
| SSE call returns 404 | The wpcom agent isn't deployed yet on that sandbox — confirm with the WPcom side implementation |
308+
| SSE call returns 401 | HMAC token not generating — check `jetpack_search_ai_answers_enabled` is `1` and the blog token is present (`jetpack docker wp eval "print_r(Automattic\Jetpack\Connection\Tokens::get_access_token(JETPACK_MASTER_USER));"`) |
309+
| Sync tests fail | Run `jetpack test php packages/sync -v` and check the error message; common cause is a missing WorDBless bootstrap |

0 commit comments

Comments
 (0)