@assistant-ui/mcp-docs-server 0.1.38 → 0.1.39

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 (207) hide show
  1. package/.docs/organized/code-examples/waterfall.md +8 -9
  2. package/.docs/organized/code-examples/with-a2a.md +16 -11
  3. package/.docs/organized/code-examples/with-ag-ui.md +16 -11
  4. package/.docs/organized/code-examples/{with-ai-sdk-v6.md → with-ai-sdk-v7.md} +32 -21
  5. package/.docs/organized/code-examples/with-artifacts.md +17 -10
  6. package/.docs/organized/code-examples/with-assistant-transport.md +15 -8
  7. package/.docs/organized/code-examples/with-browser-extension.md +15 -8
  8. package/.docs/organized/code-examples/with-chain-of-thought.md +17 -10
  9. package/.docs/organized/code-examples/with-cloud-standalone.md +10 -9
  10. package/.docs/organized/code-examples/with-cloud.md +18 -13
  11. package/.docs/organized/code-examples/with-custom-thread-list.md +17 -10
  12. package/.docs/organized/code-examples/with-elevenlabs-conversational.md +20 -13
  13. package/.docs/organized/code-examples/with-elevenlabs-scribe.md +20 -13
  14. package/.docs/organized/code-examples/with-eve.md +16 -9
  15. package/.docs/organized/code-examples/with-expo.md +27 -24
  16. package/.docs/organized/code-examples/with-external-store.md +16 -11
  17. package/.docs/organized/code-examples/with-ffmpeg.md +18 -13
  18. package/.docs/organized/code-examples/with-generative-ui.md +20 -15
  19. package/.docs/organized/code-examples/with-google-adk.md +15 -8
  20. package/.docs/organized/code-examples/with-heat-graph.md +8 -9
  21. package/.docs/organized/code-examples/with-image-generation.md +17 -10
  22. package/.docs/organized/code-examples/with-interactables.md +19 -15
  23. package/.docs/organized/code-examples/with-langchain.md +17 -10
  24. package/.docs/organized/code-examples/with-langgraph.md +17 -10
  25. package/.docs/organized/code-examples/with-livekit.md +21 -14
  26. package/.docs/organized/code-examples/with-mcp.md +25 -12
  27. package/.docs/organized/code-examples/with-opencode.md +22 -17
  28. package/.docs/organized/code-examples/with-pi.md +47 -12
  29. package/.docs/organized/code-examples/with-react-hook-form.md +19 -14
  30. package/.docs/organized/code-examples/with-react-ink-web.md +6 -6
  31. package/.docs/organized/code-examples/with-react-ink.md +2 -2
  32. package/.docs/organized/code-examples/with-react-router.md +20 -15
  33. package/.docs/organized/code-examples/with-resumable-stream.md +19 -12
  34. package/.docs/organized/code-examples/with-store.md +8 -9
  35. package/.docs/organized/code-examples/with-tanstack.md +16 -10
  36. package/.docs/organized/code-examples/with-tap-runtime.md +16 -11
  37. package/.docs/organized/code-examples/with-virtualized-thread.md +17 -12
  38. package/.docs/raw/docs/(docs)/base-ui.mdx +39 -0
  39. package/.docs/raw/docs/(docs)/cli.mdx +17 -1
  40. package/.docs/raw/docs/(docs)/installation.mdx +15 -1
  41. package/.docs/raw/docs/(docs)/rtl.mdx +2 -4
  42. package/.docs/raw/docs/(reference)/api-reference/generative-ui/actions.mdx +56 -0
  43. package/.docs/raw/docs/(reference)/api-reference/generative-ui/components.mdx +86 -0
  44. package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +19 -1
  45. package/.docs/raw/docs/(reference)/api-reference/generative-ui/json-generative-ui.mdx +42 -0
  46. package/.docs/raw/docs/(reference)/api-reference/generative-ui/rendering.mdx +53 -2
  47. package/.docs/raw/docs/(reference)/api-reference/generative-ui/slack.mdx +81 -0
  48. package/.docs/raw/docs/(reference)/api-reference/generative-ui/teams.mdx +86 -0
  49. package/.docs/raw/docs/(reference)/api-reference/generative-ui/tokens.mdx +62 -0
  50. package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +4 -1
  51. package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +4 -2
  52. package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +37 -0
  53. package/.docs/raw/docs/(reference)/api-reference/overview.mdx +1 -0
  54. package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +29 -29
  55. package/.docs/raw/docs/(reference)/api-reference/primitives/composition.mdx +1 -0
  56. package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +3 -0
  57. package/.docs/raw/docs/(reference)/api-reference/primitives/selection-toolbar.mdx +2 -0
  58. package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +0 -2
  59. package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +12 -9
  60. package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +4 -0
  61. package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +7 -1
  62. package/.docs/raw/docs/cloud/langgraph.mdx +3 -1
  63. package/.docs/raw/docs/guides/chatgpt-subscription.mdx +108 -0
  64. package/.docs/raw/docs/guides/dictation.mdx +185 -257
  65. package/.docs/raw/docs/guides/index.mdx +10 -0
  66. package/.docs/raw/docs/guides/mentions.mdx +31 -3
  67. package/.docs/raw/docs/guides/resumable-streams.mdx +12 -1
  68. package/.docs/raw/docs/guides/speech.mdx +47 -29
  69. package/.docs/raw/docs/guides/suggestions.mdx +70 -1
  70. package/.docs/raw/docs/guides/voice.mdx +197 -267
  71. package/.docs/raw/docs/ink/primitives.mdx +35 -1
  72. package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +10 -4
  73. package/.docs/raw/docs/integrations/frameworks/cloudflare-agents/overview.mdx +3 -3
  74. package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +1 -1
  75. package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +3 -3
  76. package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +1 -1
  77. package/.docs/raw/docs/integrations/gateways/index.mdx +2 -2
  78. package/.docs/raw/docs/integrations/observability/helicone.mdx +1 -1
  79. package/.docs/raw/docs/integrations/observability/langfuse.mdx +1 -1
  80. package/.docs/raw/docs/integrations/observability/langsmith.mdx +1 -1
  81. package/.docs/raw/docs/migrations/index.mdx +50 -0
  82. package/.docs/raw/docs/migrations/toolkit-tools.mdx +4 -2
  83. package/.docs/raw/docs/primitives/chain-of-thought.mdx +6 -1
  84. package/.docs/raw/docs/primitives/composer.mdx +16 -0
  85. package/.docs/raw/docs/primitives/selection-toolbar.mdx +25 -0
  86. package/.docs/raw/docs/react-native/primitives.mdx +23 -0
  87. package/.docs/raw/docs/runtimes/ag-ui/agent-state.mdx +124 -0
  88. package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +10 -1
  89. package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +13 -4
  90. package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +11 -11
  91. package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +5 -5
  92. package/.docs/raw/docs/runtimes/ai-sdk/{v6.mdx → v6-legacy.mdx} +8 -6
  93. package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +717 -0
  94. package/.docs/raw/docs/runtimes/concepts/adapters.mdx +1 -1
  95. package/.docs/raw/docs/runtimes/concepts/architecture.mdx +1 -1
  96. package/.docs/raw/docs/runtimes/custom/data-stream.mdx +10 -19
  97. package/.docs/raw/docs/runtimes/custom/external-store.mdx +1 -1
  98. package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +2 -0
  99. package/.docs/raw/docs/runtimes/eve/overview.mdx +1 -1
  100. package/.docs/raw/docs/runtimes/langgraph/agent-state.mdx +181 -0
  101. package/.docs/raw/docs/tools/backend.mdx +6 -3
  102. package/.docs/raw/docs/tools/defining-tools.mdx +7 -1
  103. package/.docs/raw/docs/tools/generative-ui.mdx +60 -2
  104. package/.docs/raw/docs/tools/mcp-apps.mdx +29 -11
  105. package/.docs/raw/docs/tools/mcp.mdx +100 -3
  106. package/.docs/raw/docs/tools/tool-ui.mdx +6 -4
  107. package/.docs/raw/docs/tools/user-managed-mcp.mdx +26 -3
  108. package/.docs/raw/docs/ui/accordion.mdx +16 -10
  109. package/.docs/raw/docs/ui/assistant-modal.mdx +8 -4
  110. package/.docs/raw/docs/ui/attachment.mdx +5 -1
  111. package/.docs/raw/docs/ui/badge.mdx +23 -12
  112. package/.docs/raw/docs/ui/follow-up-suggestions.mdx +2 -2
  113. package/.docs/raw/docs/ui/model-selector.mdx +32 -2
  114. package/.docs/raw/docs/ui/select.mdx +22 -14
  115. package/.docs/raw/docs/ui/sources.mdx +1 -1
  116. package/.docs/raw/docs/ui/tabs.mdx +25 -14
  117. package/.docs/raw/docs/utilities/heat-graph.mdx +2 -2
  118. package/dist/constants.d.ts.map +1 -1
  119. package/dist/index.d.ts +0 -1
  120. package/dist/index.d.ts.map +1 -1
  121. package/dist/index.js +39 -0
  122. package/dist/index.js.map +1 -1
  123. package/dist/prepare-docs/code-examples.d.ts.map +1 -1
  124. package/dist/prepare-docs/copy-raw.d.ts.map +1 -1
  125. package/dist/prompts/xulux-playground.d.ts +12 -0
  126. package/dist/prompts/xulux-playground.d.ts.map +1 -0
  127. package/dist/prompts/xulux-playground.js +33 -0
  128. package/dist/prompts/xulux-playground.js.map +1 -0
  129. package/dist/tools/docs.d.ts +2 -4
  130. package/dist/tools/docs.d.ts.map +1 -1
  131. package/dist/tools/docs.js +24 -8
  132. package/dist/tools/docs.js.map +1 -1
  133. package/dist/tools/examples.d.ts +2 -4
  134. package/dist/tools/examples.d.ts.map +1 -1
  135. package/dist/tools/examples.js +9 -6
  136. package/dist/tools/examples.js.map +1 -1
  137. package/dist/tools/resources.d.ts +0 -1
  138. package/dist/tools/resources.d.ts.map +1 -1
  139. package/dist/tools/search.d.ts +2 -5
  140. package/dist/tools/search.d.ts.map +1 -1
  141. package/dist/tools/tests/test-setup.d.ts.map +1 -1
  142. package/dist/tools/tests/test-setup.js +5 -1
  143. package/dist/tools/tests/test-setup.js.map +1 -1
  144. package/dist/tools/xulux-templates.d.ts +72 -0
  145. package/dist/tools/xulux-templates.d.ts.map +1 -0
  146. package/dist/tools/xulux-templates.js +82 -0
  147. package/dist/tools/xulux-templates.js.map +1 -0
  148. package/dist/utils/cache.d.ts +5 -0
  149. package/dist/utils/cache.d.ts.map +1 -0
  150. package/dist/utils/cache.js +18 -0
  151. package/dist/utils/cache.js.map +1 -0
  152. package/dist/utils/logger.d.ts.map +1 -1
  153. package/dist/utils/mcp-format.d.ts +1 -0
  154. package/dist/utils/mcp-format.d.ts.map +1 -1
  155. package/dist/utils/mcp-format.js +7 -4
  156. package/dist/utils/mcp-format.js.map +1 -1
  157. package/dist/utils/mdx.d.ts.map +1 -1
  158. package/dist/utils/paths.d.ts +1 -1
  159. package/dist/utils/paths.d.ts.map +1 -1
  160. package/dist/utils/paths.js +3 -1
  161. package/dist/utils/paths.js.map +1 -1
  162. package/dist/utils/search.d.ts.map +1 -1
  163. package/dist/utils/security.d.ts.map +1 -1
  164. package/dist/xulux/catalog-client.d.ts +14 -0
  165. package/dist/xulux/catalog-client.d.ts.map +1 -0
  166. package/dist/xulux/catalog-client.js +67 -0
  167. package/dist/xulux/catalog-client.js.map +1 -0
  168. package/dist/xulux/fallback-catalog.d.ts +7 -0
  169. package/dist/xulux/fallback-catalog.d.ts.map +1 -0
  170. package/dist/xulux/fallback-catalog.js +47 -0
  171. package/dist/xulux/fallback-catalog.js.map +1 -0
  172. package/dist/xulux/fetch-sandbox.d.ts +5 -0
  173. package/dist/xulux/fetch-sandbox.d.ts.map +1 -0
  174. package/dist/xulux/fetch-sandbox.js +40 -0
  175. package/dist/xulux/fetch-sandbox.js.map +1 -0
  176. package/dist/xulux/template-service.d.ts +84 -0
  177. package/dist/xulux/template-service.d.ts.map +1 -0
  178. package/dist/xulux/template-service.js +223 -0
  179. package/dist/xulux/template-service.js.map +1 -0
  180. package/dist/xulux/types.d.ts +55 -0
  181. package/dist/xulux/types.d.ts.map +1 -0
  182. package/dist/xulux/types.js +6 -0
  183. package/dist/xulux/types.js.map +1 -0
  184. package/package.json +5 -5
  185. package/src/index.ts +53 -0
  186. package/src/prompts/xulux-playground.ts +36 -0
  187. package/src/tools/docs.ts +25 -3
  188. package/src/tools/examples.ts +15 -10
  189. package/src/tools/tests/docs.test.ts +20 -0
  190. package/src/tools/tests/examples.test.ts +5 -5
  191. package/src/tools/tests/listings-cache.test.ts +19 -0
  192. package/src/tools/tests/mcp-protocol.test.ts +81 -1
  193. package/src/tools/tests/test-setup.ts +8 -0
  194. package/src/tools/tests/xulux-templates.test.ts +262 -0
  195. package/src/tools/xulux-templates.ts +141 -0
  196. package/src/utils/cache.ts +20 -0
  197. package/src/utils/mcp-format.ts +8 -6
  198. package/src/utils/paths.ts +4 -1
  199. package/src/utils/tests/cache.test.ts +51 -0
  200. package/src/utils/tests/mcp-format.test.ts +22 -0
  201. package/src/utils/tests/security.test.ts +1 -1
  202. package/src/xulux/catalog-client.ts +105 -0
  203. package/src/xulux/fallback-catalog.ts +63 -0
  204. package/src/xulux/fetch-sandbox.ts +56 -0
  205. package/src/xulux/template-service.ts +406 -0
  206. package/src/xulux/types.ts +60 -0
  207. package/.docs/raw/docs/(reference)/api-reference/hooks/utilities.mdx +0 -464
