@vpxa/aikit 0.1.40 → 0.1.41
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/package.json +1 -1
- package/packages/present/dist/index.html +3296 -36
- package/packages/server/dist/tools/present/helpers.d.ts +2 -1
- package/packages/server/dist/tools/present/helpers.js +1 -1
- package/packages/server/dist/tools/present/markdown.d.ts +18 -3
- package/packages/server/dist/tools/present/markdown.js +10 -7
- package/packages/server/dist/tools/present/tool.js +4 -5
|
@@ -14,5 +14,6 @@ declare function isTypedBlock(value: unknown): value is TypedBlock;
|
|
|
14
14
|
* Handles alternative field names: text, code, headers+rows → value.
|
|
15
15
|
*/
|
|
16
16
|
declare function normalizeBlock(block: TypedBlock): TypedBlock;
|
|
17
|
+
declare function normalizeContentForApp(content: unknown): unknown;
|
|
17
18
|
//#endregion
|
|
18
|
-
export { TypedBlock, formatValue, isTypedBlock, normalizeBlock, sanitizeId };
|
|
19
|
+
export { TypedBlock, formatValue, isTypedBlock, normalizeBlock, normalizeContentForApp, sanitizeId };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function e(t){return t==null?`null`:Array.isArray(t)?`[${t.map(e).join(`, `)}]`:String(t)}function t(e){return e.replace(/[^a-zA-Z0-9_]/g,`_`)}function n(e){
|
|
1
|
+
function e(t){return t==null?`null`:Array.isArray(t)?`[${t.map(e).join(`, `)}]`:String(t)}function t(e){return e.replace(/[^a-zA-Z0-9_]/g,`_`)}function n(e){if(typeof e!=`object`||!e||!(`type`in e))return!1;let t=e;return`value`in t||typeof t.text==`string`||Array.isArray(t.headers)&&Array.isArray(t.rows)||typeof t.code==`string`||Array.isArray(t.items)||!!t.entries&&typeof t.entries==`object`&&!Array.isArray(t.entries)||!!t.columns&&typeof t.columns==`object`||`chartType`in t||Array.isArray(t.data)}function r(e){if(Array.isArray(e)){let t=e.filter(e=>typeof e==`object`&&!!e),n=t.map(e=>String(e.title??``)),r=Math.max(0,...t.map(e=>Array.isArray(e.items)?e.items.length:0));return{headers:n,rows:Array.from({length:r},(e,n)=>t.map(e=>Array.isArray(e.items)?e.items[n]??``:``))}}if(!e||typeof e!=`object`)return null;let t=e,n=Object.keys(t),r=Math.max(0,...n.map(e=>Array.isArray(t[e])?t[e].length:0));return{headers:n,rows:Array.from({length:r},(e,r)=>n.map(e=>Array.isArray(t[e])?t[e][r]??``:``))}}function i(e){let t=e,n=e;if(`value`in n||(typeof t.text==`string`?n={...n,value:t.text}:typeof t.code==`string`?n={...n,value:t.code}:Array.isArray(t.headers)&&Array.isArray(t.rows)?n={...n,value:{headers:t.headers,rows:t.rows}}:Array.isArray(t.items)?n={...n,value:{items:t.items}}:(`chartType`in t||Array.isArray(t.data))&&(n={...n,value:{chartType:t.chartType,data:t.data,xKey:t.xKey??`label`,yKeys:t.yKeys??[`value`]}})),n.type===`chart`){let e=n.value;if(e&&typeof e==`object`&&!Array.isArray(e)){let t=e,r=t.data&&typeof t.data==`object`&&!Array.isArray(t.data)?t.data:null,i=Array.isArray(t.labels)?t.labels:Array.isArray(r?.labels)?r.labels:null,a=Array.isArray(t.datasets)?t.datasets:Array.isArray(r?.datasets)?r.datasets:null;if(typeof t.type==`string`&&i&&a){let e=a.map((e,t)=>String(e.label??`series${t+1}`)),r=i.map((e,t)=>{let n={label:String(e)};for(let[e,r]of a.entries()){let i=r,a=String(i.label??`series${e+1}`);n[a]=i.data?.[t]??0}return n});n={...n,value:{chartType:String(t.type),data:r,xKey:`label`,yKeys:e}}}}}let i=n;if(n.type===`text`||n.type===`paragraph`)return{...n,type:`markdown`};if(n.type===`heading`)return{...n,type:`markdown`,value:`## ${String(i.value??``)}`};if(n.type===`kv`){let e=t.entries&&typeof t.entries==`object`&&!Array.isArray(t.entries)?t.entries:i.value&&typeof i.value==`object`&&!Array.isArray(i.value)?i.value:null;if(e)return{...n,type:`table`,value:{headers:[`Key`,`Value`],rows:Object.entries(e).map(([e,t])=>[e,t])}}}if(n.type===`comparison`){let e=r(t.columns??(i.value&&typeof i.value==`object`?i.value.columns:void 0));if(e)return{...n,type:`table`,value:e};let a=i.value;if(a&&typeof a==`object`&&!Array.isArray(a)){let e=a;if(Array.isArray(e.headers)&&Array.isArray(e.rows))return{...n,type:`table`}}}if(n.type===`timeline`){let e=i.value;if(Array.isArray(e)){let t=e.map(e=>{if(e&&typeof e==`object`){let t=e;return[String(t.status??t.state??``),String(t.time??t.date??t.timestamp??``),String(t.label??t.description??t.title??t.text??``)]}return[``,``,String(e)]});return{...n,type:`table`,value:{headers:[`Status`,`Time`,`Description`],rows:t}}}}return n}function a(e){return Array.isArray(e)?e.map(e=>n(e)?i(e):e):e}export{e as formatValue,n as isTypedBlock,i as normalizeBlock,a as normalizeContentForApp,t as sanitizeId};
|
|
@@ -1,9 +1,24 @@
|
|
|
1
1
|
import { TypedBlock } from "./helpers.js";
|
|
2
2
|
|
|
3
3
|
//#region packages/server/src/tools/present/markdown.d.ts
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
interface MarkdownOptions {
|
|
5
|
+
compactTables?: boolean;
|
|
6
|
+
}
|
|
7
|
+
declare function buildMarkdown(title: string | undefined, content: unknown, options?: MarkdownOptions): string;
|
|
8
|
+
declare function renderBlockAsMarkdown(block: TypedBlock, options?: MarkdownOptions): string;
|
|
6
9
|
declare function arrayToMarkdownTable(rows: Record<string, unknown>[]): string;
|
|
10
|
+
/**
|
|
11
|
+
* Render an array-of-objects as a numbered list (safe for VS Code chat markdown).
|
|
12
|
+
* Uses the first column value as the bold label, remaining columns as inline details.
|
|
13
|
+
*/
|
|
14
|
+
declare function arrayToListTable(rows: Record<string, unknown>[], title?: string): string;
|
|
15
|
+
/**
|
|
16
|
+
* Render a comparison block as grouped bullet lists (safe for VS Code chat markdown).
|
|
17
|
+
*/
|
|
18
|
+
declare function comparisonToList(columns: Array<{
|
|
19
|
+
title: string;
|
|
20
|
+
items?: string[];
|
|
21
|
+
}>, title?: string): string;
|
|
7
22
|
declare function metricsToMarkdown(metrics: Array<{
|
|
8
23
|
label: string;
|
|
9
24
|
value: string | number;
|
|
@@ -14,4 +29,4 @@ declare function graphToMermaid(data: {
|
|
|
14
29
|
}): string;
|
|
15
30
|
declare function objectToMarkdownTree(obj: Record<string, unknown>, indent?: number): string;
|
|
16
31
|
//#endregion
|
|
17
|
-
export { arrayToMarkdownTable, buildMarkdown, graphToMermaid, metricsToMarkdown, objectToMarkdownTree, renderBlockAsMarkdown };
|
|
32
|
+
export { MarkdownOptions, arrayToListTable, arrayToMarkdownTable, buildMarkdown, comparisonToList, graphToMermaid, metricsToMarkdown, objectToMarkdownTree, renderBlockAsMarkdown };
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import{formatValue as e,isTypedBlock as t,normalizeBlock as n,sanitizeId as r}from"./helpers.js";function i(e,r){let
|
|
2
|
-
`)}function a(e){let
|
|
3
|
-
`);break;
|
|
1
|
+
import{formatValue as e,isTypedBlock as t,normalizeBlock as n,sanitizeId as r}from"./helpers.js";function i(e,r,i){let c=[];if(e&&c.push(`# ${e}\n`),typeof r==`string`)c.push(r);else if(Array.isArray(r))if(r.length===0)c.push(`*(empty)*`);else if(t(r[0]))for(let e of r)c.push(a(n(e),i));else if(typeof r[0]==`object`&&r[0]!==null)i?.compactTables?c.push(s(r)):c.push(o(r));else for(let e of r)c.push(`- ${String(e)}`);else if(typeof r==`object`&&r){let e=r;if(Array.isArray(e.blocks)&&e.blocks.length>0)for(let r of e.blocks)t(r)?c.push(a(n(r),i)):c.push(String(r));else Array.isArray(e.nodes)&&Array.isArray(e.edges)?c.push(u(e)):Array.isArray(e.metrics)?c.push(l(e.metrics)):c.push(d(e))}else c.push(String(r));return c.join(`
|
|
2
|
+
`)}function a(e,t){let n=[];switch(e.title&&n.push(`## ${e.title}\n`),e.type){case`markdown`:n.push(String(e.value??``));break;case`code`:n.push(`\`\`\`${e.language??``}\n${String(e.value??``)}\n\`\`\``);break;case`mermaid`:n.push(`\`\`\`mermaid\n${String(e.value??``)}\n\`\`\``);break;case`table`:{let r=e.value;if(Array.isArray(r)&&r.length>0)t?.compactTables?n.push(s(r,e.title)):n.push(o(r));else if(r&&typeof r==`object`&&!Array.isArray(r)&&`headers`in r&&`rows`in r){let{headers:i,rows:a}=r;if(t?.compactTables){let t=[];e.title&&t.push(`**${e.title}**\n`);for(let e=0;e<a.length;e++){let n=i.map((t,n)=>`**${t}**: ${String(a[e]?.[n]??``)}`).join(` · `);t.push(`${e+1}. ${n}`)}n.push(t.join(`
|
|
3
|
+
`))}else{n.push(`| ${i.join(` | `)} |`),n.push(`| ${i.map(()=>`---`).join(` | `)} |`);for(let e of a)n.push(`| ${e.map(e=>String(e??``)).join(` | `)} |`)}}else n.push(`*(empty table)*`);break}case`metrics`:Array.isArray(e.value)&&n.push(l(e.value));break;case`graph`:e.value&&typeof e.value==`object`&&n.push(u(e.value));break;case`cards`:if(Array.isArray(e.value))for(let t of e.value)n.push(`### ${t.title??`Card`}`),(t.body||t.description)&&n.push(String(t.body??t.description)),(t.badge||t.status)&&n.push(`> **${t.badge??t.status}**`),n.push(``);break;case`tree`:e.value&&typeof e.value==`object`&&n.push(d(e.value));break;case`chart`:{let t=e.value;t?.data&&Array.isArray(t.data)&&n.push(`*${String(t.chartType??`chart`)} chart — ${t.data.length} data points*`);break}case`timeline`:{let t=e.value;if(t?.items)for(let e of t.items){let t=e.status===`done`?`✅`:e.status===`active`?`🔄`:e.status===`error`?`❌`:`⬜`;n.push(`${t} **${e.title}**${e.description?` — ${e.description}`:``}`)}break}case`checklist`:{let t=e.value;if(t?.items)for(let e of t.items)n.push(`- [${e.checked?`x`:` `}] ${e.label}${e.note?` — ${e.note}`:``}`);break}case`comparison`:{let r=e.value;if(r?.columns&&r.columns.length>0)if(t?.compactTables)n.push(c(r.columns,e.title));else{let e=Math.max(...r.columns.map(e=>e.items?.length??0)),t=r.columns.map(e=>e.title);n.push(`| ${t.join(` | `)} |`),n.push(`| ${t.map(()=>`---`).join(` | `)} |`);for(let t=0;t<e;t++)n.push(`| ${r.columns.map(e=>e.items?.[t]??``).join(` | `)} |`)}break}case`status-board`:{let t=e.value;if(t?.items)for(let e of t.items){let t=e.status===`success`?`🟢`:e.status===`warning`?`🟡`:e.status===`error`?`🔴`:e.status===`info`?`🔵`:`⚪`;n.push(`${t} **${e.label}**${e.detail?` — ${e.detail}`:``}`)}break}case`prompt`:{let t=e.value;t?.question&&(n.push(`> **${t.question}**`),t.context&&n.push(`> ${t.context}`));break}case`progress`:{let t=e.value;if(t?.items)for(let e of t.items){let t=e.max??100,r=t>0?Math.round(e.value/t*100):0,i=Math.round(r/5),a=`█`.repeat(i)+`░`.repeat(20-i);n.push(`${e.label}: ${a} ${r}%`)}break}case`text`:n.push(String(e.value??``));break;case`heading`:{let t=Math.min(Math.max(Number(e.level)||2,1),6);n.push(`${`#`.repeat(t)} ${String(e.value??``)}\n`);break}case`paragraph`:n.push(String(e.value??``));break;case`separator`:n.push(`---
|
|
4
|
+
`);break;default:n.push(JSON.stringify(e.value,null,2))}return n.push(``),n.join(`
|
|
4
5
|
`)}function o(e){if(e.length===0)return`*(empty table)*`;let t=Object.keys(e[0]),n=[];n.push(`| ${t.join(` | `)} |`),n.push(`| ${t.map(()=>`---`).join(` | `)} |`);for(let r of e)n.push(`| ${t.map(e=>String(r[e]??``)).join(` | `)} |`);return n.join(`
|
|
5
|
-
`)}function s(e){return e.
|
|
6
|
-
`)}function c(e){let
|
|
7
|
-
`)}function l(
|
|
8
|
-
`)}
|
|
6
|
+
`)}function s(e,t){if(e.length===0)return`*(empty table)*`;let n=Object.keys(e[0]),r=[];t&&r.push(`**${t}**\n`);for(let t=0;t<e.length;t++){let i=e[t],a=String(i[n[0]]??``);if(n.length===1)r.push(`${t+1}. **${a}**`);else{let e=n.slice(1).map(e=>`${e}: ${String(i[e]??``)}`).join(` · `);r.push(`${t+1}. **${a}** — ${e}`)}}return r.join(`
|
|
7
|
+
`)}function c(e,t){let n=[];t&&n.push(`**${t}**\n`);for(let t of e){if(n.push(`**${t.title}**`),t.items&&t.items.length>0)for(let e of t.items)n.push(`- ${e}`);else n.push(`- *(none)*`);n.push(``)}return n.join(`
|
|
8
|
+
`)}function l(e){return e.map(e=>`- **${e.label}**: ${e.value}`).join(`
|
|
9
|
+
`)}function u(e){let t=["```mermaid",`graph LR`];for(let n of e.nodes){let e=r(String(n.id??n.name??``)),i=String(n.label??n.name??e);t.push(` ${e}["${i}"]`)}for(let n of e.edges){let e=r(String(n.source??n.from??``)),i=r(String(n.target??n.to??``)),a=n.label?`|${String(n.label)}|`:``;t.push(` ${e} -->${a} ${i}`)}return t.push("```"),t.join(`
|
|
10
|
+
`)}function d(t,n=0){let r=` `.repeat(n),i=[];for(let[a,o]of Object.entries(t))typeof o==`object`&&o&&!Array.isArray(o)?(i.push(`${r}- **${a}**:`),i.push(d(o,n+1))):i.push(`${r}- **${a}**: ${e(o)}`);return i.join(`
|
|
11
|
+
`)}export{s as arrayToListTable,o as arrayToMarkdownTable,i as buildMarkdown,c as comparisonToList,u as graphToMermaid,l as metricsToMarkdown,d as objectToMarkdownTree,a as renderBlockAsMarkdown};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{getToolMeta as e}from"../../tool-metadata.js";import{
|
|
1
|
+
import{getToolMeta as e}from"../../tool-metadata.js";import{normalizeContentForApp as t}from"./helpers.js";import{buildBrowserHtml as n}from"./browser.js";import{buildMarkdown as r}from"./markdown.js";import{readFileSync as i}from"node:fs";import{dirname as a,join as o}from"node:path";import{fileURLToPath as s}from"node:url";import{z as c}from"zod";import{RESOURCE_MIME_TYPE as l,registerAppResource as u,registerAppTool as d}from"@modelcontextprotocol/ext-apps/server";import{exec as f}from"node:child_process";import{createServer as p}from"node:http";import{createUIResource as m}from"@mcp-ui/server";const h=import.meta.dirname??a(s(import.meta.url)),g=`ui://aikit/present.html`,_=c.object({type:c.enum([`button`,`select`]).describe(`Action type`),id:c.string().describe(`Unique action identifier`),label:c.string().describe(`Display label`),variant:c.enum([`primary`,`danger`,`default`]).optional().describe(`Button style variant`),options:c.array(c.union([c.string(),c.object({label:c.string(),value:c.string()})])).optional().describe(`Select options (for type=select)`)}),v={format:c.enum([`html`,`browser`]).default(`html`).describe(`Output format.
|
|
2
2
|
- "html" (default): Rich markdown in chat + embedded UIResource for MCP-UI hosts. Actions shown as numbered choices.
|
|
3
|
-
- "browser": Rich markdown in chat + opens beautiful themed dashboard in the browser. When actions are provided, the browser shows interactive buttons and the tool blocks until user clicks, returning their selection.`),title:
|
|
3
|
+
- "browser": Rich markdown in chat + opens beautiful themed dashboard in the browser. When actions are provided, the browser shows interactive buttons and the tool blocks until user clicks, returning their selection.`),title:c.string().optional().describe(`Optional heading`),content:c.any().describe(`Content to present. Accepts: markdown string, array of objects (→ table), { nodes, edges } (→ mermaid graph), typed blocks [{ type, value }], or any JSON (→ tree).`),actions:c.array(_).optional().describe(`Interactive actions (buttons/selects). In html mode, shown as numbered choices. In browser mode, rendered as clickable buttons and the tool blocks until user clicks.`),template:c.enum([`auto`,`list-sort`,`data-table`,`picker`,`flame-graph`,`form`,`timeline`,`kanban`,`tree`,`diff-view`,`dashboard`]).optional().describe(`UI template for interactive display in MCP Apps hosts.
|
|
4
4
|
- auto (default): detect from content shape
|
|
5
5
|
- list-sort: drag-drop reorderable list — content: { items: [{id, label}] }
|
|
6
6
|
- data-table: filterable sortable table — content: { columns: [{key, label}], rows: [{...}], stats?: [{label, value}] }
|
|
@@ -11,9 +11,8 @@ import{getToolMeta as e}from"../../tool-metadata.js";import{buildBrowserHtml as
|
|
|
11
11
|
- kanban: drag-drop board — content: { columns: [{id, label, color?}], cards: [{id, title, column, tags?[], priority?}] }
|
|
12
12
|
- tree: collapsible tree view — content: { root: {label, children?:[...]} | [...] }
|
|
13
13
|
- diff-view: side-by-side diff — content: { files: [{path, status, additions, deletions, hunks:[{header, changes:[{type, content}]}]}] }
|
|
14
|
-
- dashboard: metric cards grid — content: { metrics: [{label, value, trend?, status?, type?}] }`)};let
|
|
14
|
+
- dashboard: metric cards grid — content: { metrics: [{label, value, trend?, status?, type?}] }`)};let y,b=!1,x=null;process.on(`exit`,()=>{if(x){try{x.close()}catch{}x=null}});function S(){return o(h,`..`,`..`,`..`,`..`,`present`,`dist`,`index.html`)}function C(){if(!y)try{y=i(S(),`utf-8`)}catch{y=``}return y}function w(t,n){let r=e(`present`),i=C(),a=`Present content to the user in the best format. Two modes:
|
|
15
15
|
- "html" (default): Rich markdown in chat + embedded UIResource. Use for display-only content (tables, charts, reports, status boards) where no user interaction is needed.
|
|
16
16
|
- "browser": Serves a themed dashboard on a local URL. Use ONLY when you need user interaction back (confirmations, selections, form input). The tool blocks until user clicks an action button, then returns their selection.
|
|
17
17
|
FORMAT RULE: If no user interaction is needed → use "html". If you need user input back → use "browser".
|
|
18
|
-
BROWSER WORKFLOW: After calling present with format "browser", you MUST extract the URL from the response and call openBrowserPage({ url }) to open it in VS Code Simple Browser. A system browser fallback also opens automatically, but always call openBrowserPage yourself.`,
|
|
19
|
-
`)}`}let c=p({uri:`ui://aikit/present-static.html`,content:{type:`rawHtml`,htmlString:t(e,r,i,a)},encoding:`text`,adapters:{mcpApps:{enabled:!0}}});return{content:[{type:`text`,text:s},c]}}export{w as formatAsBrowser,T as formatAsHtml,S as getPresentHtml,C as registerPresentTool,x as resolvePresentHtml};
|
|
18
|
+
BROWSER WORKFLOW: After calling present with format "browser", you MUST extract the URL from the response and call openBrowserPage({ url }) to open it in VS Code Simple Browser. A system browser fallback also opens automatically, but always call openBrowserPage yourself.`,o=async({format:e,title:t,content:r,actions:i,template:a})=>(e??`html`)===`browser`||Array.isArray(i)&&i.length>0?await T(t,r,i,n,a):E(t,r,i,a);if(i){b||=(u(t,`AI Kit Present App`,g,{description:`Rich interactive content viewer for AI Kit tools`},async()=>({contents:[{uri:g,mimeType:l,text:i}]})),!0),d(t,`present`,{title:r.title,description:a,annotations:r.annotations,inputSchema:v,_meta:{ui:{resourceUri:g}}},o);return}t.tool(`present`,a,v,r.annotations,o)}async function T(e,t,i,a,o){let s=r(e,t,{compactTables:!0}),c=n(e,t,i,o),l=m({uri:`ui://aikit/present-browser.html`,content:{type:`rawHtml`,htmlString:c},encoding:`text`,adapters:{mcpApps:{enabled:!0}}}),u,d,h=Array.isArray(i)?i:[],g=``,_;try{x&&=(x.close(),null),h.length>0&&(u=new Promise(e=>{d=e}));let e=!1;g=await new Promise((t,n)=>{let r=p((t,n)=>{if(e||(e=!0,_&&clearTimeout(_)),t.method===`POST`&&t.url===`/callback`){let e=``;t.on(`data`,t=>{e+=t.toString()}),t.on(`end`,()=>{n.writeHead(200,{"Content-Type":`application/json`,"Access-Control-Allow-Origin":`*`}),n.end(`{"ok":true}`);try{let t=JSON.parse(e);d?.(t)}catch{}});return}if(t.method===`OPTIONS`){n.writeHead(204,{"Access-Control-Allow-Origin":`*`,"Access-Control-Allow-Methods":`POST`,"Access-Control-Allow-Headers":`Content-Type`}),n.end();return}n.writeHead(200,{"Content-Type":`text/html; charset=utf-8`}),n.end(c)});r.listen(0,`127.0.0.1`,()=>{let i=r.address();if(typeof i==`object`&&i){x=r;let n=`http://127.0.0.1:${i.port}`;_=setTimeout(()=>{if(!e)try{f(process.platform===`win32`?`start "" "${n}"`:process.platform===`darwin`?`open "${n}"`:`xdg-open "${n}"`)}catch{}},8e3),_.unref(),t(n)}else n(Error(`Failed to start present server`))}),setTimeout(()=>{r.close(),x===r&&(x=null)},300*1e3).unref()})}catch{}let v=g?`${s}\n\n---\n🌐 **Dashboard opened in browser:** ${g}\n\n**IMPORTANT:** You MUST now open this URL using the \`openBrowserPage\` tool (Simple Browser). If that tool is unavailable, open the URL in the system browser as a fallback. If neither works, ask the user to open the URL manually.`:s;if(h.length>0&&a?.available&&u)try{let e=await Promise.race([u,new Promise((e,t)=>setTimeout(()=>t(Error(`timeout`)),300*1e3))]);return{content:[{type:`text`,text:`${v}\n\n✅ **Selected:** ${e.actionId} = \`${e.value}\``},l]}}catch{return{content:[{type:`text`,text:`${v}\n\n⚠️ *No selection received (timed out).*`},l]}}return{content:[{type:`text`,text:v},l]}}function E(e,r,i,a){let o=Array.isArray(i)?i:[],s=e?`📊 **${e}**`:`📊 **Dashboard**`,c=m({uri:`ui://aikit/present-static.html`,content:{type:`rawHtml`,htmlString:n(e,r,i,a)},encoding:`text`,adapters:{mcpApps:{enabled:!0}}});return{content:[{type:`text`,text:s},c],structuredContent:{title:e,content:t(r),actions:o}}}export{T as formatAsBrowser,E as formatAsHtml,C as getPresentHtml,w as registerPresentTool,S as resolvePresentHtml};
|