@assistant-ui/mcp-docs-server 0.1.38 → 0.2.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.
- package/.docs/organized/code-examples/waterfall.md +11 -12
- package/.docs/organized/code-examples/with-a2a.md +18 -13
- package/.docs/organized/code-examples/with-ag-ui.md +19 -14
- package/.docs/organized/code-examples/{with-ai-sdk-v6.md → with-ai-sdk-v7.md} +34 -23
- package/.docs/organized/code-examples/with-artifacts.md +473 -141
- package/.docs/organized/code-examples/with-assistant-transport.md +17 -10
- package/.docs/organized/code-examples/with-browser-extension.md +17 -10
- package/.docs/organized/code-examples/with-chain-of-thought.md +21 -14
- package/.docs/organized/code-examples/with-cloud-standalone.md +12 -11
- package/.docs/organized/code-examples/with-cloud.md +20 -15
- package/.docs/organized/code-examples/with-custom-thread-list.md +19 -12
- package/.docs/organized/code-examples/with-elevenlabs-conversational.md +22 -15
- package/.docs/organized/code-examples/with-elevenlabs-scribe.md +22 -15
- package/.docs/organized/code-examples/with-eve.md +18 -11
- package/.docs/organized/code-examples/with-expo.md +35 -52
- package/.docs/organized/code-examples/with-external-store.md +18 -13
- package/.docs/organized/code-examples/with-ffmpeg.md +20 -15
- package/.docs/organized/code-examples/with-generative-ui.md +22 -17
- package/.docs/organized/code-examples/with-google-adk.md +18 -11
- package/.docs/organized/code-examples/with-heat-graph.md +10 -11
- package/.docs/organized/code-examples/with-image-generation.md +19 -12
- package/.docs/organized/code-examples/with-interactables.md +21 -17
- package/.docs/organized/code-examples/with-langchain.md +19 -12
- package/.docs/organized/code-examples/with-langgraph.md +19 -12
- package/.docs/organized/code-examples/with-livekit.md +23 -16
- package/.docs/organized/code-examples/with-mcp.md +46 -28
- package/.docs/organized/code-examples/with-opencode.md +25 -23
- package/.docs/organized/code-examples/with-pi.md +54 -19
- package/.docs/organized/code-examples/with-react-hook-form.md +21 -16
- package/.docs/organized/code-examples/with-react-ink-web.md +9 -9
- package/.docs/organized/code-examples/with-react-ink.md +4 -4
- package/.docs/organized/code-examples/with-react-router.md +22 -17
- package/.docs/organized/code-examples/with-resumable-stream.md +21 -14
- package/.docs/organized/code-examples/with-store.md +10 -11
- package/.docs/organized/code-examples/with-tanstack.md +19 -13
- package/.docs/organized/code-examples/with-tap-runtime.md +18 -13
- package/.docs/organized/code-examples/with-virtualized-thread.md +19 -14
- package/.docs/raw/docs/(docs)/base-ui.mdx +39 -0
- package/.docs/raw/docs/(docs)/cli.mdx +19 -1
- package/.docs/raw/docs/(docs)/devtools.mdx +7 -2
- package/.docs/raw/docs/(docs)/installation.mdx +15 -1
- package/.docs/raw/docs/(docs)/rtl.mdx +2 -4
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/a2ui.mdx +40 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/actions.mdx +56 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/components.mdx +86 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/index.mdx +22 -1
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/json-generative-ui.mdx +42 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/rendering.mdx +53 -2
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/slack.mdx +81 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/teams.mdx +86 -0
- package/.docs/raw/docs/(reference)/api-reference/generative-ui/tokens.mdx +62 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/primitives.mdx +19 -420
- package/.docs/raw/docs/(reference)/api-reference/hooks/state.mdx +4 -1
- package/.docs/raw/docs/(reference)/api-reference/integrations/index.mdx +4 -1
- package/.docs/raw/docs/(reference)/api-reference/integrations/react-ai-sdk.mdx +25 -2
- package/.docs/raw/docs/(reference)/api-reference/integrations/react-data-stream.mdx +37 -0
- package/.docs/raw/docs/(reference)/api-reference/model-context/context.mdx +1 -9
- package/.docs/raw/docs/(reference)/api-reference/overview.mdx +1 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/assistant-if.mdx +14 -31
- package/.docs/raw/docs/(reference)/api-reference/primitives/composition.mdx +1 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/index.mdx +3 -0
- package/.docs/raw/docs/(reference)/api-reference/primitives/selection-toolbar.mdx +2 -0
- package/.docs/raw/docs/(reference)/api-reference/tools/status.mdx +0 -2
- package/.docs/raw/docs/(reference)/api-reference/tools/toolkits.mdx +12 -9
- package/.docs/raw/docs/(reference)/api-reference/utilities/miscellaneous.mdx +4 -0
- package/.docs/raw/docs/cloud/ai-sdk-assistant-ui.mdx +7 -1
- package/.docs/raw/docs/cloud/langgraph.mdx +4 -2
- package/.docs/raw/docs/copilots/model-context.mdx +1 -1
- package/.docs/raw/docs/copilots/motivation.mdx +1 -1
- package/.docs/raw/docs/guides/attachments.mdx +3 -3
- package/.docs/raw/docs/guides/branching.mdx +2 -2
- package/.docs/raw/docs/guides/chatgpt-subscription.mdx +108 -0
- package/.docs/raw/docs/guides/context-api.mdx +89 -111
- package/.docs/raw/docs/guides/dictation.mdx +185 -257
- package/.docs/raw/docs/guides/editing.mdx +5 -5
- package/.docs/raw/docs/guides/electron.mdx +369 -0
- package/.docs/raw/docs/guides/index.mdx +20 -0
- package/.docs/raw/docs/guides/mentions.mdx +31 -3
- package/.docs/raw/docs/guides/quoting.mdx +3 -3
- package/.docs/raw/docs/guides/resumable-stream-deployment.mdx +2 -2
- package/.docs/raw/docs/guides/resumable-streams.mdx +12 -1
- package/.docs/raw/docs/guides/speech.mdx +47 -29
- package/.docs/raw/docs/guides/suggestions.mdx +70 -1
- package/.docs/raw/docs/guides/voice.mdx +197 -267
- package/.docs/raw/docs/ink/hooks.mdx +3 -3
- package/.docs/raw/docs/ink/primitives.mdx +49 -8
- package/.docs/raw/docs/integrations/auth/better-auth.mdx +2 -2
- package/.docs/raw/docs/integrations/auth/clerk.mdx +2 -2
- package/.docs/raw/docs/integrations/auth/next-auth.mdx +3 -3
- package/.docs/raw/docs/integrations/frameworks/ai-sdk.mdx +10 -4
- package/.docs/raw/docs/integrations/frameworks/cloudflare-agents/overview.mdx +3 -3
- package/.docs/raw/docs/integrations/frameworks/mastra/full-stack.mdx +1 -1
- package/.docs/raw/docs/integrations/frameworks/mastra/overview.mdx +3 -3
- package/.docs/raw/docs/integrations/frameworks/mastra/separate-server.mdx +1 -1
- package/.docs/raw/docs/integrations/gateways/index.mdx +2 -2
- package/.docs/raw/docs/integrations/observability/helicone.mdx +1 -1
- package/.docs/raw/docs/integrations/observability/langfuse.mdx +1 -1
- package/.docs/raw/docs/integrations/observability/langsmith.mdx +2 -2
- package/.docs/raw/docs/integrations/persistence/custom-adapter.mdx +36 -9
- package/.docs/raw/docs/migrations/index.mdx +50 -0
- package/.docs/raw/docs/migrations/toolkit-tools.mdx +4 -2
- package/.docs/raw/docs/migrations/v0-15.mdx +156 -0
- package/.docs/raw/docs/primitives/chain-of-thought.mdx +6 -1
- package/.docs/raw/docs/primitives/composer.mdx +17 -1
- package/.docs/raw/docs/primitives/selection-toolbar.mdx +25 -0
- package/.docs/raw/docs/primitives/thread-list.mdx +2 -2
- package/.docs/raw/docs/react-native/hooks.mdx +3 -3
- package/.docs/raw/docs/react-native/index.mdx +2 -2
- package/.docs/raw/docs/react-native/primitives.mdx +62 -5
- package/.docs/raw/docs/runtimes/ag-ui/agent-state.mdx +124 -0
- package/.docs/raw/docs/runtimes/ag-ui/runtime-options.mdx +10 -1
- package/.docs/raw/docs/runtimes/ai-sdk/overview.mdx +14 -5
- package/.docs/raw/docs/runtimes/ai-sdk/v4-legacy.mdx +15 -15
- package/.docs/raw/docs/runtimes/ai-sdk/v5-legacy.mdx +8 -8
- package/.docs/raw/docs/runtimes/ai-sdk/{v6.mdx → v6-legacy.mdx} +11 -9
- package/.docs/raw/docs/runtimes/ai-sdk/v7.mdx +717 -0
- package/.docs/raw/docs/runtimes/concepts/adapters.mdx +1 -1
- package/.docs/raw/docs/runtimes/concepts/architecture.mdx +1 -1
- package/.docs/raw/docs/runtimes/concepts/threads.mdx +10 -10
- package/.docs/raw/docs/runtimes/custom/assistant-transport.mdx +2 -2
- package/.docs/raw/docs/runtimes/custom/data-stream.mdx +10 -19
- package/.docs/raw/docs/runtimes/custom/external-store.mdx +2 -2
- package/.docs/raw/docs/runtimes/custom/local-runtime.mdx +5 -3
- package/.docs/raw/docs/runtimes/eve/overview.mdx +1 -1
- package/.docs/raw/docs/runtimes/langchain.mdx +2 -2
- package/.docs/raw/docs/runtimes/langgraph/agent-state.mdx +181 -0
- package/.docs/raw/docs/runtimes/langgraph/overview.mdx +1 -1
- package/.docs/raw/docs/runtimes/opencode/hooks.mdx +3 -1
- package/.docs/raw/docs/tools/a2ui.mdx +107 -0
- package/.docs/raw/docs/tools/backend.mdx +6 -3
- package/.docs/raw/docs/tools/defining-tools.mdx +7 -1
- package/.docs/raw/docs/tools/generative-ui.mdx +60 -2
- package/.docs/raw/docs/tools/interactables-legacy.mdx +4 -4
- package/.docs/raw/docs/tools/interactables.mdx +3 -3
- package/.docs/raw/docs/tools/mcp-apps.mdx +90 -13
- package/.docs/raw/docs/tools/mcp.mdx +100 -3
- package/.docs/raw/docs/tools/tool-ui.mdx +6 -4
- package/.docs/raw/docs/tools/user-managed-mcp.mdx +77 -9
- package/.docs/raw/docs/ui/accordion.mdx +16 -10
- package/.docs/raw/docs/ui/assistant-modal.mdx +8 -4
- package/.docs/raw/docs/ui/attachment.mdx +5 -1
- package/.docs/raw/docs/ui/badge.mdx +23 -12
- package/.docs/raw/docs/ui/follow-up-suggestions.mdx +4 -2
- package/.docs/raw/docs/ui/model-selector.mdx +33 -3
- package/.docs/raw/docs/ui/part-grouping.mdx +0 -4
- package/.docs/raw/docs/ui/reasoning.mdx +1 -1
- package/.docs/raw/docs/ui/select.mdx +22 -14
- package/.docs/raw/docs/ui/sources.mdx +1 -1
- package/.docs/raw/docs/ui/tabs.mdx +25 -14
- package/.docs/raw/docs/utilities/heat-graph.mdx +2 -2
- package/dist/constants.d.ts.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +41 -2
- package/dist/index.js.map +1 -1
- package/dist/prepare-docs/code-examples.d.ts.map +1 -1
- package/dist/prepare-docs/code-examples.js.map +1 -1
- package/dist/prepare-docs/copy-raw.d.ts.map +1 -1
- package/dist/prepare-docs/prepare.d.ts +1 -1
- package/dist/prompts/xulux-playground.d.ts +12 -0
- package/dist/prompts/xulux-playground.d.ts.map +1 -0
- package/dist/prompts/xulux-playground.js +33 -0
- package/dist/prompts/xulux-playground.js.map +1 -0
- package/dist/stdio.d.ts +1 -1
- package/dist/tools/docs.d.ts +8 -14
- package/dist/tools/docs.d.ts.map +1 -1
- package/dist/tools/docs.js +26 -10
- package/dist/tools/docs.js.map +1 -1
- package/dist/tools/examples.d.ts +6 -12
- package/dist/tools/examples.d.ts.map +1 -1
- package/dist/tools/examples.js +11 -8
- package/dist/tools/examples.js.map +1 -1
- package/dist/tools/resources.d.ts +1 -2
- package/dist/tools/resources.d.ts.map +1 -1
- package/dist/tools/resources.js +1 -1
- package/dist/tools/resources.js.map +1 -1
- package/dist/tools/search.d.ts +6 -15
- package/dist/tools/search.d.ts.map +1 -1
- package/dist/tools/search.js +2 -2
- package/dist/tools/search.js.map +1 -1
- package/dist/tools/tests/mcp-test-client.d.ts +15 -0
- package/dist/tools/tests/mcp-test-client.d.ts.map +1 -0
- package/dist/tools/tests/mcp-test-client.js +68 -0
- package/dist/tools/tests/mcp-test-client.js.map +1 -0
- package/dist/tools/tests/test-setup.d.ts.map +1 -1
- package/dist/tools/tests/test-setup.js +5 -1
- package/dist/tools/tests/test-setup.js.map +1 -1
- package/dist/tools/xulux-templates.d.ts +58 -0
- package/dist/tools/xulux-templates.d.ts.map +1 -0
- package/dist/tools/xulux-templates.js +82 -0
- package/dist/tools/xulux-templates.js.map +1 -0
- package/dist/utils/cache.d.ts +5 -0
- package/dist/utils/cache.d.ts.map +1 -0
- package/dist/utils/cache.js +18 -0
- package/dist/utils/cache.js.map +1 -0
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/mcp-format.d.ts +1 -0
- package/dist/utils/mcp-format.d.ts.map +1 -1
- package/dist/utils/mcp-format.js +7 -4
- package/dist/utils/mcp-format.js.map +1 -1
- package/dist/utils/mdx.d.ts.map +1 -1
- package/dist/utils/paths.d.ts +1 -1
- package/dist/utils/paths.d.ts.map +1 -1
- package/dist/utils/paths.js +3 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/search.d.ts.map +1 -1
- package/dist/utils/security.d.ts.map +1 -1
- package/dist/utils/security.js.map +1 -1
- package/dist/xulux/catalog-client.d.ts +14 -0
- package/dist/xulux/catalog-client.d.ts.map +1 -0
- package/dist/xulux/catalog-client.js +67 -0
- package/dist/xulux/catalog-client.js.map +1 -0
- package/dist/xulux/fallback-catalog.d.ts +7 -0
- package/dist/xulux/fallback-catalog.d.ts.map +1 -0
- package/dist/xulux/fallback-catalog.js +47 -0
- package/dist/xulux/fallback-catalog.js.map +1 -0
- package/dist/xulux/fetch-sandbox.d.ts +5 -0
- package/dist/xulux/fetch-sandbox.d.ts.map +1 -0
- package/dist/xulux/fetch-sandbox.js +40 -0
- package/dist/xulux/fetch-sandbox.js.map +1 -0
- package/dist/xulux/template-service.d.ts +84 -0
- package/dist/xulux/template-service.d.ts.map +1 -0
- package/dist/xulux/template-service.js +223 -0
- package/dist/xulux/template-service.js.map +1 -0
- package/dist/xulux/types.d.ts +55 -0
- package/dist/xulux/types.d.ts.map +1 -0
- package/dist/xulux/types.js +6 -0
- package/dist/xulux/types.js.map +1 -0
- package/package.json +7 -6
- package/src/index.ts +55 -2
- package/src/prompts/xulux-playground.ts +36 -0
- package/src/tools/docs.ts +27 -5
- package/src/tools/examples.ts +17 -12
- package/src/tools/resources.ts +1 -4
- package/src/tools/search.ts +2 -2
- package/src/tools/tests/completions.test.ts +40 -26
- package/src/tools/tests/docs.test.ts +20 -0
- package/src/tools/tests/examples.test.ts +5 -5
- package/src/tools/tests/integration.test.ts +3 -4
- package/src/tools/tests/listings-cache.test.ts +19 -0
- package/src/tools/tests/mcp-protocol.test.ts +173 -108
- package/src/tools/tests/mcp-test-client.ts +111 -0
- package/src/tools/tests/resources.test.ts +97 -66
- package/src/tools/tests/test-setup.ts +8 -0
- package/src/tools/tests/xulux-templates.test.ts +262 -0
- package/src/tools/xulux-templates.ts +141 -0
- package/src/utils/cache.ts +20 -0
- package/src/utils/mcp-format.ts +8 -6
- package/src/utils/paths.ts +4 -1
- package/src/utils/tests/cache.test.ts +51 -0
- package/src/utils/tests/mcp-format.test.ts +22 -0
- package/src/utils/tests/security.test.ts +1 -1
- package/src/xulux/catalog-client.ts +105 -0
- package/src/xulux/fallback-catalog.ts +63 -0
- package/src/xulux/fetch-sandbox.ts +56 -0
- package/src/xulux/template-service.ts +406 -0
- package/src/xulux/types.ts +60 -0
- package/.docs/raw/docs/(reference)/api-reference/hooks/utilities.mdx +0 -464
|
@@ -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 @@
|
|
|
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"}
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
import { fetchSandboxResource } from "./fetch-sandbox.js";
|
|
2
|
+
//#region src/xulux/template-service.ts
|
|
3
|
+
/**
|
|
4
|
+
* Resolves a template by id, preserving the app-route semantics:
|
|
5
|
+
* - exact `templateId` match wins
|
|
6
|
+
* - version-specific entry ids (e.g. `webpage-assistant-product-docs`)
|
|
7
|
+
* remain valid inputs
|
|
8
|
+
* - explicit `versionId` wins when provided
|
|
9
|
+
* - otherwise the template's default version is used
|
|
10
|
+
*/
|
|
11
|
+
function resolveTemplate(catalog, templateId, versionId) {
|
|
12
|
+
let template = catalog.templates.find((t) => t.templateId === templateId || t.id === templateId);
|
|
13
|
+
let impliedVersionId;
|
|
14
|
+
if (!template) {
|
|
15
|
+
template = catalog.templates.find((t) => t.versions.some((v) => v.entryId === templateId));
|
|
16
|
+
if (template) impliedVersionId = template.versions.find((v) => v.entryId === templateId)?.id;
|
|
17
|
+
}
|
|
18
|
+
if (!template) return null;
|
|
19
|
+
const effectiveVersionId = versionId ?? impliedVersionId ?? template.versionId;
|
|
20
|
+
const version = effectiveVersionId ? template.versions.find((v) => v.id === effectiveVersionId) ?? null : null;
|
|
21
|
+
return {
|
|
22
|
+
template,
|
|
23
|
+
version
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function listTemplates(catalog) {
|
|
27
|
+
return { templates: catalog.templates.map((t) => ({
|
|
28
|
+
id: t.templateId,
|
|
29
|
+
name: t.name,
|
|
30
|
+
summary: t.summary,
|
|
31
|
+
assistantPlacement: t.assistantPlacement,
|
|
32
|
+
features: t.features,
|
|
33
|
+
customizable: t.customizable,
|
|
34
|
+
versions: t.versions.map((v) => ({
|
|
35
|
+
id: v.id,
|
|
36
|
+
name: v.name,
|
|
37
|
+
description: v.description
|
|
38
|
+
})),
|
|
39
|
+
kind: t.kind
|
|
40
|
+
})) };
|
|
41
|
+
}
|
|
42
|
+
async function fetchTemplateContract(sandboxBaseUrl, versionId) {
|
|
43
|
+
try {
|
|
44
|
+
const url = new URL("/api/template/contract", sandboxBaseUrl);
|
|
45
|
+
if (versionId) url.searchParams.set("v", versionId);
|
|
46
|
+
const res = await fetchSandboxResource(url.toString());
|
|
47
|
+
if (!res.ok) return null;
|
|
48
|
+
return await res.json();
|
|
49
|
+
} catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
async function getTemplateDetails(catalog, input) {
|
|
54
|
+
const resolved = resolveTemplate(catalog, input.templateId, input.versionId);
|
|
55
|
+
if (!resolved) return {
|
|
56
|
+
error: `Template "${input.templateId}" not found.`,
|
|
57
|
+
retryHint: "Call assistantUITemplates and use one of the returned template ids."
|
|
58
|
+
};
|
|
59
|
+
const { template, version } = resolved;
|
|
60
|
+
if (template.kind === "example") return {
|
|
61
|
+
id: template.templateId,
|
|
62
|
+
name: template.name,
|
|
63
|
+
selectedVersionId: null,
|
|
64
|
+
summary: template.summary,
|
|
65
|
+
assistantPlacement: template.assistantPlacement,
|
|
66
|
+
rules: template.rules ?? { required: ["This entry is a fixed demo and is not schema-customizable.", "Preview and download it as-is. Do not pass a config for this entry."] },
|
|
67
|
+
tools: {
|
|
68
|
+
builtIn: [],
|
|
69
|
+
customToolSupported: false,
|
|
70
|
+
renderers: []
|
|
71
|
+
},
|
|
72
|
+
exampleConfig: null,
|
|
73
|
+
...template.previewUrl ? { previewUrl: template.previewUrl } : {},
|
|
74
|
+
...template.downloadUrl ? { downloadUrl: template.downloadUrl } : {}
|
|
75
|
+
};
|
|
76
|
+
const selectedVersionId = version?.id ?? template.versionId;
|
|
77
|
+
if (!template.configRoots || !template.tools) return {
|
|
78
|
+
error: `No authoring schema found for template "${template.templateId}".`,
|
|
79
|
+
retryHint: "The catalog may be in degraded fallback mode. Retry when live catalog access is restored."
|
|
80
|
+
};
|
|
81
|
+
let exampleConfig = null;
|
|
82
|
+
let exampleConfigNote;
|
|
83
|
+
if (template.sandboxBaseUrl) {
|
|
84
|
+
exampleConfig = (await fetchTemplateContract(template.sandboxBaseUrl, selectedVersionId))?.exampleCompleteConfig ?? null;
|
|
85
|
+
exampleConfigNote = exampleConfig ? `Resolved defaults for version "${selectedVersionId}". Use as a complete working starting point.` : "Could not reach the template sandbox to resolve exampleConfig. Use configRoots schemas and defaults to author config manually.";
|
|
86
|
+
} else exampleConfigNote = "This template has no sandbox URL in the catalog, so exampleConfig is unavailable. Use configRoots schemas and defaults.";
|
|
87
|
+
return {
|
|
88
|
+
id: template.templateId,
|
|
89
|
+
name: template.name,
|
|
90
|
+
selectedVersionId,
|
|
91
|
+
summary: template.summary,
|
|
92
|
+
assistantPlacement: template.assistantPlacement,
|
|
93
|
+
configRoots: template.configRoots,
|
|
94
|
+
rules: template.rules ?? { required: [] },
|
|
95
|
+
tools: template.tools,
|
|
96
|
+
exampleConfig,
|
|
97
|
+
exampleConfigNote,
|
|
98
|
+
...version?.previewUrl ? { previewUrl: version.previewUrl } : template.previewUrl ? { previewUrl: template.previewUrl } : {},
|
|
99
|
+
...version?.downloadUrl ? { downloadUrl: version.downloadUrl } : template.downloadUrl ? { downloadUrl: template.downloadUrl } : {}
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
function toAbsolute(baseUrl, url) {
|
|
103
|
+
if (/^https?:\/\//.test(url)) return url;
|
|
104
|
+
return `${baseUrl}${url.startsWith("/") ? "" : "/"}${url}`;
|
|
105
|
+
}
|
|
106
|
+
function withVersion(url, versionId) {
|
|
107
|
+
if (!versionId) return url;
|
|
108
|
+
const [path, query = ""] = url.split("?");
|
|
109
|
+
const params = new URLSearchParams(query);
|
|
110
|
+
if (!params.has("v")) params.set("v", versionId);
|
|
111
|
+
return `${path}?${params.toString()}`;
|
|
112
|
+
}
|
|
113
|
+
function hasConfig(config) {
|
|
114
|
+
return !!config && Object.keys(config).length > 0;
|
|
115
|
+
}
|
|
116
|
+
async function createTemplatePreview(catalog, input) {
|
|
117
|
+
const resolved = resolveTemplate(catalog, input.templateId, input.versionId);
|
|
118
|
+
if (!resolved) return {
|
|
119
|
+
success: false,
|
|
120
|
+
templateId: input.templateId,
|
|
121
|
+
versionId: input.versionId ?? null,
|
|
122
|
+
error: `Template "${input.templateId}" not found.`,
|
|
123
|
+
retryHint: "Call assistantUITemplates and use one of the returned template ids."
|
|
124
|
+
};
|
|
125
|
+
const { template, version } = resolved;
|
|
126
|
+
const tid = template.templateId;
|
|
127
|
+
if (template.kind === "example") {
|
|
128
|
+
if (hasConfig(input.config)) return {
|
|
129
|
+
success: false,
|
|
130
|
+
templateId: tid,
|
|
131
|
+
versionId: null,
|
|
132
|
+
error: `Template "${tid}" is a fixed demo and does not support config.`,
|
|
133
|
+
retryHint: "Call assistantUITemplateDetails for this template. If no configRoots are returned, call assistantUITemplatePreview again without config or choose a configurable hosted template."
|
|
134
|
+
};
|
|
135
|
+
if (!template.previewUrl) return {
|
|
136
|
+
success: false,
|
|
137
|
+
templateId: tid,
|
|
138
|
+
versionId: null,
|
|
139
|
+
error: `Fixed demo "${tid}" has no preview URL in the catalog.`,
|
|
140
|
+
retryHint: "The catalog may be in degraded fallback mode. Retry when live catalog access is restored."
|
|
141
|
+
};
|
|
142
|
+
return {
|
|
143
|
+
success: true,
|
|
144
|
+
templateId: tid,
|
|
145
|
+
versionId: null,
|
|
146
|
+
previewUrl: template.previewUrl,
|
|
147
|
+
...template.downloadUrl ? { downloadUrl: template.downloadUrl } : {},
|
|
148
|
+
title: template.name,
|
|
149
|
+
customized: false,
|
|
150
|
+
summary: `Resolved ${template.name} as a fixed demo. Preview and download URLs point at hosted resources; nothing was opened in any UI.`
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
const baseUrl = template.sandboxBaseUrl;
|
|
154
|
+
if (!baseUrl) return {
|
|
155
|
+
success: false,
|
|
156
|
+
templateId: tid,
|
|
157
|
+
versionId: version?.id ?? template.versionId,
|
|
158
|
+
error: `Template "${tid}" has no sandbox URL in the catalog.`,
|
|
159
|
+
retryHint: "The catalog may be in degraded fallback mode. Retry when live catalog access is restored."
|
|
160
|
+
};
|
|
161
|
+
const effectiveVersionId = version?.id ?? template.versionId;
|
|
162
|
+
if (hasConfig(input.config)) try {
|
|
163
|
+
const sessionUrl = new URL("/api/preview/session", baseUrl);
|
|
164
|
+
if (effectiveVersionId) sessionUrl.searchParams.set("v", effectiveVersionId);
|
|
165
|
+
const res = await fetchSandboxResource(sessionUrl.toString(), {
|
|
166
|
+
method: "POST",
|
|
167
|
+
headers: { "Content-Type": "application/json" },
|
|
168
|
+
body: JSON.stringify(input.config)
|
|
169
|
+
});
|
|
170
|
+
if (!res.ok) {
|
|
171
|
+
const details = await res.text();
|
|
172
|
+
return {
|
|
173
|
+
success: false,
|
|
174
|
+
templateId: tid,
|
|
175
|
+
versionId: effectiveVersionId,
|
|
176
|
+
error: `Preview session failed: HTTP ${res.status}`,
|
|
177
|
+
details,
|
|
178
|
+
retryHint: "Check validationWarnings for the specific fields that failed. Call assistantUITemplateDetails for this template and use configRoots schemas to correct the config. Pass only hostUi, assistant, and brandTheme at the top level."
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const data = await res.json();
|
|
182
|
+
if (!data.previewUrl) return {
|
|
183
|
+
success: false,
|
|
184
|
+
templateId: tid,
|
|
185
|
+
versionId: effectiveVersionId,
|
|
186
|
+
error: "Session endpoint did not return a previewUrl."
|
|
187
|
+
};
|
|
188
|
+
return {
|
|
189
|
+
success: true,
|
|
190
|
+
templateId: tid,
|
|
191
|
+
versionId: effectiveVersionId,
|
|
192
|
+
previewUrl: toAbsolute(baseUrl, withVersion(data.previewUrl, effectiveVersionId ?? void 0)),
|
|
193
|
+
downloadUrl: toAbsolute(baseUrl, withVersion(data.downloadUrl ?? "/api/download", effectiveVersionId ?? void 0)),
|
|
194
|
+
title: version?.name ?? template.name,
|
|
195
|
+
customized: true,
|
|
196
|
+
summary: `Created a configured preview session for ${template.name}. URLs point at the hosted sandbox; nothing was opened in any UI.`,
|
|
197
|
+
validationWarnings: data.validationWarnings ?? []
|
|
198
|
+
};
|
|
199
|
+
} catch (err) {
|
|
200
|
+
return {
|
|
201
|
+
success: false,
|
|
202
|
+
templateId: tid,
|
|
203
|
+
versionId: effectiveVersionId,
|
|
204
|
+
error: err instanceof Error ? err.message : String(err)
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
const previewUrl = version?.previewUrl ?? template.previewUrl;
|
|
208
|
+
const downloadUrl = version?.downloadUrl ?? template.downloadUrl ?? `${baseUrl}/api/download`;
|
|
209
|
+
return {
|
|
210
|
+
success: true,
|
|
211
|
+
templateId: tid,
|
|
212
|
+
versionId: effectiveVersionId,
|
|
213
|
+
previewUrl: previewUrl ?? baseUrl,
|
|
214
|
+
downloadUrl,
|
|
215
|
+
title: version?.name ?? template.name,
|
|
216
|
+
customized: false,
|
|
217
|
+
summary: `Resolved preview and download URLs for ${template.name}. Nothing was opened in any UI.`
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
//#endregion
|
|
221
|
+
export { createTemplatePreview, getTemplateDetails, listTemplates, resolveTemplate };
|
|
222
|
+
|
|
223
|
+
//# sourceMappingURL=template-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"template-service.js","names":[],"sources":["../../src/xulux/template-service.ts"],"sourcesContent":["import { fetchSandboxResource } from \"./fetch-sandbox.js\";\nimport type {\n XuluxCatalog,\n XuluxCatalogTemplate,\n XuluxCatalogVersion,\n} from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Local, catalog-backed template operations for the assistant-ui template MCP tools.\n// These functions never mutate any UI. Preview operations only return URLs.\n// ---------------------------------------------------------------------------\n\nexport interface ResolvedTemplate {\n template: XuluxCatalogTemplate;\n version: XuluxCatalogVersion | null;\n}\n\n/**\n * Resolves a template by id, preserving the app-route semantics:\n * - exact `templateId` match wins\n * - version-specific entry ids (e.g. `webpage-assistant-product-docs`)\n * remain valid inputs\n * - explicit `versionId` wins when provided\n * - otherwise the template's default version is used\n */\nexport function resolveTemplate(\n catalog: XuluxCatalog,\n templateId: string,\n versionId?: string | undefined,\n): ResolvedTemplate | null {\n let template = catalog.templates.find(\n (t) => t.templateId === templateId || t.id === templateId,\n );\n let impliedVersionId: string | undefined;\n\n if (!template) {\n // Version-specific entry id such as `webpage-assistant-product-docs`.\n template = catalog.templates.find((t) =>\n t.versions.some((v) => v.entryId === templateId),\n );\n if (template) {\n impliedVersionId = template.versions.find(\n (v) => v.entryId === templateId,\n )?.id;\n }\n }\n\n if (!template) return null;\n\n const effectiveVersionId =\n versionId ?? impliedVersionId ?? template.versionId;\n const version = effectiveVersionId\n ? (template.versions.find((v) => v.id === effectiveVersionId) ?? null)\n : null;\n\n return { template, version };\n}\n\nexport interface TemplateListItem {\n id: string;\n name: string;\n summary: string;\n assistantPlacement: string;\n features: string[];\n customizable: string[];\n versions: Array<{ id: string; name: string; description: string }>;\n kind: \"template\" | \"example\";\n}\n\nexport function listTemplates(catalog: XuluxCatalog): {\n templates: TemplateListItem[];\n} {\n return {\n templates: catalog.templates.map((t) => ({\n id: t.templateId,\n name: t.name,\n summary: t.summary,\n assistantPlacement: t.assistantPlacement,\n features: t.features,\n customizable: t.customizable,\n versions: t.versions.map((v) => ({\n id: v.id,\n name: v.name,\n description: v.description,\n })),\n kind: t.kind,\n })),\n };\n}\n\nasync function fetchTemplateContract(\n sandboxBaseUrl: string,\n versionId: string | null,\n): Promise<Record<string, unknown> | null> {\n try {\n const url = new URL(\"/api/template/contract\", sandboxBaseUrl);\n if (versionId) url.searchParams.set(\"v\", versionId);\n const res = await fetchSandboxResource(url.toString());\n if (!res.ok) return null;\n return (await res.json()) as Record<string, unknown>;\n } catch {\n return null;\n }\n}\n\nexport interface TemplateDetails {\n id: string;\n name: string;\n selectedVersionId: string | null;\n summary: string;\n assistantPlacement: string;\n configRoots?: Record<string, unknown>;\n rules: {\n required: string[];\n unsupported?: string[];\n };\n tools: {\n builtIn: unknown[];\n customToolSupported: boolean;\n renderers: unknown[];\n };\n exampleConfig: Record<string, unknown> | null;\n previewUrl?: string;\n downloadUrl?: string;\n warnings?: string[];\n exampleConfigNote?: string;\n}\n\nexport interface TemplateError {\n error: string;\n retryHint?: string;\n}\n\nexport async function getTemplateDetails(\n catalog: XuluxCatalog,\n input: { templateId: string; versionId?: string | undefined },\n): Promise<TemplateDetails | TemplateError> {\n const resolved = resolveTemplate(catalog, input.templateId, input.versionId);\n if (!resolved) {\n return {\n error: `Template \"${input.templateId}\" not found.`,\n retryHint:\n \"Call assistantUITemplates and use one of the returned template ids.\",\n };\n }\n\n const { template, version } = resolved;\n\n if (template.kind === \"example\") {\n return {\n id: template.templateId,\n name: template.name,\n selectedVersionId: null,\n summary: template.summary,\n assistantPlacement: template.assistantPlacement,\n rules: template.rules ?? {\n required: [\n \"This entry is a fixed demo and is not schema-customizable.\",\n \"Preview and download it as-is. Do not pass a config for this entry.\",\n ],\n },\n tools: { builtIn: [], customToolSupported: false, renderers: [] },\n exampleConfig: null,\n ...(template.previewUrl ? { previewUrl: template.previewUrl } : {}),\n ...(template.downloadUrl ? { downloadUrl: template.downloadUrl } : {}),\n };\n }\n\n const selectedVersionId = version?.id ?? template.versionId;\n\n if (!template.configRoots || !template.tools) {\n return {\n error: `No authoring schema found for template \"${template.templateId}\".`,\n retryHint:\n \"The catalog may be in degraded fallback mode. Retry when live catalog access is restored.\",\n };\n }\n\n let exampleConfig: Record<string, unknown> | null = null;\n let exampleConfigNote: string;\n if (template.sandboxBaseUrl) {\n const contract = await fetchTemplateContract(\n template.sandboxBaseUrl,\n selectedVersionId,\n );\n exampleConfig =\n (contract?.exampleCompleteConfig as Record<string, unknown> | null) ??\n null;\n exampleConfigNote = exampleConfig\n ? `Resolved defaults for version \"${selectedVersionId}\". Use as a complete working starting point.`\n : \"Could not reach the template sandbox to resolve exampleConfig. Use configRoots schemas and defaults to author config manually.\";\n } else {\n exampleConfigNote =\n \"This template has no sandbox URL in the catalog, so exampleConfig is unavailable. Use configRoots schemas and defaults.\";\n }\n\n return {\n id: template.templateId,\n name: template.name,\n selectedVersionId,\n summary: template.summary,\n assistantPlacement: template.assistantPlacement,\n configRoots: template.configRoots,\n rules: template.rules ?? { required: [] },\n tools: template.tools,\n exampleConfig,\n exampleConfigNote,\n ...(version?.previewUrl\n ? { previewUrl: version.previewUrl }\n : template.previewUrl\n ? { previewUrl: template.previewUrl }\n : {}),\n ...(version?.downloadUrl\n ? { downloadUrl: version.downloadUrl }\n : template.downloadUrl\n ? { downloadUrl: template.downloadUrl }\n : {}),\n };\n}\n\nfunction toAbsolute(baseUrl: string, url: string): string {\n if (/^https?:\\/\\//.test(url)) return url;\n return `${baseUrl}${url.startsWith(\"/\") ? \"\" : \"/\"}${url}`;\n}\n\nfunction withVersion(url: string, versionId: string | undefined): string {\n if (!versionId) return url;\n const [path, query = \"\"] = url.split(\"?\");\n const params = new URLSearchParams(query);\n if (!params.has(\"v\")) params.set(\"v\", versionId);\n return `${path}?${params.toString()}`;\n}\n\nfunction hasConfig(config: Record<string, unknown> | undefined): boolean {\n return !!config && Object.keys(config).length > 0;\n}\n\nexport interface TemplatePreviewResult {\n success: boolean;\n templateId: string;\n versionId: string | null;\n previewUrl?: string;\n downloadUrl?: string;\n title?: string;\n customized?: boolean;\n validationWarnings?: unknown[];\n error?: string;\n retryHint?: string;\n details?: string;\n summary?: string;\n}\n\nexport async function createTemplatePreview(\n catalog: XuluxCatalog,\n input: {\n templateId: string;\n versionId?: string | undefined;\n config?: Record<string, unknown> | undefined;\n },\n): Promise<TemplatePreviewResult> {\n const resolved = resolveTemplate(catalog, input.templateId, input.versionId);\n if (!resolved) {\n return {\n success: false,\n templateId: input.templateId,\n versionId: input.versionId ?? null,\n error: `Template \"${input.templateId}\" not found.`,\n retryHint:\n \"Call assistantUITemplates and use one of the returned template ids.\",\n };\n }\n\n const { template, version } = resolved;\n const tid = template.templateId;\n\n if (template.kind === \"example\") {\n if (hasConfig(input.config)) {\n return {\n success: false,\n templateId: tid,\n versionId: null,\n error: `Template \"${tid}\" is a fixed demo and does not support config.`,\n retryHint:\n \"Call assistantUITemplateDetails for this template. If no configRoots are returned, call assistantUITemplatePreview again without config or choose a configurable hosted template.\",\n };\n }\n\n if (!template.previewUrl) {\n return {\n success: false,\n templateId: tid,\n versionId: null,\n error: `Fixed demo \"${tid}\" has no preview URL in the catalog.`,\n retryHint:\n \"The catalog may be in degraded fallback mode. Retry when live catalog access is restored.\",\n };\n }\n\n return {\n success: true,\n templateId: tid,\n versionId: null,\n previewUrl: template.previewUrl,\n ...(template.downloadUrl ? { downloadUrl: template.downloadUrl } : {}),\n title: template.name,\n customized: false,\n summary: `Resolved ${template.name} as a fixed demo. Preview and download URLs point at hosted resources; nothing was opened in any UI.`,\n };\n }\n\n const baseUrl = template.sandboxBaseUrl;\n if (!baseUrl) {\n return {\n success: false,\n templateId: tid,\n versionId: version?.id ?? template.versionId,\n error: `Template \"${tid}\" has no sandbox URL in the catalog.`,\n retryHint:\n \"The catalog may be in degraded fallback mode. Retry when live catalog access is restored.\",\n };\n }\n\n const effectiveVersionId = version?.id ?? template.versionId;\n\n if (hasConfig(input.config)) {\n try {\n const sessionUrl = new URL(\"/api/preview/session\", baseUrl);\n if (effectiveVersionId)\n sessionUrl.searchParams.set(\"v\", effectiveVersionId);\n const res = await fetchSandboxResource(sessionUrl.toString(), {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify(input.config),\n });\n if (!res.ok) {\n const details = await res.text();\n return {\n success: false,\n templateId: tid,\n versionId: effectiveVersionId,\n error: `Preview session failed: HTTP ${res.status}`,\n details,\n retryHint:\n \"Check validationWarnings for the specific fields that failed. \" +\n \"Call assistantUITemplateDetails for this template and use configRoots schemas to correct the config. \" +\n \"Pass only hostUi, assistant, and brandTheme at the top level.\",\n };\n }\n const data = (await res.json()) as {\n previewUrl?: string;\n downloadUrl?: string;\n validationWarnings?: unknown[];\n };\n if (!data.previewUrl) {\n return {\n success: false,\n templateId: tid,\n versionId: effectiveVersionId,\n error: \"Session endpoint did not return a previewUrl.\",\n };\n }\n return {\n success: true,\n templateId: tid,\n versionId: effectiveVersionId,\n previewUrl: toAbsolute(\n baseUrl,\n withVersion(data.previewUrl, effectiveVersionId ?? undefined),\n ),\n downloadUrl: toAbsolute(\n baseUrl,\n withVersion(\n data.downloadUrl ?? \"/api/download\",\n effectiveVersionId ?? undefined,\n ),\n ),\n title: version?.name ?? template.name,\n customized: true,\n summary: `Created a configured preview session for ${template.name}. URLs point at the hosted sandbox; nothing was opened in any UI.`,\n validationWarnings: data.validationWarnings ?? [],\n };\n } catch (err) {\n return {\n success: false,\n templateId: tid,\n versionId: effectiveVersionId,\n error: err instanceof Error ? err.message : String(err),\n };\n }\n }\n\n const previewUrl = version?.previewUrl ?? template.previewUrl;\n const downloadUrl =\n version?.downloadUrl ?? template.downloadUrl ?? `${baseUrl}/api/download`;\n\n return {\n success: true,\n templateId: tid,\n versionId: effectiveVersionId,\n previewUrl: previewUrl ?? baseUrl,\n downloadUrl,\n title: version?.name ?? template.name,\n customized: false,\n summary: `Resolved preview and download URLs for ${template.name}. Nothing was opened in any UI.`,\n };\n}\n"],"mappings":";;;;;;;;;;AAyBA,SAAgB,gBACd,SACA,YACA,WACyB;CACzB,IAAI,WAAW,QAAQ,UAAU,MAC9B,MAAM,EAAE,eAAe,cAAc,EAAE,OAAO,UACjD;CACA,IAAI;CAEJ,IAAI,CAAC,UAAU;EAEb,WAAW,QAAQ,UAAU,MAAM,MACjC,EAAE,SAAS,MAAM,MAAM,EAAE,YAAY,UAAU,CACjD;EACA,IAAI,UACF,mBAAmB,SAAS,SAAS,MAClC,MAAM,EAAE,YAAY,UACvB,CAAC,EAAE;CAEP;CAEA,IAAI,CAAC,UAAU,OAAO;CAEtB,MAAM,qBACJ,aAAa,oBAAoB,SAAS;CAC5C,MAAM,UAAU,qBACX,SAAS,SAAS,MAAM,MAAM,EAAE,OAAO,kBAAkB,KAAK,OAC/D;CAEJ,OAAO;EAAE;EAAU;CAAQ;AAC7B;AAaA,SAAgB,cAAc,SAE5B;CACA,OAAO,EACL,WAAW,QAAQ,UAAU,KAAK,OAAO;EACvC,IAAI,EAAE;EACN,MAAM,EAAE;EACR,SAAS,EAAE;EACX,oBAAoB,EAAE;EACtB,UAAU,EAAE;EACZ,cAAc,EAAE;EAChB,UAAU,EAAE,SAAS,KAAK,OAAO;GAC/B,IAAI,EAAE;GACN,MAAM,EAAE;GACR,aAAa,EAAE;EACjB,EAAE;EACF,MAAM,EAAE;CACV,EAAE,EACJ;AACF;AAEA,eAAe,sBACb,gBACA,WACyC;CACzC,IAAI;EACF,MAAM,MAAM,IAAI,IAAI,0BAA0B,cAAc;EAC5D,IAAI,WAAW,IAAI,aAAa,IAAI,KAAK,SAAS;EAClD,MAAM,MAAM,MAAM,qBAAqB,IAAI,SAAS,CAAC;EACrD,IAAI,CAAC,IAAI,IAAI,OAAO;EACpB,OAAQ,MAAM,IAAI,KAAK;CACzB,QAAQ;EACN,OAAO;CACT;AACF;AA8BA,eAAsB,mBACpB,SACA,OAC0C;CAC1C,MAAM,WAAW,gBAAgB,SAAS,MAAM,YAAY,MAAM,SAAS;CAC3E,IAAI,CAAC,UACH,OAAO;EACL,OAAO,aAAa,MAAM,WAAW;EACrC,WACE;CACJ;CAGF,MAAM,EAAE,UAAU,YAAY;CAE9B,IAAI,SAAS,SAAS,WACpB,OAAO;EACL,IAAI,SAAS;EACb,MAAM,SAAS;EACf,mBAAmB;EACnB,SAAS,SAAS;EAClB,oBAAoB,SAAS;EAC7B,OAAO,SAAS,SAAS,EACvB,UAAU,CACR,8DACA,qEACF,EACF;EACA,OAAO;GAAE,SAAS,CAAC;GAAG,qBAAqB;GAAO,WAAW,CAAC;EAAE;EAChE,eAAe;EACf,GAAI,SAAS,aAAa,EAAE,YAAY,SAAS,WAAW,IAAI,CAAC;EACjE,GAAI,SAAS,cAAc,EAAE,aAAa,SAAS,YAAY,IAAI,CAAC;CACtE;CAGF,MAAM,oBAAoB,SAAS,MAAM,SAAS;CAElD,IAAI,CAAC,SAAS,eAAe,CAAC,SAAS,OACrC,OAAO;EACL,OAAO,2CAA2C,SAAS,WAAW;EACtE,WACE;CACJ;CAGF,IAAI,gBAAgD;CACpD,IAAI;CACJ,IAAI,SAAS,gBAAgB;EAK3B,iBACG,MALoB,sBACrB,SAAS,gBACT,iBACF,EAAA,EAEa,yBACX;EACF,oBAAoB,gBAChB,kCAAkC,kBAAkB,gDACpD;CACN,OACE,oBACE;CAGJ,OAAO;EACL,IAAI,SAAS;EACb,MAAM,SAAS;EACf;EACA,SAAS,SAAS;EAClB,oBAAoB,SAAS;EAC7B,aAAa,SAAS;EACtB,OAAO,SAAS,SAAS,EAAE,UAAU,CAAC,EAAE;EACxC,OAAO,SAAS;EAChB;EACA;EACA,GAAI,SAAS,aACT,EAAE,YAAY,QAAQ,WAAW,IACjC,SAAS,aACP,EAAE,YAAY,SAAS,WAAW,IAClC,CAAC;EACP,GAAI,SAAS,cACT,EAAE,aAAa,QAAQ,YAAY,IACnC,SAAS,cACP,EAAE,aAAa,SAAS,YAAY,IACpC,CAAC;CACT;AACF;AAEA,SAAS,WAAW,SAAiB,KAAqB;CACxD,IAAI,eAAe,KAAK,GAAG,GAAG,OAAO;CACrC,OAAO,GAAG,UAAU,IAAI,WAAW,GAAG,IAAI,KAAK,MAAM;AACvD;AAEA,SAAS,YAAY,KAAa,WAAuC;CACvE,IAAI,CAAC,WAAW,OAAO;CACvB,MAAM,CAAC,MAAM,QAAQ,MAAM,IAAI,MAAM,GAAG;CACxC,MAAM,SAAS,IAAI,gBAAgB,KAAK;CACxC,IAAI,CAAC,OAAO,IAAI,GAAG,GAAG,OAAO,IAAI,KAAK,SAAS;CAC/C,OAAO,GAAG,KAAK,GAAG,OAAO,SAAS;AACpC;AAEA,SAAS,UAAU,QAAsD;CACvE,OAAO,CAAC,CAAC,UAAU,OAAO,KAAK,MAAM,CAAC,CAAC,SAAS;AAClD;AAiBA,eAAsB,sBACpB,SACA,OAKgC;CAChC,MAAM,WAAW,gBAAgB,SAAS,MAAM,YAAY,MAAM,SAAS;CAC3E,IAAI,CAAC,UACH,OAAO;EACL,SAAS;EACT,YAAY,MAAM;EAClB,WAAW,MAAM,aAAa;EAC9B,OAAO,aAAa,MAAM,WAAW;EACrC,WACE;CACJ;CAGF,MAAM,EAAE,UAAU,YAAY;CAC9B,MAAM,MAAM,SAAS;CAErB,IAAI,SAAS,SAAS,WAAW;EAC/B,IAAI,UAAU,MAAM,MAAM,GACxB,OAAO;GACL,SAAS;GACT,YAAY;GACZ,WAAW;GACX,OAAO,aAAa,IAAI;GACxB,WACE;EACJ;EAGF,IAAI,CAAC,SAAS,YACZ,OAAO;GACL,SAAS;GACT,YAAY;GACZ,WAAW;GACX,OAAO,eAAe,IAAI;GAC1B,WACE;EACJ;EAGF,OAAO;GACL,SAAS;GACT,YAAY;GACZ,WAAW;GACX,YAAY,SAAS;GACrB,GAAI,SAAS,cAAc,EAAE,aAAa,SAAS,YAAY,IAAI,CAAC;GACpE,OAAO,SAAS;GAChB,YAAY;GACZ,SAAS,YAAY,SAAS,KAAK;EACrC;CACF;CAEA,MAAM,UAAU,SAAS;CACzB,IAAI,CAAC,SACH,OAAO;EACL,SAAS;EACT,YAAY;EACZ,WAAW,SAAS,MAAM,SAAS;EACnC,OAAO,aAAa,IAAI;EACxB,WACE;CACJ;CAGF,MAAM,qBAAqB,SAAS,MAAM,SAAS;CAEnD,IAAI,UAAU,MAAM,MAAM,GACxB,IAAI;EACF,MAAM,aAAa,IAAI,IAAI,wBAAwB,OAAO;EAC1D,IAAI,oBACF,WAAW,aAAa,IAAI,KAAK,kBAAkB;EACrD,MAAM,MAAM,MAAM,qBAAqB,WAAW,SAAS,GAAG;GAC5D,QAAQ;GACR,SAAS,EAAE,gBAAgB,mBAAmB;GAC9C,MAAM,KAAK,UAAU,MAAM,MAAM;EACnC,CAAC;EACD,IAAI,CAAC,IAAI,IAAI;GACX,MAAM,UAAU,MAAM,IAAI,KAAK;GAC/B,OAAO;IACL,SAAS;IACT,YAAY;IACZ,WAAW;IACX,OAAO,gCAAgC,IAAI;IAC3C;IACA,WACE;GAGJ;EACF;EACA,MAAM,OAAQ,MAAM,IAAI,KAAK;EAK7B,IAAI,CAAC,KAAK,YACR,OAAO;GACL,SAAS;GACT,YAAY;GACZ,WAAW;GACX,OAAO;EACT;EAEF,OAAO;GACL,SAAS;GACT,YAAY;GACZ,WAAW;GACX,YAAY,WACV,SACA,YAAY,KAAK,YAAY,sBAAsB,KAAA,CAAS,CAC9D;GACA,aAAa,WACX,SACA,YACE,KAAK,eAAe,iBACpB,sBAAsB,KAAA,CACxB,CACF;GACA,OAAO,SAAS,QAAQ,SAAS;GACjC,YAAY;GACZ,SAAS,4CAA4C,SAAS,KAAK;GACnE,oBAAoB,KAAK,sBAAsB,CAAC;EAClD;CACF,SAAS,KAAK;EACZ,OAAO;GACL,SAAS;GACT,YAAY;GACZ,WAAW;GACX,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;EACxD;CACF;CAGF,MAAM,aAAa,SAAS,cAAc,SAAS;CACnD,MAAM,cACJ,SAAS,eAAe,SAAS,eAAe,GAAG,QAAQ;CAE7D,OAAO;EACL,SAAS;EACT,YAAY;EACZ,WAAW;EACX,YAAY,cAAc;EAC1B;EACA,OAAO,SAAS,QAAQ,SAAS;EACjC,YAAY;EACZ,SAAS,0CAA0C,SAAS,KAAK;CACnE;AACF"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
//#region src/xulux/types.d.ts
|
|
2
|
+
declare const XULUX_MCP_CATALOG_VERSION = 1;
|
|
3
|
+
interface XuluxCatalogVersion {
|
|
4
|
+
id: string;
|
|
5
|
+
entryId: string;
|
|
6
|
+
name: string;
|
|
7
|
+
description: string;
|
|
8
|
+
previewUrl: string;
|
|
9
|
+
downloadUrl: string;
|
|
10
|
+
}
|
|
11
|
+
interface XuluxCatalogTemplate {
|
|
12
|
+
id: string;
|
|
13
|
+
templateId: string;
|
|
14
|
+
versionId: string | null;
|
|
15
|
+
kind: "template" | "example";
|
|
16
|
+
name: string;
|
|
17
|
+
summary: string;
|
|
18
|
+
assistantPlacement: string;
|
|
19
|
+
features: string[];
|
|
20
|
+
customizable: string[];
|
|
21
|
+
versions: XuluxCatalogVersion[];
|
|
22
|
+
previewUrl?: string;
|
|
23
|
+
downloadUrl?: string;
|
|
24
|
+
sandboxBaseUrl?: string;
|
|
25
|
+
configRoots?: Record<string, unknown>;
|
|
26
|
+
rules?: {
|
|
27
|
+
required: string[];
|
|
28
|
+
unsupported?: string[];
|
|
29
|
+
};
|
|
30
|
+
tools?: {
|
|
31
|
+
builtIn: unknown[];
|
|
32
|
+
customToolSupported: boolean;
|
|
33
|
+
renderers: unknown[];
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
interface XuluxCatalog {
|
|
37
|
+
version: number;
|
|
38
|
+
generatedAt: string;
|
|
39
|
+
docsOrigin: string;
|
|
40
|
+
templates: XuluxCatalogTemplate[];
|
|
41
|
+
}
|
|
42
|
+
interface XuluxCatalogResult {
|
|
43
|
+
catalog: XuluxCatalog;
|
|
44
|
+
/** True when the bundled fallback catalog was used instead of live data. */
|
|
45
|
+
degraded: boolean;
|
|
46
|
+
/** Present when the live fetch failed and the fallback was used. */
|
|
47
|
+
degradedReason?: string;
|
|
48
|
+
}
|
|
49
|
+
interface XuluxCatalogError {
|
|
50
|
+
error: string;
|
|
51
|
+
hint?: string;
|
|
52
|
+
}
|
|
53
|
+
//#endregion
|
|
54
|
+
export { XULUX_MCP_CATALOG_VERSION, XuluxCatalog, XuluxCatalogError, XuluxCatalogResult, XuluxCatalogTemplate, XuluxCatalogVersion };
|
|
55
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../src/xulux/types.ts"],"mappings":";cAIa;UAEI;EACf;EACA;EACA;EACA;EACA;EACA;;UAGe;EACf;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU;EACV;EACA;EACA;EACA,cAAc;EACd;IACE;IACA;;EAEF;IACE;IACA;IACA;;;UAIa;EACf;EACA;EACA;EACA,WAAW;;UAGI;EACf,SAAS;;EAET;;EAEA;;UAGe;EACf;EACA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","names":[],"sources":["../../src/xulux/types.ts"],"sourcesContent":["// MCP-safe assistant-ui template catalog types. These mirror the payload served by the docs\n// app at GET /api/xulux/mcp-catalog. The MCP package never imports docs-app\n// internals; the endpoint payload is the contract.\n\nexport const XULUX_MCP_CATALOG_VERSION = 1;\n\nexport interface XuluxCatalogVersion {\n id: string;\n entryId: string;\n name: string;\n description: string;\n previewUrl: string;\n downloadUrl: string;\n}\n\nexport interface XuluxCatalogTemplate {\n id: string;\n templateId: string;\n versionId: string | null;\n kind: \"template\" | \"example\";\n name: string;\n summary: string;\n assistantPlacement: string;\n features: string[];\n customizable: string[];\n versions: XuluxCatalogVersion[];\n previewUrl?: string;\n downloadUrl?: string;\n sandboxBaseUrl?: string;\n configRoots?: Record<string, unknown>;\n rules?: {\n required: string[];\n unsupported?: string[];\n };\n tools?: {\n builtIn: unknown[];\n customToolSupported: boolean;\n renderers: unknown[];\n };\n}\n\nexport interface XuluxCatalog {\n version: number;\n generatedAt: string;\n docsOrigin: string;\n templates: XuluxCatalogTemplate[];\n}\n\nexport interface XuluxCatalogResult {\n catalog: XuluxCatalog;\n /** True when the bundled fallback catalog was used instead of live data. */\n degraded: boolean;\n /** Present when the live fetch failed and the fallback was used. */\n degradedReason?: string;\n}\n\nexport interface XuluxCatalogError {\n error: string;\n hint?: string;\n}\n"],"mappings":";AAIA,MAAa,4BAA4B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/mcp-docs-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "MCP server for assistant-ui documentation and examples",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"mcp",
|
|
@@ -32,15 +32,16 @@
|
|
|
32
32
|
],
|
|
33
33
|
"sideEffects": false,
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@modelcontextprotocol/
|
|
35
|
+
"@modelcontextprotocol/server": "^2.0.0",
|
|
36
36
|
"gray-matter": "^4.0.3",
|
|
37
37
|
"zod": "^4.4.3"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
|
-
"@
|
|
41
|
-
"
|
|
42
|
-
"
|
|
43
|
-
"
|
|
40
|
+
"@modelcontextprotocol/core": "^2.0.0",
|
|
41
|
+
"@types/node": "^26.1.1",
|
|
42
|
+
"tsx": "^4.23.1",
|
|
43
|
+
"vitest": "^4.1.10",
|
|
44
|
+
"@assistant-ui/x-buildutils": "0.0.20"
|
|
44
45
|
},
|
|
45
46
|
"publishConfig": {
|
|
46
47
|
"access": "public",
|
package/src/index.ts
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import { McpServer } from "@modelcontextprotocol/
|
|
2
|
-
import { StdioServerTransport } from "@modelcontextprotocol/
|
|
1
|
+
import { McpServer } from "@modelcontextprotocol/server";
|
|
2
|
+
import { StdioServerTransport } from "@modelcontextprotocol/server/stdio";
|
|
3
3
|
import { docsTools } from "./tools/docs.js";
|
|
4
4
|
import { examplesTools } from "./tools/examples.js";
|
|
5
5
|
import { searchTools } from "./tools/search.js";
|
|
6
|
+
import {
|
|
7
|
+
xuluxTemplatesListTool,
|
|
8
|
+
xuluxTemplateDetailsTool,
|
|
9
|
+
xuluxTemplatePreviewTool,
|
|
10
|
+
} from "./tools/xulux-templates.js";
|
|
11
|
+
import { xuluxPlaygroundPrompt } from "./prompts/xulux-playground.js";
|
|
6
12
|
import { registerResources } from "./tools/resources.js";
|
|
7
13
|
import { logger } from "./utils/logger.js";
|
|
8
14
|
import { PACKAGE_DIR } from "./constants.js";
|
|
@@ -50,6 +56,53 @@ server.registerTool(
|
|
|
50
56
|
searchTools.execute,
|
|
51
57
|
);
|
|
52
58
|
|
|
59
|
+
server.registerTool(
|
|
60
|
+
xuluxTemplatesListTool.name,
|
|
61
|
+
{
|
|
62
|
+
title: "assistant-ui Templates",
|
|
63
|
+
description: xuluxTemplatesListTool.description,
|
|
64
|
+
inputSchema: xuluxTemplatesListTool.parameters,
|
|
65
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
66
|
+
},
|
|
67
|
+
xuluxTemplatesListTool.execute,
|
|
68
|
+
);
|
|
69
|
+
server.registerTool(
|
|
70
|
+
xuluxTemplateDetailsTool.name,
|
|
71
|
+
{
|
|
72
|
+
title: "assistant-ui Template Details",
|
|
73
|
+
description: xuluxTemplateDetailsTool.description,
|
|
74
|
+
inputSchema: xuluxTemplateDetailsTool.parameters,
|
|
75
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
76
|
+
},
|
|
77
|
+
xuluxTemplateDetailsTool.execute,
|
|
78
|
+
);
|
|
79
|
+
server.registerTool(
|
|
80
|
+
xuluxTemplatePreviewTool.name,
|
|
81
|
+
{
|
|
82
|
+
title: "assistant-ui Template Preview URLs",
|
|
83
|
+
description: xuluxTemplatePreviewTool.description,
|
|
84
|
+
inputSchema: xuluxTemplatePreviewTool.parameters,
|
|
85
|
+
annotations: { readOnlyHint: false, openWorldHint: true },
|
|
86
|
+
},
|
|
87
|
+
xuluxTemplatePreviewTool.execute,
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
server.registerPrompt(
|
|
91
|
+
xuluxPlaygroundPrompt.name,
|
|
92
|
+
{
|
|
93
|
+
title: "assistant-ui Template Workflow",
|
|
94
|
+
description: xuluxPlaygroundPrompt.description,
|
|
95
|
+
},
|
|
96
|
+
() => ({
|
|
97
|
+
messages: [
|
|
98
|
+
{
|
|
99
|
+
role: "user" as const,
|
|
100
|
+
content: { type: "text" as const, text: xuluxPlaygroundPrompt.text },
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
}),
|
|
104
|
+
);
|
|
105
|
+
|
|
53
106
|
registerResources(server);
|
|
54
107
|
|
|
55
108
|
export async function runServer() {
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// Skill-style MCP prompt teaching agents the assistant-ui template workflow.
|
|
2
|
+
// Adapted for MCP clients: tools return URLs and data only; there is no
|
|
3
|
+
// browser canvas UI here.
|
|
4
|
+
|
|
5
|
+
export const XULUX_PLAYGROUND_PROMPT_NAME = "assistant-ui-template-workflow";
|
|
6
|
+
|
|
7
|
+
export const XULUX_PLAYGROUND_PROMPT_DESCRIPTION =
|
|
8
|
+
"How to use the assistant-ui template tools to discover hosted templates, inspect their customization contracts, and retrieve preview/download URLs.";
|
|
9
|
+
|
|
10
|
+
export const XULUX_PLAYGROUND_PROMPT = `You have access to assistant-ui template tools for hosted app templates.
|
|
11
|
+
|
|
12
|
+
<workflow>
|
|
13
|
+
Follow this template-first workflow for any assistant-ui app-building request:
|
|
14
|
+
|
|
15
|
+
1. Call **assistantUITemplates** FIRST. Never decide on a template or claim one exists without listing.
|
|
16
|
+
2. Call **assistantUITemplateDetails** on any candidate template before deciding whether it fits.
|
|
17
|
+
- Review the whole template shape: features, assistantPlacement, configRoots schemas, rules, built-in tools, renderers, and exampleConfig.
|
|
18
|
+
- If \`customizable\` is empty, the entry is a fixed demo. Use it as-is; never pass a config for it.
|
|
19
|
+
3. Decide one of three paths:
|
|
20
|
+
- The template fits as-is: call **assistantUITemplatePreview** with templateId and optional versionId.
|
|
21
|
+
- The template fits with supported customization: author a config using the configRoots schemas and rules from assistantUITemplateDetails, then call **assistantUITemplatePreview** with that config.
|
|
22
|
+
- No template fits: do NOT call assistantUITemplatePreview. Do not force the request into a template or fake domain content with mock config. Instead, ground yourself in the assistant-ui docs (assistantUIDocs, assistantUISearch, assistantUIExamples) and produce an honest, docs-grounded build guide or prompt for the user.
|
|
23
|
+
</workflow>
|
|
24
|
+
|
|
25
|
+
<important_constraints>
|
|
26
|
+
- Only use URLs copied exactly from tool results. Never guess, fabricate, or use placeholder URLs.
|
|
27
|
+
- If assistantUITemplatePreview returns validationWarnings or an error, call assistantUITemplateDetails again and correct the config against configRoots. Pass only the documented top-level config roots.
|
|
28
|
+
- Customization is for supported adaptation within a template's shape, not for turning it into a completely different kind of product.
|
|
29
|
+
- Responses may include \`catalogDegraded: true\` when the live template catalog is unreachable. In that mode, template details and preview URLs may be unavailable; tell the user rather than improvising.
|
|
30
|
+
</important_constraints>`;
|
|
31
|
+
|
|
32
|
+
export const xuluxPlaygroundPrompt = {
|
|
33
|
+
name: XULUX_PLAYGROUND_PROMPT_NAME,
|
|
34
|
+
description: XULUX_PLAYGROUND_PROMPT_DESCRIPTION,
|
|
35
|
+
text: XULUX_PLAYGROUND_PROMPT,
|
|
36
|
+
};
|