@@ -0,0 +1 @@
1
+ {"version":3,"file":"xulux-templates.js","names":[],"sources":["../../src/tools/xulux-templates.ts"],"sourcesContent":["import { z } from \"zod/v3\";\nimport { logger } from \"../utils/logger.js\";\nimport { formatMCPResponse } from \"../utils/mcp-format.js\";\nimport { getXuluxCatalog } from \"../xulux/catalog-client.js\";\nimport {\n createTemplatePreview,\n getTemplateDetails,\n listTemplates,\n} from \"../xulux/template-service.js\";\n\nconst emptyInputSchema = z.object({});\n\nconst detailsInputSchema = z.object({\n templateId: z.string().describe(\"The template id from assistantUITemplates\"),\n versionId: z\n .string()\n .optional()\n .describe(\n \"Optional version id. When provided, exampleConfig reflects that version's resolved defaults.\",\n ),\n});\n\nconst previewInputSchema = z.object({\n templateId: z.string().describe(\"The template id from assistantUITemplates\"),\n versionId: z\n .string()\n .optional()\n .describe(\"Version id to use. Uses the template default if omitted.\"),\n config: z\n .record(z.string(), z.unknown())\n .optional()\n .describe(\n \"Customization config for the preview. Must contain only the top-level keys: hostUi, assistant, and brandTheme. \" +\n \"Use the schemas from assistantUITemplateDetails.configRoots as the source of truth for each root. \" +\n \"Do not pass any other root keys.\",\n ),\n});\n\nfunction withDegradedNote<T extends Record<string, unknown>>(\n payload: T,\n degraded: boolean,\n degradedReason?: string,\n): T & { catalogDegraded?: true; catalogDegradedReason?: string } {\n if (!degraded) return payload;\n return {\n ...payload,\n catalogDegraded: true,\n ...(degradedReason ? { catalogDegradedReason: degradedReason } : {}),\n };\n}\n\nexport const xuluxTemplatesListTool = {\n name: \"assistantUITemplates\",\n description:\n \"List the available assistant-ui hosted app templates and fixed demos with their features, customizable surfaces, and versions. \" +\n \"Call this first for any assistant-ui app-building request. Use the features and customizable fields to decide which template fits. \" +\n \"If customizable is empty, the entry is a fixed demo that should be used as-is rather than configured. \" +\n \"Call assistantUITemplateDetails on the chosen template before requesting a preview.\",\n parameters: emptyInputSchema.shape,\n execute: async (_args: z.infer<typeof emptyInputSchema>) => {\n logger.info(\"Listing assistant-ui templates\");\n try {\n const { catalog, degraded, degradedReason } = await getXuluxCatalog();\n return formatMCPResponse(\n withDegradedNote(listTemplates(catalog), degraded, degradedReason),\n );\n } catch (error) {\n logger.error(\"Failed to list assistant-ui templates\", error);\n return formatMCPResponse({\n error: \"Failed to list assistant-ui templates\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n },\n};\n\nexport const xuluxTemplateDetailsTool = {\n name: \"assistantUITemplateDetails\",\n description:\n \"Get the full authoring surface for a specific assistant-ui hosted template. \" +\n \"Returns configRoots schemas (with types, defaults, and enums), rules, built-in tool input/outputShape, renderer contracts, and an exampleConfig. \" +\n \"Fixed demos return no configRoots; use those as-is without config. \" +\n \"Use this before calling assistantUITemplatePreview to understand exactly what config to write. \" +\n \"If assistantUITemplatePreview returns validationWarnings, call this again and cross-reference configRoots to correct the config.\",\n parameters: detailsInputSchema.shape,\n execute: async (args: z.infer<typeof detailsInputSchema>) => {\n logger.info(\n `Getting assistant-ui template details for: ${args.templateId}`,\n );\n try {\n const { catalog, degraded, degradedReason } = await getXuluxCatalog();\n const details = await getTemplateDetails(catalog, args);\n return formatMCPResponse(\n withDegradedNote(\n details as unknown as Record<string, unknown>,\n degraded,\n degradedReason,\n ),\n );\n } catch (error) {\n logger.error(\"Failed to get assistant-ui template details\", error);\n return formatMCPResponse({\n error: \"Failed to get assistant-ui template details\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n },\n};\n\nexport const xuluxTemplatePreviewTool = {\n name: \"assistantUITemplatePreview\",\n description:\n \"Return preview and download URLs for a selected assistant-ui hosted template. \" +\n \"The previewUrl is a hosted app URL; show it to the user first, or open it with an available browser/in-app-browser tool if your client provides one. \" +\n \"If you pass config, a preview session is created on the hosted template sandbox and the returned URLs reflect that configuration. \" +\n \"Do not pass config for fixed demos that have no configRoots in assistantUITemplateDetails. \" +\n \"This tool only returns URLs.\",\n parameters: previewInputSchema.shape,\n execute: async (args: z.infer<typeof previewInputSchema>) => {\n logger.info(\n `Creating assistant-ui template preview for: ${args.templateId}`,\n );\n try {\n const { catalog, degraded, degradedReason } = await getXuluxCatalog();\n const result = await createTemplatePreview(catalog, args);\n return formatMCPResponse(\n withDegradedNote(\n result as unknown as Record<string, unknown>,\n degraded,\n degradedReason,\n ),\n );\n } catch (error) {\n logger.error(\"Failed to create assistant-ui template preview\", error);\n return formatMCPResponse({\n error: \"Failed to create assistant-ui template preview\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n },\n};\n"],"mappings":";;;;;;AAUA,MAAM,mBAAmB,EAAE,OAAO,CAAC,CAAC;AAEpC,MAAM,qBAAqB,EAAE,OAAO;CAClC,YAAY,EAAE,OAAO,CAAC,CAAC,SAAS,2CAA2C;CAC3E,WAAW,EACR,OAAO,CAAC,CACR,SAAS,CAAC,CACV,SACC,8FACF;AACJ,CAAC;AAED,MAAM,qBAAqB,EAAE,OAAO;CAClC,YAAY,EAAE,OAAO,CAAC,CAAC,SAAS,2CAA2C;CAC3E,WAAW,EACR,OAAO,CAAC,CACR,SAAS,CAAC,CACV,SAAS,0DAA0D;CACtE,QAAQ,EACL,OAAO,EAAE,OAAO,GAAG,EAAE,QAAQ,CAAC,CAAC,CAC/B,SAAS,CAAC,CACV,SACC,mPAGF;AACJ,CAAC;AAED,SAAS,iBACP,SACA,UACA,gBACgE;CAChE,IAAI,CAAC,UAAU,OAAO;CACtB,OAAO;EACL,GAAG;EACH,iBAAiB;EACjB,GAAI,iBAAiB,EAAE,uBAAuB,eAAe,IAAI,CAAC;CACpE;AACF;AAEA,MAAa,yBAAyB;CACpC,MAAM;CACN,aACE;CAIF,YAAY,iBAAiB;CAC7B,SAAS,OAAO,UAA4C;EAC1D,OAAO,KAAK,gCAAgC;EAC5C,IAAI;GACF,MAAM,EAAE,SAAS,UAAU,mBAAmB,MAAM,gBAAgB;GACpE,OAAO,kBACL,iBAAiB,cAAc,OAAO,GAAG,UAAU,cAAc,CACnE;EACF,SAAS,OAAO;GACd,OAAO,MAAM,yCAAyC,KAAK;GAC3D,OAAO,kBAAkB;IACvB,OAAO;IACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAChE,CAAC;EACH;CACF;AACF;AAEA,MAAa,2BAA2B;CACtC,MAAM;CACN,aACE;CAKF,YAAY,mBAAmB;CAC/B,SAAS,OAAO,SAA6C;EAC3D,OAAO,KACL,8CAA8C,KAAK,YACrD;EACA,IAAI;GACF,MAAM,EAAE,SAAS,UAAU,mBAAmB,MAAM,gBAAgB;GAEpE,OAAO,kBACL,iBACE,MAHkB,mBAAmB,SAAS,IAAI,GAIlD,UACA,cACF,CACF;EACF,SAAS,OAAO;GACd,OAAO,MAAM,+CAA+C,KAAK;GACjE,OAAO,kBAAkB;IACvB,OAAO;IACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAChE,CAAC;EACH;CACF;AACF;AAEA,MAAa,2BAA2B;CACtC,MAAM;CACN,aACE;CAKF,YAAY,mBAAmB;CAC/B,SAAS,OAAO,SAA6C;EAC3D,OAAO,KACL,+CAA+C,KAAK,YACtD;EACA,IAAI;GACF,MAAM,EAAE,SAAS,UAAU,mBAAmB,MAAM,gBAAgB;GAEpE,OAAO,kBACL,iBACE,MAHiB,sBAAsB,SAAS,IAAI,GAIpD,UACA,cACF,CACF;EACF,SAAS,OAAO;GACd,OAAO,MAAM,kDAAkD,KAAK;GACpE,OAAO,kBAAkB;IACvB,OAAO;IACP,SAAS,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAChE,CAAC;EACH;CACF;AACF"}
@@ -0,0 +1,5 @@
1
+ //#region src/utils/cache.d.ts
2
+ declare function cacheListing(scan: () => Promise<string[]>): () => Promise<string[]>;
3
+ //#endregion
4
+ export { cacheListing };
5
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","names":[],"sources":["../../src/utils/cache.ts"],"mappings":";iBAAgB,aACd,YAAY,0BACL"}
@@ -0,0 +1,18 @@
1
+ //#region src/utils/cache.ts
2
+ function cacheListing(scan) {
3
+ let cache = null;
4
+ return () => {
5
+ if (!cache) cache = scan().then((result) => {
6
+ if (result.length === 0) cache = null;
7
+ return result;
8
+ }, (error) => {
9
+ cache = null;
10
+ throw error;
11
+ });
12
+ return cache;
13
+ };
14
+ }
15
+ //#endregion
16
+ export { cacheListing };
17
+
18
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","names":[],"sources":["../../src/utils/cache.ts"],"sourcesContent":["export function cacheListing(\n scan: () => Promise<string[]>,\n): () => Promise<string[]> {\n let cache: Promise<string[]> | null = null;\n return () => {\n if (!cache) {\n cache = scan().then(\n (result) => {\n if (result.length === 0) cache = null;\n return result;\n },\n (error) => {\n cache = null;\n throw error;\n },\n );\n }\n return cache;\n };\n}\n"],"mappings":";AAAA,SAAgB,aACd,MACyB;CACzB,IAAI,QAAkC;CACtC,aAAa;EACX,IAAI,CAAC,OACH,QAAQ,KAAK,CAAC,CAAC,MACZ,WAAW;GACV,IAAI,OAAO,WAAW,GAAG,QAAQ;GACjC,OAAO;EACT,IACC,UAAU;GACT,QAAQ;GACR,MAAM;EACR,CACF;EAEF,OAAO;CACT;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"logger.d.ts","names":[],"sources":["../../src/utils/logger.ts"],"mappings":";cAEa,MAAA;8BACY,IAAA;6BAKD,IAAA;8BAKC,IAAA;6BAGD,IAAA;AAAA"}
1
+ {"version":3,"file":"logger.d.ts","names":[],"sources":["../../src/utils/logger.ts"],"mappings":";cAEa;8BACY;6BAKD;8BAKC;6BAGD"}
@@ -4,6 +4,7 @@ declare function formatMCPResponse(data: any): {
4
4
  type: "text";
5
5
  text: string;
6
6
  }>;
