@sonordev/site-kit 7.1.2 → 7.3.0

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.
Files changed (176) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +60 -0
  3. package/README.md +9 -8
  4. package/agent-manifest.json +17 -7
  5. package/dist/{AnalyticsProvider-ZB33W6MC.js → AnalyticsProvider-DJQA66AG.js} +4 -4
  6. package/dist/{ArticleViewTracker-GMHYLLLZ.js → ArticleViewTracker-GFOAXFV7.js} +3 -3
  7. package/dist/{BlocksPopup-EA6LYL25.js → BlocksPopup-AHDU34TL.js} +5 -5
  8. package/dist/ChatWidget-FHBAHFZX.js +17 -0
  9. package/dist/{FileField-QKA3JB2Q.js → FileField-J5W5MIAZ.js} +3 -3
  10. package/dist/{FormSpotlight-AQTIA5TP.js → FormSpotlight-PE5YZBFZ.js} +20 -6
  11. package/dist/{FormStage-FDTLTP3B.js → FormStage-OOPQC27J.js} +27 -7
  12. package/dist/ManagedForm-JRZAJ7SZ.js +16 -0
  13. package/dist/{ManagedNewsletterForm-J6QSAGGP.js → ManagedNewsletterForm-TC5542ZG.js} +7 -5
  14. package/dist/{SignalCore-JZNXOLNT.js → SignalCore-2YP5FCAS.js} +3 -3
  15. package/dist/SiteChat-EGEZJJVV.js +5 -0
  16. package/dist/{SiteDesignReporter-W4EJUSTE.js → SiteDesignReporter-YEEWJKWN.js} +5 -5
  17. package/dist/SitePopups-LQBIXIFV.js +10 -0
  18. package/dist/SitemapSync-LSZ2EYOF.js +8 -0
  19. package/dist/_client/booking-widget.js +5 -5
  20. package/dist/affiliates/index.js +3 -3
  21. package/dist/analytics/index.js +4 -4
  22. package/dist/analytics/send-gate.d.ts +1 -1
  23. package/dist/articles/index.js +2 -2
  24. package/dist/articles/server-ui.js +3 -2
  25. package/dist/articles/server.js +2 -1
  26. package/dist/{engage → chat}/ChatWidget.d.ts +7 -6
  27. package/dist/{engage → chat}/EchoUiActions.d.ts +1 -1
  28. package/dist/chat/SiteChat.d.ts +25 -0
  29. package/dist/{engage → chat}/brand-color.d.ts +1 -1
  30. package/dist/{engage → chat}/chat-messages.d.ts +1 -1
  31. package/dist/{engage → chat}/echo-config.d.ts +1 -1
  32. package/dist/chat/index.d.ts +10 -6
  33. package/dist/chat/index.js +14 -8
  34. package/dist/{engage → chat}/launcher-placement.d.ts +1 -7
  35. package/dist/{engage → chat}/socket-loader.d.ts +2 -2
  36. package/dist/chat/types.d.ts +136 -0
  37. package/dist/chunk-27FISYK4.js +4 -0
  38. package/dist/{chunk-HF57LG73.js → chunk-2AD3CDRR.js} +43 -29
  39. package/dist/{chunk-M3YEPKP7.js → chunk-2ECWEUHP.js} +1 -1
  40. package/dist/{chunk-LUXVWITO.js → chunk-4NTBQNHA.js} +247 -78
  41. package/dist/{chunk-AH5Q262S.js → chunk-56KNHB4U.js} +1 -1
  42. package/dist/{chunk-GLHQ3LRO.js → chunk-6U3VLV2C.js} +1 -1
  43. package/dist/{chunk-3SDOQUUF.js → chunk-BEBR4OJD.js} +2 -2
  44. package/dist/{chunk-JSZN6LDZ.js → chunk-BF7TZYC3.js} +38 -31
  45. package/dist/{chunk-AQSNPZY4.js → chunk-C2FZBUSS.js} +80 -1
  46. package/dist/{chunk-PHYMNUJU.js → chunk-CYUFBKJQ.js} +1 -1
  47. package/dist/{chunk-6WIQCXOO.js → chunk-DNPNYWVL.js} +1 -1
  48. package/dist/{chunk-V6FDQLR7.js → chunk-EPT6FJUY.js} +53 -21
  49. package/dist/chunk-HODO5BX5.js +28 -0
  50. package/dist/chunk-HW7B43E5.js +14 -0
  51. package/dist/{chunk-PGMVL4AB.js → chunk-I2YX3HVD.js} +2 -2
  52. package/dist/{chunk-JTU2GOM4.js → chunk-L7U23XI2.js} +18 -6
  53. package/dist/{chunk-YEMPUQVU.js → chunk-MKMD2HJW.js} +2 -2
  54. package/dist/{chunk-Q4W23JYM.js → chunk-MRQ2U4LZ.js} +1 -1
  55. package/dist/chunk-MVR4FY5R.js +187 -0
  56. package/dist/{chunk-VGH4MDTU.js → chunk-NI2XNEMR.js} +1 -1
  57. package/dist/{chunk-4Y5FWDPM.js → chunk-NZ4RXN3G.js} +55 -7
  58. package/dist/{chunk-RHNWA34F.js → chunk-O5RGXTWU.js} +41 -7
  59. package/dist/{chunk-TXBAOEKG.js → chunk-PKGN32AU.js} +5 -4
  60. package/dist/chunk-Q6E4OPGG.js +40 -0
  61. package/dist/chunk-RDPW4D33.js +45 -0
  62. package/dist/{chunk-UXOGCKL6.js → chunk-T4DLETKR.js} +1 -1
  63. package/dist/{chunk-NK4CSJNP.js → chunk-UPRSH6Q4.js} +2 -2
  64. package/dist/{chunk-ERXXITG4.js → chunk-VF4F5WXZ.js} +1 -1
  65. package/dist/chunk-VWWITFWM.js +300 -0
  66. package/dist/{chunk-WWSHFRDL.js → chunk-WDQB4OXY.js} +7 -3
  67. package/dist/{chunk-VDF5DFWT.js → chunk-WGG6GTKW.js} +1 -1
  68. package/dist/{chunk-CSTQDNGK.js → chunk-WGIDC6QP.js} +43 -24
  69. package/dist/{chunk-V3PUVBME.js → chunk-XLSQTTUE.js} +2 -4
  70. package/dist/{chunk-JBE46QJZ.js → chunk-Y6LP36UW.js} +1 -1
  71. package/dist/chunk-YJLS6JBI.js +370 -0
  72. package/dist/{chunk-QEDHRBAT.js → chunk-Z65DHMTW.js} +26 -9
  73. package/dist/{chunk-ILU5I6RW.js → chunk-ZHS2XFLV.js} +1 -1
  74. package/dist/{chunk-D5EC5KVO.js → chunk-ZKHI4E2B.js} +2 -2
  75. package/dist/{chunk-CIG5UL2S.js → chunk-ZTLMPUO6.js} +3 -2
  76. package/dist/client/index.js +3 -3
  77. package/dist/commerce/index.js +4 -4
  78. package/dist/contracts/color.d.ts +1 -1
  79. package/dist/contracts/entries.d.ts +1 -1
  80. package/dist/contracts/error-page.d.ts +183 -0
  81. package/dist/contracts/llms.d.ts +1 -0
  82. package/dist/contracts/proposal-sitemap.d.ts +130 -0
  83. package/dist/contracts/schema-placeholders.d.ts +87 -0
  84. package/dist/engage/EngageWidget.d.ts +13 -12
  85. package/dist/engage/index.d.ts +10 -9
  86. package/dist/engage/index.js +31 -35
  87. package/dist/engage/types.d.ts +19 -244
  88. package/dist/fleet/FleetHeartbeat.d.ts +1 -1
  89. package/dist/fleet/index.js +4 -4
  90. package/dist/forms/FormEnhancer.d.ts +25 -12
  91. package/dist/forms/ServerForm.d.ts +11 -10
  92. package/dist/forms/StaticForm.d.ts +3 -1
  93. package/dist/forms/field-autocomplete.d.ts +28 -0
  94. package/dist/forms/form-dom-values.d.ts +42 -0
  95. package/dist/forms/index.js +11 -9
  96. package/dist/forms/server.js +6 -4
  97. package/dist/forms/static.js +3 -2
  98. package/dist/forms/submitForm.d.ts +8 -1
  99. package/dist/forms/types.d.ts +41 -2
  100. package/dist/forms/useForm.d.ts +21 -4
  101. package/dist/forms/webmcp.d.ts +38 -0
  102. package/dist/images/index.js +4 -4
  103. package/dist/index.d.ts +4 -1
  104. package/dist/index.js +1 -1
  105. package/dist/layout/SiteKitClientProviders.d.ts +3 -3
  106. package/dist/layout/SiteKitLayout.d.ts +4 -4
  107. package/dist/layout/client.d.ts +3 -3
  108. package/dist/layout/client.js +7 -7
  109. package/dist/layout/index.js +8 -8
  110. package/dist/layout/types.d.ts +5 -4
  111. package/dist/llms/agent-access.d.ts +4 -0
  112. package/dist/llms/contract.js +1 -1
  113. package/dist/llms/index.js +6 -6
  114. package/dist/maps/index.js +3 -3
  115. package/dist/mcp/WebMcpTools.d.ts +5 -4
  116. package/dist/mcp/client.js +14 -7
  117. package/dist/mcp/discovery.d.ts +48 -0
  118. package/dist/mcp/handlers.d.ts +13 -7
  119. package/dist/mcp/index.d.ts +5 -3
  120. package/dist/mcp/index.js +62 -30
  121. package/dist/mcp/serverCard.d.ts +6 -7
  122. package/dist/mcp/sonor.js +14 -11
  123. package/dist/revalidate/index.js +2 -2
  124. package/dist/seo/client.js +4 -4
  125. package/dist/seo/index.js +15 -8
  126. package/dist/seo/llms/contract.js +1 -1
  127. package/dist/seo/llms.js +6 -6
  128. package/dist/seo/register-sitemap-cli.js +1 -1
  129. package/dist/seo/sitemap.js +4 -4
  130. package/dist/server/index.js +2 -2
  131. package/dist/shared/dialog.d.ts +27 -0
  132. package/dist/shared/identity.d.ts +1 -1
  133. package/dist/shared/layers.d.ts +7 -0
  134. package/dist/shared/mid-form.d.ts +53 -0
  135. package/dist/shared/reporting-gate.d.ts +1 -1
  136. package/dist/shared/version.d.ts +1 -1
  137. package/dist/shared/visual-viewport-gap.d.ts +1 -1
  138. package/dist/signal/index.js +2 -2
  139. package/dist/signal/types.d.ts +1 -1
  140. package/dist/sitemap/index.js +4 -4
  141. package/dist/{socket-loader-R24ZSRSQ.js → socket-loader-CGIPEG74.js} +1 -1
  142. package/dist/sync/index.js +5 -5
  143. package/dist/types.d.ts +3 -1
  144. package/dist/{web-vitals.attribution-GD6LGLVF.js → web-vitals.attribution-N2PCCF4Q.js} +1 -1
  145. package/dist/website/BlocksPopup.d.ts +1 -1
  146. package/dist/website/PopupBlocks.d.ts +5 -2
  147. package/dist/website/SitePopups.d.ts +25 -0
  148. package/dist/website/images.js +4 -4
  149. package/dist/website/index.js +6 -6
  150. package/dist/website/popup-rules.d.ts +46 -0
  151. package/dist/website/popup-types.d.ts +113 -0
  152. package/dist/website/popups.d.ts +2 -6
  153. package/dist/website/popups.js +6 -14
  154. package/dist/{writeLLMsTxt-G3JBNBC5.js → writeLLMsTxt-2NQVDGYI.js} +3 -3
  155. package/docs/MIGRATING-TO-7.md +41 -9
  156. package/docs.json +2 -1
  157. package/package.json +2 -2
  158. package/src/analytics/README.md +2 -2
  159. package/src/articles/README.md +4 -1
  160. package/src/{engage → chat}/README.md +63 -62
  161. package/src/forms/README.md +49 -3
  162. package/src/layout/README.md +8 -5
  163. package/src/llms/README.md +69 -0
  164. package/src/mcp/README.md +50 -16
  165. package/src/seo/README.md +3 -1
  166. package/src/sync/README.md +10 -0
  167. package/src/website/README.md +133 -0
  168. package/dist/ChatWidget-UCDWMWCW.js +0 -15
  169. package/dist/EngageWidget-7ZYSK4GE.js +0 -11
  170. package/dist/ManagedForm-H7BVAH2W.js +0 -14
  171. package/dist/SitemapSync-XBANGKHZ.js +0 -8
  172. package/dist/chunk-NDF4A5JM.js +0 -37
  173. package/dist/chunk-VLARKWZU.js +0 -100
  174. package/dist/chunk-YCJT4JJG.js +0 -837
  175. package/dist/engage/DesignRenderer.d.ts +0 -57
  176. package/dist/engage/element-rules.d.ts +0 -38
