@algolia/wizard 0.103.0-rc.217.761 → 0.103.0-rc.217.763

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main.js CHANGED
@@ -2467,7 +2467,7 @@ async function ensureApplication(resumeAppId) {
2467
2467
  // package.json
2468
2468
  var package_default = {
2469
2469
  name: "@algolia/wizard",
2470
- version: "0.103.0-rc.217.761",
2470
+ version: "0.103.0-rc.217.763",
2471
2471
  description: "Magically implement Algolia functionality in your codebase",
2472
2472
  type: "module",
2473
2473
  engines: {
@@ -5044,7 +5044,6 @@ async function classifyCommandSafety(createModel, command, cwd, explanation, app
5044
5044
  const { output, usage } = await generateText({
5045
5045
  model: anthropic(profile.model),
5046
5046
  maxOutputTokens: CLASSIFIER_MAX_OUTPUT_TOKENS,
5047
- temperature: 0,
5048
5047
  providerOptions: {
5049
5048
  anthropic: {
5050
5049
  thinking: modelOptions.thinking,
@@ -6762,6 +6761,7 @@ function searchInstructions(input) {
6762
6761
  "Style the search surfaces through the widget's class and CSS-variable overrides (or, when hand-built, the app's existing theme tokens): give the results panel and the element that actually draws the input's border and background \u2014 for a widget, the form or wrapper it renders around the bare input \u2014 non-transparent surfaces, keep that frame distinguishable from the background behind it in every supported theme, and never assume a light surface or reuse the surrounding page's colors unchanged inside the panel.",
6763
6762
  "The panel takes its width from the input by default, so a small input makes it unreadably narrow: give it `min-width: min(320px, calc(100vw - 2rem))` independent of the input, cap its maximum width to the viewport, and anchor it to the input edge it opens from so widening does not push it off-screen.",
6764
6763
  "Match the application styles closely, including light, dark, and high-contrast themes the project already supports.",
6764
+ "Give the search input frame the same height, corner radius, border color and width, background, and focus style as the input it replaces. When it replaces nothing, copy them from the form controls beside it. Read these values from their source (the theme, the component props, or the CSS). Do not keep the widget theme defaults, for example a 44px height and 4px corners, and do not invent colors. When the app theme exists only in code, take the values from that theme object.",
6765
6765
  "When you add UI text to a localized dictionary or message file, add the same keys, translated, to every locale the project supports.",
6766
6766
  "Before reporting, mount the component. Do not run a type check, build, or test command unless a later instruction allows it: the validation pass runs the type check, after the developer agrees to it. If a tool limit is reached or an error remains unresolved, keep the implementation, report status=success, and name the remaining issue in the summary so validation can drive the next pass. Report status=fail only when no search implementation can be written, with the concrete blocker as the reason.",
6767
6767
  "The summary should be extremely concise; do not mention manual testing steps."
@@ -6868,16 +6868,18 @@ function validationInstructions(input) {
6868
6868
  `The confirmed placement candidate was "${input.searchLocation ?? "unknown"}", but verify the actual mount rather than assuming the candidate was used.`,
6869
6869
  "Inspect the generated search component, its actual mount file, that file's parent layout and sibling controls, and the relevant content UI. Do not rely only on type checks or tests.",
6870
6870
  "Confirm that the application renders exactly one search bar. Check for an old search bar and duplicate mounts.",
6871
- "If the project sets a Content-Security-Policy, confirm that connect-src allows https://*.algolia.net, https://*.algolianet.com, and https://insights.algolia.io, and that search-insights is loaded from npm (not a CDN). If a CSP exists and fails either check, set sufficient=false. If the project has no CSP, skip both checks: do not set sufficient=false, and do not ask to add a CSP.",
6871
+ "If the project sets a Content-Security-Policy, confirm that connect-src allows https://*.algolia.net, https://*.algolianet.com, and https://insights.algolia.io, and that search-insights is loaded from npm (not a CDN). If a CSP exists and fails either check, set sufficient=false. If the project has no CSP, skip both checks: do not set sufficient=false, and do not ask to add a CSP. Without a CSP, insights={true} (or insights: true) with no search-insights package is correct, because the widget loads search-insights from its CDN: do not report a missing search-insights package.",
6872
6872
  "Confirm content-specific search is placed with the corresponding content or task controls. Shared navigation is valid only for genuinely app-wide search that fits the visual hierarchy and responsive layout without crowding primary actions.",
6873
6873
  "Confirm the input has a persistent accessible name; widget-provided combobox, popup, and item relationships and keyboard behavior are preserved; and loading, empty, and error status text is perceivable to assistive technology.",
6874
6874
  "Inspect the CSS that actually applies to the generated DOM. Confirm the results panel and the element drawing the input frame have non-transparent surfaces, the input frame is distinguishable from its surrounding background in every supported theme, text meets 4.5:1 contrast, meaningful boundaries and focus indicators meet 3:1, and no state relies on color alone.",
6875
6875
  "Confirm the search experience reflows without horizontal page scrolling at 320 CSS pixels, keeps its panel on-screen, preserves visible focus, and respects reduced-motion preferences for any added animation.",
6876
6876
  "If the project imports an InstantSearch theme, confirm that the project sets the theme palette to the app colors in each theme that the app supports: --ais-primary-color-rgb to the app accent color, and --ais-background-color-rgb, --ais-text-color-rgb, and --ais-border-color-rgb to the app surface, text, and border colors. If the project keeps the theme defaults, set sufficient=false, because the search icon, focus ring, and active item then show the theme blue, and the panel shows the theme surface instead of the app surface. A match between the light and dark themes of the widget and the page is not enough. The theme colors .ais-Highlight-highlighted and .ais-Snippet-highlighted with a fixed blue that the palette does not change: if the results show either class and the project does not restyle it, set sufficient=false.",
6877
6877
  "Then confirm that the palette overrides (--ais-*-rgb) win over the theme: they must use a higher specificity than the theme, for example `:root:root`, and for a dark mode `:root:root.dark` or `:root:root[data-theme=dark]`, because the theme sets its own blue in `:root` and in `:root[data-theme=dark], .dark`. `:root:root` alone ties with `:root[data-theme=dark]`. If an override can lose to the theme, set sufficient=false, because the search icon and focus ring then show the theme blue instead of the app accent color.",
6878
- "Find how the app selects each theme it supports (a class or attribute on an ancestor, a prefers-color-scheme media query, or a theme that exists only in code). Confirm that the search input and results panel take their colors from the active app theme through that same switch. A search widget whose colors do not match the page theme, for example a light panel on a dark page, is a failure: set sufficient=false.",
6878
+ "Find how the app selects each theme it supports (a class or attribute on an ancestor, a prefers-color-scheme media query, or a theme that exists only in code). A theme is supported only when the app can select it at runtime: a mounted theme switch, or a stored or system preference that the app applies. A theme file or theme option that the app never selects, for example because the app forces one mode, does not count. Confirm that the search input and results panel take their colors from the active app theme through that same switch. A search widget whose colors do not match the page theme, for example a light panel on a dark page, is a failure: set sufficient=false.",
6879
6879
  "When the project has a package.json, confirm that the theme CSS of the search widget (for InstantSearch, a theme from instantsearch.css) is imported once from a legal global-CSS entry for that framework (Next.js Pages Router: pages/_app; Next.js App Router: root layout; otherwise the app global stylesheet or a component module when allowed). If it is installed but not imported, or imported from a Next.js component file, set sufficient=false.",
6880
6880
  "Confirm that the search component is reachable from and fits the corresponding content task at every supported breakpoint; require app-wide reachability only when the search scope is genuinely app-wide.",
6881
+ "For an InstantSearch Autocomplete, confirm that the item component (the React itemComponent, or the item template in indices[].templates) calls the onSelect that it receives when the user clicks the result, for example onClick={onSelect} on its root element. The widget goes to the getURL route only through onSelect: the click on its <li> only sends the Insights event. If the item ignores onSelect, set sufficient=false, because a click on a result then does nothing.",
6882
+ "Confirm that the search input frame has the same height, corner radius, border, and background as the input that it replaces, or as the form controls beside it when it replaces nothing. If the frame keeps the widget theme defaults or uses colors that the app does not use, set sufficient=false.",
6881
6883
  "Do not run the test suite or any test command.",
6882
6884
  "Do not modify files. Report each implementation issue as a concrete instruction for the next implementation pass.",
6883
6885
  `Detected verification tools: ${JSON.stringify(input.findings.verification ?? [])}. Use only a type checker; ignore any linter or formatter in this list.`,
@@ -6892,7 +6894,7 @@ function validationInstructions(input) {
6892
6894
  "Set sufficient=false when a required placement, accessibility, or theme-color property is observed to fail, the implementation is incomplete, or checks have implementation-caused failures; include concrete additionalInstructions for the next pass.",
6893
6895
  "You can only read source files. If a required property can be checked in the source, check it there. If it can be established only in a browser (rendered contrast, keyboard behavior, 320-pixel reflow, live-region status, computed accessible name), set sufficient=true when the source shows no violation. Never request devtools, a screenshot, or a contrast tool, and never repeat a finding that an earlier pass already fixed.",
6894
6896
  "If a check fails only in untouched code, set unrelatedFailure to a concise failure description.",
6895
- "Set styleOnly=true when sufficient=false and every finding is one of these: the theme palette defaults remain, a palette override loses to the theme, or the highlight classes keep the theme blue. If any other finding exists, for example a light panel on a dark page, do not set styleOnly.",
6897
+ "Set styleOnly=true when sufficient=false and every finding is one of these: the theme palette defaults remain, a palette override loses to the theme, the highlight classes keep the theme blue, or the input frame does not match the size, radius, border, or background of the controls that it must match. If any other finding exists, for example a light panel on a dark page or a result that a click does not open, do not set styleOnly.",
6896
6898
  "Keep the summary to one short sentence. Put the details in additionalInstructions."
6897
6899
  ];
6898
6900
  }
@@ -7196,6 +7198,13 @@ function validationRunInstructions(plan, attempt) {
7196
7198
  "Do not use an autofix option during validation."
7197
7199
  ];
7198
7200
  }
7201
+ function previousFindingsInstructions(findings) {
7202
+ if (!findings) return [];
7203
+ return [
7204
+ `The previous validation pass reported these findings: ${findings}`,
7205
+ "Check those findings first. Keep the conclusions of that pass that the changes did not affect, for example which themes the app supports. Report a new finding only when it breaks the search (the search bar does not render, search returns no results, or a click on a result does not open it), fails an accessibility requirement, or comes from a change made after the previous pass. Do not set sufficient=false for any other new issue: name it briefly in the summary."
7206
+ ];
7207
+ }
7199
7208
  function retryTypeCheckInstructions(plan) {
7200
7209
  if (!plan.run) return [];
7201
7210
  return [
@@ -7639,6 +7648,7 @@ ${detail}` : ""}`
7639
7648
  );
7640
7649
  let extraInstructions = [];
7641
7650
  let buildCheckPlan;
7651
+ let previousFindings;
7642
7652
  const confirmedFrameworks = language.frameworks ?? [];
7643
7653
  const detectedFrameworks = scan.frameworks ?? [];
7644
7654
  const framework = confirmedFrameworks[0]?.name ?? "unknown";
@@ -7684,9 +7694,10 @@ ${detail}` : ""}`
7684
7694
  searchConfigFile = searchResult.searchConfigFile;
7685
7695
  }
7686
7696
  buildCheckPlan ??= await resolveBuildCheckPlan(ctx, repoRoot, input);
7687
- const validation = await runValidationUseCase(
7688
- validationRunInstructions(buildCheckPlan, attempt)
7689
- );
7697
+ const validation = await runValidationUseCase([
7698
+ ...validationRunInstructions(buildCheckPlan, attempt),
7699
+ ...previousFindingsInstructions(previousFindings)
7700
+ ]);
7690
7701
  summaries.push(formatSummary("validation", validation.summary));
7691
7702
  const finalAttempt = attempt === MAX_IMPLEMENT_VALIDATION_ATTEMPTS;
7692
7703
  let investigateUnrelated = false;
@@ -7737,6 +7748,7 @@ ${detail}` : ""}`
7737
7748
  `Unable to validate the implementation after ${MAX_IMPLEMENT_VALIDATION_ATTEMPTS} attempts (details in wizard.log): ${briefSummary(validation.summary)}`
7738
7749
  );
7739
7750
  }
7751
+ previousFindings = validation.sufficient ? void 0 : validation.additionalInstructions ?? validation.summary;
7740
7752
  extraInstructions = validation.sufficient ? [] : validationRetryInstructions(validation);
7741
7753
  if (validation.unrelatedFailure && investigateUnrelated) {
7742
7754
  extraInstructions.push(
@@ -10162,7 +10174,7 @@ async function resetProjectState() {
10162
10174
  // package.json with { type: 'json' }
10163
10175
  var package_default2 = {
10164
10176
  name: "@algolia/wizard",
10165
- version: "0.103.0-rc.217.761",
10177
+ version: "0.103.0-rc.217.763",
10166
10178
  description: "Magically implement Algolia functionality in your codebase",
10167
10179
  type: "module",
10168
10180
  engines: {
@@ -87,14 +87,15 @@ Ensure the attributes you map into the component match the entity. 'title' above
87
87
  `searchParameters` (for example `['body:20']`), or as an index setting. Do both
88
88
  for the same attribute names the template passes to Snippet.
89
89
 
90
- ### Navigation is `getURL`'s job, not the template's
90
+ ### Navigation: `getURL` plus the template's `onSelect`
91
91
 
92
92
  - `indices[].getURL` — `(item) => string`, a route that already exists; don't invent one.
93
- It navigates on click **and** on Enter over a highlighted item, and records the click
94
- event.
95
- - The `item` template renders content only: **no `<a>`, no `href`, no click handler of
96
- your own, never `stopPropagation`.** The widget's `<li>` owns the click — it sends the
97
- Insights `click`, closes the panel, clears the active option.
93
+ The widget goes there when `onSelect` runs: on Enter over a highlighted item, and on a
94
+ click only when the `item` template calls `onSelect`.
95
+ - The `item` template **must call the `onSelect` it is handed on click**, for example
96
+ `` html`<div onClick=${onSelect}>…</div>` ``. The widget's `<li>` click only sends the
97
+ Insights `click`. Without `onSelect`, a click on a result does nothing. No `<a>`, no
98
+ `href`, no other click handler, never `stopPropagation`.
98
99
  - Do not pass a top-level `onSelect` to `autocomplete()` to navigate. `getURL` already
99
100
  navigates.
100
101
  - `getSearchPageURL` sends Enter with nothing highlighted to a full results page; pass it
@@ -287,8 +288,8 @@ insights: {
287
288
 
288
289
  With `insights: true`, `autocomplete` sends `view` (on render) and `click` (from the
289
290
  result element's own handler) itself. Its item template gets `{ item, onSelect }` and
290
- **no `sendEvent`** — nothing to wire. Call `onSelect` for the widget's selection behavior
291
- (close the panel, record a recent search); the click event fires either way.
291
+ **no `sendEvent`** — nothing to wire. Call `onSelect` on click: it goes to
292
+ the `getURL` route and closes the panel. The click event fires either way.
292
293
 
293
294
  `hits` and `infiniteHits` behave the same; only a custom `item` template whose click
294
295
  target is your own element needs wiring — it gets `sendEvent` as the second argument.
@@ -79,14 +79,15 @@ Ensure the attributes you map into the component match the entity. 'title' above
79
79
  `searchParameters` (for example `['body:20']`), or as an index setting. Do both
80
80
  for the same attribute names the component passes to Snippet.
81
81
 
82
- ### Navigation is `getURL`'s job, not the item component's
82
+ ### Navigation: `getURL` plus the item's `onSelect`
83
83
 
84
84
  - `indices[].getURL` — `(item) => string`, a route that already exists; don't invent one.
85
- It navigates on click **and** on Enter over a highlighted item, and records the click
86
- event.
87
- - `itemComponent` renders content only: **no `<a>`, no `href`, no `onClick` beyond the
88
- `onSelect` it is handed, never `stopPropagation`.** The widget's `<li>` owns the click —
89
- it sends the Insights `click`, closes the panel, clears the active option.
85
+ The widget goes there when `onSelect` runs: on Enter over a highlighted item, and on a
86
+ click only when the item component calls `onSelect`.
87
+ - `itemComponent` **must call the `onSelect` it is handed on click**, for example
88
+ `<div onClick={onSelect}>`. The widget's `<li>` click only sends the Insights `click`.
89
+ Without `onSelect`, a click on a result does nothing. No `<a>`, no `href`, no other
90
+ `onClick`, never `stopPropagation`.
90
91
  - Do not pass a top-level `onSelect` to `<Autocomplete>` (for example to call
91
92
  `router.push`). `getURL` already navigates. The top-level callback can receive a
92
93
  `SyntheticEvent` instead of `{ item }`, so reading `item` from it fails the type check.
@@ -281,8 +282,8 @@ policy allows it:
281
282
  With `insights={true}`, `<Autocomplete>` sends `view` (on render) and `click` (from the
282
283
  result element's own handler) itself. Its `itemComponent` receives
283
284
  `{ item, onSelect, onApply }` and **no `sendEvent`** — nothing to wire. Call `onSelect`
284
- for the widget's selection behavior (close the panel, record a recent search); the click
285
- event fires either way.
285
+ on click: it goes to the `getURL` route and closes the panel. The click event fires
286
+ either way.
286
287
 
287
288
  `<Hits>` and `<InfiniteHits>` behave the same way. Two cases there need explicit wiring:
288
289
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algolia/wizard",
3
- "version": "0.103.0-rc.217.761",
3
+ "version": "0.103.0-rc.217.763",
4
4
  "description": "Magically implement Algolia functionality in your codebase",
5
5
  "type": "module",
6
6
  "engines": {