7
+ structuredContent?: Record<string, unknown>;
7
8
  };
8
9
  //#endregion
9
10
  export { formatMCPResponse };
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-format.d.ts","names":[],"sources":["../../src/utils/mcp-format.ts"],"mappings":";iBAAgB,iBAAA,CAAkB,IAAA;EAChC,OAAA,EAAS,KAAK;IAAG,IAAA;IAAc,IAAA;EAAA;AAAA"}
1
+ {"version":3,"file":"mcp-format.d.ts","names":[],"sources":["../../src/utils/mcp-format.ts"],"mappings":";iBAAgB,kBAAkB;EAChC,SAAS;IAAQ;IAAc;;EAC/B,oBAAoB"}
@@ -1,9 +1,12 @@
1
1
  //#region src/utils/mcp-format.ts
2
2
  function formatMCPResponse(data) {
3
- return { content: [{
4
- type: "text",
5
- text: typeof data === "string" ? data : JSON.stringify(data, null, 2)
6
- }] };
3
+ return {
4
+ content: [{
5
+ type: "text",
6
+ text: typeof data === "string" ? data : JSON.stringify(data, null, 2)
7
+ }],
8
+ ...typeof data === "object" && data !== null && !Array.isArray(data) && { structuredContent: data }
9
+ };
7
10
  }