@@ -9,7 +9,7 @@
9
9
  * const { form, fields, values, errors, setFieldValue, submit, isSubmitting } = useForm('contact-form')
10
10
  *
11
11
  * return (
12
- * <form onSubmit={(e) => { e.preventDefault(); submit() }}>
12
+ * <form {...toolAttributes} onSubmit={handleSubmit}>
13
13
  * {fields.map(field => (
14
14
  * <MyCustomInput
15
15
  * key={field.slug}
@@ -24,7 +24,9 @@
24
24
  * )
25
25
  * ```
26
26
  */
27
- import type { ManagedFormConfig, FormField, FormSubmitResult } from './types';
27
+ import type { DeclarativeToolFormAttributes } from '../mcp/declarative';
28
+ import type { FormEvent } from 'react';
29
+ import type { ManagedFormConfig, FormField, FormSubmitOptions, FormSubmitOutcome, FormSubmitResult } from './types';
28
30
  export interface UseFormOptions {
29
31
  /** Project ID (defaults to SiteKitLayout config) */
30
32
  projectId?: string;
@@ -98,8 +100,23 @@ export interface UseFormReturn {
98
100
  validateField: (field: FormField) => string | null;
99
101
  /** Check if a field is visible (conditional logic) */
100
102
  isFieldVisible: (field: FormField) => boolean;
101
- /** Submit the form */
102
- submit: () => Promise<void>;
103
+ /**
104
+ * Submit the form. Resolves with what happened (sent, invalid, failed,
105
+ * busy); ignoring the result is fine.
106
+ */
107
+ submit: (options?: FormSubmitOptions) => Promise<FormSubmitOutcome>;
108
+ /**
109
+ * A ready-made `<form onSubmit>`: prevents the native submit, moves to the
110
+ * next step or submits, and hands an AI agent that submitted through
111
+ * WebMCP the outcome. Prefer it to calling `submit()` yourself.
112
+ */
113
+ handleSubmit: (event: FormEvent<HTMLFormElement>) => void;
114
+ /**
115
+ * WebMCP attributes for your `<form>` (`toolname`, `tooldescription`), so
116
+ * a browser agent can fill it as a tool. Spread them on the form element.
117
+ * Null until the form config loads.
118
+ */
119
+ toolAttributes: DeclarativeToolFormAttributes | null;
103
120
  /** Submission state */
104
121
  isSubmitting: boolean;
105
122
  isComplete: boolean;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * @sonordev/site-kit/forms - managed forms as WebMCP tools
3
+ *
4
+ * Every managed form carries the declarative WebMCP attributes (`toolname`,
5
+ * `tooldescription`), so a browser agent can treat it as a tool: it fills the
6
+ * same controls a person would and the submit runs the same validation and
7
+ * files the same lead. There is deliberately no `toolautosubmit`. The agent
8
+ * fills the fields and the person it's helping presses Send, which is the
9
+ * right default for anything that files a lead or sends a message.
10
+ *
11
+ * Browsers that don't implement WebMCP ignore the attributes. Each field's
12
+ * label is what an agent reads to understand it (FormField adds the help
13
+ * text as `toolparamdescription` where there is some).
14
+ *
15
+ * Single source of truth for a managed form's tool name and description, and
16
+ * for reading an agent's submit (`SubmitEvent.agentInvoked`, `respondWith`).
17
+ * FormClient, FormSpotlight, FormStage, StaticForm and useForm all use it.
18
+ */
19
+ import { type DeclarativeToolFormAttributes } from '../mcp/declarative';
20
+ import type { ManagedFormConfig } from './types';
21
+ /** `contact-page` -> `submit_contact_page`. Stable, snake_case, unique per form. */
22
+ export declare function formToolName(config: Pick<ManagedFormConfig, 'slug'>): string;
23
+ /** The tool description an agent reads to decide whether this form is the one. */
24
+ export declare function formToolDescription(config: Pick<ManagedFormConfig, 'name' | 'form_type' | 'description'>): string;
25
+ /** Spread onto the managed form's `<form>` element. */
26
+ export declare function formToolAttributes(config: Pick<ManagedFormConfig, 'slug' | 'name' | 'form_type' | 'description'>): DeclarativeToolFormAttributes;
27
+ export interface AgentSubmit {
28
+ /** True when the browser reports that an AI agent submitted the form. */
29
+ invoked: boolean;
30
+ /**
31
+ * Hand the agent the outcome of its submit. Call it synchronously inside
32
+ * the submit handler, after `preventDefault()`. A no-op unless an agent
33
+ * submitted and the browser supports `respondWith`.
34
+ */
35
+ respond: (outcome: Promise<unknown>) => void;
36
+ }
37
+ /** Read an agent's submit off a native SubmitEvent (`e.nativeEvent` in React). */
38
+ export declare function readAgentSubmit(event: Event | null | undefined): AgentSubmit;
@@ -1,6 +1,6 @@
1
- export { ManagedImage, assignImageToSlot, clearImageSlot, fetchManagedImage, fetchManagedImages, listImageFiles, uploadImage } from '../chunk-ILU5I6RW.js';
1
+ export { ManagedImage, assignImageToSlot, clearImageSlot, fetchManagedImage, fetchManagedImages, listImageFiles, uploadImage } from '../chunk-ZHS2XFLV.js';
2
2
  export { ManagedFavicon, getManagedFaviconUrl } from '../chunk-GW7GSBO7.js';
3
- import '../chunk-3SDOQUUF.js';
4
- import '../chunk-VDF5DFWT.js';
5
- import '../chunk-AH5Q262S.js';
3
+ import '../chunk-BEBR4OJD.js';
4
+ import '../chunk-WGG6GTKW.js';
5
+ import '../chunk-56KNHB4U.js';
6
6
  import '../chunk-PKBMQBKP.js';
package/dist/index.d.ts CHANGED
@@ -15,7 +15,10 @@
15
15
  export { SITE_KIT_VERSION } from './shared/version';
16
16
  export type { ManagedMetadataResult, ManagedSchemaProps, ManagedFAQData } from './seo/types';
17
17
  export type { AnalyticsConfig, AnalyticsEvent, PageView } from './analytics/types';
18
- export type { EngageElement, WidgetConfig, ChatConfig } from './engage/types';
18
+ export type { ChatConfig } from './chat/types';
19
+ export type { SitePopup } from './website/popup-types';
20
+ /** Deprecated names (engage was retired): SitePopup and SitePopupConfig. */
21
+ export type { EngageElement, WidgetConfig } from './engage/types';
19
22
  export type { ManagedFormConfig, FormSubmission, FormSubmitResult, FormField } from './forms/types';
20
23
  export type { Article as ArticleType, ArticleAuthor, ArticleCategory } from './articles/types';
21
24
  export type { CommerceOffering, CommerceCategory, CommerceVariant, CommerceSchedule, OfferingType, Cart, CartItem, } from './commerce/types';
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- export { SITE_KIT_VERSION } from './chunk-AH5Q262S.js';
1
+ export { SITE_KIT_VERSION } from './chunk-56KNHB4U.js';
2
2
  import './chunk-PKBMQBKP.js';
@@ -2,7 +2,7 @@
2
2
  * SiteKitClientProviders — Client Island
3
3
  *
4
4
  * This is the 'use client' boundary for SiteKitLayout.
5
- * It composes the client-only providers (Analytics, Engage, Signal, SitemapSync)
5
+ * It composes the client-only providers (Analytics, chat, popups, Signal, SitemapSync)
6
6
  * that require React context or browser APIs.
7
7
  *
8
8
  * All modules are lazy-loaded via next/dynamic so their JS is only downloaded
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * All modules share a unified identity (visitor ID + session ID) read from
12
12
  * the storage-backed singleton (shared/identity), ensuring consistent
13
- * tracking across Analytics, Signal, and Engage.
13
+ * tracking across Analytics, Signal, chat and popups.
14
14
  *
15
15
  * 4.0 INVARIANT — CHILDREN ARE NEVER WRAPPED. Every module here renders as a
16
16
  * childless sibling AFTER {children}; nothing provides context around page
@@ -56,7 +56,7 @@ export interface SiteKitClientProvidersProps {
56
56
  */
57
57
  design?: boolean | DesignConfig;
58
58
  /**
59
- * Defer Analytics / Engage / SitemapSync until window load + idle or first
59
+ * Defer Analytics / chat / popups / SitemapSync until window load + idle or first
60
60
  * interaction (default true). Pass false to restore legacy eager mounting
61
61
  * on hydration. SignalBridge is never deferred — it must apply experiment
62
62
  * variants as early as possible.
@@ -11,7 +11,7 @@
11
11
  *
12
12
  * Client-side (island):
13
13
  * - AnalyticsProvider (page views, scroll depth, heatmap, web vitals)
14
- * - EngageWidget (popups, nudges, chat)
14
+ * - SitePopups (Website → Popups & Banners) and SiteChat (Website chat)
15
15
  * - SignalBridge (A/B experiments, behavior tracking)
16
16
  * - SitemapSync (keeps Sonor seo_pages in sync)
17
17
  *
@@ -37,7 +37,7 @@
37
37
  *
38
38
  * @example Opt out of specific features:
39
39
  * ```tsx
40
- * <SiteKitLayout engage={false} signal={false}>
40
+ * <SiteKitLayout chat={false} popups={false} signal={false}>
41
41
  * {children}
42
42
  * </SiteKitLayout>
43
43
  * ```
@@ -50,7 +50,7 @@ export interface SiteKitLayoutProps {
50
50
  apiKey?: string;
51
51
  /** Sonor API URL. Defaults to env or https://api.sonor.io */
52
52
  apiUrl?: string;
53
- /** Project ID (for Engage chat room routing). Auto-resolved if not provided. */
53
+ /** Project ID (for chat routing). Auto-resolved if not provided. */
54
54
  projectId?: string;
55
55
  /** Analytics tracking. true (default) | false | config object */
56
56
  analytics?: boolean | AnalyticsConfig;
@@ -100,7 +100,7 @@ export interface SiteKitLayoutProps {
100
100
  */
101
101
  design?: boolean | DesignConfig;
102
102
  /**
103
- * Defer client modules (Analytics, Engage, SitemapSync) until window load +
103
+ * Defer client modules (Analytics, chat, popups, SitemapSync) until window load +
104
104
  * idle or the first user interaction, keeping their JS and mount work out of
105
105
  * the critical hydration path. Default: true. Pass false to restore legacy
106
106
  * eager mounting. SignalBridge is never deferred.
@@ -2,7 +2,7 @@
2
2
  * SiteKitClientProviders — Client Island
3
3
  *
4
4
  * This is the 'use client' boundary for SiteKitLayout.
5
- * It composes the client-only providers (Analytics, Engage, Signal, SitemapSync)
5
+ * It composes the client-only providers (Analytics, chat, popups, Signal, SitemapSync)
6
6
  * that require React context or browser APIs.
7
7
  *
8
8
  * All modules are lazy-loaded via next/dynamic so their JS is only downloaded
@@ -10,7 +10,7 @@
10
10
  *
11
11
  * All modules share a unified identity (visitor ID + session ID) read from
12
12
  * the storage-backed singleton (shared/identity), ensuring consistent
13
- * tracking across Analytics, Signal, and Engage.
13
+ * tracking across Analytics, Signal, chat and popups.
14
14
  *
15
15
  * 4.0 INVARIANT — CHILDREN ARE NEVER WRAPPED. Every module here renders as a
16
16
  * childless sibling AFTER {children}; nothing provides context around page
@@ -56,7 +56,7 @@ export interface SiteKitClientProvidersProps {
56
56
  */
57
57
  design?: boolean | DesignConfig;
58
58
  /**
59
- * Defer Analytics / Engage / SitemapSync until window load + idle or first
59
+ * Defer Analytics / chat / popups / SitemapSync until window load + idle or first
60
60
  * interaction (default true). Pass false to restore legacy eager mounting
61
61
  * on hydration. SignalBridge is never deferred — it must apply experiment
62
62
  * variants as early as possible.
@@ -1,10 +1,10 @@
1
1
  'use client';
2
- export { SiteKitClientProviders } from '../chunk-HF57LG73.js';
2
+ export { SiteKitClientProviders } from '../chunk-2AD3CDRR.js';
3
3
  import '../chunk-6G43IRWR.js';
4
- import '../chunk-ERXXITG4.js';
5
- import '../chunk-NK4CSJNP.js';
4
+ import '../chunk-VF4F5WXZ.js';
5
+ import '../chunk-UPRSH6Q4.js';
6
6
  import '../chunk-ZTZQPYP6.js';
7
- import '../chunk-PHYMNUJU.js';
7
+ import '../chunk-CYUFBKJQ.js';
8
8
  import '../chunk-YC7ELZS3.js';
9
9
  import '../chunk-FESKKJAS.js';
10
10
  import '../chunk-A4CC4ZG3.js';
@@ -12,7 +12,7 @@ import '../chunk-24QZEO3Q.js';
12
12
  import '../chunk-GJWI74ZZ.js';
13
13
  import '../chunk-43OCZ3JA.js';
14
14
  import '../chunk-EKBEOXTH.js';
15
- import '../chunk-3SDOQUUF.js';
16
- import '../chunk-VDF5DFWT.js';
17
- import '../chunk-AH5Q262S.js';
15
+ import '../chunk-BEBR4OJD.js';
16
+ import '../chunk-WGG6GTKW.js';
17
+ import '../chunk-56KNHB4U.js';
18
18
  import '../chunk-PKBMQBKP.js';
@@ -1,12 +1,12 @@
1
- import { SiteKitClientProviders } from '../chunk-HF57LG73.js';
1
+ import { SiteKitClientProviders } from '../chunk-2AD3CDRR.js';
2
2
  import '../chunk-6G43IRWR.js';
3
- import '../chunk-ERXXITG4.js';
4
- import '../chunk-NK4CSJNP.js';
3
+ import '../chunk-VF4F5WXZ.js';
4
+ import '../chunk-UPRSH6Q4.js';
5
5
  import '../chunk-ZTZQPYP6.js';
6
6
  import { ManagedFavicon } from '../chunk-GW7GSBO7.js';
7
- import '../chunk-PHYMNUJU.js';
7
+ import '../chunk-CYUFBKJQ.js';
8
8
  import '../chunk-YC7ELZS3.js';
9
- import { resolveClientCredential } from '../chunk-6WIQCXOO.js';
9
+ import { resolveClientCredential } from '../chunk-DNPNYWVL.js';
10
10
  import '../chunk-VX5CMNMM.js';
11
11
  import { ManagedScripts } from '../chunk-MVLMXC44.js';
12
12
  import { resolveApiOrigin } from '../chunk-X6F6SO4S.js';
@@ -17,9 +17,9 @@ import '../chunk-24QZEO3Q.js';
17
17
  import '../chunk-GJWI74ZZ.js';
18
18
  import '../chunk-43OCZ3JA.js';
19
19
  import '../chunk-EKBEOXTH.js';
20
- import '../chunk-3SDOQUUF.js';
21
- import '../chunk-VDF5DFWT.js';
22
- import '../chunk-AH5Q262S.js';
20
+ import '../chunk-BEBR4OJD.js';
21
+ import '../chunk-WGG6GTKW.js';
22
+ import '../chunk-56KNHB4U.js';
23
23
  import '../chunk-PKBMQBKP.js';
24
24
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
25
25
 
@@ -3,7 +3,7 @@
3
3
  * Kept in a shared file so both server (SiteKitLayout) and client
4
4
  * (SiteKitClientProviders) components can reference them.
5
5
  */
6
- import type { ChatLauncherPlacement } from '../engage/types';
6
+ import type { ChatLauncherPlacement } from '../chat/types';
7
7
  import type { SiteDesignConfig } from '../website/design';
8
8
  /**
9
9
  * The site's design, for popups (Website → Popups & Banners). site-kit
@@ -47,9 +47,10 @@ export interface AnalyticsConfig {
47
47
  allowLocalhost?: boolean;
48
48
  }
49
49
  /**
50
- * Launcher placement (`position`, `offsetBottom`, `zIndex`) comes from
51
- * ChatLauncherPlacement in engage/types, the one definition every Engage
52
- * config surface extends.
50
+ * The deprecated `engage` prop's config. Launcher placement (`position`,
51
+ * `offsetBottom`, `zIndex`) comes from ChatLauncherPlacement in chat/types,
52
+ * the one definition every chat config surface extends; `zIndex` also stacks
53
+ * popups.
53
54
  */
54
55
  export interface EngageConfig extends ChatLauncherPlacement {
55
56
  chatEnabled?: boolean;
@@ -14,6 +14,10 @@ export interface AgentAccessOptions {
14
14
  endpoint?: string;
15
15
  /** The server card's path (default `/.well-known/mcp-server-card`). */
16
16
  card?: string;
17
+ /** Optional AI catalog path. Only set when the site serves this experimental discovery document. */
18
+ catalog?: string;
19
+ /** Place discovery before the first content section, preserving the title and introduction. */
20
+ position?: 'after-intro' | 'end';
17
21
  /** Tool names worth naming, e.g. the built-in ones. Optional. */
18
22
  tools?: string[];
19
23
  }
@@ -1,2 +1,2 @@
1
- export { LLMS_DISCLAIMER_MAX_LENGTH, LLMS_PUBLIC_SUMMARY_MAX_LENGTH, LLM_GEO_CONTRACT_VERSION, MANAGED_LLM_SCHEMA_KNOWN_KEYS, isEmittableReviewNode, pickManagedLlmSchemaForJsonLd, sanitizeLlmsDisclaimerLine, sanitizeLlmsPublicSummary, sanitizePrimaryLanguageTag } from '../chunk-4Y5FWDPM.js';
1
+ export { LLMS_DISCLAIMER_MAX_LENGTH, LLMS_PUBLIC_SUMMARY_MAX_LENGTH, LLM_GEO_CONTRACT_VERSION, MANAGED_LLM_SCHEMA_KNOWN_KEYS, clipAtWordBoundary, isEmittableReviewNode, pickManagedLlmSchemaForJsonLd, sanitizeLlmsDisclaimerLine, sanitizeLlmsPublicSummary, sanitizePrimaryLanguageTag } from '../chunk-NZ4RXN3G.js';
2
2
  import '../chunk-PKBMQBKP.js';
@@ -1,19 +1,19 @@
1
- export { createLLMsFullTxtHandler, createLLMsTxtHandler, formatSourcedFactsSection, llmsResponseHeaders } from '../chunk-WWSHFRDL.js';
1
+ export { createLLMsFullTxtHandler, createLLMsTxtHandler, formatSourcedFactsSection, llmsResponseHeaders } from '../chunk-WDQB4OXY.js';
2
2
  export { buildAiDiscoveryHeaders, wantsLlmsDiscoveryLink } from '../chunk-PO2TRJPY.js';
3
3
  export { AI_RETRIEVAL_CRAWLERS, AI_TRAINING_CRAWLERS, buildAiCrawlerRules, createRobotsTxtHandler } from '../chunk-QLTDFUJ7.js';
4
- export { LEGACY_PUBLICATION_PATH, SEO_REVALIDATION_MAX_BODY_BYTES, SEO_REVALIDATION_MAX_ITEMS, createLlmsRevalidateHandler, createSeoRevalidationHandler, parseSeoRevalidationPayload } from '../chunk-VGH4MDTU.js';
4
+ export { LEGACY_PUBLICATION_PATH, SEO_REVALIDATION_MAX_BODY_BYTES, SEO_REVALIDATION_MAX_ITEMS, createLlmsRevalidateHandler, createSeoRevalidationHandler, parseSeoRevalidationPayload } from '../chunk-NI2XNEMR.js';
5
5
  import '../chunk-XTRZGXB2.js';
6
6
  export { AEOBlock, AEOCitedContent, AEOClaim, AEOComparison, AEODefinition, AEOEntity, AEOProvenanceList, AEOStep, AEOSteps, AEOSummary, DEFAULT_SPEAKABLE_SELECTORS, SpeakableSchema, createSpeakableSchema, getSpeakableSelectorsForPage } from '../chunk-PSAG45YF.js';
7
- export { AGENT_ACCESS_HEADING, appendAgentAccessSection, describesMcp, detectMcpServer, formatAgentAccessSection, generateLLMsFullTxt, generateLLMsTxt, writeLLMsTxtToPublic } from '../chunk-QEDHRBAT.js';
8
- export { getBusinessInfo, getFAQItems, getLLMsData, getOptimizedLLMsTxt, getPageSummaries, getServices } from '../chunk-GLHQ3LRO.js';
7
+ export { AGENT_ACCESS_HEADING, appendAgentAccessSection, describesMcp, detectMcpServer, formatAgentAccessSection, generateLLMsFullTxt, generateLLMsTxt, writeLLMsTxtToPublic } from '../chunk-Z65DHMTW.js';
8
+ export { getBusinessInfo, getFAQItems, getLLMsData, getOptimizedLLMsTxt, getPageSummaries, getServices } from '../chunk-6U3VLV2C.js';
9
9
  import '../chunk-L5UOHS6E.js';
10
10
  import '../chunk-WMVK77ND.js';
11
11
  import '../chunk-VX5CMNMM.js';
12
- export { LLMS_DISCLAIMER_MAX_LENGTH, LLMS_PUBLIC_SUMMARY_MAX_LENGTH, LLM_GEO_CONTRACT_VERSION, MANAGED_LLM_SCHEMA_KNOWN_KEYS, pickManagedLlmSchemaForJsonLd, sanitizeLlmsDisclaimerLine, sanitizeLlmsPublicSummary, sanitizePrimaryLanguageTag } from '../chunk-4Y5FWDPM.js';
12
+ export { LLMS_DISCLAIMER_MAX_LENGTH, LLMS_PUBLIC_SUMMARY_MAX_LENGTH, LLM_GEO_CONTRACT_VERSION, MANAGED_LLM_SCHEMA_KNOWN_KEYS, pickManagedLlmSchemaForJsonLd, sanitizeLlmsDisclaimerLine, sanitizeLlmsPublicSummary, sanitizePrimaryLanguageTag } from '../chunk-NZ4RXN3G.js';
13
13
  import '../chunk-4KZ6W3ZH.js';
14
14
  import '../chunk-MJP63SSS.js';
15
15
  import '../chunk-YVKRYQRG.js';
16
16
  import '../chunk-FESKKJAS.js';
17
17
  import '../chunk-A4CC4ZG3.js';
18
- import '../chunk-AH5Q262S.js';
18
+ import '../chunk-56KNHB4U.js';
19
19
  import '../chunk-PKBMQBKP.js';
@@ -1,8 +1,8 @@
1
1
  'use client';
2
2
  import { monotonicMs } from '../chunk-MH2DSGC6.js';
3
- import { sonorFetch } from '../chunk-3SDOQUUF.js';
4
- import '../chunk-VDF5DFWT.js';
5
- import '../chunk-AH5Q262S.js';
3
+ import { sonorFetch } from '../chunk-BEBR4OJD.js';
4
+ import '../chunk-WGG6GTKW.js';
5
+ import '../chunk-56KNHB4U.js';
6
6
  import '../chunk-PKBMQBKP.js';
7
7
  import { useState, useCallback, useEffect } from 'react';
8
8
  import { APIProvider, Map as Map$1, AdvancedMarker, Pin, InfoWindow } from '@vis.gl/react-google-maps';
@@ -29,11 +29,12 @@ export interface WebMcpToolsProps {
29
29
  /** MCP endpoint on this origin (default `/api/mcp`). */
30
30
  endpoint?: string;
31
31
  /**
32
- * Wait for the page to go quiet before registering (default true).
32
+ * Wait for the page to go quiet before registering (default false).
33
33
  *
34
- * Registration is not user-visible and must never compete with hydration.
35
- * An agent arriving at the page polls or listens for `toolchange`, so a
36
- * couple of hundred milliseconds costs nothing; a blocked LCP costs a lot.
34
+ * Supported browsers discover tools as soon as this component mounts, so
35
+ * an agent need not wait for window load, idle, or a human interaction.
36
+ * Pass true to retain load + idle activation. Unsupported browsers never
37
+ * fetch a catalog or register tools, regardless of this setting.
37
38
  */
38
39
  defer?: boolean;
39
40
  /**
@@ -6,21 +6,28 @@ import { useEffect } from 'react';
6
6
  function getModelContext() {
7
7
  if (typeof window === "undefined") return null;
8
8
  const doc = document;
9
- if (doc.modelContext) return doc.modelContext;
10
9
  const nav = navigator;
11
- return nav.modelContext ?? null;
10
+ for (const context of [doc.modelContext, nav.modelContext]) {
11
+ if (typeof context?.registerTool === "function" || typeof context?.provideContext === "function") {
12
+ return context;
13
+ }
14
+ }
15
+ return null;
12
16
  }
13
17
  function isWebMcpAvailable() {
14
18
  return getModelContext() !== null;
15
19
  }
20
+ var EMPTY_TOOLS = [];
21
+ var EMPTY_LOCAL_TOOLS = [];
16
22
  function WebMcpTools({
17
- tools = [],
18
- localTools = [],
23
+ tools = EMPTY_TOOLS,
24
+ localTools = EMPTY_LOCAL_TOOLS,
19
25
  endpoint = "/api/mcp",
20
- defer = true,
26
+ defer = false,
21
27
  discover = true
22
28
  }) {
23
- const ready = useDeferredActivation(defer);
29
+ const deferredReady = useDeferredActivation(defer);
30
+ const ready = !defer || deferredReady;
24
31
  useEffect(() => {
25
32
  if (!ready) return;
26
33
  const modelContext = getModelContext();
@@ -113,7 +120,7 @@ function WebMcpTools({
113
120
  await modelContext.provideContext({ tools: definitions });
114
121
  }
115
122
  } catch (error) {
116
- if (process.env.NODE_ENV !== "production") {
123
+ if (!controller.signal.aborted && process.env.NODE_ENV !== "production") {
117
124
  console.warn("[site-kit/mcp] WebMCP registration failed:", error);
118
125
  }
119
126
  }
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Experimental domain discovery from the MCP Server Cards discovery draft.
3
+ * The catalog points at the existing card; it never copies tools or identity
4
+ * metadata whose authoritative source is the server/card itself.
5
+ *
6
+ * @see https://github.com/modelcontextprotocol/ext-server-card/blob/main/docs/discovery.md
7
+ */
8
+ import type { McpServerInfo } from './types';
9
+ import { MCP_SERVER_CARD_MEDIA_TYPE } from './serverCard';
10
+ export declare const MCP_AI_CATALOG_PATH = "/.well-known/ai-catalog.json";
11
+ export declare const MCP_AI_CATALOG_MEDIA_TYPE = "application/ai-catalog+json";
12
+ export interface McpAiCatalog {
13
+ specVersion: '1.0';
14
+ entries: {
15
+ identifier: string;
16
+ type: typeof MCP_SERVER_CARD_MEDIA_TYPE;
17
+ url: string;
18
+ }[];
19
+ }
20
+ export interface BuildMcpAiCatalogOptions {
21
+ /** Reuse the server identity; `io.example/weather` becomes `mcp:weather`. */
22
+ info: Pick<McpServerInfo, 'name'>;
23
+ /** Explicit public site origin. Never inferred from an untrusted Host header. */
24
+ baseUrl: string;
25
+ /** Origin-relative card path, e.g. `/api/mcp/server-card`. */
26
+ serverCardPath: string;
27
+ }
28
+ /** Build the small, experimental catalog without duplicating the server card. */
29
+ export declare function buildMcpAiCatalog(options: BuildMcpAiCatalogOptions): McpAiCatalog;
30
+ export interface McpAiCatalogHandlerOptions extends BuildMcpAiCatalogOptions {
31
+ /** Seconds for `Cache-Control: public, max-age=…` (default 3600). */
32
+ maxAge?: number;
33
+ }
34
+ export interface McpDiscoveryRouteHandlers {
35
+ GET: (request?: Request) => Promise<Response>;
36
+ OPTIONS: () => Promise<Response>;
37
+ }
38
+ /**
39
+ * Serve the experimental catalog at `MCP_AI_CATALOG_PATH`. This static-safe
40
+ * handler leaves conditional ETag requests to the host/CDN, like llms.txt and
41
+ * the default card handler; it never reads incoming request headers.
42
+ */
43
+ export declare function createMcpAiCatalogHandler(options: McpAiCatalogHandlerOptions): McpDiscoveryRouteHandlers;
44
+ /** Shared public response policy for catalogs and cards; not an auth surface. */
45
+ export declare function createMcpDiscoveryHandlers(document: unknown, options: {
46
+ mediaType: string;
47
+ maxAge?: number;
48
+ }): McpDiscoveryRouteHandlers;
@@ -14,7 +14,8 @@
14
14
  */
15
15
  import { MCP_SUPPORTED_PROTOCOL_VERSIONS, type DispatchOutcome, type JsonRpcRequest, type McpServerDefinition } from './protocol';
16
16
  import type { McpToolCallRecord } from './types';
17
- import { type BuildMcpServerCardOptions } from './serverCard';
17
+ import { type BuildMcpServerCardOptions, MCP_SERVER_CARD_MEDIA_TYPE } from './serverCard';
18
+ import { type McpDiscoveryRouteHandlers } from './discovery';
18
19
  /**
19
20
  * Undo the spec's Base64 sentinel wrapper: `=?base64?{b64}?=`.
20
21
  * Values that aren't wrapped come back untouched.
@@ -74,18 +75,23 @@ export declare function createMcpHandler(options: McpHandlerOptions): McpRouteHa
74
75
  export interface McpServerCardHandlerOptions extends BuildMcpServerCardOptions {
75
76
  /** Seconds for `Cache-Control: public, max-age=…` (default 3600). */
76
77
  maxAge?: number;
78
+ /**
79
+ * Use the draft media type for a new canonical card URL. Existing routes
80
+ * default to application/json for compatibility. Both remain static-safe.
81
+ */
82
+ contentType?: 'application/json' | typeof MCP_SERVER_CARD_MEDIA_TYPE;
77
83
  }
78
- export interface McpServerCardRouteHandlers {
79
- GET: () => Promise<Response>;
80
- OPTIONS: () => Promise<Response>;
84
+ export interface McpServerCardRouteHandlers extends McpDiscoveryRouteHandlers {
81
85
  }
82
86
  /**
83
- * Serve the SEP-2127 server card. Mount at BOTH well-known paths.
87
+ * Serve the server card. Keep both existing well-known paths available; the
88
+ * experimental AI Catalog can also point to an alias under the MCP endpoint.
84
89
  *
85
- * The handler never reads the incoming Request, so the route stays statically
90
+ * The handler never reads Request, so the route stays statically
86
91
  * prerenderable — the same constraint the llms.txt handlers document, and for
87
92
  * the same reason: touching `request.headers` opts the route into dynamic
88
- * rendering and it stops being served from the CDN.
93
+ * rendering. ETag validation is left to the host/CDN. Canonical card routes
94
+ * can use `contentType: MCP_SERVER_CARD_MEDIA_TYPE`; legacy aliases keep JSON.
89
95
  *
90
96
  * @example
91
97
  * ```ts
@@ -8,8 +8,8 @@
8
8
  *
9
9
  * 1. Remote MCP endpoint — `createMcpHandler`. Streamable HTTP, dual-era
10
10
  * (2026-07-28 modern + the `initialize` handshake older clients speak).
11
- * 2. Discovery — `createMcpServerCardHandler`, the SEP-2127 card served at
12
- * `/.well-known/mcp-server-card` and `/.well-known/mcp.json`.
11
+ * 2. Discovery — `createMcpAiCatalogHandler` (experimental draft) points to
12
+ * `createMcpServerCardHandler`; existing well-known card URLs still work.
13
13
  * 3. In-page WebMCP — `<WebMcpTools>` (imperative) and
14
14
  * `declarativeToolForm` (declarative), for browser-driving agents.
15
15
  *
@@ -20,8 +20,10 @@ export type { JsonSchemaNode, JsonSchemaObject, McpContent, McpTextContent, McpR
20
20
  export { defineMcpTool } from './types';
21
21
  export { MCP_PROTOCOL_VERSION_MODERN, MCP_PROTOCOL_VERSIONS_LEGACY, MCP_SUPPORTED_PROTOCOL_VERSIONS, META_PROTOCOL_VERSION, META_CLIENT_INFO, META_SERVER_INFO, MCP_ERROR_HEADER_MISMATCH, MCP_ERROR_UNSUPPORTED_PROTOCOL_VERSION, JSONRPC_METHOD_NOT_FOUND, dispatch, toToolResult, toolErrorResult, toToolDescriptor, validateArgs, isSupportedVersion, } from './protocol';
22
22
  export type { JsonRpcRequest, JsonRpcResponse, JsonRpcError, DispatchOutcome, DispatchOptions, McpServerDefinition, McpToolDescriptor, } from './protocol';
23
- export { buildMcpServerCard, validateMcpServerCard, MCP_SERVER_CARD_SCHEMA, MCP_SERVER_CARD_PATH, MCP_SERVER_CARD_LEGACY_PATH, SITE_KIT_CARD_META_KEY, } from './serverCard';
23
+ export { buildMcpServerCard, validateMcpServerCard, MCP_SERVER_CARD_SCHEMA, MCP_SERVER_CARD_PATH, MCP_SERVER_CARD_LEGACY_PATH, MCP_SERVER_CARD_MEDIA_TYPE, SITE_KIT_CARD_META_KEY, } from './serverCard';
24
24
  export type { McpServerCard, McpRemote, BuildMcpServerCardOptions, } from './serverCard';
25
+ export { buildMcpAiCatalog, createMcpAiCatalogHandler, MCP_AI_CATALOG_PATH, MCP_AI_CATALOG_MEDIA_TYPE, } from './discovery';
26
+ export type { McpAiCatalog, BuildMcpAiCatalogOptions, McpAiCatalogHandlerOptions, McpDiscoveryRouteHandlers, } from './discovery';
25
27
  export { createMcpHandler, createMcpServerCardHandler, decodeHeaderValue, toolCallRecord, WEBMCP_SURFACE_HEADER, } from './handlers';
26
28
  export type { McpHandlerOptions, McpRouteHandlers, McpServerCardHandlerOptions, McpServerCardRouteHandlers, } from './handlers';
27
29
  export { declarativeToolForm, declarativeToolField } from './declarative';