8
11
  //#endregion
9
12
  export { formatMCPResponse };
@@ -1 +1 @@
1
- {"version":3,"file":"mcp-format.js","names":[],"sources":["../../src/utils/mcp-format.ts"],"sourcesContent":["export function formatMCPResponse(data: any): {\n content: Array<{ type: \"text\"; text: string }>;\n} {\n return {\n content: [\n {\n type: \"text\",\n text: typeof data === \"string\" ? data : JSON.stringify(data, null, 2),\n },\n ],\n };\n}\n"],"mappings":";AAAA,SAAgB,kBAAkB,MAEhC;CACA,OAAO,EACL,SAAS,CACP;EACE,MAAM;EACN,MAAM,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,MAAM,MAAM,CAAC;CACtE,CACF,EACF;AACF"}
1
+ {"version":3,"file":"mcp-format.js","names":[],"sources":["../../src/utils/mcp-format.ts"],"sourcesContent":["export function formatMCPResponse(data: any): {\n content: Array<{ type: \"text\"; text: string }>;\n structuredContent?: Record<string, unknown>;\n} {\n const text = typeof data === \"string\" ? data : JSON.stringify(data, null, 2);\n const isStructured =\n typeof data === \"object\" && data !== null && !Array.isArray(data);\n return {\n content: [{ type: \"text\", text }],\n ...(isStructured && {\n structuredContent: data as Record<string, unknown>,\n }),\n };\n}\n"],"mappings":";AAAA,SAAgB,kBAAkB,MAGhC;CAIA,OAAO;EACL,SAAS,CAAC;GAAE,MAAM;GAAQ,MAJf,OAAO,SAAS,WAAW,OAAO,KAAK,UAAU,MAAM,MAAM,CAAC;EAI1C,CAAC;EAChC,GAHA,OAAO,SAAS,YAAY,SAAS,QAAQ,CAAC,MAAM,QAAQ,IAAI,KAG5C,EAClB,mBAAmB,KACrB;CACF;AACF"}
@@ -1 +1 @@
1
- {"version":3,"file":"mdx.d.ts","names":[],"sources":["../../src/utils/mdx.ts"],"mappings":";UAKU,UAAA;EACR,OAAA;EACA,WAAA,EAAa,MAAM;EACnB,OAAA;AAAA;AAAA,iBAGoB,WAAA,CACpB,QAAA,WACC,OAAO,CAAC,UAAA;AAAA,iBAsBW,eAAA,CACpB,QAAA,WACC,OAAO,CAAC,UAAA;AAAA,iBAiBK,gBAAA,CAAiB,UAAsB,EAAV,UAAU"}
1
+ {"version":3,"file":"mdx.d.ts","names":[],"sources":["../../src/utils/mdx.ts"],"mappings":";UAKU;EACR;EACA,aAAa;EACb;;iBAGoB,YACpB,mBACC,QAAQ;iBAsBW,gBACpB,mBACC,QAAQ;iBAiBK,iBAAiB,YAAY"}
@@ -4,7 +4,7 @@ declare function listDirContents(dirPath: string): Promise<{
4
4
  files: string[];
5
5
  }>;
6
6
  declare function getAvailablePaths(): Promise<string[]>;
7
- declare function getAvailableDocFiles(): Promise<string[]>;
7
+ declare const getAvailableDocFiles: () => Promise<string[]>;
8
8
  declare function findNearestPaths(requestedPath: string, availablePaths: string[]): string[];
9
9
  declare function pathExists(path: string): Promise<boolean>;
10
10
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","names":[],"sources":["../../src/utils/paths.ts"],"mappings":";iBAYsB,eAAA,CAAgB,OAAA,WAAkB,OAAO;EAC7D,WAAA;EACA,KAAA;AAAA;AAAA,iBA4BoB,iBAAA,IAAqB,OAAO;AAAA,iBA0B5B,oBAAA,IAAwB,OAAO;AAAA,iBAsBrC,gBAAA,CACd,aAAA,UACA,cAAwB;AAAA,iBAoCJ,UAAA,CAAW,IAAA,WAAe,OAAO"}
1
+ {"version":3,"file":"paths.d.ts","names":[],"sources":["../../src/utils/paths.ts"],"mappings":";iBAasB,gBAAgB,kBAAkB;EACtD;EACA;;iBA4BoB,qBAAqB;cA0B9B,4BAAoB;iBAwBjB,iBACd,uBACA;iBAoCoB,WAAW,eAAe"}
@@ -1,5 +1,6 @@
1
1
  import { DOCS_PATH, MDX_EXTENSION } from "../constants.js";
2
2
  import { logger } from "./logger.js";
3
+ import { cacheListing } from "./cache.js";
3
4
  import { extname, join } from "node:path";
4
5
  import { readdir, stat } from "node:fs/promises";
5
6
  //#region src/utils/paths.ts
@@ -42,7 +43,8 @@ async function getAvailablePaths() {
42
43
  await scanDirectory(DOCS_PATH);
43
44
  return paths.sort();
44
45
  }
45
- async function getAvailableDocFiles() {
46
+ const getAvailableDocFiles = cacheListing(scanDocFiles);
47
+ async function scanDocFiles() {
46
48
  const files = [];
47
49
  async function scanDirectory(dir, prefix = "") {
48
50
  const { directories, files: dirFiles } = await listDirContents(dir);
@@ -1 +1 @@
1
- {"version":3,"file":"paths.js","names":[],"sources":["../../src/utils/paths.ts"],"sourcesContent":["import { readdir, stat } from \"node:fs/promises\";\nimport { join, extname } from \"node:path\";\nimport { DOCS_PATH, MDX_EXTENSION, MD_EXTENSION } from \"../constants.js\";\nimport { logger } from \"./logger.js\";\n\nconst SIMILARITY_THRESHOLDS = {\n EXACT_MATCH: 1,\n CONTAINS_MATCH: 0.8,\n PARTIAL_MATCH: 0.5,\n MIN_SUGGESTION: 0.3,\n} as const;\n\nexport async function listDirContents(dirPath: string): Promise<{\n directories: string[];\n files: string[];\n}> {\n try {\n const items = await readdir(dirPath, { withFileTypes: true });\n\n const directories = items\n .filter((item) => item.isDirectory())\n .map((item) => item.name)\n .filter((name) => !name.startsWith(\".\"))\n .sort();\n\n const files = items\n .filter(\n (item) =>\n item.isFile() &&\n (extname(item.name) === MDX_EXTENSION ||\n extname(item.name) === MD_EXTENSION),\n )\n .map((item) => item.name)\n .sort();\n\n return { directories, files };\n } catch (error) {\n logger.error(`Failed to list directory contents: ${dirPath}`, error);\n return { directories: [], files: [] };\n }\n}\n\nexport async function getAvailablePaths(): Promise<string[]> {\n const paths: string[] = [];\n\n async function scanDirectory(\n dir: string,\n prefix: string = \"\",\n ): Promise<void> {\n const { directories, files } = await listDirContents(dir);\n\n for (const file of files) {\n const name = file.replace(MDX_EXTENSION, \"\").replace(MD_EXTENSION, \"\");\n paths.push(prefix ? `${prefix}/${name}` : name);\n }\n\n for (const subdir of directories) {\n const subdirPath = join(dir, subdir);\n const newPrefix = prefix ? `${prefix}/${subdir}` : subdir;\n paths.push(newPrefix);\n await scanDirectory(subdirPath, newPrefix);\n }\n }\n\n await scanDirectory(DOCS_PATH);\n return paths.sort();\n}\n\nexport async function getAvailableDocFiles(): Promise<string[]> {\n const files: string[] = [];\n\n async function scanDirectory(dir: string, prefix = \"\"): Promise<void> {\n const { directories, files: dirFiles } = await listDirContents(dir);\n\n for (const file of dirFiles) {\n if (extname(file) !== MDX_EXTENSION) continue;\n const name = file.replace(MDX_EXTENSION, \"\");\n files.push(prefix ? `${prefix}/${name}` : name);\n }\n\n for (const subdir of directories) {\n const newPrefix = prefix ? `${prefix}/${subdir}` : subdir;\n await scanDirectory(join(dir, subdir), newPrefix);\n }\n }\n\n await scanDirectory(DOCS_PATH);\n return files.sort();\n}\n\nexport function findNearestPaths(\n requestedPath: string,\n availablePaths: string[],\n): string[] {\n const normalizedRequest = requestedPath\n .toLowerCase()\n .replace(/[^a-z0-9]/g, \"\");\n\n const scored = availablePaths.map((path) => {\n const normalizedPath = path.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n\n if (normalizedPath.includes(normalizedRequest)) {\n return { path, score: SIMILARITY_THRESHOLDS.EXACT_MATCH };\n }\n\n if (normalizedRequest.includes(normalizedPath)) {\n return { path, score: SIMILARITY_THRESHOLDS.CONTAINS_MATCH };\n }\n\n const overlap = [...normalizedRequest].filter((char) =>\n normalizedPath.includes(char),\n ).length;\n\n return {\n path,\n score:\n (overlap / normalizedRequest.length) *\n SIMILARITY_THRESHOLDS.PARTIAL_MATCH,\n };\n });\n\n return scored\n .filter((item) => item.score > SIMILARITY_THRESHOLDS.MIN_SUGGESTION)\n .sort((a, b) => b.score - a.score)\n .slice(0, 3)\n .map((item) => item.path);\n}\n\nexport async function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"paths.js","names":[],"sources":["../../src/utils/paths.ts"],"sourcesContent":["import { readdir, stat } from \"node:fs/promises\";\nimport { join, extname } from \"node:path\";\nimport { DOCS_PATH, MDX_EXTENSION, MD_EXTENSION } from \"../constants.js\";\nimport { cacheListing } from \"./cache.js\";\nimport { logger } from \"./logger.js\";\n\nconst SIMILARITY_THRESHOLDS = {\n EXACT_MATCH: 1,\n CONTAINS_MATCH: 0.8,\n PARTIAL_MATCH: 0.5,\n MIN_SUGGESTION: 0.3,\n} as const;\n\nexport async function listDirContents(dirPath: string): Promise<{\n directories: string[];\n files: string[];\n}> {\n try {\n const items = await readdir(dirPath, { withFileTypes: true });\n\n const directories = items\n .filter((item) => item.isDirectory())\n .map((item) => item.name)\n .filter((name) => !name.startsWith(\".\"))\n .sort();\n\n const files = items\n .filter(\n (item) =>\n item.isFile() &&\n (extname(item.name) === MDX_EXTENSION ||\n extname(item.name) === MD_EXTENSION),\n )\n .map((item) => item.name)\n .sort();\n\n return { directories, files };\n } catch (error) {\n logger.error(`Failed to list directory contents: ${dirPath}`, error);\n return { directories: [], files: [] };\n }\n}\n\nexport async function getAvailablePaths(): Promise<string[]> {\n const paths: string[] = [];\n\n async function scanDirectory(\n dir: string,\n prefix: string = \"\",\n ): Promise<void> {\n const { directories, files } = await listDirContents(dir);\n\n for (const file of files) {\n const name = file.replace(MDX_EXTENSION, \"\").replace(MD_EXTENSION, \"\");\n paths.push(prefix ? `${prefix}/${name}` : name);\n }\n\n for (const subdir of directories) {\n const subdirPath = join(dir, subdir);\n const newPrefix = prefix ? `${prefix}/${subdir}` : subdir;\n paths.push(newPrefix);\n await scanDirectory(subdirPath, newPrefix);\n }\n }\n\n await scanDirectory(DOCS_PATH);\n return paths.sort();\n}\n\nexport const getAvailableDocFiles = cacheListing(scanDocFiles);\n\nasync function scanDocFiles(): Promise<string[]> {\n const files: string[] = [];\n\n async function scanDirectory(dir: string, prefix = \"\"): Promise<void> {\n const { directories, files: dirFiles } = await listDirContents(dir);\n\n for (const file of dirFiles) {\n if (extname(file) !== MDX_EXTENSION) continue;\n const name = file.replace(MDX_EXTENSION, \"\");\n files.push(prefix ? `${prefix}/${name}` : name);\n }\n\n for (const subdir of directories) {\n const newPrefix = prefix ? `${prefix}/${subdir}` : subdir;\n await scanDirectory(join(dir, subdir), newPrefix);\n }\n }\n\n await scanDirectory(DOCS_PATH);\n return files.sort();\n}\n\nexport function findNearestPaths(\n requestedPath: string,\n availablePaths: string[],\n): string[] {\n const normalizedRequest = requestedPath\n .toLowerCase()\n .replace(/[^a-z0-9]/g, \"\");\n\n const scored = availablePaths.map((path) => {\n const normalizedPath = path.toLowerCase().replace(/[^a-z0-9]/g, \"\");\n\n if (normalizedPath.includes(normalizedRequest)) {\n return { path, score: SIMILARITY_THRESHOLDS.EXACT_MATCH };\n }\n\n if (normalizedRequest.includes(normalizedPath)) {\n return { path, score: SIMILARITY_THRESHOLDS.CONTAINS_MATCH };\n }\n\n const overlap = [...normalizedRequest].filter((char) =>\n normalizedPath.includes(char),\n ).length;\n\n return {\n path,\n score:\n (overlap / normalizedRequest.length) *\n SIMILARITY_THRESHOLDS.PARTIAL_MATCH,\n };\n });\n\n return scored\n .filter((item) => item.score > SIMILARITY_THRESHOLDS.MIN_SUGGESTION)\n .sort((a, b) => b.score - a.score)\n .slice(0, 3)\n .map((item) => item.path);\n}\n\nexport async function pathExists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"search.d.ts","names":[],"sources":["../../src/utils/search.ts"],"mappings":";UAkBiB,YAAA;EACf,IAAA;EACA,KAAA;EACA,OAAA;AAAA;AAAA,iBA0FoB,UAAA,CACpB,KAAA,UACA,KAAA,YACC,OAAO,CAAC,YAAA"}
1
+ {"version":3,"file":"search.d.ts","names":[],"sources":["../../src/utils/search.ts"],"mappings":";UAkBiB;EACf;EACA;EACA;;iBA0FoB,WACpB,eACA,iBACC,QAAQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"security.d.ts","names":[],"sources":["../../src/utils/security.ts"],"mappings":";iBAEgB,YAAA,CAAa,QAAgB"}
1
+ {"version":3,"file":"security.d.ts","names":[],"sources":["../../src/utils/security.ts"],"mappings":";iBAEgB,aAAa"}
@@ -0,0 +1,14 @@
1
+ import { XuluxCatalogResult } from "./types.js";
2
+ //#region src/xulux/catalog-client.d.ts
3
+ declare const DEFAULT_CATALOG_URL = "https://www.assistant-ui.com/api/xulux/mcp-catalog";
4
+ declare function getCatalogUrl(): string;
5
+ declare function clearCatalogCache(): void;
6
+ /**
7
+ * Returns the assistant-ui template catalog. Uses an in-memory five-minute cache, and falls
8
+ * back to a minimal bundled catalog (marked degraded) when the live fetch
9
+ * fails and no cached copy exists.
10
+ */
11
+ declare function getXuluxCatalog(): Promise<XuluxCatalogResult>;
12
+ //#endregion
13
+ export { DEFAULT_CATALOG_URL, clearCatalogCache, getCatalogUrl, getXuluxCatalog };
14
+ //# sourceMappingURL=catalog-client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-client.d.ts","names":[],"sources":["../../src/xulux/catalog-client.ts"],"mappings":";;cAIa;iBAKG;iBA0CA;;;;;;iBAoBM,mBAAmB,QAAQ"}
@@ -0,0 +1,67 @@
1
+ import { logger } from "../utils/logger.js";
2
+ import { FALLBACK_CATALOG, FALLBACK_NOTE } from "./fallback-catalog.js";
3
+ //#region src/xulux/catalog-client.ts
4
+ const DEFAULT_CATALOG_URL = "https://www.assistant-ui.com/api/xulux/mcp-catalog";
5
+ const CATALOG_TTL_MS = 300 * 1e3;
6
+ function getCatalogUrl() {
7
+ return process.env.XULUX_CATALOG_URL?.trim() || "https://www.assistant-ui.com/api/xulux/mcp-catalog";
8
+ }
9
+ function validateCatalog(data) {
10
+ if (!data || typeof data !== "object" || Array.isArray(data)) throw new Error("Catalog response is not a JSON object.");
11
+ const catalog = data;
12
+ if (catalog.version !== 1) throw new Error(`Unsupported catalog version: ${String(catalog.version)}. Expected 1.`);
13
+ if (!Array.isArray(catalog.templates)) throw new Error("Catalog response has no templates array.");
14
+ for (const template of catalog.templates) if (!template || typeof template !== "object" || typeof template.id !== "string" || typeof template.templateId !== "string" || template.kind !== "template" && template.kind !== "example") throw new Error("Catalog response contains a malformed template entry (missing id/templateId/kind).");
15
+ return catalog;
16
+ }
17
+ let cache = null;
18
+ function clearCatalogCache() {
19
+ cache = null;
20
+ }
21
+ async function fetchCatalog(url) {
22
+ const res = await fetch(url, { headers: { Accept: "application/json" } });
23
+ if (!res.ok) throw new Error(`Catalog fetch failed: HTTP ${res.status}`);
24
+ return validateCatalog(await res.json());
25
+ }
26
+ /**
27
+ * Returns the assistant-ui template catalog. Uses an in-memory five-minute cache, and falls
28
+ * back to a minimal bundled catalog (marked degraded) when the live fetch
29
+ * fails and no cached copy exists.
30
+ */
31
+ async function getXuluxCatalog() {
32
+ const url = getCatalogUrl();
33
+ const now = Date.now();
34
+ if (cache && cache.url === url && now - cache.fetchedAt < CATALOG_TTL_MS) return {
35
+ catalog: cache.catalog,
36
+ degraded: false
37
+ };
38
+ try {
39
+ const catalog = await fetchCatalog(url);
40
+ cache = {
41
+ catalog,
42
+ fetchedAt: now,
43
+ url
44
+ };
45
+ return {
46
+ catalog,
47
+ degraded: false
48
+ };
49
+ } catch (error) {
50
+ const message = error instanceof Error ? error.message : String(error);
51
+ logger.warn(`assistant-ui template catalog fetch failed (${url}): ${message}`);
52
+ if (cache && cache.url === url) return {
53
+ catalog: cache.catalog,
54
+ degraded: true,
55
+ degradedReason: `Live catalog refresh failed (${message}); using previously fetched catalog.`
56
+ };
57
+ return {
58
+ catalog: FALLBACK_CATALOG,
59
+ degraded: true,
60
+ degradedReason: `${message} ${FALLBACK_NOTE}`
61
+ };
62
+ }
63
+ }
64
+ //#endregion
65
+ export { DEFAULT_CATALOG_URL, clearCatalogCache, getCatalogUrl, getXuluxCatalog };
66
+
67
+ //# sourceMappingURL=catalog-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-client.js","names":[],"sources":["../../src/xulux/catalog-client.ts"],"sourcesContent":["import { logger } from \"../utils/logger.js\";\nimport { FALLBACK_CATALOG, FALLBACK_NOTE } from \"./fallback-catalog.js\";\nimport type { XuluxCatalog, XuluxCatalogResult } from \"./types.js\";\n\nexport const DEFAULT_CATALOG_URL =\n \"https://www.assistant-ui.com/api/xulux/mcp-catalog\";\n\nconst CATALOG_TTL_MS = 5 * 60 * 1000;\n\nexport function getCatalogUrl(): string {\n const override = process.env.XULUX_CATALOG_URL?.trim();\n return override || DEFAULT_CATALOG_URL;\n}\n\nfunction validateCatalog(data: unknown): XuluxCatalog {\n if (!data || typeof data !== \"object\" || Array.isArray(data)) {\n throw new Error(\"Catalog response is not a JSON object.\");\n }\n const catalog = data as XuluxCatalog;\n if (catalog.version !== 1) {\n throw new Error(\n `Unsupported catalog version: ${String(catalog.version)}. Expected 1.`,\n );\n }\n if (!Array.isArray(catalog.templates)) {\n throw new Error(\"Catalog response has no templates array.\");\n }\n for (const template of catalog.templates) {\n if (\n !template ||\n typeof template !== \"object\" ||\n typeof template.id !== \"string\" ||\n typeof template.templateId !== \"string\" ||\n (template.kind !== \"template\" && template.kind !== \"example\")\n ) {\n throw new Error(\n \"Catalog response contains a malformed template entry (missing id/templateId/kind).\",\n );\n }\n }\n return catalog;\n}\n\ninterface CacheEntry {\n catalog: XuluxCatalog;\n fetchedAt: number;\n url: string;\n}\n\nlet cache: CacheEntry | null = null;\n\nexport function clearCatalogCache(): void {\n cache = null;\n}\n\nasync function fetchCatalog(url: string): Promise<XuluxCatalog> {\n const res = await fetch(url, {\n headers: { Accept: \"application/json\" },\n });\n if (!res.ok) {\n throw new Error(`Catalog fetch failed: HTTP ${res.status}`);\n }\n const data: unknown = await res.json();\n return validateCatalog(data);\n}\n\n/**\n * Returns the assistant-ui template catalog. Uses an in-memory five-minute cache, and falls\n * back to a minimal bundled catalog (marked degraded) when the live fetch\n * fails and no cached copy exists.\n */\nexport async function getXuluxCatalog(): Promise<XuluxCatalogResult> {\n const url = getCatalogUrl();\n const now = Date.now();\n\n if (cache && cache.url === url && now - cache.fetchedAt < CATALOG_TTL_MS) {\n return { catalog: cache.catalog, degraded: false };\n }\n\n try {\n const catalog = await fetchCatalog(url);\n cache = { catalog, fetchedAt: now, url };\n return { catalog, degraded: false };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n logger.warn(\n `assistant-ui template catalog fetch failed (${url}): ${message}`,\n );\n\n // Prefer a stale cached copy over the minimal fallback.\n if (cache && cache.url === url) {\n return {\n catalog: cache.catalog,\n degraded: true,\n degradedReason: `Live catalog refresh failed (${message}); using previously fetched catalog.`,\n };\n }\n\n return {\n catalog: FALLBACK_CATALOG,\n degraded: true,\n degradedReason: `${message} ${FALLBACK_NOTE}`,\n };\n }\n}\n"],"mappings":";;;AAIA,MAAa,sBACX;AAEF,MAAM,iBAAiB,MAAS;AAEhC,SAAgB,gBAAwB;CAEtC,OADiB,QAAQ,IAAI,mBAAmB,KAAK,KAAA;AAEvD;AAEA,SAAS,gBAAgB,MAA6B;CACpD,IAAI,CAAC,QAAQ,OAAO,SAAS,YAAY,MAAM,QAAQ,IAAI,GACzD,MAAM,IAAI,MAAM,wCAAwC;CAE1D,MAAM,UAAU;CAChB,IAAI,QAAQ,YAAY,GACtB,MAAM,IAAI,MACR,gCAAgC,OAAO,QAAQ,OAAO,EAAE,cAC1D;CAEF,IAAI,CAAC,MAAM,QAAQ,QAAQ,SAAS,GAClC,MAAM,IAAI,MAAM,0CAA0C;CAE5D,KAAK,MAAM,YAAY,QAAQ,WAC7B,IACE,CAAC,YACD,OAAO,aAAa,YACpB,OAAO,SAAS,OAAO,YACvB,OAAO,SAAS,eAAe,YAC9B,SAAS,SAAS,cAAc,SAAS,SAAS,WAEnD,MAAM,IAAI,MACR,oFACF;CAGJ,OAAO;AACT;AAQA,IAAI,QAA2B;AAE/B,SAAgB,oBAA0B;CACxC,QAAQ;AACV;AAEA,eAAe,aAAa,KAAoC;CAC9D,MAAM,MAAM,MAAM,MAAM,KAAK,EAC3B,SAAS,EAAE,QAAQ,mBAAmB,EACxC,CAAC;CACD,IAAI,CAAC,IAAI,IACP,MAAM,IAAI,MAAM,8BAA8B,IAAI,QAAQ;CAG5D,OAAO,gBAAgB,MADK,IAAI,KAAK,CACV;AAC7B;;;;;;AAOA,eAAsB,kBAA+C;CACnE,MAAM,MAAM,cAAc;CAC1B,MAAM,MAAM,KAAK,IAAI;CAErB,IAAI,SAAS,MAAM,QAAQ,OAAO,MAAM,MAAM,YAAY,gBACxD,OAAO;EAAE,SAAS,MAAM;EAAS,UAAU;CAAM;CAGnD,IAAI;EACF,MAAM,UAAU,MAAM,aAAa,GAAG;EACtC,QAAQ;GAAE;GAAS,WAAW;GAAK;EAAI;EACvC,OAAO;GAAE;GAAS,UAAU;EAAM;CACpC,SAAS,OAAO;EACd,MAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;EACrE,OAAO,KACL,+CAA+C,IAAI,KAAK,SAC1D;EAGA,IAAI,SAAS,MAAM,QAAQ,KACzB,OAAO;GACL,SAAS,MAAM;GACf,UAAU;GACV,gBAAgB,gCAAgC,QAAQ;EAC1D;EAGF,OAAO;GACL,SAAS;GACT,UAAU;GACV,gBAAgB,GAAG,QAAQ,GAAG;EAChC;CACF;AACF"}
@@ -0,0 +1,7 @@
1
+ import { XuluxCatalog } from "./types.js";
2
+ //#region src/xulux/fallback-catalog.d.ts
3
+ declare const FALLBACK_NOTE: string;
4
+ declare const FALLBACK_CATALOG: XuluxCatalog;
5
+ //#endregion
6
+ export { FALLBACK_CATALOG, FALLBACK_NOTE };
7
+ //# sourceMappingURL=fallback-catalog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback-catalog.d.ts","names":[],"sources":["../../src/xulux/fallback-catalog.ts"],"mappings":";;cAWa;cAiBA,kBAAkB"}
@@ -0,0 +1,47 @@
1
+ import "./types.js";
2
+ //#region src/xulux/fallback-catalog.ts
3
+ const FALLBACK_NOTE = "The live assistant-ui template catalog could not be fetched, so this is minimal bundled fallback data. Template details, previews, and downloads require live catalog access. Check network access to the docs site or set XULUX_CATALOG_URL to a reachable catalog endpoint.";
4
+ const fallbackTemplate = (overrides) => ({
5
+ templateId: overrides.id,
6
+ versionId: null,
7
+ assistantPlacement: "unavailable in fallback mode",
8
+ features: [],
9
+ customizable: [],
10
+ versions: [],
11
+ ...overrides
12
+ });
13
+ const FALLBACK_CATALOG = {
14
+ version: 1,
15
+ generatedAt: "fallback",
16
+ docsOrigin: "https://www.assistant-ui.com",
17
+ templates: [
18
+ fallbackTemplate({
19
+ id: "base-assistant-ui",
20
+ kind: "template",
21
+ name: "Configurable Base Assistant UI",
22
+ summary: "Hosted configurable assistant-ui Base chat template with threads, composer, suggestions, and no-key demo flows."
23
+ }),
24
+ fallbackTemplate({
25
+ id: "webpage-assistant",
26
+ kind: "template",
27
+ name: "Webpage with Assistant",
28
+ summary: "Docs/website layout with a sidebar or modal assistant grounded in configurable pages."
29
+ }),
30
+ fallbackTemplate({
31
+ id: "product-page-assistant",
32
+ kind: "template",
33
+ name: "Product Page with Floating Assistant",
34
+ summary: "Mock product dashboard with a floating modal support assistant and analyze-then-handoff flow."
35
+ }),
36
+ fallbackTemplate({
37
+ id: "expo-react-native",
38
+ kind: "example",
39
+ name: "Expo React Native Assistant",
40
+ summary: "Mobile AI chat app built with Expo and assistant-ui React Native primitives."
41
+ })
42
+ ]
43
+ };
44
+ //#endregion
45
+ export { FALLBACK_CATALOG, FALLBACK_NOTE };
46
+
47
+ //# sourceMappingURL=fallback-catalog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fallback-catalog.js","names":[],"sources":["../../src/xulux/fallback-catalog.ts"],"sourcesContent":["import {\n XULUX_MCP_CATALOG_VERSION,\n type XuluxCatalog,\n type XuluxCatalogTemplate,\n} from \"./types.js\";\n\n// Minimal bundled fallback catalog for degraded mode. It supports discovery\n// (ids + names) only. Full authoring details and preview/download URLs\n// require the live catalog endpoint. Do NOT grow this into a copy of the\n// full template knowledge base — the docs endpoint owns freshness.\n\nexport const FALLBACK_NOTE =\n \"The live assistant-ui template catalog could not be fetched, so this is minimal bundled fallback data. \" +\n \"Template details, previews, and downloads require live catalog access. \" +\n \"Check network access to the docs site or set XULUX_CATALOG_URL to a reachable catalog endpoint.\";\n\nconst fallbackTemplate = (\n overrides: Pick<XuluxCatalogTemplate, \"id\" | \"kind\" | \"name\" | \"summary\">,\n): XuluxCatalogTemplate => ({\n templateId: overrides.id,\n versionId: null,\n assistantPlacement: \"unavailable in fallback mode\",\n features: [],\n customizable: [],\n versions: [],\n ...overrides,\n});\n\nexport const FALLBACK_CATALOG: XuluxCatalog = {\n version: XULUX_MCP_CATALOG_VERSION,\n generatedAt: \"fallback\",\n docsOrigin: \"https://www.assistant-ui.com\",\n templates: [\n fallbackTemplate({\n id: \"base-assistant-ui\",\n kind: \"template\",\n name: \"Configurable Base Assistant UI\",\n summary:\n \"Hosted configurable assistant-ui Base chat template with threads, composer, suggestions, and no-key demo flows.\",\n }),\n fallbackTemplate({\n id: \"webpage-assistant\",\n kind: \"template\",\n name: \"Webpage with Assistant\",\n summary:\n \"Docs/website layout with a sidebar or modal assistant grounded in configurable pages.\",\n }),\n fallbackTemplate({\n id: \"product-page-assistant\",\n kind: \"template\",\n name: \"Product Page with Floating Assistant\",\n summary:\n \"Mock product dashboard with a floating modal support assistant and analyze-then-handoff flow.\",\n }),\n fallbackTemplate({\n id: \"expo-react-native\",\n kind: \"example\",\n name: \"Expo React Native Assistant\",\n summary:\n \"Mobile AI chat app built with Expo and assistant-ui React Native primitives.\",\n }),\n ],\n};\n"],"mappings":";;AAWA,MAAa,gBACX;AAIF,MAAM,oBACJ,eAC0B;CAC1B,YAAY,UAAU;CACtB,WAAW;CACX,oBAAoB;CACpB,UAAU,CAAC;CACX,cAAc,CAAC;CACf,UAAU,CAAC;CACX,GAAG;AACL;AAEA,MAAa,mBAAiC;CAC5C,SAAA;CACA,aAAa;CACb,YAAY;CACZ,WAAW;EACT,iBAAiB;GACf,IAAI;GACJ,MAAM;GACN,MAAM;GACN,SACE;EACJ,CAAC;EACD,iBAAiB;GACf,IAAI;GACJ,MAAM;GACN,MAAM;GACN,SACE;EACJ,CAAC;EACD,iBAAiB;GACf,IAAI;GACJ,MAAM;GACN,MAAM;GACN,SACE;EACJ,CAAC;EACD,iBAAiB;GACf,IAAI;GACJ,MAAM;GACN,MAAM;GACN,SACE;EACJ,CAAC;CACH;AACF"}
@@ -0,0 +1,5 @@
1
+ //#region src/xulux/fetch-sandbox.d.ts
2
+ declare function fetchSandboxResource(url: string | URL, init?: RequestInit): Promise<Response>;
3
+ //#endregion
4
+ export { fetchSandboxResource };
5
+ //# sourceMappingURL=fetch-sandbox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-sandbox.d.ts","names":[],"sources":["../../src/xulux/fetch-sandbox.ts"],"mappings":";iBAgCsB,qBACpB,cAAc,KACd,OAAO,cACN,QAAQ"}
@@ -0,0 +1,40 @@
1
+ //#region src/xulux/fetch-sandbox.ts
2
+ const SANDBOX_FETCH_HEADERS = {
3
+ Accept: "application/json, application/zip, application/octet-stream, */*",
4
+ "User-Agent": "curl/8.7.1"
5
+ };
6
+ const MAX_ATTEMPTS = 3;
7
+ const RETRY_DELAY_MS = 300;
8
+ function isRetryableFetchError(error) {
9
+ if (!(error instanceof Error)) return false;
10
+ const code = error.cause?.code ?? error.message;
11
+ return code === "ECONNRESET" || code === "ETIMEDOUT" || code === "ECONNREFUSED" || code === "fetch failed";
12
+ }
13
+ function sleep(ms) {
14
+ return new Promise((resolve) => setTimeout(resolve, ms));
15
+ }
16
+ function mergeHeaders(headers) {
17
+ const merged = new Headers(SANDBOX_FETCH_HEADERS);
18
+ if (!headers) return merged;
19
+ new Headers(headers).forEach((value, key) => merged.set(key, value));
20
+ return merged;
21
+ }
22
+ async function fetchSandboxResource(url, init) {
23
+ let lastError;
24
+ for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt += 1) try {
25
+ return await fetch(url, {
26
+ ...init,
27
+ cache: "no-store",
28
+ headers: mergeHeaders(init?.headers)
29
+ });
30
+ } catch (error) {
31
+ lastError = error;
32
+ if (!isRetryableFetchError(error) || attempt === MAX_ATTEMPTS) throw error;
33
+ await sleep(RETRY_DELAY_MS * attempt);
34
+ }
35
+ throw lastError;
36
+ }
37
+ //#endregion
38
+ export { fetchSandboxResource };
39
+
40
+ //# sourceMappingURL=fetch-sandbox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fetch-sandbox.js","names":[],"sources":["../../src/xulux/fetch-sandbox.ts"],"sourcesContent":["const SANDBOX_FETCH_HEADERS = {\n Accept: \"application/json, application/zip, application/octet-stream, */*\",\n // Blaxel preview hosts intermittently reset Node's default fetch path.\n \"User-Agent\": \"curl/8.7.1\",\n};\n\nconst MAX_ATTEMPTS = 3;\nconst RETRY_DELAY_MS = 300;\n\nfunction isRetryableFetchError(error: unknown) {\n if (!(error instanceof Error)) return false;\n const cause = error.cause as { code?: string } | undefined;\n const code = cause?.code ?? error.message;\n return (\n code === \"ECONNRESET\" ||\n code === \"ETIMEDOUT\" ||\n code === \"ECONNREFUSED\" ||\n code === \"fetch failed\"\n );\n}\n\nfunction sleep(ms: number) {\n return new Promise((resolve) => setTimeout(resolve, ms));\n}\n\nfunction mergeHeaders(headers?: HeadersInit): Headers {\n const merged = new Headers(SANDBOX_FETCH_HEADERS);\n if (!headers) return merged;\n new Headers(headers).forEach((value, key) => merged.set(key, value));\n return merged;\n}\n\nexport async function fetchSandboxResource(\n url: string | URL,\n init?: RequestInit,\n): Promise<Response> {\n let lastError: unknown;\n\n for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt += 1) {\n try {\n return await fetch(url, {\n ...init,\n cache: \"no-store\",\n headers: mergeHeaders(init?.headers),\n });\n } catch (error) {\n lastError = error;\n if (!isRetryableFetchError(error) || attempt === MAX_ATTEMPTS) {\n throw error;\n }\n await sleep(RETRY_DELAY_MS * attempt);\n }\n }\n\n throw lastError;\n}\n"],"mappings":";AAAA,MAAM,wBAAwB;CAC5B,QAAQ;CAER,cAAc;AAChB;AAEA,MAAM,eAAe;AACrB,MAAM,iBAAiB;AAEvB,SAAS,sBAAsB,OAAgB;CAC7C,IAAI,EAAE,iBAAiB,QAAQ,OAAO;CAEtC,MAAM,OADQ,MAAM,OACA,QAAQ,MAAM;CAClC,OACE,SAAS,gBACT,SAAS,eACT,SAAS,kBACT,SAAS;AAEb;AAEA,SAAS,MAAM,IAAY;CACzB,OAAO,IAAI,SAAS,YAAY,WAAW,SAAS,EAAE,CAAC;AACzD;AAEA,SAAS,aAAa,SAAgC;CACpD,MAAM,SAAS,IAAI,QAAQ,qBAAqB;CAChD,IAAI,CAAC,SAAS,OAAO;CACrB,IAAI,QAAQ,OAAO,CAAC,CAAC,SAAS,OAAO,QAAQ,OAAO,IAAI,KAAK,KAAK,CAAC;CACnE,OAAO;AACT;AAEA,eAAsB,qBACpB,KACA,MACmB;CACnB,IAAI;CAEJ,KAAK,IAAI,UAAU,GAAG,WAAW,cAAc,WAAW,GACxD,IAAI;EACF,OAAO,MAAM,MAAM,KAAK;GACtB,GAAG;GACH,OAAO;GACP,SAAS,aAAa,MAAM,OAAO;EACrC,CAAC;CACH,SAAS,OAAO;EACd,YAAY;EACZ,IAAI,CAAC,sBAAsB,KAAK,KAAK,YAAY,cAC/C,MAAM;EAER,MAAM,MAAM,iBAAiB,OAAO;CACtC;CAGF,MAAM;AACR"}
@@ -0,0 +1,84 @@
1
+ import { XuluxCatalog, XuluxCatalogTemplate, XuluxCatalogVersion } from "./types.js";
2
+ //#region src/xulux/template-service.d.ts
3
+ interface ResolvedTemplate {
4
+ template: XuluxCatalogTemplate;
5
+ version: XuluxCatalogVersion | null;
6
+ }
7
+ /**
8
+ * Resolves a template by id, preserving the app-route semantics:
9
+ * - exact `templateId` match wins
10
+ * - version-specific entry ids (e.g. `webpage-assistant-product-docs`)
11
+ * remain valid inputs
12
+ * - explicit `versionId` wins when provided
13
+ * - otherwise the template's default version is used
14
+ */
15
+ declare function resolveTemplate(catalog: XuluxCatalog, templateId: string, versionId?: string | undefined): ResolvedTemplate | null;
16
+ interface TemplateListItem {
17
+ id: string;
18
+ name: string;
19
+ summary: string;
20
+ assistantPlacement: string;
21
+ features: string[];
22
+ customizable: string[];
23
+ versions: Array<{
24
+ id: string;
25
+ name: string;
26
+ description: string;
27
+ }>;
28
+ kind: "template" | "example";
29
+ }
30
+ declare function listTemplates(catalog: XuluxCatalog): {
31
+ templates: TemplateListItem[];
32
+ };
33
+ interface TemplateDetails {
34
+ id: string;
35
+ name: string;
36
+ selectedVersionId: string | null;
37
+ summary: string;
38
+ assistantPlacement: string;
39
+ configRoots?: Record<string, unknown>;
40
+ rules: {
41
+ required: string[];
42
+ unsupported?: string[];
43
+ };
44
+ tools: {
45
+ builtIn: unknown[];
46
+ customToolSupported: boolean;
47
+ renderers: unknown[];
48
+ };
49
+ exampleConfig: Record<string, unknown> | null;
50
+ previewUrl?: string;
51
+ downloadUrl?: string;
52
+ warnings?: string[];
53
+ exampleConfigNote?: string;
54
+ }
55
+ interface TemplateError {
56
+ error: string;
57
+ retryHint?: string;
58
+ }
59
+ declare function getTemplateDetails(catalog: XuluxCatalog, input: {
60
+ templateId: string;
61
+ versionId?: string | undefined;
62
+ }): Promise<TemplateDetails | TemplateError>;
63
+ interface TemplatePreviewResult {
64
+ success: boolean;
65
+ templateId: string;
66
+ versionId: string | null;
67
+ previewUrl?: string;
68
+ downloadUrl?: string;
69
+ title?: string;
70
+ customized?: boolean;
71
+ validationWarnings?: unknown[];
72
+ error?: string;
73
+ retryHint?: string;
74
+ details?: string;
75
+ summary?: string;
76
+ }
77
+ declare function createTemplatePreview(catalog: XuluxCatalog, input: {
78
+ templateId: string;
79
+ versionId?: string | undefined;
80
+ config?: Record<string, unknown> | undefined;
81
+ }): Promise<TemplatePreviewResult>;
82
+ //#endregion
83
+ export { ResolvedTemplate, TemplateDetails, TemplateError, TemplateListItem, TemplatePreviewResult, createTemplatePreview, getTemplateDetails, listTemplates, resolveTemplate };
84
+ //# sourceMappingURL=template-service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"template-service.d.ts","names":[],"sources":["../../src/xulux/template-service.ts"],"mappings":";;UAYiB;EACf,UAAU;EACV,SAAS;;;;;;;;;;iBAWK,gBACd,SAAS,cACT,oBACA,iCACC;UA6Bc;EACf;EACA;EACA;EACA;EACA;EACA;EACA,UAAU;IAAQ;IAAY;IAAc;;EAC5C;;iBAGc,cAAc,SAAS;EACrC,WAAW;;UAmCI;EACf;EACA;EACA;EACA;EACA;EACA,cAAc;EACd;IACE;IACA;;EAEF;IACE;IACA;IACA;;EAEF,eAAe;EACf;EACA;EACA;EACA;;UAGe;EACf;EACA;;iBAGoB,mBACpB,SAAS,cACT;EAAS;EAAoB;IAC5B,QAAQ,kBAAkB;UAqGZ;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;iBAGoB,sBACpB,SAAS,cACT;EACE;EACA;EACA,SAAS;IAEV,QAAQ"}