@microi.net/cli 5.4.9 → 5.5.1
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/.codebuddy-plugin/marketplace.json +2 -2
- package/.codebuddy-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/.workbuddy-plugin/marketplace.json +2 -2
- package/.workbuddy-plugin/plugin.json +1 -1
- package/assets/build-meta.json +6 -6
- package/cordis.patch.yml +1 -1
- package/package.json +1 -1
- package/scripts/mcp-server.js +3 -3
- package/scripts/microi-cli.js +93 -0
- package/scripts/microi-skills.meta.json +206 -197
- package/skills/.microi-skills-version.json +2 -2
- package/skills/.progressive-disclosure-manifest.json +7 -7
- package/skills/README.md +103 -102
- package/skills/ai-engine/SKILL.md +90 -89
- package/skills/microi-db-schema/references/core-tables.md +1 -1
- package/skills/microi-db-schema/references/table-catalog.md +1 -1
- package/skills/microi-docs-coverage/references/capability-map.md +6 -2
- package/skills/microi-microservice/SKILL.md +292 -260
- package/skills/v8-api-config/SKILL.md +275 -263
- package/skills/v8-cache-pattern/SKILL.md +3 -1
- package/skills/v8-file-upload/SKILL.md +9 -9
- package/skills/v8-menu-buttons/references/progressive-02-8-/346/250/241/345/274/217-f-/345/220/216/345/217/260/344/273/273/345/212/241/346/214/211/351/222/256-/351/225/277/344/273/273/345/212/241.md +26 -22
- package/skills/v8-saas-multi-tenant/SKILL.md +113 -97
- package/skills/vision-engine/SKILL.md +152 -0
- package/skills/vision-engine/agents/openai.yaml +4 -0
- package/skills/vision-engine/references/architecture-and-acceptance.md +172 -0
package/scripts/mcp-server.js
CHANGED
|
@@ -208,8 +208,8 @@ ${JSON.stringify({results:p},null,2)}`,!0)}}),t.tool("microi_list_roles",`List r
|
|
|
208
208
|
`;function f$(t,e,r){let n=r.osClient;t.tool("microi_get_blueprint_schema","Return the System Blueprint protocol guide (3-layer model: domain/process/behavior). Read this BEFORE creating or editing any blueprint, especially when AI is generating systems for the first time.",{},async()=>as(OG)),t.tool("microi_list_blueprints",`List business blueprints for OsClient ${n}. Lightweight metadata only (no BlueprintData). Use this to discover existing system blueprints before generating new code.`,{keyword:d.string().optional().describe("Search by Name/Code/Description")},async({keyword:i})=>Tn("Blueprints",await e.listBlueprints(i))),t.tool("microi_get_blueprint",`Get full blueprint detail (including BlueprintData JSON) by Id or Name. AI MUST call this before generating any system code so generation is grounded on the blueprint, not guessed. OsClient: ${n}`,{blueprintId:d.string().describe("Blueprint Id or Name (Name fallback if Id not matched)")},async({blueprintId:i})=>Tn("Blueprint Detail",await e.getBlueprint(i))),t.tool("microi_list_blueprint_history",`List immutable history snapshots for a blueprint. Returns metadata, stable SHA-256 hashes and the current draft hash without returning snapshot bodies. OsClient: ${n}`,{blueprintId:d.string().describe("Blueprint Id or Name"),pageIndex:d.number().int().min(1).optional().describe("1-based page index, default 1"),pageSize:d.number().int().min(1).max(100).optional().describe("Page size, default 50, max 100")},async({blueprintId:i,pageIndex:o,pageSize:a})=>Tn("Blueprint History",await e.listBlueprintHistory(i,o??1,a??50))),t.tool("microi_get_blueprint_history",`Read one immutable blueprint history snapshot including BlueprintData. The history row must belong to the requested blueprint and current tenant. OsClient: ${n}`,{blueprintId:d.string().describe("Blueprint Id or Name"),historyId:d.string().describe("History snapshot Id")},async({blueprintId:i,historyId:o})=>Tn("Blueprint History Detail",await e.getBlueprintHistory(i,o))),t.tool("microi_compare_blueprint_versions",`Compare blueprint JSON semantically. Arrays with stable id/key values are matched by identity, so pure ordering changes do not create noisy diffs. Omit rightHistoryId to compare with the current draft; omit leftHistoryId to use the latest snapshot. OsClient: ${n}`,{blueprintId:d.string().describe("Blueprint Id or Name"),leftHistoryId:d.string().optional().describe("Left snapshot Id; latest snapshot when omitted"),rightHistoryId:d.string().optional().describe("Right snapshot Id; current draft when omitted")},async({blueprintId:i,leftHistoryId:o,rightHistoryId:a})=>Tn("Blueprint Version Diff",await e.compareBlueprintVersions(i,o,a))),t.tool("microi_export_blueprint",`Export the current blueprint as a portable microi.blueprint.v1 JSON snapshot with a stable SHA-256 content hash. Read-only. OsClient: ${n}`,{blueprintId:d.string().describe("Blueprint Id or Name")},async({blueprintId:i})=>Tn("Export Blueprint",await e.exportBlueprint(i))),t.tool("microi_save_blueprint",`Create or update a system blueprint. Auto-saves a history snapshot (sys_blueprint_history) and rebuilds the reverse-reference index (sys_blueprint_relation). Pass the blueprint per microi_get_blueprint_schema. OsClient: ${n}`,{blueprint:$G.describe("Blueprint object: { Id?, Name, Code?, Description?, Version?, RootDiagramId?, Status?, BlueprintData (JSON string), ChangeSummary? }"),confirmExecution:d.string().optional().describe('Must equal blueprint Name or "EXECUTE" to actually write')},async({blueprint:i,confirmExecution:o})=>{let a=i?.Name||i?.name||"";return a?o!==a&&o!=="EXECUTE"?as(`\u5199\u5165\u5DF2\u62E6\u622A\uFF1A\u8BF7\u4F20 confirmExecution="${a}" \u6216 "EXECUTE"\u3002`,!0):(await p0(e,"microi_save_blueprint",a,i),Tn("Save Blueprint",await e.saveBlueprint(i))):as("blueprint.Name \u4E0D\u80FD\u4E3A\u7A7A",!0)}),t.tool("microi_delete_blueprint",`Soft-delete a blueprint and its reverse-reference rows (history snapshots are preserved). OsClient: ${n}`,{blueprintId:d.string().describe("Blueprint Id"),confirmExecution:d.string().describe('Must equal blueprintId or "EXECUTE"')},async({blueprintId:i,confirmExecution:o})=>o!==i&&o!=="EXECUTE"?as(`\u5220\u9664\u5DF2\u62E6\u622A\uFF1A\u8BF7\u4F20 confirmExecution="${i}" \u6216 "EXECUTE"\u3002`,!0):(await p0(e,"microi_delete_blueprint",i,{BlueprintId:i}),Tn("Delete Blueprint",await e.deleteBlueprint(i)))),t.tool("microi_rollback_blueprint",`Restore a blueprint from an immutable history snapshot. Rollback creates a pre-rollback snapshot, rebuilds reverse references in the same database transaction and requires ExpectedCurrentHash to reject concurrent overwrites. OsClient: ${n}`,{blueprintId:d.string().describe("Blueprint Id or Name"),historyId:d.string().describe("Target history snapshot Id"),expectedCurrentHash:d.string().regex(/^[a-f0-9]{64}$/i).describe("CurrentHash from microi_list_blueprint_history or compare result"),newVersion:d.string().max(20).optional().describe("Optional version label; defaults to target snapshot version"),changeSummary:d.string().max(2e3).optional().describe("Rollback reason recorded in history and audit"),confirmExecution:d.string().describe('Must equal blueprintId or "EXECUTE"')},async({blueprintId:i,historyId:o,expectedCurrentHash:a,newVersion:s,changeSummary:c,confirmExecution:l})=>{if(l!==i&&l!=="EXECUTE")return as(`\u56DE\u6EDA\u5DF2\u62E6\u622A\uFF1A\u8BF7\u4F20 confirmExecution="${i}" \u6216 "EXECUTE"\u3002`,!0);let u={BlueprintId:i,HistoryId:o,ExpectedCurrentHash:a,...s?{NewVersion:s}:{},...c?{ChangeSummary:c}:{}};return await p0(e,"microi_rollback_blueprint",i,{HistoryId:o,ExpectedCurrentHash:a,NewVersion:s,ChangeSummary:c}),Tn("Rollback Blueprint",await e.rollbackBlueprint(u))}),t.tool("microi_validate_blueprint",`Validate that all platform resources referenced by a blueprint (tables/fields/engines/menus/v8Events) still exist. Returns errors/warnings/CheckedRefs. AI should call this AFTER any system change to detect blueprint drift. OsClient: ${n}`,{blueprintId:d.string().describe("Blueprint Id or Name")},async({blueprintId:i})=>Tn("Validate Blueprint",await e.validateBlueprint(i)))}var NG=d.record(d.unknown());function Jt(t,e=!1){return{content:[{type:"text",text:t}],isError:e}}function Wn(t,e,r){let n=r?{response:e.Data??{},...r}:e.Data??{},i=[`## ${t}`,`- Code: ${e.Code}`,e.Msg?`- Message: ${e.Msg}`:"","","```json",JSON.stringify(n,null,2),"```"].filter(Boolean);return Jt(i.join(`
|
|
209
209
|
`),e.Code!==1)}async function MG(t,e,r,n){try{await t.writeAuditLog(e,r,JSON.stringify(n).slice(0,6e3))}catch(i){console.error("[microi-mcp] page design audit log failed:",i instanceof Error?i.message:String(i))}}function m$(t,e,r){let n=r.osClient;t.tool("microi_validate_page_design",`Validate and normalize a Microi Page Engine JsonObj for OsClient ${n}. Accepts raw JsonObj, a mic_page row, {JsonObj}, {JsonStr}, or {formData:{JsonObj}} and returns the canonical JsonObj string saved to mic_page.JsonObj.`,{json:d.unknown().describe("Page Engine JSON in any common AI output shape.")},async({json:i})=>{let o=Hn(i);return Jt(JSON.stringify(o,null,2),!o.ok)}),t.tool("microi_validate_print_design",`Validate and normalize a Microi Print Engine PageObj/PrintObj pair for OsClient ${n}. PageObj must contain hiprint panels and printElements.`,{pageObj:d.unknown().describe("Print Engine PageObj, or a wrapper containing PageObj/pageObj."),printObj:d.unknown().optional().describe("Optional PrintObj sample/runtime data.")},async({pageObj:i,printObj:o})=>{let a=Oo(i),s=No(o),c=a.ok&&s.ok;return Jt(JSON.stringify({ok:c,page:a,printObj:s},null,2),!c)}),t.tool("microi_build_page_design",`Build a good-looking Page Engine dashboard JsonObj from a natural language description. By default this is a dry run; to write mic_page pass save=true and confirmExecution equal to the title or "EXECUTE". OsClient ${n}.`,{prompt:d.string().describe('Natural language design request, such as "\u505A\u4E00\u4E2A\u7EF4\u4FDD\u5DE5\u5355\u8FD0\u8425\u9A7E\u9A76\u8231\uFF0C\u5305\u542B\u5DE5\u5355\u8D8B\u52BF\u3001\u8BBE\u5907\u98CE\u9669\u3001\u5F85\u529E\u5217\u8868".'),title:d.string().optional().describe("Page title. Auto-generated from prompt if omitted."),number:d.string().optional().describe("Page Number/code. Auto-generated if omitted."),desc:d.string().optional().describe("Page description."),theme:d.string().optional().describe("Optional business theme: maintenance, mall, sales, finance, operations."),style:d.string().optional().describe("Optional visual style, e.g. light, dark, \u5927\u5C4F, \u7B80\u6D01."),routePath:d.string().optional().describe("Optional route path saved to mic_page.RoutePath."),componentPath:d.string().optional().describe("Optional component path saved to mic_page.ComponentPath."),save:d.boolean().optional().describe("Default false. When true, save to mic_page."),confirmExecution:d.string().optional().describe('Required when save=true. Must equal the title or "EXECUTE".')},async i=>{let o=j4(i),a=Hn(o.jsonObj);if(!a.ok||!a.json)return Jt(JSON.stringify(a,null,2),!0);if(!i.save)return Jt(JSON.stringify({ok:!0,dryRun:!0,title:o.title,number:o.number,desc:o.desc,jsonStr:a.json,jsonObj:a.value,warnings:a.warnings,next:`Call this tool again with save=true and confirmExecution="${o.title}" to write mic_page.`},null,2));if(i.confirmExecution!==o.title&&i.confirmExecution!=="EXECUTE")return Jt(`Write blocked. Pass confirmExecution="${o.title}" or "EXECUTE".`,!0);let s=await e.savePageEngine({Title:o.title,Number:o.number,Desc:o.desc,JsonStr:a.json,RoutePath:i.routePath,ComponentPath:i.componentPath});return Wn("Build And Save Page Design",s,{title:o.title,number:o.number,warnings:a.warnings})}),t.tool("microi_build_print_template_design",`Build a good-looking Print Engine hiprint template from a natural language description. By default this is a dry run; to write mic_print pass save=true and confirmExecution equal to the title or "EXECUTE". OsClient ${n}.`,{prompt:d.string().describe('Natural language print template request, such as "\u505A\u4E00\u5F20\u7EF4\u4FDD\u5DE5\u5355\u6253\u5370\u6A21\u677F\uFF0C\u542B\u5BA2\u6237\u3001\u8BBE\u5907\u3001\u6545\u969C\u3001\u5904\u7406\u660E\u7EC6\u3001\u7B7E\u5B57\u533A".'),title:d.string().optional().describe("Template title. Auto-generated from prompt if omitted."),number:d.string().optional().describe("Template Number/code. Auto-generated if omitted."),desc:d.string().optional().describe("Template description."),dataApi:d.string().optional().describe("Optional DataApi called by print renderer for runtime data."),paperType:d.string().optional().describe("Paper type. Default A4."),save:d.boolean().optional().describe("Default false. When true, save to mic_print."),confirmExecution:d.string().optional().describe('Required when save=true. Must equal the title or "EXECUTE".')},async i=>{let o=q4(i),a=Oo(o.pageObj),s=No(o.printObj);if(!a.ok||!s.ok||!a.json||!s.json)return Jt(JSON.stringify({ok:!1,page:a,printObj:s},null,2),!0);if(!i.save)return Jt(JSON.stringify({ok:!0,dryRun:!0,title:o.title,number:o.number,desc:o.desc,dataApi:o.dataApi,pageObj:a.value,printObj:s.value,pageObjStr:a.json,printObjStr:s.json,warnings:[...a.warnings,...s.warnings],next:`Call this tool again with save=true and confirmExecution="${o.title}" to write mic_print.`},null,2));if(i.confirmExecution!==o.title&&i.confirmExecution!=="EXECUTE")return Jt(`Write blocked. Pass confirmExecution="${o.title}" or "EXECUTE".`,!0);let c=await e.savePrintTemplate({Title:o.title,Number:o.number,Desc:o.desc,DataApi:o.dataApi,PageObj:a.json,PrintObj:s.json});return Wn("Build And Save Print Template",c,{title:o.title,number:o.number,warnings:[...a.warnings,...s.warnings]})}),t.tool("microi_save_page_design",`Create or update mic_page with Page Engine JsonObj normalization. This is the write-safe version for AI generated JSON. Writes require confirmExecution equal to title or "EXECUTE". OsClient ${n}.`,{pageId:d.string().optional(),title:d.string(),number:d.string().optional(),desc:d.string().optional(),json:d.unknown().describe("Raw JsonObj, {JsonObj}, {JsonStr}, mic_page row, or {formData:{JsonObj}}."),routePath:d.string().optional(),componentPath:d.string().optional(),expectedCurrentHash:d.string().regex(/^[a-f0-9]{64}$/i).optional().describe("CurrentHash returned by page history; rejects concurrent overwrites."),changeSummary:d.string().max(2e3).optional().describe("Reason recorded in immutable page history."),confirmExecution:d.string().optional()},async({pageId:i,title:o,number:a,desc:s,json:c,routePath:l,componentPath:u,expectedCurrentHash:p,changeSummary:f,confirmExecution:h})=>{if(h!==o&&h!=="EXECUTE")return Jt(`Write blocked. Pass confirmExecution="${o}" or "EXECUTE".`,!0);let m=Hn(c);if(!m.ok||!m.json)return Jt(JSON.stringify(m,null,2),!0);let g=await e.savePageEngine({PageId:i,Title:o,Number:a,Desc:s,JsonStr:m.json,RoutePath:l,ComponentPath:u,ExpectedCurrentHash:p,ChangeSummary:f});return Wn("Save Page Design",g,{warnings:m.warnings})}),t.tool("microi_list_page_history",`List immutable history for one Page Engine design, including the current SHA-256 hash used for optimistic concurrency. Snapshot bodies are omitted. OsClient ${n}.`,{pageId:d.string().describe("mic_page.Id"),pageIndex:d.number().int().min(1).optional(),pageSize:d.number().int().min(1).max(100).optional()},async({pageId:i,pageIndex:o,pageSize:a})=>Wn("Page Design History",await e.listPageEngineHistory(i,o??1,a??50))),t.tool("microi_get_page_history",`Read one immutable Page Engine history snapshot. The history row must belong to the requested page and tenant. OsClient ${n}.`,{pageId:d.string().describe("mic_page.Id"),historyId:d.string().describe("mci_resource_version.Id")},async({pageId:i,historyId:o})=>Wn("Page Design History Detail",await e.getPageEngineHistory(i,o))),t.tool("microi_compare_page_versions",`Compare two Page Engine snapshots semantically. Stable widget ids are matched by identity so pure reordering is ignored. Omit rightHistoryId to compare with the current design; omit leftHistoryId for the latest snapshot. OsClient ${n}.`,{pageId:d.string().describe("mic_page.Id"),leftHistoryId:d.string().optional(),rightHistoryId:d.string().optional()},async({pageId:i,leftHistoryId:o,rightHistoryId:a})=>Wn("Page Design Version Diff",await e.comparePageEngineVersions(i,o,a))),t.tool("microi_export_page_design",`Export a canonical, portable Microi Page Engine snapshot with schema version and content hash. Read-only. OsClient ${n}.`,{pageId:d.string().describe("mic_page.Id")},async({pageId:i})=>Wn("Export Page Design",await e.exportPageEngine(i))),t.tool("microi_rollback_page_design",`Restore Page Engine design from an immutable snapshot. Requires the current hash to reject concurrent overwrites and creates a new audit version instead of deleting history. OsClient ${n}.`,{pageId:d.string().describe("mic_page.Id"),historyId:d.string().describe("Target mci_resource_version.Id"),expectedCurrentHash:d.string().regex(/^[a-f0-9]{64}$/i).describe("CurrentHash from microi_list_page_history"),changeSummary:d.string().max(2e3).optional(),confirmExecution:d.string().describe('Must equal pageId or "EXECUTE".')},async({pageId:i,historyId:o,expectedCurrentHash:a,changeSummary:s,confirmExecution:c})=>{if(c!==i&&c!=="EXECUTE")return Jt(`Rollback blocked. Pass confirmExecution="${i}" or "EXECUTE".`,!0);let l={PageId:i,HistoryId:o,ExpectedCurrentHash:a,...s?{ChangeSummary:s}:{}};return await MG(e,"microi_rollback_page_design",i,l),Wn("Rollback Page Design",await e.rollbackPageEngine(l))}),t.tool("microi_save_print_template_design",`Create or update mic_print with Print Engine PageObj/PrintObj normalization. Writes require confirmExecution equal to title or "EXECUTE". OsClient ${n}.`,{template:NG.describe("Template with Title/title, optional Id/Number/Desc/DataApi, PageObj/pageObj and PrintObj/printObj."),confirmExecution:d.string().optional()},async({template:i,confirmExecution:o})=>{let a=typeof i.Title=="string"?i.Title:typeof i.title=="string"?i.title:"";if(!a)return Jt("Template Title cannot be empty.",!0);if(o!==a&&o!=="EXECUTE")return Jt(`Write blocked. Pass confirmExecution="${a}" or "EXECUTE".`,!0);let s=Oo(i.PageObj??i.pageObj),c=No(i.PrintObj??i.printObj);if(!s.ok||!c.ok||!s.json||!c.json)return Jt(JSON.stringify({ok:!1,page:s,printObj:c},null,2),!0);let l=await e.savePrintTemplate({...i,Title:a,PageObj:s.json,PrintObj:c.json});return Wn("Save Print Template Design",l,{warnings:[...s.warnings,...c.warnings]})})}var DG="host",E$="queue/data",FG="queue/join",h$="upload",zG="login",Xd="config",LG="info",jG="runtime",qG="sleeptime",VG="heartbeat",BG="component_server",UG="reset",JG="cancel",HG="app_id",k$="This application is currently busy. Please try again. ",hl="Connection errored out. ",Ri="Could not resolve app config. ",ZG="Could not get space status. ",KG="Could not get API info. ",y0="Space metadata could not be loaded. ",WG="Invalid URL. A full URL path is required.",GG="Not authorized to access this space. ",T$="Invalid credentials. Could not login. ",XG="Login credentials are required to access this space.",YG="File system access is only available in Node.js environments",C$="Root URL not found in client config",QG="Error uploading file";async function g$(t,e,r){try{return(await(await fetch(`https://huggingface.co/api/spaces/${t}/jwt`,{headers:{Authorization:`Bearer ${e}`,...r?{Cookie:r}:{}}})).json()).token||!1}catch{return!1}}function eX(t){let e={};return t.forEach(({api_name:r,id:n})=>{r&&(e[r]=n)}),e}async function tX(t){let e=this.options.token?{Authorization:`Bearer ${this.options.token}`}:{};if(e["Content-Type"]="application/json",typeof window<"u"&&window.gradio_config&&location.origin!=="http://localhost:9876"){if(window.gradio_config.current_page&&(t=t.substring(0,t.lastIndexOf("/"))),window.gradio_config.dev_mode){let r=f0(t,this.deep_link?Xd+"?deep_link="+this.deep_link:Xd),n=await this.fetch(r,{headers:e,credentials:"include"}),i=await y$(n,t,!!this.options.auth);window.gradio_config={...i,current_page:window.gradio_config.current_page}}return window.gradio_config.root=t,{...window.gradio_config}}else if(t){let r=f0(t,this.deep_link?Xd+"?deep_link="+this.deep_link:Xd),n=await this.fetch(r,{headers:e,credentials:"include"});return y$(n,t,!!this.options.auth)}throw new Error(Ri)}async function y$(t,e,r){if(t?.status===401&&!r){let i=(await t.json())?.detail?.auth_message;throw new Error(i||XG)}else if(t?.status===401&&r)throw new Error(T$);if(t?.status===200){let n=await t.json();return n.root=e,n.dependencies?.forEach((i,o)=>{i.id===void 0&&(i.id=o)}),n}else if(t?.status===401)throw new Error(GG);throw new Error(Ri)}async function rX(){let{http_protocol:t,host:e}=await v0(this.app_reference,this.options.token);try{if(this.options.auth){let r=await A$(t,e,this.options.auth,this.fetch,this.options.token);r&&this.set_cookies(r)}}catch(r){throw Error(r.message)}}async function A$(t,e,r,n,i){let o=new FormData;o.append("username",r?.[0]),o.append("password",r?.[1]);let a={};i&&(a.Authorization=`Bearer ${i}`);let s=await n(`${t}//${e}/${zG}`,{headers:a,method:"POST",body:o,credentials:"include"});if(s.status===200)return s.headers.get("set-cookie");throw s.status===401?new Error(T$):new Error(y0)}function d0(t){if(t.startsWith("http")){let{protocol:e,host:r,pathname:n}=new URL(t);return{ws_protocol:e==="https:"?"wss":"ws",http_protocol:e,host:r+(n!=="/"?n:"")}}return{ws_protocol:"wss",http_protocol:"https:",host:new URL(t).host}}var I$=t=>{let e=[];return t.split(/,(?=\s*[^\s=;]+=[^\s=;]+)/).forEach(n=>{let[i,o]=n.split(";")[0].split("=");i&&o&&e.push(`${i.trim()}=${o.trim()}`)}),e},b0=/^[a-zA-Z0-9_\-\.]+\/[a-zA-Z0-9_\-\.]+$/,nX=/.*hf\.space\/{0,1}.*$/;async function v0(t,e){let r={};e&&(r.Authorization=`Bearer ${e}`);let n=t.trim().replace(/\/$/,"");if(b0.test(n))try{let o=(await(await fetch(`https://huggingface.co/api/spaces/${n}/${DG}`,{headers:r})).json()).host;return{space_id:t,...d0(o)}}catch{throw new Error(y0)}if(nX.test(n)){let{ws_protocol:i,http_protocol:o,host:a}=d0(n);return{space_id:a.split("/")[0].replace(".hf.space",""),ws_protocol:i,http_protocol:o,host:a}}return{space_id:!1,...d0(n)}}var f0=(...t)=>{try{return t.reduce((e,r)=>(e=e.replace(/\/+$/,""),r=r.replace(/^\/+/,""),new URL(r,e+"/").toString()))}catch{throw new Error(WG)}};function iX(t,e,r){let n={named_endpoints:{},unnamed_endpoints:{}};return Object.keys(t).forEach(i=>{(i==="named_endpoints"||i==="unnamed_endpoints")&&(n[i]={},Object.entries(t[i]).forEach(([o,{parameters:a,returns:s}])=>{let c=e.dependencies.find(p=>p.api_name===o||p.api_name===o.replace("/",""))?.id||r[o.replace("/","")]||-1,l=c!==-1?e.dependencies.find(p=>p.id==c)?.types:{generator:!1,cancel:!1};if(c!==-1&&e.dependencies.find(p=>p.id==c)?.inputs?.length!==a.length){let p=e.dependencies.find(f=>f.id==c).inputs.map(f=>e.components.find(h=>h.id===f)?.type);try{p.forEach((f,h)=>{if(f==="state"){let m={component:"state",example:null,parameter_default:null,parameter_has_default:!0,parameter_name:null,hidden:!0};a.splice(h,0,m)}})}catch(f){console.error(f)}}let u=(p,f,h,m)=>({...p,description:aX(p?.type,h),type:oX(p?.type,f,h,m)||""});n[i][o]={parameters:a.map(p=>u(p,p?.component,p?.serializer,"parameter")),returns:s.map(p=>u(p,p?.component,p?.serializer,"return")),type:l}}))}),n}function oX(t,e,r,n){if(e==="Api")return t.type;switch(t?.type){case"string":return"string";case"boolean":return"boolean";case"number":return"number"}if(r==="JSONSerializable"||r==="StringSerializable")return"any";if(r==="ListStringSerializable")return"string[]";if(e==="Image")return n==="parameter"?"Blob | File | Buffer":"string";if(r==="FileSerializable")return t?.type==="array"?n==="parameter"?"(Blob | File | Buffer)[]":"{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}[]":n==="parameter"?"Blob | File | Buffer":"{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}";if(r==="GallerySerializable")return n==="parameter"?"[(Blob | File | Buffer), (string | null)][]":"[{ name: string; data: string; size?: number; is_file?: boolean; orig_name?: string}, (string | null))][]"}function aX(t,e){return e==="GallerySerializable"?"array of [file, label] tuples":e==="ListStringSerializable"?"array of strings":e==="FileSerializable"?"array of files or single file":t?.description}function b$(t,e){switch(t.msg){case"send_data":return{type:"data"};case"send_hash":return{type:"hash"};case"queue_full":return{type:"update",status:{queue:!0,message:k$,stage:"error",code:t.code,success:t.success}};case"heartbeat":return{type:"heartbeat"};case"unexpected_error":return{type:"unexpected_error",status:{queue:!0,message:t.message,session_not_found:t.session_not_found,stage:"error",success:!1}};case"broken_connection":return{type:"broken_connection",status:{queue:!0,message:t.message,stage:"error",success:!1}};case"estimation":return{type:"update",status:{queue:!0,stage:e||"pending",code:t.code,size:t.queue_size,position:t.rank,eta:t.rank_eta,success:t.success}};case"progress":return{type:"update",status:{queue:!0,stage:"pending",code:t.code,progress_data:t.progress_data,success:t.success}};case"log":return{type:"log",data:t};case"process_generating":return{type:"generating",status:{queue:!0,message:t.success?null:t.output.error,stage:t.success?"generating":"error",code:t.code,progress_data:t.progress_data,eta:t.average_duration,changed_state_ids:t.success?t.output.changed_state_ids:void 0},data:t.success?t.output:null};case"process_streaming":return{type:"streaming",status:{queue:!0,message:t.output.error,stage:"streaming",time_limit:t.time_limit,code:t.code,progress_data:t.progress_data,eta:t.eta},data:t.output};case"process_completed":return"error"in t.output?{type:"update",status:{queue:!0,title:t.output.title??"Error",message:t.output.error??"An error occurred",visible:t.output.visible,duration:t.output.duration,stage:"error",code:t.code,success:t.success}}:{type:"complete",status:{queue:!0,message:t.success?void 0:t.output.error,stage:t.success?"complete":"error",code:t.code,progress_data:t.progress_data,changed_state_ids:t.success?t.output.changed_state_ids:void 0},data:t.success?t.output:null};case"process_starts":return{type:"update",status:{queue:!0,stage:"pending",code:t.code,size:t.rank,position:0,success:t.success,eta:t.eta},original_msg:"process_starts"}}return{type:"none",status:{stage:"error",queue:!0}}}var sX=(t=[],e)=>{let r=e?e.parameters:[];if(Array.isArray(t))return e&&r.length>0&&t.length>r.length&&console.warn("Too many arguments provided for the endpoint."),t;let n=[],i=Object.keys(t);return r.forEach((o,a)=>{if(t.hasOwnProperty(o.parameter_name))n[a]=t[o.parameter_name];else if(o.parameter_has_default)n[a]=o.parameter_default;else throw new Error(`No value provided for required parameter: ${o.parameter_name}`)}),i.forEach(o=>{if(!r.some(a=>a.parameter_name===o))throw new Error(`Parameter \`${o}\` is not a valid keyword argument. Please refer to the API for usage.`)}),n.forEach((o,a)=>{if(o===void 0&&!r[a].parameter_has_default)throw new Error(`No value provided for required parameter: ${r[a].parameter_name}`)}),n};async function cX(){if(this.api_info)return this.api_info;let{token:t}=this.options,{config:e}=this,r={"Content-Type":"application/json"};if(t&&(r.Authorization=`Bearer ${t}`),!!e)try{let n,i;if(typeof window<"u"&&window.gradio_api_info)i=window.gradio_api_info;else{let o=f0(e.root,this.api_prefix,LG);if(n=await this.fetch(o,{headers:r,credentials:"include"}),!n.ok)throw new Error(hl);i=await n.json()}return"api"in i&&(i=i.api),i.named_endpoints["/predict"]&&!i.unnamed_endpoints[0]&&(i.unnamed_endpoints[0]=i.named_endpoints["/predict"]),iX(i,e,this.api_map)}catch(n){throw new Error("Could not get API info. "+n.message)}}async function lX(t,e,r){let n={};this?.options?.token&&(n.Authorization=`Bearer ${this.options.token}`);let i=1e3,o=[],a;for(let s=0;s<e.length;s+=i){let c=e.slice(s,s+i),l=new FormData;c.forEach(p=>{l.append("files",p)});try{let p=r?`${t}${this.api_prefix}/${h$}?upload_id=${r}`:`${t}${this.api_prefix}/${h$}`;a=await this.fetch(p,{method:"POST",body:l,headers:n,credentials:"include"})}catch(p){throw new Error(hl+p.message)}if(!a.ok){let p=await a.text();return{error:`HTTP ${a.status}: ${p}`}}let u=await a.json();u&&o.push(...u)}return{files:o}}var uX={radix:1e3,unit:["b","kb","Mb","Gb","Tb","Pb","Eb","Zb","Yb"]},pX={radix:1024,unit:["b","Kib","Mib","Gib","Tib","Pib","Eib","Zib","Yib"]},dX={radix:1024,unit:["b","Kb","Mb","Gb","Tb","Pb","Eb","Zb","Yb"]},v$={si:uX,iec:pX,jedec:dX};function fX(t,e=1,r="jedec"){t=Math.abs(t);let{radix:n,unit:i}=v$[r]||v$.jedec,o=0;for(;t>=n;)t/=n,++o;return`${t.toFixed(e)} ${i[o]}`}async function mX(t,e,r,n){let i=(Array.isArray(t)?t:[t]).map(a=>a.blob),o=i.filter(a=>a.size>(n??1/0));if(o.length)throw new Error(`File(s) exceed the maximum allowed size of ${fX(n||1/0)}: ${o.map(a=>`"${a.name}"`).join(", ")}`);return await Promise.all(await this.upload_files(e,i,r).then(async a=>{if(a.error)throw new Error(a.error);return a.files?a.files.map((s,c)=>new ml({...t[c],path:s,url:`${e}${this.api_prefix}/file=${s}`})):[]}))}var ml=class{path;url;orig_name;size;blob;is_stream;mime_type;alt_text;b64;meta={_type:"gradio.FileData"};constructor({path:e,url:r,orig_name:n,size:i,blob:o,is_stream:a,mime_type:s,alt_text:c,b64:l}){this.path=e,this.url=r,this.orig_name=n,this.size=i,this.blob=r?void 0:o,this.is_stream=a,this.mime_type=s,this.alt_text=c,this.b64=l}},m0=class{type;command;meta;fileData;constructor(e,r){this.type="command",this.command=e,this.meta=r}},Ale=typeof process<"u"&&process.versions&&process.versions.node;function x$(t,e,r){for(;r.length>1;){let i=r.shift();if(typeof i=="string"||typeof i=="number")t=t[i];else throw new Error("Invalid key type")}let n=r.shift();if(typeof n=="string"||typeof n=="number")t[n]=e;else throw new Error("Invalid key type")}async function h0(t,e=void 0,r=[],n=!1,i=void 0){if(Array.isArray(t)){let o=[];return await Promise.all(t.map(async(a,s)=>{let c=r.slice();c.push(String(s));let l=await h0(t[s],n?i?.parameters[s]?.component||void 0:e,c,!1,i);o=o.concat(l)})),o}else{if(globalThis.Buffer&&t instanceof globalThis.Buffer||t instanceof Blob)return[{path:r,blob:new Blob([t]),type:e}];if(typeof t=="object"&&t!==null){let o=[];for(let a of Object.keys(t)){let s=[...r,a],c=t[a];o=o.concat(await h0(c,void 0,s,!1,i))}return o}}return[]}function hX(t,e){let r=e?.dependencies?.find(n=>n.id==t)?.queue;return r!=null?!r:!e.enable_queue}function gX(t,e){return new Promise((r,n)=>{let i=new MessageChannel;i.port1.onmessage=({data:o})=>{i.port1.close(),r(o)},window.parent.postMessage(t,e,[i.port2])})}function Yd(t,e,r,n,i=!1){if(n==="input"&&!i)throw new Error("Invalid code path. Cannot skip state inputs for input.");if(n==="output"&&i)return t;let o=[],a=0,s=n==="input"?e.inputs:e.outputs;for(let c=0;c<s.length;c++){let l=s[c];if(r.find(p=>p.id===l)?.type==="state"){if(i)if(t.length===s.length){let p=t[a];o.push(p),a++}else o.push(null);else{a++;continue}continue}else{let p=t[a];o.push(p),a++}}return o}async function yX(t,e,r){let n=this;await bX(n,e);let i=await h0(e,void 0,[],!0,r);return(await Promise.all(i.map(async({path:a,blob:s,type:c})=>{if(!s)return{path:a,type:c};let l=await n.upload_files(t,[s]),u=l.files&&l.files[0];return{path:a,file_url:u,type:c,name:typeof File<"u"&&s instanceof File?s?.name:void 0}}))).forEach(({path:a,file_url:s,type:c,name:l})=>{if(c==="Gallery")x$(e,s,a);else if(s){let u=new ml({path:s,orig_name:l});x$(e,u,a)}}),e}async function bX(t,e){if(!(t.config?.root||t.config?.root_url))throw new Error(C$);await P$(t,e)}async function P$(t,e,r=[]){for(let n in e)e[n]instanceof m0?await vX(t,e,n):typeof e[n]=="object"&&e[n]!==null&&await P$(t,e[n],[...r,n])}async function vX(t,e,r){let n=e[r],i=t.config?.root||t.config?.root_url;if(!i)throw new Error(C$);try{let o,a;if(typeof process<"u"&&process.versions&&process.versions.node){let u=await import("fs/promises");a=(await import("path")).resolve(process.cwd(),n.meta.path),o=await u.readFile(a)}else throw new Error(YG);let s=new Blob([o],{type:"application/octet-stream"}),c=await t.upload_files(i,[s]),l=c.files&&c.files[0];if(l){let u=new ml({path:l,orig_name:n.meta.name||""});e[r]=u}}catch(o){console.error(QG,o)}}async function xX(t,e,r){let n={"Content-Type":"application/json"};this.options.token&&(n.Authorization=`Bearer ${this.options.token}`);try{var i=await this.fetch(t,{method:"POST",body:JSON.stringify(e),headers:{...n,...r},credentials:"include"})}catch{return[{error:hl},500]}let o,a;try{o=await i.json(),a=i.status}catch(s){o={error:`Could not parse server response: ${s}`},a=500}return[o,a]}async function wX(t,e={}){let r=!1,n=!1;if(!this.config)throw new Error("Could not resolve app config");if(typeof t=="number")this.config.dependencies.find(i=>i.id==t);else{let i=t.replace(/^\//,"");this.config.dependencies.find(o=>o.id==this.api_map[i])}return new Promise(async(i,o)=>{let a=this.submit(t,e,null,null,!0),s;for await(let c of a)c.type==="data"&&(n&&i(s),r=!0,s=c),c.type==="status"&&(c.stage==="error"&&o(c),c.stage==="complete"&&(n=!0,r&&i(s)))})}async function fl(t,e,r){let n=e==="subdomain"?`https://huggingface.co/api/spaces/by-subdomain/${t}`:`https://huggingface.co/api/spaces/${t}`,i,o;try{if(i=await fetch(n),o=i.status,o!==200)throw new Error;i=await i.json()}catch{r({status:"error",load_status:"error",message:ZG,detail:"NOT_FOUND"});return}if(!i||o!==200)return;let{runtime:{stage:a},id:s}=i;switch(a){case"STOPPED":case"SLEEPING":r({status:"sleeping",load_status:"pending",message:"Space is asleep. Waking it up...",detail:a}),setTimeout(()=>{fl(t,e,r)},1e3);break;case"PAUSED":r({status:"paused",load_status:"error",message:"This space has been paused by the author. If you would like to try this demo, consider duplicating the space.",detail:a,discussions_enabled:await w$(s)});break;case"RUNNING":case"RUNNING_BUILDING":r({status:"running",load_status:"complete",message:"Space is running.",detail:a});break;case"BUILDING":r({status:"building",load_status:"pending",message:"Space is building...",detail:a}),setTimeout(()=>{fl(t,e,r)},1e3);break;case"APP_STARTING":r({status:"starting",load_status:"pending",message:"Space is starting...",detail:a}),setTimeout(()=>{fl(t,e,r)},1e3);break;default:r({status:"space_error",load_status:"error",message:"This space is experiencing an issue.",detail:a,discussions_enabled:await w$(s)});break}}var R$=async(t,e)=>{let r=0,n=12,i=5e3;return new Promise(o=>{fl(t,b0.test(t)?"space_name":"subdomain",a=>{e(a),a.status==="running"||a.status==="error"||a.status==="paused"||a.status==="space_error"?o():(a.status==="sleeping"||a.status==="building")&&(r<n?(r++,setTimeout(()=>{R$(t,e).then(o)},i)):o())})})},_X=/^(?=[^]*\b[dD]iscussions{0,1}\b)(?=[^]*\b[dD]isabled\b)[^]*$/;async function w$(t){try{let e=await fetch(`https://huggingface.co/api/spaces/${t}/discussions`,{method:"HEAD"}),r=e.headers.get("x-error-message");return!(!e.ok||r&&_X.test(r))}catch{return!1}}async function SX(t,e){let r={};e&&(r.Authorization=`Bearer ${e}`);try{let n=await fetch(`https://huggingface.co/api/spaces/${t}/${jG}`,{headers:r});if(n.status!==200)throw new Error("Space hardware could not be obtained.");let{hardware:i}=await n.json();return i.current}catch(n){throw new Error(n.message)}}async function EX(t,e,r){let n={};r&&(n.Authorization=`Bearer ${r}`);let i={seconds:e};try{let o=await fetch(`https://huggingface.co/api/spaces/${t}/${qG}`,{method:"POST",headers:{"Content-Type":"application/json",...n},body:JSON.stringify(i)});if(o.status!==200)throw new Error("Could not set sleep timeout on duplicated Space. Please visit *ADD HF LINK TO SETTINGS* to set a timeout manually to reduce billing charges.");return await o.json()}catch(o){throw new Error(o.message)}}var _$=["cpu-basic","cpu-upgrade","cpu-xl","t4-small","t4-medium","a10g-small","a10g-large","a10g-largex2","a10g-largex4","a100-large","zero-a10g","h100","h100x8"];async function kX(t,e){let{token:r,private:n,hardware:i,timeout:o,auth:a}=e;if(i&&!_$.includes(i))throw new Error(`Invalid hardware type provided. Valid types are: ${_$.map(y=>`"${y}"`).join(",")}.`);let{http_protocol:s,host:c}=await v0(t,r),l=null;if(a){let y=await A$(s,c,a,fetch);y&&(l=I$(y))}let u={Authorization:`Bearer ${r}`,"Content-Type":"application/json",...l?{Cookie:l.join("; ")}:{}},p=(await(await fetch("https://huggingface.co/api/whoami-v2",{headers:u})).json()).name,f=t.split("/")[1],h={repository:`${p}/${f}`};n&&(h.private=!0);let m;try{i||(m=await SX(t,r))}catch(y){throw Error(y0+y.message)}let g=i||m||"cpu-basic";h.hardware=g;try{let y=await fetch(`https://huggingface.co/api/spaces/${t}/duplicate`,{method:"POST",headers:u,body:JSON.stringify(h)});if(y.status===409)try{return await ss.connect(`${p}/${f}`,e)}catch(x){throw console.error("Failed to connect Client instance:",x),x}else if(y.status!==200)throw new Error(y.statusText);let v=await y.json();return await EX(`${p}/${f}`,o||300,r),await ss.connect(TX(v.url),e)}catch(y){throw new Error(y)}}function TX(t){let e=/https:\/\/huggingface.co\/spaces\/([^/]+\/[^/]+)/,r=t.match(e);if(r)return r[1]}var g0=class extends TransformStream{#e="";constructor(e={allowCR:!1}){super({transform:(r,n)=>{for(r=this.#e+r;;){let i=r.indexOf(`
|
|
210
210
|
`),o=e.allowCR?r.indexOf("\r"):-1;if(o!==-1&&o!==r.length-1&&(i===-1||i-1>o)){n.enqueue(r.slice(0,o)),r=r.slice(o+1);continue}if(i===-1)break;let a=r[i-1]==="\r"?i-1:i;n.enqueue(r.slice(0,a)),r=r.slice(i+1)}this.#e=r},flush:r=>{if(this.#e==="")return;let n=e.allowCR&&this.#e.endsWith("\r")?this.#e.slice(0,-1):this.#e;r.enqueue(n)}})}};function CX(t){let e=new TextDecoderStream,r=new g0({allowCR:!0});return t.pipeThrough(e).pipeThrough(r)}function AX(t){let r=/[:]\s*/.exec(t),n=r&&r.index;if(n)return[t.substring(0,n),t.substring(n+r[0].length)]}function S$(t,e,r){t.get(e)||t.set(e,r)}async function*IX(t,e){if(!t.body)return;let r=CX(t.body),n,i=r.getReader(),o;for(;;){if(e&&e.aborted)return i.cancel();if(n=await i.read(),n.done)return;if(!n.value){o&&(yield o),o=void 0;continue}let[a,s]=AX(n.value)||[];a==="data"?(o||={},o[a]=o[a]?o[a]+`
|
|
211
|
-
`+s:s):a==="event"?(o||={},o[a]=s):a==="id"?(o||={},o[a]=String(+s)===s?+s:s):a==="retry"&&(o||={},o[a]=+s||void 0)}}async function PX(t,e){let r=new Request(t,e);S$(r.headers,"Accept","text/event-stream"),S$(r.headers,"Content-Type","application/json");let n=await fetch(r);if(!n.ok)throw n;return IX(n,r.signal)}async function RX(){let{event_callbacks:t,unclosed_events:e,pending_stream_messages:r,stream_status:n,config:i,jwt:o}=this,a=this;if(!i)throw new Error("Could not resolve app config");n.open=!0;let s=null,c=new URLSearchParams({session_hash:this.session_hash}).toString(),l=new URL(`${i.root}${this.api_prefix}/${E$}?${c}`);if(o&&l.searchParams.set("__sign",o),s=this.stream(l),!s){console.warn("Cannot connect to SSE endpoint: "+l.toString());return}s.onmessage=async function(u){let p=JSON.parse(u.data);if(p.msg==="close_stream"){x0(n,a.abort_controller);return}let f=p.event_id;if(!f)await Promise.all(Object.keys(t).map(h=>t[h](p)));else if(t[f]&&i){p.msg==="process_completed"&&["sse","sse_v1","sse_v2","sse_v2.1","sse_v3"].includes(i.protocol)&&e.delete(f);let h=t[f];typeof window<"u"&&typeof document<"u"?setTimeout(h,0,p):h(p)}else r[f]||(r[f]=[]),r[f].push(p)},s.onerror=async function(u){console.error(u),await Promise.all(Object.keys(t).map(p=>t[p]({msg:"broken_connection",message:hl})))}}function x0(t,e){t&&(t.open=!1,e?.abort())}function $X(t,e,r){!t[e]?(t[e]=[],r.data.forEach((i,o)=>{t[e][o]=i})):r.data.forEach((i,o)=>{let a=OX(t[e][o],i);t[e][o]=a,r.data[o]=a})}function OX(t,e){return e.forEach(([r,n,i])=>{t=NX(t,n,r,i)}),t}function NX(t,e,r,n){if(e.length===0){if(r==="replace")return n;if(r==="append")return t+n;throw new Error(`Unsupported action: ${r}`)}let i=t;for(let a=0;a<e.length-1;a++)i=i[e[a]];let o=e[e.length-1];switch(r){case"replace":i[o]=n;break;case"append":i[o]+=n;break;case"add":Array.isArray(i)?i.splice(Number(o),0,n):i[o]=n;break;case"delete":Array.isArray(i)?i.splice(Number(o),1):delete i[o];break;default:throw new Error(`Unknown action: ${r}`)}return t}function MX(t,e={}){let r={close:()=>{console.warn("Method not implemented.")},onerror:null,onmessage:null,onopen:null,readyState:0,url:t.toString(),withCredentials:!1,CONNECTING:0,OPEN:1,CLOSED:2,addEventListener:()=>{throw new Error("Method not implemented.")},dispatchEvent:()=>{throw new Error("Method not implemented.")},removeEventListener:()=>{throw new Error("Method not implemented.")}};return PX(t,e).then(async n=>{r.readyState=r.OPEN;try{for await(let i of n)r.onmessage&&r.onmessage(i);r.readyState=r.CLOSED}catch(i){r.onerror&&r.onerror(i),r.readyState=r.CLOSED}}).catch(n=>{console.error(n),r.onerror&&r.onerror(n),r.readyState=r.CLOSED}),r}function DX(t,e={},r,n,i){try{let o=function(ce){(i||lf[ce.type])&&l(ce)},a=function(){for(jo=!0;jr.length>0;)jr.shift()({value:void 0,done:!0})},s=function(ce){jr.length>0?jr.shift()(ce):An.push(ce)},c=function(ce){s(FX(ce)),a()},l=function(ce){s({value:ce,done:!1})},u=function(){return An.length>0?Promise.resolve(An.shift()):new Promise(ce=>jr.push(ce))},{token:p}=this.options,{fetch:f,app_reference:h,config:m,session_hash:g,api_info:y,api_map:v,stream_status:x,pending_stream_messages:b,pending_diff_streams:_,event_callbacks:E,unclosed_events:w,post_data:T,options:A,api_prefix:P}=this,I=this;if(!y)throw new Error("No API found");if(!m)throw new Error("Could not resolve app config");let{fn_index:C,endpoint_info:D,dependency:q}=zX(y,t,v,m),V=sX(e,D),K,re=m.protocol??"ws";if(re==="ws")throw new Error("WebSocket protocol is not supported in this version");let Fe="",Ce=()=>Fe,fe=typeof t=="number"?"/predict":t,We,ut=null,nn=!1,xl={},Oi=typeof window<"u"&&typeof document<"u"?new URLSearchParams(window.location.search).toString():"",lf=A?.events?.reduce((ce,Kt)=>(ce[Kt]=!0,ce),{})||{};async function uf(){let ce={},Kt={};ce={event_id:ut},Kt={event_id:ut,session_hash:g,fn_index:C};try{if(!m)throw new Error("Could not resolve app config");"event_id"in Kt&&await f(`${m.root}${P}/${JG}`,{headers:{"Content-Type":"application/json"},method:"POST",body:JSON.stringify(Kt)}),await f(`${m.root}${P}/${UG}`,{headers:{"Content-Type":"application/json"},method:"POST",body:JSON.stringify(ce)})}catch{console.warn("The `/reset` endpoint could not be called. Subsequent endpoint results may be unreliable.")}}let pf=async ce=>{await this._resolve_heartbeat(ce)};async function wl(ce){if(!m)return;let Kt=ce.render_id;m.components=[...m.components.filter(Ct=>Ct.props.rendered_in!==Kt),...ce.components],m.dependencies=[...m.dependencies.filter(Ct=>Ct.rendered_in!==Kt),...ce.dependencies];let Gn=m.components.some(Ct=>Ct.type==="state"),tt=m.dependencies.some(Ct=>Ct.targets.some(qr=>qr[1]==="unload"));m.connect_heartbeat=Gn||tt,await pf(m),o({type:"render",data:ce,endpoint:fe,fn_index:C})}let Lo=this.handle_blob(m.root,V,D).then(async ce=>{if(We={data:Yd(ce,q,m.components,"input",!0)||[],event_data:r,fn_index:C,trigger_id:n},hX(C,m))o({type:"status",endpoint:fe,stage:"pending",queue:!1,fn_index:C,time:new Date}),T(`${m.root}${P}/run${fe.startsWith("/")?fe:`/${fe}`}${Oi?"?"+Oi:""}`,{...We,session_hash:g}).then(async([tt,Ct])=>{let qr=tt.data;Ct==200?(o({type:"data",endpoint:fe,fn_index:C,data:Yd(qr,q,m.components,"output",A.with_null_state),time:new Date,event_data:r,trigger_id:n}),tt.render_config&&await wl(tt.render_config),o({type:"status",endpoint:fe,fn_index:C,stage:"complete",eta:tt.average_duration,queue:!1,time:new Date})):o({type:"status",stage:"error",endpoint:fe,fn_index:C,message:tt.error,queue:!1,time:new Date})}).catch(tt=>{o({type:"status",stage:"error",message:tt.message,endpoint:fe,fn_index:C,queue:!1,time:new Date})});else if(re=="sse"){o({type:"status",stage:"pending",queue:!0,endpoint:fe,fn_index:C,time:new Date});var Gn=new URLSearchParams({fn_index:C.toString(),session_hash:g}).toString();let tt=new URL(`${m.root}${P}/${E$}?${Oi?Oi+"&":""}${Gn}`);if(this.jwt&&tt.searchParams.set("__sign",this.jwt),K=this.stream(tt),!K)return Promise.reject(new Error("Cannot connect to SSE endpoint: "+tt.toString()));K.onmessage=async function(Ct){let qr=JSON.parse(Ct.data),{type:Vr,status:on,data:Wt}=b$(qr,xl[C]);if(Vr==="update"&&on&&!nn)o({type:"status",endpoint:fe,fn_index:C,time:new Date,...on}),on.stage==="error"&&(K?.close(),a());else if(Vr==="data"){let[br,Xn]=await T(`${m.root}${P}/queue/data`,{...We,session_hash:g,event_id:ut});Xn!==200&&(o({type:"status",stage:"error",message:hl,queue:!0,endpoint:fe,fn_index:C,time:new Date}),K?.close(),a())}else Vr==="complete"?nn=on:Vr==="log"?o({type:"log",title:Wt.title,log:Wt.log,level:Wt.level,endpoint:fe,duration:Wt.duration,visible:Wt.visible,fn_index:C}):(Vr==="generating"||Vr==="streaming")&&o({type:"status",time:new Date,...on,stage:on?.stage,queue:!0,endpoint:fe,fn_index:C});Wt&&(o({type:"data",time:new Date,data:Yd(Wt.data,q,m.components,"output",A.with_null_state),endpoint:fe,fn_index:C,event_data:r,trigger_id:n}),nn&&(o({type:"status",time:new Date,...nn,stage:on?.stage,queue:!0,endpoint:fe,fn_index:C}),K?.close(),a()))}}else if(re=="sse_v1"||re=="sse_v2"||re=="sse_v2.1"||re=="sse_v3"){o({type:"status",stage:"pending",queue:!0,endpoint:fe,fn_index:C,time:new Date});let tt="";typeof window<"u"&&typeof document<"u"&&(tt=window?.location?.hostname);let qr=tt.includes(".dev.")?`https://moon-${tt.split(".")[1]}.dev.spaces.huggingface.tech`:"https://huggingface.co";return(typeof window<"u"&&typeof document<"u"&&window.parent!=window&&window.supports_zerogpu_headers?gX("zerogpu-headers",qr):Promise.resolve(null)).then(br=>T(`${m.root}${P}/${FG}?${Oi}`,{...We,session_hash:g},br)).then(async([br,Xn])=>{if(br.event_id&&(Fe=br.event_id),Xn===503)o({type:"status",stage:"error",message:k$,queue:!0,endpoint:fe,fn_index:C,time:new Date,visible:!0});else if(Xn===422)o({type:"status",stage:"error",message:br.detail,queue:!0,endpoint:fe,fn_index:C,code:"validation_error",time:new Date,visible:!0}),a();else if(Xn!==200)o({type:"status",stage:"error",broken:!1,message:br.detail,queue:!0,endpoint:fe,fn_index:C,time:new Date,visible:!0});else{ut=br.event_id,Fe=ut;let In=async function(Pn){try{let{type:ur,status:pr,data:Br,original_msg:h2}=b$(Pn,xl[C]);if(ur=="heartbeat")return;if(ur==="update"&&pr&&!nn)o({type:"status",endpoint:fe,fn_index:C,time:new Date,original_msg:h2,...pr});else if(ur==="complete")nn=pr;else if(ur=="unexpected_error"||ur=="broken_connection"){console.error("Unexpected error",pr?.message);let g2=ur==="broken_connection";o({type:"status",stage:"error",message:pr?.message||"An Unexpected Error Occurred!",queue:!0,endpoint:fe,broken:g2,session_not_found:pr?.session_not_found,fn_index:C,time:new Date})}else if(ur==="log"){o({type:"log",title:Br.title,log:Br.log,level:Br.level,endpoint:fe,duration:Br.duration,visible:Br.visible,fn_index:C});return}else(ur==="generating"||ur==="streaming")&&(o({type:"status",time:new Date,...pr,stage:pr?.stage,queue:!0,endpoint:fe,fn_index:C}),Br&&q.connection!=="stream"&&["sse_v2","sse_v2.1","sse_v3"].includes(re)&&$X(_,ut,Br));Br&&(o({type:"data",time:new Date,data:Yd(Br.data,q,m.components,"output",A.with_null_state),endpoint:fe,fn_index:C}),Br.render_config&&await wl(Br.render_config),nn&&(o({type:"status",time:new Date,...nn,stage:pr?.stage,queue:!0,endpoint:fe,fn_index:C}),a())),(pr?.stage==="complete"||pr?.stage==="error")&&(E[ut]&&delete E[ut],ut in _&&delete _[ut])}catch(ur){console.error("Unexpected client exception",ur),o({type:"status",stage:"error",message:"An Unexpected Error Occurred!",queue:!0,endpoint:fe,fn_index:C,time:new Date}),["sse_v2","sse_v2.1","sse_v3"].includes(re)&&(x0(x,I.abort_controller),x.open=!1,a())}};ut in b&&(b[ut].forEach(Pn=>In(Pn)),delete b[ut]),E[ut]=In,w.add(ut),x.open||await this.open_stream()}})}}),jo=!1,An=[],jr=[],ms={[Symbol.asyncIterator]:()=>ms,next:u,throw:async ce=>(c(ce),u()),return:async()=>(a(),{value:void 0,done:!0}),cancel:uf,send_chunk:ce=>{this.post_data(`${m.root}${P}/stream/${Fe}`,{...ce,session_hash:this.session_hash})},close_stream:()=>{this.post_data(`${m.root}${P}/stream/${Fe}/close`,{}),a()},event_id:()=>Fe,wait_for_id:async()=>(await Lo,ut)};return ms}catch(o){throw console.error("Submit function encountered an error:",o),o}}function FX(t){return{then:(e,r)=>r(t)}}function zX(t,e,r,n){let i,o,a;if(typeof e=="number")i=e,o=t.unnamed_endpoints[i],a=n.dependencies.find(s=>s.id==e);else{let s=e.replace(/^\//,"");i=r[s],o=t.named_endpoints[e.trim()],a=n.dependencies.find(c=>c.id==r[s])}if(typeof i!="number")throw new Error("There is no endpoint matching that name of fn_index matching that number.");return{fn_index:i,endpoint_info:o,dependency:a}}var ss=class{app_reference;options;deep_link=null;config;api_prefix="";api_info;api_map={};session_hash=Math.random().toString(36).substring(2);jwt=!1;last_status={};cookies=null;stream_status={open:!1};closed=!1;pending_stream_messages={};pending_diff_streams={};event_callbacks={};unclosed_events=new Set;heartbeat_event=null;abort_controller=null;stream_instance=null;current_payload;get_url_config(e=null){if(!this.config)throw new Error(Ri);e===null&&(e=window.location.href);let r=a=>a.replace(/^\/+|\/+$/g,""),n=r(new URL(this.config.root).pathname),i=r(new URL(e).pathname),o;return i.startsWith(n)?o=r(i.substring(n.length)):o="",this.get_page_config(o)}get_page_config(e){if(!this.config)throw new Error(Ri);let r=this.config;return e in r.page||(e=""),{...r,current_page:e,layout:r.page[e].layout,components:r.components.filter(n=>r.page[e].components.includes(n.id)),dependencies:this.config.dependencies.filter(n=>r.page[e].dependencies.includes(n.id))}}fetch(e,r){let n=new Headers(r?.headers||{});if(this&&this.cookies&&n.append("Cookie",this.cookies),this&&this.options.headers)for(let i in this.options.headers)n.append(i,this.options.headers[i]);return fetch(e,{...r,headers:n})}stream(e){let r=new Headers;if(this&&this.cookies&&r.append("Cookie",this.cookies),this&&this.options.headers)for(let n in this.options.headers)r.append(n,this.options.headers[n]);return this&&this.options.token&&r.append("Authorization",`Bearer ${this.options.token}`),this.abort_controller=new AbortController,this.stream_instance=MX(e.toString(),{credentials:"include",headers:r,signal:this.abort_controller.signal}),this.stream_instance}view_api;upload_files;upload;handle_blob;post_data;submit;predict;open_stream;resolve_config;resolve_cookies;constructor(e,r={events:["data"]}){this.app_reference=e,this.deep_link=r.query_params?.deep_link||null,r.events||(r.events=["data"]),this.options=r,this.current_payload={},this.view_api=cX.bind(this),this.upload_files=lX.bind(this),this.handle_blob=yX.bind(this),this.post_data=xX.bind(this),this.submit=DX.bind(this),this.predict=wX.bind(this),this.open_stream=RX.bind(this),this.resolve_config=tX.bind(this),this.resolve_cookies=rX.bind(this),this.upload=mX.bind(this),this.fetch=this.fetch.bind(this),this.handle_space_success=this.handle_space_success.bind(this),this.stream=this.stream.bind(this)}async init(){this.options.auth&&await this.resolve_cookies(),await this._resolve_config().then(({config:e})=>this._resolve_heartbeat(e)),this.api_info=await this.view_api(),this.api_map=eX(this.config?.dependencies||[])}async _resolve_heartbeat(e){if(e&&(this.config=e,this.api_prefix=e.api_prefix||"",this.config&&this.config.connect_heartbeat&&this.config.space_id&&this.options.token&&(this.jwt=await g$(this.config.space_id,this.options.token,this.cookies))),e.space_id&&this.options.token&&(this.jwt=await g$(e.space_id,this.options.token)),this.config&&this.config.connect_heartbeat){let r=new URL(`${this.config.root}${this.api_prefix}/${VG}/${this.session_hash}`);this.jwt&&r.searchParams.set("__sign",this.jwt),this.heartbeat_event||(this.heartbeat_event=this.stream(r))}}static async connect(e,r={events:["data"]}){let n=new this(e,r);return r.session_hash&&(n.session_hash=r.session_hash),await n.init(),n}async reconnect(){let e=new URL(`${this.config.root}${this.api_prefix}/${HG}`),r;try{let n=await this.fetch(e);if(!n.ok)throw new Error;r=(await n.json()).app_id}catch{return"broken"}return r!==this.config.app_id?"changed":"connected"}close(){this.closed=!0,x0(this.stream_status,this.abort_controller)}set_current_payload(e){this.current_payload=e}static async duplicate(e,r={events:["data"]}){return kX(e,r)}async _resolve_config(){let{http_protocol:e,host:r,space_id:n}=await v0(this.app_reference,this.options.token),{status_callback:i}=this.options;n&&i&&await R$(n,i);let o;try{let a=`${e}//${r}`;if(o=await this.resolve_config(a),!o)throw new Error(Ri);return this.config_success(o)}catch(a){if(n&&i)fl(n,b0.test(n)?"space_name":"subdomain",this.handle_space_success);else throw i&&i({status:"error",message:"Could not load this space.",load_status:"error",detail:"NOT_FOUND"}),Error(a)}}async config_success(e){if(this.config=e,this.api_prefix=e.api_prefix||"",this.config.auth_required)return this.prepare_return_obj();try{this.api_info=await this.view_api()}catch(r){console.error(KG+r.message)}return this.prepare_return_obj()}async handle_space_success(e){if(!this)throw new Error(Ri);let{status_callback:r}=this.options;if(r&&r(e),e.status==="running")try{if(this.config=await this._resolve_config(),this.api_prefix=this?.config?.api_prefix||"",!this.config)throw new Error(Ri);return await this.config_success(this.config)}catch(n){throw r&&r({status:"error",message:"Could not load this space.",load_status:"error",detail:"NOT_FOUND"}),n}}async component_server(e,r,n){if(!this.config)throw new Error(Ri);let i={},{token:o}=this.options,{session_hash:a}=this;o&&(i.Authorization=`Bearer ${this.options.token}`);let s,c=this.config.components.find(u=>u.id===e);c?.props?.root_url?s=c.props.root_url:s=this.config.root;let l;if("binary"in n){l=new FormData;for(let u in n.data)u!=="binary"&&l.append(u,n.data[u]);l.set("component_id",e.toString()),l.set("fn_name",r),l.set("session_hash",a)}else l=JSON.stringify({data:n,component_id:e,fn_name:r,session_hash:a}),i["Content-Type"]="application/json";o&&(i.Authorization=`Bearer ${o}`);try{let u=await this.fetch(`${s}${this.api_prefix}/${BG}/`,{method:"POST",body:l,headers:i,credentials:"include"});if(!u.ok)throw new Error("Could not connect to component server: "+u.statusText);return await u.json()}catch(u){console.warn(u)}}set_cookies(e){this.cookies=I$(e).join("; ")}prepare_return_obj(){return{config:this.config,predict:this.predict,submit:this.submit,view_api:this.view_api,component_server:this.component_server}}};var _0=ke(require("node:crypto"),1),$i=ke(require("node:fs"),1),D$=ke(require("node:os"),1),cs=ke(require("node:path"),1),$$="MiniMaxAI/MiniMax-Music3",O$="https://minimaxai-minimax-music3.hf.space",N$=32*1024*1024;function F$(t){let e=String(t?.Msg||"");return t?.Code!==1&&/\b410\b/u.test(e)&&/Music API is no longer available to new users/iu.test(e)&&/MiniMax-Music3/iu.test(e)}function LX(t){let e=String(t||"").trim();return{mode:"studio",description:e,instrumental:!0,title:"Microi Original Game Music",lyrics:"[instrumental]",global_meta:["Premium original game soundtrack, 44.1 kHz stereo master.","Clear theme, polished transients, controlled low end, wide but mono-compatible image.","Designed for a seamless gameplay loop and long listening without fatigue."].join(" "),vocals:"Instrumental only. No singing, spoken words, chants, or vocal samples.",arrangement:`${e} Start the musical hook within two seconds. Use clear eight-bar sections, purposeful transitions, and an ending tail that can crossfade seamlessly into the opening.`}}function M$(t){return _0.default.createHash("sha256").update(t,"utf8").digest("hex")}function w0(t,e){let r=`${t}.${process.pid}.tmp`;$i.default.writeFileSync(r,`${JSON.stringify(e,null,2)}
|
|
212
|
-
`,{encoding:"utf8",flag:"w"}),$i.default.renameSync(r,t)}function jX(t){try{return JSON.parse($i.default.readFileSync(t,"utf8"))}catch{return}}function qX(t){if(typeof t=="string")return t;if(!t||typeof t!="object")return"";let e=t.url;return typeof e=="string"?e:""}function VX(t){return t.length>=12&&t.subarray(0,4).toString("ascii")==="RIFF"&&t.subarray(8,12).toString("ascii")==="WAVE"}function BX(t){if(t instanceof Error&&t.message)return t.message;if(t&&typeof t=="object")try{let e=JSON.stringify(t);if(e&&e!=="{}")return e}catch{}return String(t)}async function z$(t,e){let r=Math.max(10,Math.min(60,Math.trunc(e.durationSeconds||20))),n=M$(JSON.stringify({requestId:e.requestId,prompt:e.prompt.trim(),durationSeconds:r,model:$$})),i=cs.default.resolve(e.stateDirectory||process.env.MICROI_MCP_STATE_DIR||cs.default.join(D$.default.homedir(),".microi-mcp")),o=cs.default.join(i,"minimax-music3");$i.default.mkdirSync(o,{recursive:!0});let a=M$(`${e.apiBaseUrl}|${e.osClient}|${e.requestId}`),s=cs.default.join(o,`${a}.json`),c=cs.default.join(o,`${a}.lock`),l=jX(s);if(l)return l.Fingerprint!==n?{Code:0,Data:{},Msg:"\u76F8\u540C RequestId \u5DF2\u7528\u4E8E\u53E6\u4E00\u7EC4 MiniMax-Music3 \u53C2\u6570\uFF0C\u8BF7\u6362\u65B0 RequestId\u3002"}:l.State==="Succeeded"&&l.Result?{Code:1,Data:{...l.Result,Replayed:!0},Msg:"\u5DF2\u8FD4\u56DE\u672C\u673A MCP \u5E42\u7B49\u8BB0\u5F55\u4E2D\u7684 MiniMax-Music3 \u97F3\u4E50\u3002"}:{Code:2,Data:{Status:l.State},Msg:l.Error||"\u540C\u4E00 RequestId \u6B63\u5728\u751F\u6210\u6216\u7ED3\u679C\u4E0D\u786E\u5B9A\uFF0C\u672A\u91CD\u590D\u8C03\u7528 MiniMax-Music3\u3002"};let u;try{u=$i.default.openSync(c,"wx")}catch{return{Code:2,Data:{Status:"Generating"},Msg:"\u540C\u4E00 RequestId \u6B63\u5728\u7531\u53E6\u4E00\u4E2A MCP \u8FDB\u7A0B\u751F\u6210\uFF0C\u672A\u91CD\u590D\u63D0\u4EA4\u3002"}}w0(s,{State:"Generating",Fingerprint:n,UpdatedAtUtc:new Date().toISOString()});let p=!1;try{let f=await ss.connect(O$);p=!0;let h=Number.parseInt(n.slice(0,8),16)&2147483647,m=await f.predict("/studio_generate",{state:LX(e.prompt),duration:r,seed:h,randomize_seed:!1,headroom:0,steps:30,guidance:1.7}),g=Array.isArray(m.data)?m.data:[],y=qX(g[2]),v=y?new URL(y):null;if(!v||v.protocol!=="https:"||v.port||v.hostname.toLowerCase()!==new URL(O$).hostname.toLowerCase())throw new Error("MiniMax-Music3 \u8FD4\u56DE\u7684\u6587\u4EF6\u5730\u5740\u672A\u901A\u8FC7\u5B98\u65B9 Space \u767D\u540D\u5355\u6821\u9A8C\u3002");let x=await fetch(v,{redirect:"error"});if(!x.ok)throw new Error(`MiniMax-Music3 \u6587\u4EF6\u4E0B\u8F7D\u5931\u8D25\uFF1AHTTP ${x.status}`);if(Number(x.headers.get("content-length")||0)>N$)throw new Error("MiniMax-Music3 \u97F3\u4E50\u8D85\u8FC7 MCP 32MiB \u5B89\u5168\u4E0A\u9650\u3002");let _=Buffer.from(await x.arrayBuffer());if(_.length>N$||!VX(_))throw new Error("MiniMax-Music3 \u672A\u8FD4\u56DE\u6709\u6548\u7684 WAV \u97F3\u4E50\u3002");let E=await t.uploadFileBase64({FileName:`minimax-music3-${n.slice(0,12)}.wav`,FileByteBase64:_.toString("base64"),Path:"ai-music",Limit:!1,Preview:!1});if(E.Code!==1||!E.Data||typeof E.Data!="object")throw new Error(`\u97F3\u4E50\u5DF2\u751F\u6210\u4F46 HDFS \u5199\u5165\u5931\u8D25\uFF1A${E.Msg||"unknown error"}`);let w=E.Data,T={RequestId:e.requestId,Model:$$,RequestedModel:"music-2.6",ModelFallbackUsed:!0,ModelFallbackReason:"MiniMax \u5B98\u65B9\u65E7 Music API \u5BF9\u65B0\u8D26\u53F7\u8FD4\u56DE 410\uFF0C\u6309\u5B98\u65B9\u6307\u5F15\u5207\u6362 MiniMax-Music3\u3002",Route:"MiniMax-Official-HuggingFace-Space",DurationMilliseconds:r*1e3,SampleRate:44100,Channels:2,Format:"wav",FileSize:_.length,FileSha256:_0.default.createHash("sha256").update(_).digest("hex"),Hdfs:w,Permanent:!0,Storage:"Microi.HDFS",Replayed:!1,Attribution:"MiniMax-Music3"};return w0(s,{State:"Succeeded",Fingerprint:n,Result:T,UpdatedAtUtc:new Date().toISOString()}),{Code:1,Data:T,Msg:"MiniMax-Music3 \u539F\u521B\u97F3\u4E50\u5DF2\u751F\u6210\u5E76\u5199\u5165\u5F53\u524D\u79DF\u6237\u516C\u6709 HDFS\u3002"}}catch(f){let h=BX(f);return w0(s,{State:p?"Uncertain":"Failed",Fingerprint:n,Error:p?`MiniMax-Music3 \u7ED3\u679C\u4E0D\u786E\u5B9A\uFF0C\u672A\u7528\u540C\u4E00 RequestId \u81EA\u52A8\u91CD\u8BD5\uFF1A${h}`:`MiniMax-Music3 \u63D0\u4EA4\u524D\u5931\u8D25\uFF1A${h}`,UpdatedAtUtc:new Date().toISOString()}),{Code:0,Data:{Status:p?"Uncertain":"Failed"},Msg:p?`MiniMax-Music3 \u7ED3\u679C\u4E0D\u786E\u5B9A\uFF0C\u672A\u7528\u540C\u4E00 RequestId \u81EA\u52A8\u91CD\u8BD5\uFF1A${h}`:`MiniMax-Music3 \u63D0\u4EA4\u524D\u5931\u8D25\uFF1A${h}`}}finally{u!==void 0&&$i.default.closeSync(u);try{$i.default.unlinkSync(c)}catch{}}}var S0=ke(require("node:crypto"),1),Ht=ke(require("node:fs"),1),gt=ke(require("node:path"),1),UX=/^[a-z0-9](?:[a-z0-9_-]{0,62}[a-z0-9])?$/u,JX=/^\/(?:[A-Za-z0-9][A-Za-z0-9_-]*(?:\/[A-Za-z0-9][A-Za-z0-9_-]*)*)?$/u,HX=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/u,ZX=/^v\d+\.\d+\.\d+$/u,KX="3.5.40",WX="7.3.6",GX="6.0.8",XX="5.9.3",YX="3.3.9";function QX(t){if(!t||!gt.default.isAbsolute(t))throw new Error("AI \u5E94\u7528\u76EE\u5F55\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002");let e=gt.default.resolve(t);if(gt.default.basename(e)!=="AI\u5E94\u7528")throw new Error(`\u672C\u5730\u811A\u624B\u67B6\u53EA\u80FD\u5199\u5165\u540D\u4E3A\u201CAI\u5E94\u7528\u201D\u7684\u76EE\u5F55\uFF1A${e}`);let r=Ht.default.lstatSync(e);if(!r.isDirectory()||r.isSymbolicLink())throw new Error(`AI \u5E94\u7528\u76EE\u5F55\u5FC5\u987B\u662F\u771F\u5B9E\u76EE\u5F55\u4E14\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5\uFF1A${e}`);return Ht.default.realpathSync(e)}function eY(t){let e=String(t||"v0.1.0").trim();if(!ZX.test(e))throw new Error(`buildVersion \u5FC5\u987B\u662F v1.2.3 \u5F62\u5F0F\uFF1A${t}`);return e}function tY(t){let e=t.split(/[-_]+/u).filter(Boolean).map(r=>r.charAt(0).toUpperCase()+r.slice(1)).join("").replace(/[^A-Za-z0-9]/gu,"");if(!e||!/^[A-Za-z]/u.test(e))throw new Error(`\u8DEF\u7531 name \u65E0\u6CD5\u751F\u6210\u5B89\u5168\u7684 Vue \u7EC4\u4EF6\u540D\uFF1A${t}`);return e}function rY(t){if(!Array.isArray(t)||t.length<1||t.length>50)throw new Error("routes \u6570\u91CF\u5FC5\u987B\u5728 1 \u5230 50 \u4E4B\u95F4\u3002");let e=new Set,r=new Set,n=new Set,i=t.filter(o=>o.isHome===!0);if(i.length>1)throw new Error("routes \u6700\u591A\u53EA\u80FD\u6709\u4E00\u4E2A isHome=true\u3002");return t.map((o,a)=>{let s=String(o.path||"").trim(),c=String(o.name||"").trim(),l=String(o.title||"").trim();if(!JX.test(s)||s.includes(".."))throw new Error(`\u8DEF\u7531 path \u4E0D\u5408\u6CD5\uFF1A${o.path}`);if(!HX.test(c))throw new Error(`\u8DEF\u7531 name \u4E0D\u5408\u6CD5\uFF1A${o.name}`);if(!l||l.length>100)throw new Error(`\u8DEF\u7531 title \u4E0D\u80FD\u4E3A\u7A7A\u4E14\u4E0D\u80FD\u8D85\u8FC7 100 \u4E2A\u5B57\u7B26\uFF1A${o.title}`);let u=s.toLowerCase(),p=c.toLowerCase();if(e.has(u))throw new Error(`\u8DEF\u7531 path \u91CD\u590D\uFF1A${s}`);if(r.has(p))throw new Error(`\u8DEF\u7531 name \u91CD\u590D\uFF1A${c}`);e.add(u),r.add(p);let f=`src/pages/${tY(c)}Page.vue`;if(n.has(f.toLowerCase()))throw new Error(`\u8DEF\u7531\u9875\u9762\u6587\u4EF6\u540D\u91CD\u590D\uFF1A${f}`);return n.add(f.toLowerCase()),{path:s,name:c,title:l,description:String(o.description||"").trim(),sourceFile:f,sort:a*10,isHome:i.length>0?o.isHome===!0:a===0}})}function nY(){return["function createClient(initial = {}) {",' const readStoredToken = () => { try { return localStorage.getItem("Token") || localStorage.getItem("authorization") || "" } catch { return "" } }',' const storeToken = (token) => { try { localStorage.setItem("Token", token); localStorage.setItem("authorization", token) } catch {} }',' let config = { apiBase: "", osClient: "", token: readStoredToken(), ...(initial || {}) }'," const configure = (next = {}) => { config = { ...config, ...(next || {}) }; return client }"," const getConfig = () => ({ ...config })"," const setToken = (token) => {",' const previousToken = String(config.token || "")',' config.token = String(token || "")'," storeToken(config.token)",' if (config.token !== previousToken && typeof config.onTokenChanged === "function") config.onTokenChanged(config.token, previousToken, client)'," return client"," }",' const clearToken = () => setToken("")'," const getToken = () => String(config.token || readStoredToken())"," async function post(url, data = {}) {",' const target = /^https?:\\/\\//i.test(url) ? url : String(config.apiBase || "").replace(/\\/+$/, "") + "/" + String(url || "").replace(/^\\/+/, "")',' const headers = { "Content-Type": "application/json", osclient: config.osClient || "" }'," const requestToken = getToken()",' if (requestToken) headers.Authorization = "Bearer " + requestToken',' const response = await fetch(target, { method: "POST", headers, body: JSON.stringify(data || {}) })'," const body = await response.json()",' const responseToken = response.headers.get("authorization") || response.headers.get("token") || body?.DataAppend?.Token || body?.Data?.Token || body?.Token || ""',' const normalizedToken = String(responseToken || "").replace(/^Bearer\\s+/i, "")'," if (normalizedToken && (!requestToken || getToken() === requestToken)) setToken(normalizedToken)"," if ([401, -1, 1001, 1002].includes(Number(body?.Code)) && (!requestToken || getToken() === requestToken)) {"," clearToken()",' if (typeof config.onAuthExpired === "function") config.onAuthExpired(body, client)'," }"," return body"," }"," const install = (app) => {"," if (app?.config?.globalProperties) app.config.globalProperties.$V8 = client",' if (typeof app?.provide === "function") app.provide("MicroiV8", client)'," return client"," }"," const client = {"," configure, getConfig, setToken, clearToken, getToken, GetToken: getToken, post, install,",' GetSysConfig: async () => { const result = await post("/api/DiyTable/getSysConfig", { OsClient: config.osClient, _SearchEqual: { IsEnable: 1 } }); return result?.Code === 1 ? (result.Data || {}) : null },',' Login: (data = {}) => post("/api/SysUser/login", { _ClientType: "PC", ...(data || {}) }),',' ApiEngine: { Run: (key, data = {}) => post("/apiengine/" + encodeURIComponent(key), data) },',' FormEngine: { GetTableData: (table, data = {}) => post("/api/FormEngine/GetTableData", { FormEngineKey: table, ...(data || {}) }) },'," }"," return client","}","export function createMicroiV8(options = {}) { return createClient(options) }","export const V8 = createMicroiV8()","export const MicroiV8 = V8","export default V8",""].join(`
|
|
211
|
+
`+s:s):a==="event"?(o||={},o[a]=s):a==="id"?(o||={},o[a]=String(+s)===s?+s:s):a==="retry"&&(o||={},o[a]=+s||void 0)}}async function PX(t,e){let r=new Request(t,e);S$(r.headers,"Accept","text/event-stream"),S$(r.headers,"Content-Type","application/json");let n=await fetch(r);if(!n.ok)throw n;return IX(n,r.signal)}async function RX(){let{event_callbacks:t,unclosed_events:e,pending_stream_messages:r,stream_status:n,config:i,jwt:o}=this,a=this;if(!i)throw new Error("Could not resolve app config");n.open=!0;let s=null,c=new URLSearchParams({session_hash:this.session_hash}).toString(),l=new URL(`${i.root}${this.api_prefix}/${E$}?${c}`);if(o&&l.searchParams.set("__sign",o),s=this.stream(l),!s){console.warn("Cannot connect to SSE endpoint: "+l.toString());return}s.onmessage=async function(u){let p=JSON.parse(u.data);if(p.msg==="close_stream"){x0(n,a.abort_controller);return}let f=p.event_id;if(!f)await Promise.all(Object.keys(t).map(h=>t[h](p)));else if(t[f]&&i){p.msg==="process_completed"&&["sse","sse_v1","sse_v2","sse_v2.1","sse_v3"].includes(i.protocol)&&e.delete(f);let h=t[f];typeof window<"u"&&typeof document<"u"?setTimeout(h,0,p):h(p)}else r[f]||(r[f]=[]),r[f].push(p)},s.onerror=async function(u){console.error(u),await Promise.all(Object.keys(t).map(p=>t[p]({msg:"broken_connection",message:hl})))}}function x0(t,e){t&&(t.open=!1,e?.abort())}function $X(t,e,r){!t[e]?(t[e]=[],r.data.forEach((i,o)=>{t[e][o]=i})):r.data.forEach((i,o)=>{let a=OX(t[e][o],i);t[e][o]=a,r.data[o]=a})}function OX(t,e){return e.forEach(([r,n,i])=>{t=NX(t,n,r,i)}),t}function NX(t,e,r,n){if(e.length===0){if(r==="replace")return n;if(r==="append")return t+n;throw new Error(`Unsupported action: ${r}`)}let i=t;for(let a=0;a<e.length-1;a++)i=i[e[a]];let o=e[e.length-1];switch(r){case"replace":i[o]=n;break;case"append":i[o]+=n;break;case"add":Array.isArray(i)?i.splice(Number(o),0,n):i[o]=n;break;case"delete":Array.isArray(i)?i.splice(Number(o),1):delete i[o];break;default:throw new Error(`Unknown action: ${r}`)}return t}function MX(t,e={}){let r={close:()=>{console.warn("Method not implemented.")},onerror:null,onmessage:null,onopen:null,readyState:0,url:t.toString(),withCredentials:!1,CONNECTING:0,OPEN:1,CLOSED:2,addEventListener:()=>{throw new Error("Method not implemented.")},dispatchEvent:()=>{throw new Error("Method not implemented.")},removeEventListener:()=>{throw new Error("Method not implemented.")}};return PX(t,e).then(async n=>{r.readyState=r.OPEN;try{for await(let i of n)r.onmessage&&r.onmessage(i);r.readyState=r.CLOSED}catch(i){r.onerror&&r.onerror(i),r.readyState=r.CLOSED}}).catch(n=>{console.error(n),r.onerror&&r.onerror(n),r.readyState=r.CLOSED}),r}function DX(t,e={},r,n,i){try{let o=function(ce){(i||lf[ce.type])&&l(ce)},a=function(){for(jo=!0;jr.length>0;)jr.shift()({value:void 0,done:!0})},s=function(ce){jr.length>0?jr.shift()(ce):An.push(ce)},c=function(ce){s(FX(ce)),a()},l=function(ce){s({value:ce,done:!1})},u=function(){return An.length>0?Promise.resolve(An.shift()):new Promise(ce=>jr.push(ce))},{token:p}=this.options,{fetch:f,app_reference:h,config:m,session_hash:g,api_info:y,api_map:v,stream_status:x,pending_stream_messages:b,pending_diff_streams:_,event_callbacks:E,unclosed_events:w,post_data:T,options:A,api_prefix:P}=this,I=this;if(!y)throw new Error("No API found");if(!m)throw new Error("Could not resolve app config");let{fn_index:C,endpoint_info:D,dependency:q}=zX(y,t,v,m),V=sX(e,D),K,re=m.protocol??"ws";if(re==="ws")throw new Error("WebSocket protocol is not supported in this version");let Fe="",Ce=()=>Fe,fe=typeof t=="number"?"/predict":t,We,ut=null,nn=!1,xl={},Oi=typeof window<"u"&&typeof document<"u"?new URLSearchParams(window.location.search).toString():"",lf=A?.events?.reduce((ce,Kt)=>(ce[Kt]=!0,ce),{})||{};async function uf(){let ce={},Kt={};ce={event_id:ut},Kt={event_id:ut,session_hash:g,fn_index:C};try{if(!m)throw new Error("Could not resolve app config");"event_id"in Kt&&await f(`${m.root}${P}/${JG}`,{headers:{"Content-Type":"application/json"},method:"POST",body:JSON.stringify(Kt)}),await f(`${m.root}${P}/${UG}`,{headers:{"Content-Type":"application/json"},method:"POST",body:JSON.stringify(ce)})}catch{console.warn("The `/reset` endpoint could not be called. Subsequent endpoint results may be unreliable.")}}let pf=async ce=>{await this._resolve_heartbeat(ce)};async function wl(ce){if(!m)return;let Kt=ce.render_id;m.components=[...m.components.filter(Ct=>Ct.props.rendered_in!==Kt),...ce.components],m.dependencies=[...m.dependencies.filter(Ct=>Ct.rendered_in!==Kt),...ce.dependencies];let Gn=m.components.some(Ct=>Ct.type==="state"),tt=m.dependencies.some(Ct=>Ct.targets.some(qr=>qr[1]==="unload"));m.connect_heartbeat=Gn||tt,await pf(m),o({type:"render",data:ce,endpoint:fe,fn_index:C})}let Lo=this.handle_blob(m.root,V,D).then(async ce=>{if(We={data:Yd(ce,q,m.components,"input",!0)||[],event_data:r,fn_index:C,trigger_id:n},hX(C,m))o({type:"status",endpoint:fe,stage:"pending",queue:!1,fn_index:C,time:new Date}),T(`${m.root}${P}/run${fe.startsWith("/")?fe:`/${fe}`}${Oi?"?"+Oi:""}`,{...We,session_hash:g}).then(async([tt,Ct])=>{let qr=tt.data;Ct==200?(o({type:"data",endpoint:fe,fn_index:C,data:Yd(qr,q,m.components,"output",A.with_null_state),time:new Date,event_data:r,trigger_id:n}),tt.render_config&&await wl(tt.render_config),o({type:"status",endpoint:fe,fn_index:C,stage:"complete",eta:tt.average_duration,queue:!1,time:new Date})):o({type:"status",stage:"error",endpoint:fe,fn_index:C,message:tt.error,queue:!1,time:new Date})}).catch(tt=>{o({type:"status",stage:"error",message:tt.message,endpoint:fe,fn_index:C,queue:!1,time:new Date})});else if(re=="sse"){o({type:"status",stage:"pending",queue:!0,endpoint:fe,fn_index:C,time:new Date});var Gn=new URLSearchParams({fn_index:C.toString(),session_hash:g}).toString();let tt=new URL(`${m.root}${P}/${E$}?${Oi?Oi+"&":""}${Gn}`);if(this.jwt&&tt.searchParams.set("__sign",this.jwt),K=this.stream(tt),!K)return Promise.reject(new Error("Cannot connect to SSE endpoint: "+tt.toString()));K.onmessage=async function(Ct){let qr=JSON.parse(Ct.data),{type:Vr,status:on,data:Wt}=b$(qr,xl[C]);if(Vr==="update"&&on&&!nn)o({type:"status",endpoint:fe,fn_index:C,time:new Date,...on}),on.stage==="error"&&(K?.close(),a());else if(Vr==="data"){let[br,Xn]=await T(`${m.root}${P}/queue/data`,{...We,session_hash:g,event_id:ut});Xn!==200&&(o({type:"status",stage:"error",message:hl,queue:!0,endpoint:fe,fn_index:C,time:new Date}),K?.close(),a())}else Vr==="complete"?nn=on:Vr==="log"?o({type:"log",title:Wt.title,log:Wt.log,level:Wt.level,endpoint:fe,duration:Wt.duration,visible:Wt.visible,fn_index:C}):(Vr==="generating"||Vr==="streaming")&&o({type:"status",time:new Date,...on,stage:on?.stage,queue:!0,endpoint:fe,fn_index:C});Wt&&(o({type:"data",time:new Date,data:Yd(Wt.data,q,m.components,"output",A.with_null_state),endpoint:fe,fn_index:C,event_data:r,trigger_id:n}),nn&&(o({type:"status",time:new Date,...nn,stage:on?.stage,queue:!0,endpoint:fe,fn_index:C}),K?.close(),a()))}}else if(re=="sse_v1"||re=="sse_v2"||re=="sse_v2.1"||re=="sse_v3"){o({type:"status",stage:"pending",queue:!0,endpoint:fe,fn_index:C,time:new Date});let tt="";typeof window<"u"&&typeof document<"u"&&(tt=window?.location?.hostname);let qr=tt.includes(".dev.")?`https://moon-${tt.split(".")[1]}.dev.spaces.huggingface.tech`:"https://huggingface.co";return(typeof window<"u"&&typeof document<"u"&&window.parent!=window&&window.supports_zerogpu_headers?gX("zerogpu-headers",qr):Promise.resolve(null)).then(br=>T(`${m.root}${P}/${FG}?${Oi}`,{...We,session_hash:g},br)).then(async([br,Xn])=>{if(br.event_id&&(Fe=br.event_id),Xn===503)o({type:"status",stage:"error",message:k$,queue:!0,endpoint:fe,fn_index:C,time:new Date,visible:!0});else if(Xn===422)o({type:"status",stage:"error",message:br.detail,queue:!0,endpoint:fe,fn_index:C,code:"validation_error",time:new Date,visible:!0}),a();else if(Xn!==200)o({type:"status",stage:"error",broken:!1,message:br.detail,queue:!0,endpoint:fe,fn_index:C,time:new Date,visible:!0});else{ut=br.event_id,Fe=ut;let In=async function(Pn){try{let{type:ur,status:pr,data:Br,original_msg:h2}=b$(Pn,xl[C]);if(ur=="heartbeat")return;if(ur==="update"&&pr&&!nn)o({type:"status",endpoint:fe,fn_index:C,time:new Date,original_msg:h2,...pr});else if(ur==="complete")nn=pr;else if(ur=="unexpected_error"||ur=="broken_connection"){console.error("Unexpected error",pr?.message);let g2=ur==="broken_connection";o({type:"status",stage:"error",message:pr?.message||"An Unexpected Error Occurred!",queue:!0,endpoint:fe,broken:g2,session_not_found:pr?.session_not_found,fn_index:C,time:new Date})}else if(ur==="log"){o({type:"log",title:Br.title,log:Br.log,level:Br.level,endpoint:fe,duration:Br.duration,visible:Br.visible,fn_index:C});return}else(ur==="generating"||ur==="streaming")&&(o({type:"status",time:new Date,...pr,stage:pr?.stage,queue:!0,endpoint:fe,fn_index:C}),Br&&q.connection!=="stream"&&["sse_v2","sse_v2.1","sse_v3"].includes(re)&&$X(_,ut,Br));Br&&(o({type:"data",time:new Date,data:Yd(Br.data,q,m.components,"output",A.with_null_state),endpoint:fe,fn_index:C}),Br.render_config&&await wl(Br.render_config),nn&&(o({type:"status",time:new Date,...nn,stage:pr?.stage,queue:!0,endpoint:fe,fn_index:C}),a())),(pr?.stage==="complete"||pr?.stage==="error")&&(E[ut]&&delete E[ut],ut in _&&delete _[ut])}catch(ur){console.error("Unexpected client exception",ur),o({type:"status",stage:"error",message:"An Unexpected Error Occurred!",queue:!0,endpoint:fe,fn_index:C,time:new Date}),["sse_v2","sse_v2.1","sse_v3"].includes(re)&&(x0(x,I.abort_controller),x.open=!1,a())}};ut in b&&(b[ut].forEach(Pn=>In(Pn)),delete b[ut]),E[ut]=In,w.add(ut),x.open||await this.open_stream()}})}}),jo=!1,An=[],jr=[],ms={[Symbol.asyncIterator]:()=>ms,next:u,throw:async ce=>(c(ce),u()),return:async()=>(a(),{value:void 0,done:!0}),cancel:uf,send_chunk:ce=>{this.post_data(`${m.root}${P}/stream/${Fe}`,{...ce,session_hash:this.session_hash})},close_stream:()=>{this.post_data(`${m.root}${P}/stream/${Fe}/close`,{}),a()},event_id:()=>Fe,wait_for_id:async()=>(await Lo,ut)};return ms}catch(o){throw console.error("Submit function encountered an error:",o),o}}function FX(t){return{then:(e,r)=>r(t)}}function zX(t,e,r,n){let i,o,a;if(typeof e=="number")i=e,o=t.unnamed_endpoints[i],a=n.dependencies.find(s=>s.id==e);else{let s=e.replace(/^\//,"");i=r[s],o=t.named_endpoints[e.trim()],a=n.dependencies.find(c=>c.id==r[s])}if(typeof i!="number")throw new Error("There is no endpoint matching that name of fn_index matching that number.");return{fn_index:i,endpoint_info:o,dependency:a}}var ss=class{app_reference;options;deep_link=null;config;api_prefix="";api_info;api_map={};session_hash=Math.random().toString(36).substring(2);jwt=!1;last_status={};cookies=null;stream_status={open:!1};closed=!1;pending_stream_messages={};pending_diff_streams={};event_callbacks={};unclosed_events=new Set;heartbeat_event=null;abort_controller=null;stream_instance=null;current_payload;get_url_config(e=null){if(!this.config)throw new Error(Ri);e===null&&(e=window.location.href);let r=a=>a.replace(/^\/+|\/+$/g,""),n=r(new URL(this.config.root).pathname),i=r(new URL(e).pathname),o;return i.startsWith(n)?o=r(i.substring(n.length)):o="",this.get_page_config(o)}get_page_config(e){if(!this.config)throw new Error(Ri);let r=this.config;return e in r.page||(e=""),{...r,current_page:e,layout:r.page[e].layout,components:r.components.filter(n=>r.page[e].components.includes(n.id)),dependencies:this.config.dependencies.filter(n=>r.page[e].dependencies.includes(n.id))}}fetch(e,r){let n=new Headers(r?.headers||{});if(this&&this.cookies&&n.append("Cookie",this.cookies),this&&this.options.headers)for(let i in this.options.headers)n.append(i,this.options.headers[i]);return fetch(e,{...r,headers:n})}stream(e){let r=new Headers;if(this&&this.cookies&&r.append("Cookie",this.cookies),this&&this.options.headers)for(let n in this.options.headers)r.append(n,this.options.headers[n]);return this&&this.options.token&&r.append("Authorization",`Bearer ${this.options.token}`),this.abort_controller=new AbortController,this.stream_instance=MX(e.toString(),{credentials:"include",headers:r,signal:this.abort_controller.signal}),this.stream_instance}view_api;upload_files;upload;handle_blob;post_data;submit;predict;open_stream;resolve_config;resolve_cookies;constructor(e,r={events:["data"]}){this.app_reference=e,this.deep_link=r.query_params?.deep_link||null,r.events||(r.events=["data"]),this.options=r,this.current_payload={},this.view_api=cX.bind(this),this.upload_files=lX.bind(this),this.handle_blob=yX.bind(this),this.post_data=xX.bind(this),this.submit=DX.bind(this),this.predict=wX.bind(this),this.open_stream=RX.bind(this),this.resolve_config=tX.bind(this),this.resolve_cookies=rX.bind(this),this.upload=mX.bind(this),this.fetch=this.fetch.bind(this),this.handle_space_success=this.handle_space_success.bind(this),this.stream=this.stream.bind(this)}async init(){this.options.auth&&await this.resolve_cookies(),await this._resolve_config().then(({config:e})=>this._resolve_heartbeat(e)),this.api_info=await this.view_api(),this.api_map=eX(this.config?.dependencies||[])}async _resolve_heartbeat(e){if(e&&(this.config=e,this.api_prefix=e.api_prefix||"",this.config&&this.config.connect_heartbeat&&this.config.space_id&&this.options.token&&(this.jwt=await g$(this.config.space_id,this.options.token,this.cookies))),e.space_id&&this.options.token&&(this.jwt=await g$(e.space_id,this.options.token)),this.config&&this.config.connect_heartbeat){let r=new URL(`${this.config.root}${this.api_prefix}/${VG}/${this.session_hash}`);this.jwt&&r.searchParams.set("__sign",this.jwt),this.heartbeat_event||(this.heartbeat_event=this.stream(r))}}static async connect(e,r={events:["data"]}){let n=new this(e,r);return r.session_hash&&(n.session_hash=r.session_hash),await n.init(),n}async reconnect(){let e=new URL(`${this.config.root}${this.api_prefix}/${HG}`),r;try{let n=await this.fetch(e);if(!n.ok)throw new Error;r=(await n.json()).app_id}catch{return"broken"}return r!==this.config.app_id?"changed":"connected"}close(){this.closed=!0,x0(this.stream_status,this.abort_controller)}set_current_payload(e){this.current_payload=e}static async duplicate(e,r={events:["data"]}){return kX(e,r)}async _resolve_config(){let{http_protocol:e,host:r,space_id:n}=await v0(this.app_reference,this.options.token),{status_callback:i}=this.options;n&&i&&await R$(n,i);let o;try{let a=`${e}//${r}`;if(o=await this.resolve_config(a),!o)throw new Error(Ri);return this.config_success(o)}catch(a){if(n&&i)fl(n,b0.test(n)?"space_name":"subdomain",this.handle_space_success);else throw i&&i({status:"error",message:"Could not load this space.",load_status:"error",detail:"NOT_FOUND"}),Error(a)}}async config_success(e){if(this.config=e,this.api_prefix=e.api_prefix||"",this.config.auth_required)return this.prepare_return_obj();try{this.api_info=await this.view_api()}catch(r){console.error(KG+r.message)}return this.prepare_return_obj()}async handle_space_success(e){if(!this)throw new Error(Ri);let{status_callback:r}=this.options;if(r&&r(e),e.status==="running")try{if(this.config=await this._resolve_config(),this.api_prefix=this?.config?.api_prefix||"",!this.config)throw new Error(Ri);return await this.config_success(this.config)}catch(n){throw r&&r({status:"error",message:"Could not load this space.",load_status:"error",detail:"NOT_FOUND"}),n}}async component_server(e,r,n){if(!this.config)throw new Error(Ri);let i={},{token:o}=this.options,{session_hash:a}=this;o&&(i.Authorization=`Bearer ${this.options.token}`);let s,c=this.config.components.find(u=>u.id===e);c?.props?.root_url?s=c.props.root_url:s=this.config.root;let l;if("binary"in n){l=new FormData;for(let u in n.data)u!=="binary"&&l.append(u,n.data[u]);l.set("component_id",e.toString()),l.set("fn_name",r),l.set("session_hash",a)}else l=JSON.stringify({data:n,component_id:e,fn_name:r,session_hash:a}),i["Content-Type"]="application/json";o&&(i.Authorization=`Bearer ${o}`);try{let u=await this.fetch(`${s}${this.api_prefix}/${BG}/`,{method:"POST",body:l,headers:i,credentials:"include"});if(!u.ok)throw new Error("Could not connect to component server: "+u.statusText);return await u.json()}catch(u){console.warn(u)}}set_cookies(e){this.cookies=I$(e).join("; ")}prepare_return_obj(){return{config:this.config,predict:this.predict,submit:this.submit,view_api:this.view_api,component_server:this.component_server}}};var _0=ke(require("node:crypto"),1),$i=ke(require("node:fs"),1),D$=ke(require("node:os"),1),cs=ke(require("node:path"),1),$$="MiniMaxAI/MiniMax-Music3",O$="https://minimaxai-minimax-music3.hf.space",N$=32*1024*1024;function F$(t){let e=String(t?.Msg||"");return t?.Code!==1&&/\b410\b/u.test(e)&&/Music API is no longer available to new users/iu.test(e)}function LX(t){let e=String(t||"").trim();return{mode:"studio",description:e,instrumental:!0,title:"Microi Original Game Music",lyrics:"[instrumental]",global_meta:["Premium original game soundtrack, 44.1 kHz stereo master.","Clear theme, polished transients, controlled low end, wide but mono-compatible image.","Designed for a seamless gameplay loop and long listening without fatigue."].join(" "),vocals:"Instrumental only. No singing, spoken words, chants, or vocal samples.",arrangement:`${e} Start the musical hook within two seconds. Use clear eight-bar sections, purposeful transitions, and an ending tail that can crossfade seamlessly into the opening.`}}function M$(t){return _0.default.createHash("sha256").update(t,"utf8").digest("hex")}function w0(t,e){let r=`${t}.${process.pid}.tmp`;$i.default.writeFileSync(r,`${JSON.stringify(e,null,2)}
|
|
212
|
+
`,{encoding:"utf8",flag:"w"}),$i.default.renameSync(r,t)}function jX(t){try{return JSON.parse($i.default.readFileSync(t,"utf8"))}catch{return}}function qX(t){if(typeof t=="string")return t;if(!t||typeof t!="object")return"";let e=t.url;return typeof e=="string"?e:""}function VX(t){return t.length>=12&&t.subarray(0,4).toString("ascii")==="RIFF"&&t.subarray(8,12).toString("ascii")==="WAVE"}function BX(t){if(t instanceof Error&&t.message)return t.message;if(t&&typeof t=="object")try{let e=JSON.stringify(t);if(e&&e!=="{}")return e}catch{}return String(t)}async function z$(t,e){let r=Math.max(10,Math.min(60,Math.trunc(e.durationSeconds||20))),n=M$(JSON.stringify({requestId:e.requestId,prompt:e.prompt.trim(),durationSeconds:r,model:$$})),i=cs.default.resolve(e.stateDirectory||process.env.MICROI_MCP_STATE_DIR||cs.default.join(D$.default.homedir(),".microi-mcp")),o=cs.default.join(i,"minimax-music3");$i.default.mkdirSync(o,{recursive:!0});let a=M$(`${e.apiBaseUrl}|${e.osClient}|${e.requestId}`),s=cs.default.join(o,`${a}.json`),c=cs.default.join(o,`${a}.lock`),l=jX(s);if(l)return l.Fingerprint!==n?{Code:0,Data:{},Msg:"\u76F8\u540C RequestId \u5DF2\u7528\u4E8E\u53E6\u4E00\u7EC4 MiniMax-Music3 \u53C2\u6570\uFF0C\u8BF7\u6362\u65B0 RequestId\u3002"}:l.State==="Succeeded"&&l.Result?{Code:1,Data:{...l.Result,Replayed:!0},Msg:"\u5DF2\u8FD4\u56DE\u672C\u673A MCP \u5E42\u7B49\u8BB0\u5F55\u4E2D\u7684 MiniMax-Music3 \u97F3\u4E50\u3002"}:{Code:2,Data:{Status:l.State},Msg:l.Error||"\u540C\u4E00 RequestId \u6B63\u5728\u751F\u6210\u6216\u7ED3\u679C\u4E0D\u786E\u5B9A\uFF0C\u672A\u91CD\u590D\u8C03\u7528 MiniMax-Music3\u3002"};let u;try{u=$i.default.openSync(c,"wx")}catch{return{Code:2,Data:{Status:"Generating"},Msg:"\u540C\u4E00 RequestId \u6B63\u5728\u7531\u53E6\u4E00\u4E2A MCP \u8FDB\u7A0B\u751F\u6210\uFF0C\u672A\u91CD\u590D\u63D0\u4EA4\u3002"}}w0(s,{State:"Generating",Fingerprint:n,UpdatedAtUtc:new Date().toISOString()});let p=!1;try{let f=await ss.connect(O$);p=!0;let h=Number.parseInt(n.slice(0,8),16)&2147483647,m=await f.predict("/studio_generate",{state:LX(e.prompt),duration:r,seed:h,randomize_seed:!1,headroom:0,steps:30,guidance:1.7}),g=Array.isArray(m.data)?m.data:[],y=qX(g[2]),v=y?new URL(y):null;if(!v||v.protocol!=="https:"||v.port||v.hostname.toLowerCase()!==new URL(O$).hostname.toLowerCase())throw new Error("MiniMax-Music3 \u8FD4\u56DE\u7684\u6587\u4EF6\u5730\u5740\u672A\u901A\u8FC7\u5B98\u65B9 Space \u767D\u540D\u5355\u6821\u9A8C\u3002");let x=await fetch(v,{redirect:"error"});if(!x.ok)throw new Error(`MiniMax-Music3 \u6587\u4EF6\u4E0B\u8F7D\u5931\u8D25\uFF1AHTTP ${x.status}`);if(Number(x.headers.get("content-length")||0)>N$)throw new Error("MiniMax-Music3 \u97F3\u4E50\u8D85\u8FC7 MCP 32MiB \u5B89\u5168\u4E0A\u9650\u3002");let _=Buffer.from(await x.arrayBuffer());if(_.length>N$||!VX(_))throw new Error("MiniMax-Music3 \u672A\u8FD4\u56DE\u6709\u6548\u7684 WAV \u97F3\u4E50\u3002");let E=await t.uploadFileBase64({FileName:`minimax-music3-${n.slice(0,12)}.wav`,FileByteBase64:_.toString("base64"),Path:"ai-music",Limit:!1,Preview:!1});if(E.Code!==1||!E.Data||typeof E.Data!="object")throw new Error(`\u97F3\u4E50\u5DF2\u751F\u6210\u4F46 HDFS \u5199\u5165\u5931\u8D25\uFF1A${E.Msg||"unknown error"}`);let w=E.Data,T={RequestId:e.requestId,Model:$$,RequestedModel:"music-3.0",ModelFallbackUsed:!0,ModelFallbackReason:"MiniMax \u6258\u7BA1 Music API \u8FD4\u56DE\u660E\u786E 410\uFF0C\u6309\u5B98\u65B9\u6307\u5F15\u5207\u6362\u5F00\u6E90 MiniMax-Music3\u3002",Route:"MiniMax-Official-HuggingFace-Space",DurationMilliseconds:r*1e3,SampleRate:44100,Channels:2,Format:"wav",FileSize:_.length,FileSha256:_0.default.createHash("sha256").update(_).digest("hex"),Hdfs:w,Permanent:!0,Storage:"Microi.HDFS",Replayed:!1,Attribution:"MiniMax-Music3"};return w0(s,{State:"Succeeded",Fingerprint:n,Result:T,UpdatedAtUtc:new Date().toISOString()}),{Code:1,Data:T,Msg:"MiniMax-Music3 \u539F\u521B\u97F3\u4E50\u5DF2\u751F\u6210\u5E76\u5199\u5165\u5F53\u524D\u79DF\u6237\u516C\u6709 HDFS\u3002"}}catch(f){let h=BX(f);return w0(s,{State:p?"Uncertain":"Failed",Fingerprint:n,Error:p?`MiniMax-Music3 \u7ED3\u679C\u4E0D\u786E\u5B9A\uFF0C\u672A\u7528\u540C\u4E00 RequestId \u81EA\u52A8\u91CD\u8BD5\uFF1A${h}`:`MiniMax-Music3 \u63D0\u4EA4\u524D\u5931\u8D25\uFF1A${h}`,UpdatedAtUtc:new Date().toISOString()}),{Code:0,Data:{Status:p?"Uncertain":"Failed"},Msg:p?`MiniMax-Music3 \u7ED3\u679C\u4E0D\u786E\u5B9A\uFF0C\u672A\u7528\u540C\u4E00 RequestId \u81EA\u52A8\u91CD\u8BD5\uFF1A${h}`:`MiniMax-Music3 \u63D0\u4EA4\u524D\u5931\u8D25\uFF1A${h}`}}finally{u!==void 0&&$i.default.closeSync(u);try{$i.default.unlinkSync(c)}catch{}}}var S0=ke(require("node:crypto"),1),Ht=ke(require("node:fs"),1),gt=ke(require("node:path"),1),UX=/^[a-z0-9](?:[a-z0-9_-]{0,62}[a-z0-9])?$/u,JX=/^\/(?:[A-Za-z0-9][A-Za-z0-9_-]*(?:\/[A-Za-z0-9][A-Za-z0-9_-]*)*)?$/u,HX=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/u,ZX=/^v\d+\.\d+\.\d+$/u,KX="3.5.40",WX="7.3.6",GX="6.0.8",XX="5.9.3",YX="3.3.9";function QX(t){if(!t||!gt.default.isAbsolute(t))throw new Error("AI \u5E94\u7528\u76EE\u5F55\u5FC5\u987B\u662F\u7EDD\u5BF9\u8DEF\u5F84\u3002");let e=gt.default.resolve(t);if(gt.default.basename(e)!=="AI\u5E94\u7528")throw new Error(`\u672C\u5730\u811A\u624B\u67B6\u53EA\u80FD\u5199\u5165\u540D\u4E3A\u201CAI\u5E94\u7528\u201D\u7684\u76EE\u5F55\uFF1A${e}`);let r=Ht.default.lstatSync(e);if(!r.isDirectory()||r.isSymbolicLink())throw new Error(`AI \u5E94\u7528\u76EE\u5F55\u5FC5\u987B\u662F\u771F\u5B9E\u76EE\u5F55\u4E14\u4E0D\u80FD\u662F\u7B26\u53F7\u94FE\u63A5\uFF1A${e}`);return Ht.default.realpathSync(e)}function eY(t){let e=String(t||"v0.1.0").trim();if(!ZX.test(e))throw new Error(`buildVersion \u5FC5\u987B\u662F v1.2.3 \u5F62\u5F0F\uFF1A${t}`);return e}function tY(t){let e=t.split(/[-_]+/u).filter(Boolean).map(r=>r.charAt(0).toUpperCase()+r.slice(1)).join("").replace(/[^A-Za-z0-9]/gu,"");if(!e||!/^[A-Za-z]/u.test(e))throw new Error(`\u8DEF\u7531 name \u65E0\u6CD5\u751F\u6210\u5B89\u5168\u7684 Vue \u7EC4\u4EF6\u540D\uFF1A${t}`);return e}function rY(t){if(!Array.isArray(t)||t.length<1||t.length>50)throw new Error("routes \u6570\u91CF\u5FC5\u987B\u5728 1 \u5230 50 \u4E4B\u95F4\u3002");let e=new Set,r=new Set,n=new Set,i=t.filter(o=>o.isHome===!0);if(i.length>1)throw new Error("routes \u6700\u591A\u53EA\u80FD\u6709\u4E00\u4E2A isHome=true\u3002");return t.map((o,a)=>{let s=String(o.path||"").trim(),c=String(o.name||"").trim(),l=String(o.title||"").trim();if(!JX.test(s)||s.includes(".."))throw new Error(`\u8DEF\u7531 path \u4E0D\u5408\u6CD5\uFF1A${o.path}`);if(!HX.test(c))throw new Error(`\u8DEF\u7531 name \u4E0D\u5408\u6CD5\uFF1A${o.name}`);if(!l||l.length>100)throw new Error(`\u8DEF\u7531 title \u4E0D\u80FD\u4E3A\u7A7A\u4E14\u4E0D\u80FD\u8D85\u8FC7 100 \u4E2A\u5B57\u7B26\uFF1A${o.title}`);let u=s.toLowerCase(),p=c.toLowerCase();if(e.has(u))throw new Error(`\u8DEF\u7531 path \u91CD\u590D\uFF1A${s}`);if(r.has(p))throw new Error(`\u8DEF\u7531 name \u91CD\u590D\uFF1A${c}`);e.add(u),r.add(p);let f=`src/pages/${tY(c)}Page.vue`;if(n.has(f.toLowerCase()))throw new Error(`\u8DEF\u7531\u9875\u9762\u6587\u4EF6\u540D\u91CD\u590D\uFF1A${f}`);return n.add(f.toLowerCase()),{path:s,name:c,title:l,description:String(o.description||"").trim(),sourceFile:f,sort:a*10,isHome:i.length>0?o.isHome===!0:a===0}})}function nY(){return["function createClient(initial = {}) {",' const readStoredToken = () => { try { return localStorage.getItem("Token") || localStorage.getItem("authorization") || "" } catch { return "" } }',' const storeToken = (token) => { try { localStorage.setItem("Token", token); localStorage.setItem("authorization", token) } catch {} }',' let config = { apiBase: "", osClient: "", token: readStoredToken(), ...(initial || {}) }'," const configure = (next = {}) => { config = { ...config, ...(next || {}) }; return client }"," const getConfig = () => ({ ...config })"," const setToken = (token) => {",' const previousToken = String(config.token || "")',' config.token = String(token || "")'," storeToken(config.token)",' if (config.token !== previousToken && typeof config.onTokenChanged === "function") config.onTokenChanged(config.token, previousToken, client)'," return client"," }",' const clearToken = () => setToken("")'," const getToken = () => String(config.token || readStoredToken())"," async function post(url, data = {}) {",' const target = /^https?:\\/\\//i.test(url) ? url : String(config.apiBase || "").replace(/\\/+$/, "") + "/" + String(url || "").replace(/^\\/+/, "")',' const headers = { "Content-Type": "application/json", osclient: config.osClient || "" }'," const requestToken = getToken()",' if (requestToken) headers.Authorization = "Bearer " + requestToken',' const response = await fetch(target, { method: "POST", headers, body: JSON.stringify(data || {}) })'," const body = await response.json()",' const responseToken = response.headers.get("authorization") || response.headers.get("token") || body?.DataAppend?.Token || body?.Data?.Token || body?.Token || ""',' const normalizedToken = String(responseToken || "").replace(/^Bearer\\s+/i, "")'," if (normalizedToken && (!requestToken || getToken() === requestToken)) setToken(normalizedToken)"," if ([401, -1, 1001, 1002].includes(Number(body?.Code)) && (!requestToken || getToken() === requestToken)) {"," clearToken()",' if (typeof config.onAuthExpired === "function") config.onAuthExpired(body, client)'," }"," return body"," }"," const install = (app) => {"," if (app?.config?.globalProperties) app.config.globalProperties.$V8 = client",' if (typeof app?.provide === "function") app.provide("MicroiV8", client)'," return client"," }"," const client = {"," configure, getConfig, setToken, clearToken, getToken, GetToken: getToken, post, install,",' GetSysConfig: async () => { const result = await post("/api/DiyTable/getSysConfig", { OsClient: config.osClient, _SearchEqual: { IsEnable: 1 } }); return result?.Code === 1 ? (result.Data || {}) : null },',' Login: (data = {}) => post("/api/SysUser/login", { _ClientType: "PC", ...(data || {}) }),',' ApiEngine: { Run: (key, data = {}) => post("/apiengine/" + encodeURIComponent(key), data) },',' FormEngine: { GetTableData: (table, data = {}) => post("/api/FormEngine/GetTableData", { FormEngineKey: table, ...(data || {}) }) },'," }"," return client","}","export function createMicroiV8(options = {}) { return createClient(options) }","export const V8 = createMicroiV8()","export const MicroiV8 = V8","export default V8",""].join(`
|
|
213
213
|
`)}function L$(t){let e=[process.env.MICROI_V8_SDK_PATH,t?gt.default.join(t,"microi.skills","microi.v8.js"):"",process.env.MICROI_WORKSPACE_ROOT?gt.default.join(process.env.MICROI_WORKSPACE_ROOT,"microi.skills","microi.v8.js"):"",gt.default.join(process.cwd(),"microi.skills","microi.v8.js")].filter(Boolean);for(let r of e)try{let n=gt.default.resolve(r),i=Ht.default.lstatSync(n);if(i.isFile()&&!i.isSymbolicLink())return Ht.default.readFileSync(n,"utf8")}catch{}}function iY(t){return["import { createMicroiV8 } from './utils/microi.v8.js'","",`const standaloneDefaults = ${JSON.stringify({apiBase:t.apiBaseUrl||"",osClient:t.osClient||""})} as const`,"","export interface MicroiRouteContext {"," microRoute?: string"," microRoutePath?: string"," [key: string]: unknown","}","","export interface MicroiContext {"," apiBase: string"," osClient: string"," token: string"," menuId: string"," menuName: string"," moduleEngineKey: string"," diyTableId: string"," appKey: string"," version: string"," microRoute: string"," route: MicroiRouteContext","}","","type MicroiV8Runtime = ReturnType<typeof createMicroiV8> & {"," GetToken?: () => string"," GetSysConfig?: (refresh?: boolean) => Promise<Record<string, unknown> | null>"," Login?: (payload: Record<string, unknown>) => Promise<{ Code: number; Msg?: string; Data?: unknown }>","}","","function stringValue(value: unknown): string {"," return typeof value === 'string' ? value : ''","}","","function getLocalRoutePath(): string {"," const hashPath = String(window.location.hash || '').replace(/^#/, '').split('?')[0] || ''"," return hashPath.startsWith('/') ? hashPath : ''","}","","export function getMicroiContext(): MicroiContext {"," const data = window.microApp?.getData?.() || {}"," const route = data.route && typeof data.route === 'object' ? data.route as MicroiRouteContext : {}"," const permission = data.permissionContext && typeof data.permissionContext === 'object' ? data.permissionContext as Record<string, unknown> : {}"," return {"," apiBase: stringValue(data.apiBase) || standaloneDefaults.apiBase,"," osClient: stringValue(data.osClient) || standaloneDefaults.osClient,"," token: stringValue(data.token),"," menuId: stringValue(data.menuId) || stringValue(permission.sysMenuId),"," menuName: stringValue(data.menuName),"," moduleEngineKey: stringValue(data.moduleEngineKey) || stringValue(permission.moduleEngineKey),"," diyTableId: stringValue(data.diyTableId) || stringValue(permission.diyTableId),"," appKey: stringValue(data.appKey),"," version: stringValue(data.version),"," microRoute: stringValue(data.microRoute) || stringValue(route.microRoute) || stringValue(route.microRoutePath) || (window.microApp ? '' : getLocalRoutePath()),"," route,"," }","}","","export const microiV8 = createMicroiV8() as MicroiV8Runtime","let appliedHostToken = ''","","export function configureMicroiV8(context: MicroiContext = getMicroiContext()) {"," microiV8.configure?.({"," apiBase: context.apiBase,"," osClient: context.osClient,"," onTokenChanged: (token: string, requestToken: string) => {"," window.microApp?.dispatch?.({ type: 'micro-app:token', data: { token, requestToken } })"," },"," onAuthExpired: () => window.dispatchEvent(new CustomEvent('microi:auth-expired')),"," })"," if (context.token && context.token !== appliedHostToken) {"," appliedHostToken = context.token"," microiV8.setToken?.(context.token)"," }"," return microiV8","}",""].join(`
|
|
214
214
|
`)}function oY(){return["import { reactive } from 'vue'","import { configureMicroiV8, microiV8 } from './microi'","import type { MicroiContext } from './microi'","","export function isEnabledFlag(value: unknown): boolean {"," if (value === true || value === 1) return true"," if (typeof value !== 'string') return false"," return ['1', 'true', 'yes', 'on'].includes(value.trim().toLowerCase())","}","","export function useMicroiAuthentication() {"," const state = reactive({"," account: '', password: '', captchaId: '', captchaValue: '', captchaImage: '',"," captchaEnabled: false, loading: true, authenticated: false, error: '',"," })",""," function revokeCaptcha() {"," if (state.captchaImage.startsWith('blob:')) URL.revokeObjectURL(state.captchaImage)"," state.captchaImage = ''"," }",""," async function refreshCaptcha(context: MicroiContext) {"," revokeCaptcha()"," state.captchaId = ''"," state.captchaValue = ''"," if (!state.captchaEnabled) return"," const apiBase = String(context.apiBase || '').replace(/\\/+$/, '')"," if (!apiBase || !context.osClient) throw new Error('\u72EC\u7ACB\u8FD0\u884C\u7F3A\u5C11 apiBase \u6216 osClient')"," const url = new URL(apiBase + '/api/Captcha/GetCaptcha')"," url.searchParams.set('OsClient', context.osClient)"," const response = await fetch(url, { headers: { osclient: context.osClient } })"," if (!response.ok) throw new Error('\u9A8C\u8BC1\u7801\u52A0\u8F7D\u5931\u8D25\uFF1AHTTP ' + response.status)"," const captchaId = response.headers.get('captchaid') || ''"," if (!captchaId) throw new Error('\u9A8C\u8BC1\u7801\u54CD\u5E94\u7F3A\u5C11 captchaid')"," state.captchaId = captchaId"," state.captchaImage = URL.createObjectURL(await response.blob())"," }",""," function acceptHostContext(context: MicroiContext) {"," configureMicroiV8(context)"," if (context.token) state.authenticated = true"," }",""," async function initialize(context: MicroiContext) {"," state.loading = true"," state.error = ''"," try {"," acceptHostContext(context)"," if (context.token || microiV8.GetToken?.()) {"," state.authenticated = true"," return"," }"," const sysConfig = await microiV8.GetSysConfig?.(true)"," if (!sysConfig || typeof sysConfig !== 'object') throw new Error('\u65E0\u6CD5\u8BFB\u53D6\u5F53\u524D\u79DF\u6237\u7CFB\u7EDF\u914D\u7F6E')"," state.captchaEnabled = isEnabledFlag((sysConfig as Record<string, unknown>).EnableCaptcha)"," await refreshCaptcha(context)"," state.authenticated = false"," } catch (error) {"," state.error = error instanceof Error ? error.message : String(error || '\u521D\u59CB\u5316\u767B\u5F55\u5931\u8D25')"," state.authenticated = false"," } finally {"," state.loading = false"," }"," }",""," async function login(context: MicroiContext) {"," if (!state.account.trim() || !state.password) { state.error = '\u8BF7\u8F93\u5165\u5E10\u53F7\u548C\u5BC6\u7801'; return false }"," if (state.captchaEnabled && (!state.captchaId || !state.captchaValue.trim())) { state.error = '\u8BF7\u8F93\u5165\u9A8C\u8BC1\u7801'; return false }"," state.loading = true"," state.error = ''"," try {"," configureMicroiV8(context)"," const payload: Record<string, unknown> = {"," Account: state.account.trim(), Pwd: state.password, _ClientType: 'PC',"," }"," if (state.captchaEnabled) {"," payload._CaptchaId = state.captchaId"," payload._CaptchaValue = state.captchaValue.trim()"," }"," const result = await microiV8.Login?.(payload)"," if (!result || result.Code !== 1) throw new Error(result?.Msg || '\u767B\u5F55\u5931\u8D25')"," if (!microiV8.GetToken?.()) throw new Error('\u767B\u5F55\u6210\u529F\u54CD\u5E94\u7F3A\u5C11 Token')"," state.authenticated = true"," state.password = ''"," revokeCaptcha()"," return true"," } catch (error) {"," state.error = error instanceof Error ? error.message : String(error || '\u767B\u5F55\u5931\u8D25')"," if (state.captchaEnabled) await refreshCaptcha(context).catch(() => undefined)"," return false"," } finally {"," state.loading = false"," }"," }",""," async function expire(context: MicroiContext) {"," state.authenticated = false"," state.error = '\u767B\u5F55\u5DF2\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55'"," await initialize(context)"," }",""," return { state, initialize, login, refreshCaptcha, acceptHostContext, expire, revokeCaptcha }","}",""].join(`
|
|
215
215
|
`)}function aY(t){let e=t.map((n,i)=>`import RoutePage${i+1} from './pages/${gt.default.basename(n.sourceFile)}'`),r=t.map((n,i)=>` { path: ${JSON.stringify(n.path)}, name: ${JSON.stringify(n.name)}, title: ${JSON.stringify(n.title)}, isHome: ${n.isHome}, component: RoutePage${i+1} },`);return["import type { Component } from 'vue'",...e,"","export interface MicroServiceRoute {"," path: string"," name: string"," title: string"," isHome: boolean"," component: Component","}","","export const routes: readonly MicroServiceRoute[] = [",...r,"]","","export function normalizeRoutePath(value: unknown): string {"," const routePath = String(value || '').trim()"," return routePath ? (routePath.startsWith('/') ? routePath : '/' + routePath) : routes.find(route => route.isHome)?.path || routes[0]!.path","}","","export function findRoute(value: unknown): MicroServiceRoute {"," const normalized = normalizeRoutePath(value)"," return routes.find(route => route.path === normalized) || routes.find(route => route.isHome) || routes[0]!","}",""].join(`
|
|
@@ -540,7 +540,7 @@ MCP \u540E\u7AEF\u4F1A\u81EA\u52A8\u89E3\u6790 \`data\` \u5B57\u7B26\u4E32\u5E76
|
|
|
540
540
|
| html | \u81EA\u5B9A\u4E49HTML |
|
|
541
541
|
| iframe | \u5185\u5D4C\u9875\u9762 |`}function R0(t,e){let{osClient:r}=e,n=tQ(e),i=new Fd({name:n,version:"1.0.0"},{instructions:pQ(e)}),o=oQ(i);return i.tool("microi_codex",`Codex-compatible single entry point for all Microi tools on OsClient "${r}". Use action="list_tools" with optional params.keyword to discover tools, action="describe_tool" with params.name to inspect exact arguments, or pass any existing Microi tool name such as microi_get_status, microi_get_db_schema, microi_get_table_data, microi_get_module, microi_update_module, microi_get_engine_code, or microi_save_engine_code. The dispatcher reuses the original tool validation, write confirmation, audit, and readback logic.`,{action:d.string().describe("list_tools | describe_tool | an existing microi_* tool name"),params:Tt.optional().describe("Arguments for the selected action. Use {keyword?} for list_tools and {name} for describe_tool.")},async({action:a,params:s})=>{try{if(a==="list_tools"){let c=Mt(s,"keyword","Keyword"),l=o.list(c);return{content:[{type:"text",text:JSON.stringify({count:l.length,keyword:c||null,tools:l,next:'Call action="describe_tool" with params.name before invoking an unfamiliar write tool.'},null,2)}]}}if(a==="describe_tool"){let c=Mt(s,"name","Name","tool","Tool"),l=o.describe(c);return l?{content:[{type:"text",text:JSON.stringify(l,null,2)}]}:{content:[{type:"text",text:`Unknown Microi tool: ${c||"(empty)"}`}],isError:!0}}return await o.invoke(a,s)}catch(c){return{content:[{type:"text",text:`Microi dispatcher failed: ${c instanceof Error?c.message:String(c)}`}],isError:!0}}}),i.resource("microi_codex_status","microi://codex/status",{title:`Microi ${r} status`,description:"Read-only connection status fallback for Codex clients that fail to inject MCP tools.",mimeType:"application/json"},async a=>{let s=await o.invoke("microi_get_status",{});return{contents:[{uri:a.href,mimeType:"application/json",text:Q$(s)}]}}),i.resource("microi_codex_tools","microi://codex/tools",{title:`Microi ${r} tool catalog`,description:"Lists Microi tool names for Codex resource-mode fallback.",mimeType:"application/json"},async a=>({contents:[{uri:a.href,mimeType:"application/json",text:JSON.stringify({tools:o.list(),actionTemplate:"microi://codex/action/{action}/{params}",params:"URI-encoded JSON object. Example: microi://codex/action/microi_get_status/%7B%7D"},null,2)}]})),i.resource("microi_codex_action",new zd("microi://codex/action/{action}/{params}",{list:void 0}),{title:`Microi ${r} action fallback`,description:"Invokes an original microi_* tool through a resource URI when Codex does not expose MCP tools. Write confirmations remain mandatory.",mimeType:"application/json"},async(a,s)=>{try{let c=String(s.action||""),l=iQ(s.params),u=await o.invoke(c,l);return{contents:[{uri:a.href,mimeType:"application/json",text:Q$(u)}]}}catch(c){return{contents:[{uri:a.href,mimeType:"application/json",text:JSON.stringify({isError:!0,error:c instanceof Error?c.message:String(c)},null,2)}]}}}),i.tool("microi_get_status",`Check connection status to Microi server (OsClient: ${r}, API: ${e.apiBaseUrl})`,{},async()=>{try{let a=await t.getStatus();return a.Code===1?{content:[{type:"text",text:`\u2705 Server is online.
|
|
542
542
|
|
|
543
|
-
${JSON.stringify(a.Data,null,2)}`}]}:{content:[{type:"text",text:`\u26A0\uFE0F Server returned Code=${a.Code}: ${a.Msg}`}]}}catch(a){return{content:[{type:"text",text:`\u274C Connection failed: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}}),i.tool("microi_chat",`Chat with Microi.AI on the MCP-bound server and OsClient "${r}". Uses the current authenticated MCP user, tenant model configuration, local officially-signed Microi License and server-side provider credentials. The tool never accepts identity, OsClient, Endpoint, ApiKey or Authorization overrides. This is a non-streaming MCP result; UI typewriter output is available through V8.AI.ChatStream.`,{question:d.string().min(1).max(32e3).describe("User question or instruction."),systemPrompt:d.string().max(16e3).optional().describe("Optional per-call system guidance; tenant model credentials and endpoint remain server-side."),aiModel:d.string().min(1).max(200).describe("Enabled model display name in the current tenant."),aiModelId:d.string().max(100).optional().describe("Optional mic_ai row Id; preferred when model names may repeat."),relayModel:d.string().max(200).optional().describe("Optional official relay runtime model."),conversationId:d.string().max(100).optional().describe("Optional existing conversation Id owned by the current authenticated user."),reasoningEffort:d.enum(["auto","low","medium","high"]).optional().describe("Reasoning effort for supported models."),mode:d.enum(["chat","data","code","builder","project"]).optional().describe("Conversation mode hint.")},async({question:a,systemPrompt:s,aiModel:c,aiModelId:l,relayModel:u,conversationId:p,reasoningEffort:f,mode:h})=>{try{let m=await t.chat({question:a,systemPrompt:s,aiModel:c,aiModelId:l,relayModel:u,conversationId:p,reasoningEffort:f,mode:h});return{content:[{type:"text",text:typeof m.Data=="string"?m.Data:JSON.stringify(m,null,2)}],structuredContent:{Code:m.Code,Data:m.Data,Msg:m.Msg||""},...m.Code!==1?{isError:!0}:{}}}catch(m){return{content:[{type:"text",text:`Microi.AI chat failed: ${m instanceof Error?m.message:String(m)}`}],isError:!0}}}),i.tool("microi_get_administrative_capabilities",`Verify the current MCP session against the current tenant database and return the authoritative Microi platform-administrator capability/catalog for OsClient "${r}". Requires an interactive DiyToken with Level >= 9999 and an active administrator role; access-key sessions are rejected.`,{},async()=>{try{let a=await t.getAdministrativeCapabilities();return{content:[{type:"text",text:JSON.stringify(a.Data??a,null,2)}],...a.Code!==1?{isError:!0}:{}}}catch(a){return{content:[{type:"text",text:`Error: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}}),i.tool("microi_generate_minimax_music",`Generate one original instrumental game-music asset through the authenticated Microi AI engine for OsClient "${r}". The server fixes MiniMax music-2.6, 44.1kHz, 256kbps MP3, keeps provider credentials private, persists the result to tenant HDFS, and uses RequestId for idempotency. This consumes an external AI quota, so confirmExecution must exactly equal requestId.`,{requestId:d.string().min(8).max(160).regex(/^[A-Za-z0-9._:-]+$/u).describe("Stable idempotency key. Reuse it for retries of the same prompt."),prompt:d.string().min(1).max(2e3).describe("Original instrumental music brief. Do not request imitation of a living artist or copyrighted recording."),durationSeconds:d.number().int().min(10).max(60).optional().describe("MiniMax-Music3 fallback duration. Default 20 seconds."),confirmExecution:d.string().optional().describe("Required for generation and must exactly equal requestId; omit for a no-cost dry run.")},async({requestId:a,prompt:s,durationSeconds:c,confirmExecution:l})=>{let u={RequestId:a,Prompt:s,Model:"music-2.6",IsInstrumental:!0,SampleRate:44100,Bitrate:256e3,Format:"mp3"};if(l!==a)return{content:[{type:"text",text:JSON.stringify({dryRun:!0,payload:u,requiredConfirmation:a},null,2)}]};try{let p=await t.generateMiniMaxMusic(u);return F$(p)&&(p=await z$(t,{apiBaseUrl:e.apiBaseUrl,osClient:r,requestId:a,prompt:s,durationSeconds:c})),{content:[{type:"text",text:JSON.stringify(p,null,2)}],structuredContent:p,...p.Code!==1?{isError:!0}:{}}}catch(p){return{content:[{type:"text",text:`MiniMax music generation failed: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_generate_minimax_speech",`Generate one original Chinese game voice line through the authenticated Microi AI engine for OsClient "${r}". The server fixes MiniMax speech-2.8-hd, approved system voices and mono MP3 output, keeps provider credentials private, persists the result to tenant HDFS, and uses RequestId for idempotency. This consumes an external AI quota, so confirmExecution must exactly equal requestId.`,{requestId:d.string().min(8).max(160).regex(/^[A-Za-z0-9._:-]+$/u).describe("Stable idempotency key. Reuse it for retries of the same line."),text:d.string().min(1).max(800).describe("Chinese voice line, normally one short gameplay announcement."),speaker:d.enum(["female","male"]).optional().describe("Approved system voice gender. Default female."),speed:d.number().min(.8).max(1.2).optional(),volume:d.number().min(.8).max(1.2).optional(),pitch:d.number().int().min(-2).max(2).optional(),emotion:d.enum(["calm","happy","sad","surprised"]).optional(),confirmExecution:d.string().optional().describe("Required for generation and must exactly equal requestId; omit for a no-cost dry run.")},async({requestId:a,text:s,speaker:c,speed:l,volume:u,pitch:p,emotion:f,confirmExecution:h})=>{let m={RequestId:a,Text:s,Speaker:c||"female",Model:"speech-2.8-hd",Speed:l??1,Volume:u??1,Pitch:p??0,Emotion:f||"calm",SampleRate:32e3,Bitrate:128e3,Channel:1,Format:"mp3"};if(h!==a)return{content:[{type:"text",text:JSON.stringify({dryRun:!0,payload:m,requiredConfirmation:a},null,2)}]};try{let g=await t.generateMiniMaxSpeech(m);return{content:[{type:"text",text:JSON.stringify(g,null,2)}],structuredContent:g,...g.Code!==1?{isError:!0}:{}}}catch(g){return{content:[{type:"text",text:`MiniMax speech generation failed: ${g instanceof Error?g.message:String(g)}`}],isError:!0}}}),i.tool("microi_ocr_recognize",`Recognize text in one image or PDF through the authenticated Microi OCR gateway for OsClient "${r}". Provide exactly one of filePath (absolute local regular file, symlinks rejected) or fileByteBase64. This transmits document bytes to the OCR provider configured by the tenant administrator, so confirmExecution="OCR" is mandatory. Endpoint, Provider, ApiKey, headers, Authorization and OsClient overrides are never accepted. Audit logs contain only safe filename, byte count, SHA-256 and option flags\u2014not the local path, file bytes, recognized text or credentials.`,{filePath:d.string().max(32767).optional().describe("Absolute local path to one PDF/image. Mutually exclusive with fileByteBase64; symlinks and non-regular files are rejected."),fileByteBase64:d.string().max(Dx).optional().describe("PDF/image Base64 or data URI. Mutually exclusive with filePath; backend validates file magic and tenant limits again."),fileName:d.string().max(255).optional().describe("Optional safe filename. For filePath, the basename is used when omitted."),useDocOrientationClassify:d.boolean().optional().describe("Enable document orientation classification when supported by the configured pipeline."),useDocUnwarping:d.boolean().optional().describe("Enable document unwarping when supported by the configured pipeline."),useTextlineOrientation:d.boolean().optional().describe("Enable text-line orientation classification when supported by the configured pipeline."),textRecScoreThresh:d.number().min(0).max(1).optional().describe("Per-call recognition threshold, 0..1. It can only raise the tenant minimum."),returnWordBox:d.boolean().optional().describe("Ask the provider for word-level boxes when supported."),includePages:d.boolean().optional().describe("Include bounded page texts. Default false to keep MCP output compact."),includeRegions:d.boolean().optional().describe("Include region polygons/confidence and implicitly include pages. Default false."),maxTextChars:d.number().int().min(1e3).max(2e5).optional().describe("Maximum characters for full text and cumulative page text; default 100000."),confirmExecution:d.string().optional().describe("Required because document bytes leave MCP for the tenant-configured OCR provider. Use exactly OCR.")},async({filePath:a,fileByteBase64:s,fileName:c,useDocOrientationClassify:l,useDocUnwarping:u,useTextlineOrientation:p,textRecScoreThresh:f,returnWordBox:h,includePages:m,includeRegions:g,maxTextChars:y,confirmExecution:v})=>{try{if(v!=="OCR")return{content:[{type:"text",text:'\u6267\u884C\u5DF2\u62E6\u622A\uFF1Amicroi_ocr_recognize \u4F1A\u628A\u6587\u6863\u53D1\u9001\u5230\u5F53\u524D\u79DF\u6237\u7BA1\u7406\u5458\u914D\u7F6E\u7684 OCR \u670D\u52A1\uFF0C\u8BF7\u786E\u8BA4\u8BE5\u6587\u4EF6\u5141\u8BB8\u5904\u7406\u540E\u91CD\u65B0\u8C03\u7528\u5E76\u4F20 confirmExecution="OCR"\u3002'}],isError:!0};let x=Fx({filePath:a,fileByteBase64:s,fileName:c,useDocOrientationClassify:l,useDocUnwarping:u,useTextlineOrientation:p,textRecScoreThresh:f,returnWordBox:h});await t.writeAuditLog("microi_ocr_recognize",x.auditFileName,JSON.stringify({byteLength:x.byteLength,sha256:x.sha256,useDocOrientationClassify:l,useDocUnwarping:u,useTextlineOrientation:p,textRecScoreThresh:f,returnWordBox:h,includePages:!!(m||g),includeRegions:!!g}));let b=await t.recognizeOcr(x.request),_=zx(b.Data,{includePages:!!(m||g),includeRegions:!!g,maxTextChars:y}),E={Code:b.Code,Data:_,Msg:b.Msg||""};return{content:[{type:"text",text:JSON.stringify(E,null,2)}],structuredContent:E,isError:b.Code!==1}}catch(x){return{content:[{type:"text",text:`OCR failed: ${x instanceof Error?x.message:String(x)}`}],isError:!0}}}),i.tool("microi_translate",`Translate one text or a bounded batch through the authenticated Microi translation gateway for OsClient "${r}". Provide exactly one of sourceText/sourceTexts. Supports source auto-detection, text/HTML and up to 10 alternatives when the tenant uses LibreTranslate. Provider URL, API key, Authorization and OsClient are always server-side and cannot be overridden.`,{sourceText:d.string().max(5e4).optional().describe("One source text. Mutually exclusive with sourceTexts."),sourceTexts:d.array(d.string().min(1).max(5e4)).max(50).optional().describe("Up to 50 texts and 200000 total characters. Mutually exclusive with sourceText."),fromLang:d.string().max(32).optional().default("auto").describe("Source language code or auto."),targetLang:d.string().min(1).max(32).describe("Target language code."),format:d.enum(["text","html"]).optional().default("text").describe("Source format."),alternatives:d.number().int().min(0).max(10).optional().default(0).describe("Preferred alternative translation count.")},async({sourceText:a,sourceTexts:s,fromLang:c,targetLang:l,format:u,alternatives:p})=>{try{let f=!!a?.trim(),h=!!s?.length;if(f===h)throw new Error("sourceText \u4E0E sourceTexts \u5FC5\u987B\u4E14\u53EA\u80FD\u63D0\u4F9B\u4E00\u4E2A\u3002");if(s&&s.reduce((y,v)=>y+v.length,0)>2e5)throw new Error("sourceTexts \u603B\u5B57\u7B26\u6570\u4E0D\u80FD\u8D85\u8FC7 200000\u3002");let m=await t.translateText({...f?{SourceText:a}:{SourceTexts:s},FromLang:c||"auto",Lang:l,Format:u||"text",Alternatives:p||0}),g={Code:m.Code,Data:m.Data,Msg:m.Msg||""};return{content:[{type:"text",text:JSON.stringify(g,null,2)}],structuredContent:g,...m.Code!==1?{isError:!0}:{}}}catch(f){return{content:[{type:"text",text:`Translate failed: ${f instanceof Error?f.message:String(f)}`}],isError:!0}}}),i.tool("microi_detect_language",`Detect the language of one text before a translate operation through the authenticated Microi translation gateway for OsClient "${r}". The text is sent only to the provider configured by the tenant administrator; caller-supplied endpoint, key and OsClient fields are ignored.`,{sourceText:d.string().min(1).max(5e4).describe("Text whose language should be detected.")},async({sourceText:a})=>{try{let s=await t.detectLanguage(a),c={Code:s.Code,Data:s.Data,Msg:s.Msg||""};return{content:[{type:"text",text:JSON.stringify(c,null,2)}],structuredContent:c,...s.Code!==1?{isError:!0}:{}}}catch(s){return{content:[{type:"text",text:`Language detection failed: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}}),i.tool("microi_list_translate_languages",`List the current tenant translation provider's installed source languages and exact reachable target codes for OsClient "${r}". No provider credentials or internal endpoint are returned.`,{},async()=>{try{let a=await t.listTranslateLanguages(),s={Code:a.Code,Data:a.Data,Msg:a.Msg||""};return{content:[{type:"text",text:JSON.stringify(s,null,2)}],structuredContent:s,...a.Code!==1?{isError:!0}:{}}}catch(a){return{content:[{type:"text",text:`List translation languages failed: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}}),i.tool("microi_translate_file",`Translate one supported document through the authenticated Microi translation gateway for OsClient "${r}". Provide exactly one input (absolute non-symlink filePath or Base64+fileName) and exactly one output mode (new absolute outputFilePath or includeFileByteBase64=true for results up to 2 MB). Document bytes leave MCP for the tenant-configured provider, so confirmExecution="TRANSLATE_FILE" is mandatory. Endpoint, API key, Authorization and OsClient overrides are never accepted; audit logs contain hashes and sizes, never paths or document content.`,{filePath:d.string().max(32767).optional().describe("Absolute local source file path. Mutually exclusive with fileByteBase64."),fileByteBase64:d.string().max(qx).optional().describe("Source document Base64/data URI. Mutually exclusive with filePath."),fileName:d.string().max(255).optional().describe("Required for Base64; optional safe override for filePath."),fromLang:d.string().max(32).optional().default("auto").describe("Source language code or auto."),targetLang:d.string().min(1).max(32).describe("Target language code."),outputFilePath:d.string().max(32767).optional().describe("New absolute local file path. Existing files and symlink parent directories are rejected."),includeFileByteBase64:d.boolean().optional().default(!1).describe("Return Base64 inline only for translated results up to 2 MB. Mutually exclusive with outputFilePath."),confirmExecution:d.string().optional().describe("Required exact value: TRANSLATE_FILE.")},async({filePath:a,fileByteBase64:s,fileName:c,fromLang:l,targetLang:u,outputFilePath:p,includeFileByteBase64:f,confirmExecution:h})=>{try{if(h!=="TRANSLATE_FILE")return{content:[{type:"text",text:'\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u6587\u4EF6\u4F1A\u53D1\u9001\u5230\u5F53\u524D\u79DF\u6237\u914D\u7F6E\u7684\u7FFB\u8BD1\u670D\u52A1\uFF1B\u786E\u8BA4\u540E\u8BF7\u4F20 confirmExecution="TRANSLATE_FILE"\u3002'}],isError:!0};if(!!p?.trim()==!!f)throw new Error("outputFilePath \u4E0E includeFileByteBase64=true \u5FC5\u987B\u4E14\u53EA\u80FD\u9009\u62E9\u4E00\u79CD\u8F93\u51FA\u65B9\u5F0F\u3002");let m=Vx({filePath:a,fileByteBase64:s,fileName:c,fromLang:l,targetLang:u});if(f&&m.byteLength>jx)throw new Error("\u6E90\u6587\u4EF6\u8D85\u8FC7 2 MB\uFF0C\u8BF7\u4F7F\u7528 outputFilePath\uFF0C\u907F\u514D\u5927 Base64 \u8FDB\u5165 MCP \u4E0A\u4E0B\u6587\u3002");await t.writeAuditLog("microi_translate_file",m.auditFileName,JSON.stringify({byteLength:m.byteLength,sha256:m.sha256,fromLang:m.request.FromLang,targetLang:m.request.Lang,outputMode:p?"local-file":"inline-base64"}));let g=await t.translateFile(m.request);if(g.Code!==1){let _={Code:g.Code,Data:null,Msg:g.Msg||""};return{content:[{type:"text",text:JSON.stringify(_,null,2)}],structuredContent:_,isError:!0}}let y=Bx(g.Data);if(f&&y.length>jx)throw new Error("\u8BD1\u540E\u6587\u4EF6\u8D85\u8FC7 2 MB\uFF0C\u8BF7\u6539\u7528 outputFilePath\u3002");let v=et.default.createHash("sha256").update(y).digest("hex"),x={Provider:g.Data?.Provider,FileName:g.Data?.FileName,ContentType:g.Data?.ContentType,ByteLength:y.length,Sha256:v};p?x.SavedToPath=N4(p,y):x.FileByteBase64=y.toString("base64");let b={Code:1,Data:x,Msg:g.Msg||""};return{content:[{type:"text",text:JSON.stringify(b,null,2)}],structuredContent:b}}catch(m){return{content:[{type:"text",text:`File translation failed: ${m instanceof Error?m.message:String(m)}`}],isError:!0}}}),i.tool("microi_suggest_translation",`Submit a translation improvement suggestion to the current tenant's LibreTranslate-compatible provider. This mutates provider-side suggestion data and requires confirmExecution="TRANSLATE_SUGGEST". Audit logs contain only text lengths and SHA-256 values; source/suggestion text, endpoint, credentials and tenant secrets are never logged or caller-overridable.`,{sourceText:d.string().min(1).max(5e4).describe("Original source text."),suggestedText:d.string().min(1).max(5e4).describe("Proposed translated text."),fromLang:d.string().min(1).max(32).describe("Explicit source language; auto is not accepted."),targetLang:d.string().min(1).max(32).describe("Target language."),confirmExecution:d.string().optional().describe("Required exact value: TRANSLATE_SUGGEST.")},async({sourceText:a,suggestedText:s,fromLang:c,targetLang:l,confirmExecution:u})=>{try{if(u!=="TRANSLATE_SUGGEST")return{content:[{type:"text",text:'\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u5EFA\u8BAE\u4F1A\u5199\u5165\u7FFB\u8BD1\u670D\u52A1\uFF1B\u786E\u8BA4\u540E\u8BF7\u4F20 confirmExecution="TRANSLATE_SUGGEST"\u3002'}],isError:!0};await t.writeAuditLog("microi_suggest_translation",`${c}->${l}`,JSON.stringify({sourceLength:a.length,sourceSha256:et.default.createHash("sha256").update(a,"utf8").digest("hex"),suggestionLength:s.length,suggestionSha256:et.default.createHash("sha256").update(s,"utf8").digest("hex")}));let p=await t.suggestTranslation({SourceText:a,SuggestedText:s,FromLang:c,Lang:l}),f={Code:p.Code,Data:p.Data,Msg:p.Msg||""};return{content:[{type:"text",text:JSON.stringify(f,null,2)}],structuredContent:f,...p.Code!==1?{isError:!0}:{}}}catch(p){return{content:[{type:"text",text:`Translation suggestion failed: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_get_translate_health","Read a safe health/capability summary for the current tenant's translation gateway. It returns provider name, status and supported business operations, but never the internal URL, API key or frontend/metrics settings.",{},async()=>{try{let a=await t.getTranslateHealth(),s={Code:a.Code,Data:a.Data,Msg:a.Msg||""};return{content:[{type:"text",text:JSON.stringify(s,null,2)}],structuredContent:s,...a.Code!==1?{isError:!0}:{}}}catch(a){return{content:[{type:"text",text:`Translation health failed: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}}),i.tool("microi_transition_application_stream_gate","Preview or execute one application-stream gate transition for the exact MCP-bound tenant coordinate. Allowed transitions are LegacyOpen -> Drain, Drain -> V3Only, and the safety rollback Drain -> LegacyOpen; every successful transition must advance the server epoch. V3Only never permits downgrade. The first call never reaches the server and returns ConfirmationSha256. A server call is possible only when confirmExecution=true and confirmationSha256 exactly matches that preview; the server must independently recompute the same hash.",{osClient:d.string().min(1).max(100).describe("Exact OsClient from the active MCP coordinate."),osClientType:d.string().max(100).describe("Exact OsClientType from the active MCP coordinate; pass an explicit empty string when unset."),osClientNetwork:d.string().max(100).describe("Exact OsClientNetwork from the active MCP coordinate; pass an explicit empty string when unset."),expectedMode:d.enum(["LegacyOpen","Drain","V3Only"]).describe("Compare-and-swap source mode."),expectedMinProtocol:d.union([d.literal(2),d.literal(3)]).describe("Compare-and-swap source minimum protocol."),expectedGateEpoch:d.string().describe("Canonical non-negative Int64 decimal string; no leading zeroes."),targetMode:d.enum(["LegacyOpen","Drain","V3Only"]).describe("Target mode. Drain -> LegacyOpen is the only rollback and still advances the gate epoch; V3Only cannot transition."),transitionId:d.string().min(8).max(100).describe("Stable idempotency/audit identifier."),reason:d.string().min(1).max(1e3).describe("Auditable transition reason with no leading/trailing whitespace."),drainProofJson:d.string().min(2).max(1024*1024).describe("Canonical JSON object proving the drain observation."),drainProofHash:d.string().length(64).describe("Lowercase SHA-256 of the exact UTF-8 DrainProofJson bytes."),confirmExecution:d.boolean().optional().describe("Omit/false for preview. Only literal true can execute."),confirmationSha256:d.string().optional().describe("Exact lowercase ConfirmationSha256 returned by the preview of this unchanged payload.")},async({osClient:a,osClientType:s,osClientNetwork:c,expectedMode:l,expectedMinProtocol:u,expectedGateEpoch:p,targetMode:f,transitionId:h,reason:m,drainProofJson:g,drainProofHash:y,confirmExecution:v,confirmationSha256:x})=>{let b=!1;try{let _=OY({osClient:a,osClientType:s,osClientNetwork:c,expectedMode:l,expectedMinProtocol:u,expectedGateEpoch:p,targetMode:f,transitionId:h,reason:m,drainProofJson:g,drainProofHash:y},e),E={Preview:!0,RemoteWriteAttempted:!1,ConfirmationSha256:_.confirmationSha256,Transition:_.payload,Next:"Repeat the unchanged payload with confirmExecution=true and confirmationSha256 exactly equal to ConfirmationSha256."};if(v!==!0)return{content:[{type:"text",text:JSON.stringify(E,null,2)}]};if(x!==_.confirmationSha256)return{content:[{type:"text",text:JSON.stringify({...E,Error:"confirmationSha256 \u4E0E\u5F53\u524D\u89C4\u8303\u5316\u8F6C\u6362\u8F7D\u8377\u4E0D\u5B8C\u5168\u4E00\u81F4\uFF1B\u672A\u8C03\u7528\u670D\u52A1\u5668\u3002"},null,2)}],isError:!0};b=!0;let w=await t.transitionApplicationStreamGate({..._.payload,ConfirmationSha256:_.confirmationSha256,ConfirmExecution:!0});return w.Code!==1?{content:[{type:"text",text:JSON.stringify({Preview:!1,RemoteWriteAttempted:!0,ConfirmationSha256:_.confirmationSha256,Transition:_.payload,Result:w},null,2)}],isError:!0}:{content:[{type:"text",text:JSON.stringify({Preview:!1,RemoteWriteAttempted:!0,ConfirmationSha256:_.confirmationSha256,Transition:_.payload,Result:w},null,2)}]}}catch(_){return{content:[{type:"text",text:JSON.stringify({Preview:!b,RemoteWriteAttempted:b,OutcomeUncertain:b,Error:_ instanceof Error?_.message:String(_)},null,2)}],isError:!0}}}),i.tool("microi_list_my_access_keys",`List the current authenticated user's access keys for OsClient "${r}". The response contains only public metadata and never returns the credential or its hash. Access-key sessions cannot manage keys. Requires confirmExecution="LIST" because key prefixes and usage metadata are security-sensitive.`,{confirmExecution:d.string().optional().describe("Required. Pass LIST.")},async({confirmExecution:a})=>{if(a!=="LIST")return{content:[{type:"text",text:'\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u8BBF\u95EE\u5BC6\u94A5\u5217\u8868\u5305\u542B\u5B89\u5168\u5143\u6570\u636E\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528\u5E76\u4F20 confirmExecution="LIST"\u3002'}],isError:!0};try{let s=await t.listMyUserAccessKeys();return s.Code!==1?{content:[{type:"text",text:`\u8BFB\u53D6\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${s.Msg||`Code=${s.Code}`}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(s.Data||[],null,2)}]}}catch(s){return{content:[{type:"text",text:`\u8BFB\u53D6\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${s instanceof Error?s.message:String(s)}`}],isError:!0}}}),i.tool("microi_create_my_access_key",`Create one revocable, bounded access key for the current authenticated user on OsClient "${r}". This is not a permanent admin/MCP bypass: the backend stores only a SHA-256 hash, returns plaintext exactly once, and exchanges the key for a short scoped session. The MCP surface never creates permanent keys; omitting expiresAt uses the backend's bounded default (currently 90 days). Omit scopes for the minimum page:open + form:read permissions. For a browser kiosk, combine the one-time AccessKey with the Microi.Client frontend origin using /?OsClient=${encodeURIComponent(r)}#/access-login?access_key=<AccessKey>&redirect=<encodeURIComponent(redirectPath)>; do not use the API origin and do not append the key to the destination page. The first call is a dry confirmation step and returns RequiredConfirmationSha256; repeat the exact same payload with confirmExecution equal to that SHA-256.`,{name:d.string().min(1).max(200).describe("Human-readable key name."),allowedRoutes:d.array(d.string().min(1).max(500)).min(1).max(100).describe("Exact allowed routes. Use * only after explicit risk review."),allowedTableNames:d.array(d.string().min(1).max(200)).min(1).max(100).describe("Exact table names. Use * only after explicit risk review."),scopes:d.array(d.enum(["page:open","form:read","api-engine:run","data-source:run","file:read"])).min(1).max(5).optional().describe("Omit for minimum page:open + form:read. MCP does not expose form:write/form:export until the backend path facade supports them."),redirectPath:d.string().max(500).optional().describe("Internal Hash route beginning with /; must be included in allowedRoutes. Example: /mic/data-dashboard/preview/01KK988A0YPHKAM8SF216917HX. MCP URL-encodes the entire value into the browser login redirect parameter."),allowedApiEngineKeys:d.array(d.string().min(1).max(200)).max(100).optional().describe("Exact keys; required only with api-engine:run. Wildcards are rejected."),allowedDataSourceKeys:d.array(d.string().min(1).max(200)).max(100).optional().describe("Exact keys; required only with data-source:run. Wildcards are rejected."),expiresAt:d.string().optional().describe("Optional server-local expiry time, later than now and no more than 365 days. Omit for the bounded default."),remark:d.string().max(1e3).optional(),confirmExecution:d.string().optional().describe("Required for the real create. First omit it; then pass the returned RequiredConfirmationSha256 with the exact same payload.")},async({name:a,allowedRoutes:s,allowedTableNames:c,scopes:l,redirectPath:u,allowedApiEngineKeys:p,allowedDataSourceKeys:f,expiresAt:h,remark:m,confirmExecution:g})=>{let y=eQ({name:a,allowedRoutes:s,allowedTableNames:c,scopes:l,redirectPath:u,allowedApiEngineKeys:p,allowedDataSourceKeys:f,expiresAt:h,remark:m});if(String(g||"").trim().toLowerCase()!==y.sha256)return{content:[{type:"text",text:JSON.stringify({Blocked:!0,Message:"\u521B\u5EFA\u8BBF\u95EE\u5BC6\u94A5\u4F1A\u4EA7\u751F\u65B0\u7684\u767B\u5F55\u51ED\u636E\u3002\u8BF7\u6838\u5BF9\u4EE5\u4E0B\u89C4\u8303\u5316\u6743\u9650\u8F7D\u8377\uFF0C\u5E76\u4F7F\u7528\u5BF9\u5E94 SHA-256 \u786E\u8BA4\u3002",NormalizedGrant:y.normalized,RequiredConfirmationSha256:y.sha256,Next:"\u4FDD\u6301\u5176\u5B83\u53C2\u6570\u5B8C\u5168\u4E0D\u53D8\uFF0C\u5E76\u5C06 confirmExecution \u8BBE\u7F6E\u4E3A RequiredConfirmationSha256\u3002"},null,2)}],isError:!0};try{let v=await t.createMyUserAccessKey({name:y.normalized.name,allowedRoutes:y.normalized.allowedRoutes,allowedTableNames:y.normalized.allowedTableNames,scopes:y.normalized.scopes,redirectPath:y.normalized.redirectPath||void 0,allowedApiEngineKeys:y.normalized.allowedApiEngineKeys,allowedDataSourceKeys:y.normalized.allowedDataSourceKeys,expiresAt:y.normalized.expiresAt||void 0,remark:y.normalized.remark||void 0});if(v.Code!==1||!v.Data?.AccessKey)return{content:[{type:"text",text:`\u521B\u5EFA\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${v.Msg||`Code=${v.Code}`}`}],isError:!0};let x=QY(r,y.normalized.redirectPath);return{content:[{type:"text",text:JSON.stringify({AccessKey:v.Data.AccessKey,Record:v.Data.Record||null,Notice:"\u660E\u6587\u4EC5\u672C\u6B21\u8FD4\u56DE\u3002\u8BF7\u7ACB\u5373\u5B58\u5165\u5B89\u5168\u51ED\u636E\u5E93\uFF1B\u540E\u7EED\u5217\u8868\u548C\u65E5\u5FD7\u4E0D\u4F1A\u518D\u6B21\u663E\u793A\u3002",LoginUrlRelativeTemplate:x.relative,LoginUrlTemplate:x.absolute,LoginUrlNotice:"\u8BF7\u7528 Microi.Client \u524D\u7AEF\u57DF\u540D\u66FF\u6362\u5360\u4F4D\u7B26\uFF0C\u5E76\u7528\u672C\u6B21 AccessKey \u66FF\u6362 <AccessKey>\u3002\u56FA\u5B9A\u7EC8\u7AEF\u5E94\u4FDD\u5B58\u5B8C\u6574 access-login \u542F\u52A8\u94FE\u63A5\uFF1B\u767B\u5F55\u540E\u76EE\u6807\u9875\u9762\u4E0D\u518D\u663E\u793A access_key \u5C5E\u4E8E\u6B63\u5E38\u7684\u5B89\u5168\u6E05\u7406\u3002"},null,2)}]}}catch(v){return{content:[{type:"text",text:`\u521B\u5EFA\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${v instanceof Error?v.message:String(v)}`}],isError:!0}}}),i.tool("microi_revoke_my_access_key",`Revoke one access key owned by the current authenticated user on OsClient "${r}". Revocation is idempotent and invalidates the shared runtime cache. Requires confirmExecution equal to id. For rotation, create a new bounded key first, securely store its one-time plaintext, then revoke the old id.`,{id:d.string().min(1).max(100).describe("Access key record Id from microi_list_my_access_keys."),confirmExecution:d.string().optional().describe("Required. Pass the exact id.")},async({id:a,confirmExecution:s})=>{if(s!==a)return{content:[{type:"text",text:`\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u540A\u9500\u540E\u8BE5\u8BBF\u95EE\u5BC6\u94A5\u5C06\u7ACB\u5373\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528\u5E76\u4F20 confirmExecution="${a}"\u3002`}],isError:!0};try{let c=await t.revokeMyUserAccessKey(a);return c.Code!==1?{content:[{type:"text",text:`\u540A\u9500\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${c.Msg||`Code=${c.Code}`}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify({Id:a,Revoked:!0,Record:c.Data||null,Message:c.Msg||"\u8BBF\u95EE\u5BC6\u94A5\u5DF2\u540A\u9500\u3002"},null,2)}]}}catch(c){return{content:[{type:"text",text:`\u540A\u9500\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${c instanceof Error?c.message:String(c)}`}],isError:!0}}}),i.tool("microi_redis_statistics",`Get Redis server/keyspace statistics for OsClient "${r}". Uses the current tenant Redis by default; pass connectionId only for a connection previously saved in mci_redis_connection. Never pass Redis passwords through MCP.`,{database:d.number().int().min(0).max(1023).optional().describe("Redis database index. Default: 0."),connectionId:d.string().optional().describe("Optional saved mci_redis_connection Id. Omit for current tenant Redis.")},async({database:a,connectionId:s})=>{try{let c=await t.getRedisStatistics(a||0,s);return c.Code!==1?{content:[{type:"text",text:`Error: ${c.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(c.Data,null,2)}]}}catch(c){return{content:[{type:"text",text:`Error: ${c instanceof Error?c.message:String(c)}`}],isError:!0}}}),i.tool("microi_redis_list_keys",`SCAN Redis keys for OsClient "${r}" without using blocking KEYS. Returns type, TTL, memory estimate and an opaque next cursor.`,{pattern:d.string().optional().describe("Redis glob pattern. Plain text is treated as a contains search. Default: *."),database:d.number().int().min(0).max(1023).optional().describe("Redis database index. Default: 0."),pageSize:d.number().int().min(10).max(500).optional().describe("Page size. Default: 100."),cursor:d.string().optional().describe("Opaque NextCursor from the previous call."),connectionId:d.string().optional().describe("Optional saved connection Id. Omit for current tenant Redis.")},async({pattern:a,database:s,pageSize:c,cursor:l,connectionId:u})=>{try{let p=await t.getRedisKeys(a||"*",s||0,c||100,l,u);return p.Code!==1?{content:[{type:"text",text:`Error: ${p.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(p.Data,null,2)}]}}catch(p){return{content:[{type:"text",text:`Error: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_redis_get_key",`Read one Redis key for OsClient "${r}". Supports String, Hash, List, Set, Sorted Set and Stream with bounded pagination.`,{key:d.string().describe("Exact Redis key."),database:d.number().int().min(0).max(1023).optional().describe("Redis database index. Default: 0."),pageIndex:d.number().int().min(1).optional().describe("Collection page index. Default: 1."),pageSize:d.number().int().min(10).max(1e3).optional().describe("Collection page size. Default: 500."),connectionId:d.string().optional().describe("Optional saved connection Id. Omit for current tenant Redis.")},async({key:a,database:s,pageIndex:c,pageSize:l,connectionId:u})=>{try{let p=await t.getRedisKey(a,s||0,c||1,l||500,u);return p.Code!==1?{content:[{type:"text",text:`Error: ${p.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(p.Data,null,2)}]}}catch(p){return{content:[{type:"text",text:`Error: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_redis_delete_keys",`Delete up to 500 Redis keys for OsClient "${r}". This is irreversible and requires confirmExecution="DELETE".`,{keys:d.array(d.string()).min(1).max(500).describe("Exact Redis keys to delete."),database:d.number().int().min(0).max(1023).optional().describe("Redis database index. Default: 0."),connectionId:d.string().optional().describe("Optional saved connection Id. Omit for current tenant Redis."),confirmExecution:d.string().optional().describe("Required. Pass DELETE after reviewing the key list.")},async({keys:a,database:s,connectionId:c,confirmExecution:l})=>{if(l!=="DELETE")return{content:[{type:"text",text:JSON.stringify({dryRun:!0,action:"delete",database:s||0,connectionId:c||null,keys:a},null,2)}]};try{let u=await t.deleteRedisKeys(a,s||0,c);return u.Code!==1?{content:[{type:"text",text:`Error: ${u.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(u.Data||{ok:!0},null,2)}]}}catch(u){return{content:[{type:"text",text:`Error: ${u instanceof Error?u.message:String(u)}`}],isError:!0}}}),i.tool("microi_redis_replace_value",`Create or replace a Redis String/Hash/List/Set/Sorted Set for OsClient "${r}". Existing content is replaced; confirmExecution must equal the exact key or EXECUTE.`,{key:d.string().describe("Exact Redis key."),dataType:d.enum(["string","hash","list","set","sortedset"]).describe("Target Redis data type."),value:d.string().describe("String value, or JSON object/array for collection types."),ttlSeconds:d.number().int().min(-1).optional().describe("-1 permanent, 0 delete immediately, positive seconds. Omit to preserve existing TTL."),database:d.number().int().min(0).max(1023).optional().describe("Redis database index. Default: 0."),connectionId:d.string().optional().describe("Optional saved connection Id. Omit for current tenant Redis."),confirmExecution:d.string().optional().describe("Required. Pass the exact key or EXECUTE.")},async({key:a,dataType:s,value:c,ttlSeconds:l,database:u,connectionId:p,confirmExecution:f})=>{if(f!==a&&f!=="EXECUTE")return{content:[{type:"text",text:JSON.stringify({dryRun:!0,key:a,dataType:s,ttlSeconds:l,database:u||0,connectionId:p||null,valueLength:c.length},null,2)}]};try{let h=await t.replaceRedisValue(a,s,c,u||0,l,p);return h.Code!==1?{content:[{type:"text",text:`Error: ${h.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(h.Data||{ok:!0},null,2)}]}}catch(h){return{content:[{type:"text",text:`Error: ${h instanceof Error?h.message:String(h)}`}],isError:!0}}}),i.tool("microi_redis_rename_key",`Rename a Redis key for OsClient "${r}" without overwriting an existing target. Requires confirmExecution equal to the new key or EXECUTE.`,{key:d.string().describe("Existing Redis key."),newKey:d.string().describe("New Redis key."),database:d.number().int().min(0).max(1023).optional(),connectionId:d.string().optional(),confirmExecution:d.string().optional().describe("Required. Pass newKey or EXECUTE.")},async({key:a,newKey:s,database:c,connectionId:l,confirmExecution:u})=>{if(u!==s&&u!=="EXECUTE")return{content:[{type:"text",text:JSON.stringify({dryRun:!0,action:"rename",key:a,newKey:s,database:c||0},null,2)}]};try{let p=await t.renameRedisKey(a,s,c||0,l);return p.Code!==1?{content:[{type:"text",text:`Error: ${p.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(p.Data||{ok:!0},null,2)}]}}catch(p){return{content:[{type:"text",text:`Error: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_redis_set_ttl",`Set Redis TTL for OsClient "${r}". -1 persists, 0 deletes, positive values are seconds. Requires confirmExecution equal to the key or EXECUTE.`,{key:d.string().describe("Exact Redis key."),ttlSeconds:d.number().int().min(-1).describe("-1 permanent, 0 delete, positive seconds."),database:d.number().int().min(0).max(1023).optional(),connectionId:d.string().optional(),confirmExecution:d.string().optional().describe("Required. Pass key or EXECUTE.")},async({key:a,ttlSeconds:s,database:c,connectionId:l,confirmExecution:u})=>{if(u!==a&&u!=="EXECUTE")return{content:[{type:"text",text:JSON.stringify({dryRun:!0,action:"ttl",key:a,ttlSeconds:s,database:c||0},null,2)}]};try{let p=await t.setRedisTtl(a,s,c||0,l);return p.Code!==1?{content:[{type:"text",text:`Error: ${p.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(p.Data||{ok:!0},null,2)}]}}catch(p){return{content:[{type:"text",text:`Error: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_get_db_schema",`Get database table structures for OsClient "${r}". Returns table names, field names, MySQL column types, labels. ALWAYS call this first before creating tables or adding fields to understand the existing data model.`,{tableName:d.string().optional().describe("Filter tables by name (case-insensitive partial match). Omit to get all tables.")},async({tableName:a})=>{try{let s=await t.getDbSchema();if(s.Code!==1)return{content:[{type:"text",text:`Error: ${s.Msg}`}],isError:!0};let c=s.Data?.Tables||[];if(a){let l=a.toLowerCase();c=c.filter(u=>u.Name.toLowerCase().includes(l)||u.Description&&u.Description.toLowerCase().includes(l))}return{content:[{type:"text",text:aQ(c)}]}}catch(s){return{content:[{type:"text",text:`Error: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}}),i.tool("microi_get_table_indexes",`List normalized physical database indexes for one table in OsClient "${r}". Returns one item per index with ordered Columns, IsUnique and IsPrimary. Use this before changing indexes and again for readback verification.`,{tableName:d.string().min(1).describe("Physical table name, e.g. Biz_Order or sys_apiengine.")},async({tableName:a})=>{try{let s=await t.getTableIndexes(a);return s.Code!==1?{content:[{type:"text",text:`Error: ${s.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify({TableName:a,IndexCount:s.Data?.length||0,Indexes:s.Data||[]},null,2)}]}}catch(s){return{content:[{type:"text",text:`Error: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}}),i.tool("microi_create_table_index",`Create an idempotent physical database index for OsClient "${r}". The backend validates the real table/columns, skips an equivalent existing index, and verifies the result by readback. Indexes created on a diy_table are immediately visible in Microi.Client's \u7D22\u5F15\u7BA1\u7406 dialog. Requires confirmExecution equal to tableName or EXECUTE.`,{tableName:d.string().min(1).describe("Physical table name."),columns:d.array(d.string().min(1)).min(1).max(8).describe("Ordered index columns. Put equality/tenant columns first and range/order columns last."),indexName:d.string().optional().describe("Optional index name. Omit for a stable idx_<table>_<columns> name."),unique:d.boolean().optional().describe("Create a UNIQUE index. Default false. Use only when this is a real business invariant."),confirmExecution:d.string().optional().describe("Required. Pass the exact tableName or EXECUTE.")},async({tableName:a,columns:s,indexName:c,unique:l,confirmExecution:u})=>{if(u!==a&&u!=="EXECUTE")return{content:[{type:"text",text:`\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u521B\u5EFA\u6570\u636E\u5E93\u7D22\u5F15\u4F1A\u6267\u884C DDL\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528\u5E76\u4F20 confirmExecution="${a}" \u6216 "EXECUTE"\u3002`}],isError:!0};try{let p=await t.createTableIndex({TableName:a,Columns:s,IndexName:c,Unique:l});return p.Code!==1?{content:[{type:"text",text:`Error: ${p.Msg}
|
|
543
|
+
${JSON.stringify(a.Data,null,2)}`}]}:{content:[{type:"text",text:`\u26A0\uFE0F Server returned Code=${a.Code}: ${a.Msg}`}]}}catch(a){return{content:[{type:"text",text:`\u274C Connection failed: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}}),i.tool("microi_chat",`Chat with Microi.AI on the MCP-bound server and OsClient "${r}". Uses the current authenticated MCP user, tenant model configuration, local officially-signed Microi License and server-side provider credentials. The tool never accepts identity, OsClient, Endpoint, ApiKey or Authorization overrides. This is a non-streaming MCP result; UI typewriter output is available through V8.AI.ChatStream.`,{question:d.string().min(1).max(32e3).describe("User question or instruction."),systemPrompt:d.string().max(16e3).optional().describe("Optional per-call system guidance; tenant model credentials and endpoint remain server-side."),aiModel:d.string().min(1).max(200).describe("Enabled model display name in the current tenant."),aiModelId:d.string().max(100).optional().describe("Optional mic_ai row Id; preferred when model names may repeat."),relayModel:d.string().max(200).optional().describe("Optional official relay runtime model."),conversationId:d.string().max(100).optional().describe("Optional existing conversation Id owned by the current authenticated user."),reasoningEffort:d.enum(["auto","low","medium","high"]).optional().describe("Reasoning effort for supported models."),mode:d.enum(["chat","data","code","builder","project"]).optional().describe("Conversation mode hint.")},async({question:a,systemPrompt:s,aiModel:c,aiModelId:l,relayModel:u,conversationId:p,reasoningEffort:f,mode:h})=>{try{let m=await t.chat({question:a,systemPrompt:s,aiModel:c,aiModelId:l,relayModel:u,conversationId:p,reasoningEffort:f,mode:h});return{content:[{type:"text",text:typeof m.Data=="string"?m.Data:JSON.stringify(m,null,2)}],structuredContent:{Code:m.Code,Data:m.Data,Msg:m.Msg||""},...m.Code!==1?{isError:!0}:{}}}catch(m){return{content:[{type:"text",text:`Microi.AI chat failed: ${m instanceof Error?m.message:String(m)}`}],isError:!0}}}),i.tool("microi_get_administrative_capabilities",`Verify the current MCP session against the current tenant database and return the authoritative Microi platform-administrator capability/catalog for OsClient "${r}". Requires an interactive DiyToken with Level >= 9999 and an active administrator role; access-key sessions are rejected.`,{},async()=>{try{let a=await t.getAdministrativeCapabilities();return{content:[{type:"text",text:JSON.stringify(a.Data??a,null,2)}],...a.Code!==1?{isError:!0}:{}}}catch(a){return{content:[{type:"text",text:`Error: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}}),i.tool("microi_generate_minimax_music",`Generate one original instrumental music asset through the authenticated Microi AI engine for OsClient "${r}". The server prefers MiniMax music-3.0 and safely falls back to the official open-source MiniMax-Music3 Space only after an explicit 410 retirement response. It keeps provider credentials private, persists the result to tenant HDFS, and uses RequestId for idempotency. This may consume external AI quota, so confirmExecution must exactly equal requestId.`,{requestId:d.string().min(8).max(160).regex(/^[A-Za-z0-9._:-]+$/u).describe("Stable idempotency key. Reuse it for retries of the same prompt."),prompt:d.string().min(1).max(2e3).describe("Original instrumental music brief. Do not request imitation of a living artist or copyrighted recording."),durationSeconds:d.number().int().min(10).max(60).optional().describe("MiniMax-Music3 fallback duration. Default 20 seconds."),confirmExecution:d.string().optional().describe("Required for generation and must exactly equal requestId; omit for a no-cost dry run.")},async({requestId:a,prompt:s,durationSeconds:c,confirmExecution:l})=>{let u={RequestId:a,Prompt:s,Model:"music-3.0",IsInstrumental:!0,SampleRate:44100,Bitrate:256e3,Format:"mp3",DurationSeconds:c||20};if(l!==a)return{content:[{type:"text",text:JSON.stringify({dryRun:!0,payload:u,requiredConfirmation:a},null,2)}]};try{let p=await t.generateMiniMaxMusic(u);return F$(p)&&(p=await z$(t,{apiBaseUrl:e.apiBaseUrl,osClient:r,requestId:a,prompt:s,durationSeconds:c})),{content:[{type:"text",text:JSON.stringify(p,null,2)}],structuredContent:p,...p.Code!==1?{isError:!0}:{}}}catch(p){return{content:[{type:"text",text:`MiniMax music generation failed: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_generate_minimax_speech",`Generate one original Chinese game voice line through the authenticated Microi AI engine for OsClient "${r}". The server fixes MiniMax speech-2.8-hd, approved system voices and mono MP3 output, keeps provider credentials private, persists the result to tenant HDFS, and uses RequestId for idempotency. This consumes an external AI quota, so confirmExecution must exactly equal requestId.`,{requestId:d.string().min(8).max(160).regex(/^[A-Za-z0-9._:-]+$/u).describe("Stable idempotency key. Reuse it for retries of the same line."),text:d.string().min(1).max(800).describe("Chinese voice line, normally one short gameplay announcement."),speaker:d.enum(["female","male"]).optional().describe("Approved system voice gender. Default female."),speed:d.number().min(.8).max(1.2).optional(),volume:d.number().min(.8).max(1.2).optional(),pitch:d.number().int().min(-2).max(2).optional(),emotion:d.enum(["calm","happy","sad","surprised"]).optional(),confirmExecution:d.string().optional().describe("Required for generation and must exactly equal requestId; omit for a no-cost dry run.")},async({requestId:a,text:s,speaker:c,speed:l,volume:u,pitch:p,emotion:f,confirmExecution:h})=>{let m={RequestId:a,Text:s,Speaker:c||"female",Model:"speech-2.8-hd",Speed:l??1,Volume:u??1,Pitch:p??0,Emotion:f||"calm",SampleRate:32e3,Bitrate:128e3,Channel:1,Format:"mp3"};if(h!==a)return{content:[{type:"text",text:JSON.stringify({dryRun:!0,payload:m,requiredConfirmation:a},null,2)}]};try{let g=await t.generateMiniMaxSpeech(m);return{content:[{type:"text",text:JSON.stringify(g,null,2)}],structuredContent:g,...g.Code!==1?{isError:!0}:{}}}catch(g){return{content:[{type:"text",text:`MiniMax speech generation failed: ${g instanceof Error?g.message:String(g)}`}],isError:!0}}}),i.tool("microi_ocr_recognize",`Recognize text in one image or PDF through the authenticated Microi OCR gateway for OsClient "${r}". Provide exactly one of filePath (absolute local regular file, symlinks rejected) or fileByteBase64. This transmits document bytes to the OCR provider configured by the tenant administrator, so confirmExecution="OCR" is mandatory. Endpoint, Provider, ApiKey, headers, Authorization and OsClient overrides are never accepted. Audit logs contain only safe filename, byte count, SHA-256 and option flags\u2014not the local path, file bytes, recognized text or credentials.`,{filePath:d.string().max(32767).optional().describe("Absolute local path to one PDF/image. Mutually exclusive with fileByteBase64; symlinks and non-regular files are rejected."),fileByteBase64:d.string().max(Dx).optional().describe("PDF/image Base64 or data URI. Mutually exclusive with filePath; backend validates file magic and tenant limits again."),fileName:d.string().max(255).optional().describe("Optional safe filename. For filePath, the basename is used when omitted."),useDocOrientationClassify:d.boolean().optional().describe("Enable document orientation classification when supported by the configured pipeline."),useDocUnwarping:d.boolean().optional().describe("Enable document unwarping when supported by the configured pipeline."),useTextlineOrientation:d.boolean().optional().describe("Enable text-line orientation classification when supported by the configured pipeline."),textRecScoreThresh:d.number().min(0).max(1).optional().describe("Per-call recognition threshold, 0..1. It can only raise the tenant minimum."),returnWordBox:d.boolean().optional().describe("Ask the provider for word-level boxes when supported."),includePages:d.boolean().optional().describe("Include bounded page texts. Default false to keep MCP output compact."),includeRegions:d.boolean().optional().describe("Include region polygons/confidence and implicitly include pages. Default false."),maxTextChars:d.number().int().min(1e3).max(2e5).optional().describe("Maximum characters for full text and cumulative page text; default 100000."),confirmExecution:d.string().optional().describe("Required because document bytes leave MCP for the tenant-configured OCR provider. Use exactly OCR.")},async({filePath:a,fileByteBase64:s,fileName:c,useDocOrientationClassify:l,useDocUnwarping:u,useTextlineOrientation:p,textRecScoreThresh:f,returnWordBox:h,includePages:m,includeRegions:g,maxTextChars:y,confirmExecution:v})=>{try{if(v!=="OCR")return{content:[{type:"text",text:'\u6267\u884C\u5DF2\u62E6\u622A\uFF1Amicroi_ocr_recognize \u4F1A\u628A\u6587\u6863\u53D1\u9001\u5230\u5F53\u524D\u79DF\u6237\u7BA1\u7406\u5458\u914D\u7F6E\u7684 OCR \u670D\u52A1\uFF0C\u8BF7\u786E\u8BA4\u8BE5\u6587\u4EF6\u5141\u8BB8\u5904\u7406\u540E\u91CD\u65B0\u8C03\u7528\u5E76\u4F20 confirmExecution="OCR"\u3002'}],isError:!0};let x=Fx({filePath:a,fileByteBase64:s,fileName:c,useDocOrientationClassify:l,useDocUnwarping:u,useTextlineOrientation:p,textRecScoreThresh:f,returnWordBox:h});await t.writeAuditLog("microi_ocr_recognize",x.auditFileName,JSON.stringify({byteLength:x.byteLength,sha256:x.sha256,useDocOrientationClassify:l,useDocUnwarping:u,useTextlineOrientation:p,textRecScoreThresh:f,returnWordBox:h,includePages:!!(m||g),includeRegions:!!g}));let b=await t.recognizeOcr(x.request),_=zx(b.Data,{includePages:!!(m||g),includeRegions:!!g,maxTextChars:y}),E={Code:b.Code,Data:_,Msg:b.Msg||""};return{content:[{type:"text",text:JSON.stringify(E,null,2)}],structuredContent:E,isError:b.Code!==1}}catch(x){return{content:[{type:"text",text:`OCR failed: ${x instanceof Error?x.message:String(x)}`}],isError:!0}}}),i.tool("microi_translate",`Translate one text or a bounded batch through the authenticated Microi translation gateway for OsClient "${r}". Provide exactly one of sourceText/sourceTexts. Supports source auto-detection, text/HTML and up to 10 alternatives when the tenant uses LibreTranslate. Provider URL, API key, Authorization and OsClient are always server-side and cannot be overridden.`,{sourceText:d.string().max(5e4).optional().describe("One source text. Mutually exclusive with sourceTexts."),sourceTexts:d.array(d.string().min(1).max(5e4)).max(50).optional().describe("Up to 50 texts and 200000 total characters. Mutually exclusive with sourceText."),fromLang:d.string().max(32).optional().default("auto").describe("Source language code or auto."),targetLang:d.string().min(1).max(32).describe("Target language code."),format:d.enum(["text","html"]).optional().default("text").describe("Source format."),alternatives:d.number().int().min(0).max(10).optional().default(0).describe("Preferred alternative translation count.")},async({sourceText:a,sourceTexts:s,fromLang:c,targetLang:l,format:u,alternatives:p})=>{try{let f=!!a?.trim(),h=!!s?.length;if(f===h)throw new Error("sourceText \u4E0E sourceTexts \u5FC5\u987B\u4E14\u53EA\u80FD\u63D0\u4F9B\u4E00\u4E2A\u3002");if(s&&s.reduce((y,v)=>y+v.length,0)>2e5)throw new Error("sourceTexts \u603B\u5B57\u7B26\u6570\u4E0D\u80FD\u8D85\u8FC7 200000\u3002");let m=await t.translateText({...f?{SourceText:a}:{SourceTexts:s},FromLang:c||"auto",Lang:l,Format:u||"text",Alternatives:p||0}),g={Code:m.Code,Data:m.Data,Msg:m.Msg||""};return{content:[{type:"text",text:JSON.stringify(g,null,2)}],structuredContent:g,...m.Code!==1?{isError:!0}:{}}}catch(f){return{content:[{type:"text",text:`Translate failed: ${f instanceof Error?f.message:String(f)}`}],isError:!0}}}),i.tool("microi_detect_language",`Detect the language of one text before a translate operation through the authenticated Microi translation gateway for OsClient "${r}". The text is sent only to the provider configured by the tenant administrator; caller-supplied endpoint, key and OsClient fields are ignored.`,{sourceText:d.string().min(1).max(5e4).describe("Text whose language should be detected.")},async({sourceText:a})=>{try{let s=await t.detectLanguage(a),c={Code:s.Code,Data:s.Data,Msg:s.Msg||""};return{content:[{type:"text",text:JSON.stringify(c,null,2)}],structuredContent:c,...s.Code!==1?{isError:!0}:{}}}catch(s){return{content:[{type:"text",text:`Language detection failed: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}}),i.tool("microi_list_translate_languages",`List the current tenant translation provider's installed source languages and exact reachable target codes for OsClient "${r}". No provider credentials or internal endpoint are returned.`,{},async()=>{try{let a=await t.listTranslateLanguages(),s={Code:a.Code,Data:a.Data,Msg:a.Msg||""};return{content:[{type:"text",text:JSON.stringify(s,null,2)}],structuredContent:s,...a.Code!==1?{isError:!0}:{}}}catch(a){return{content:[{type:"text",text:`List translation languages failed: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}}),i.tool("microi_translate_file",`Translate one supported document through the authenticated Microi translation gateway for OsClient "${r}". Provide exactly one input (absolute non-symlink filePath or Base64+fileName) and exactly one output mode (new absolute outputFilePath or includeFileByteBase64=true for results up to 2 MB). Document bytes leave MCP for the tenant-configured provider, so confirmExecution="TRANSLATE_FILE" is mandatory. Endpoint, API key, Authorization and OsClient overrides are never accepted; audit logs contain hashes and sizes, never paths or document content.`,{filePath:d.string().max(32767).optional().describe("Absolute local source file path. Mutually exclusive with fileByteBase64."),fileByteBase64:d.string().max(qx).optional().describe("Source document Base64/data URI. Mutually exclusive with filePath."),fileName:d.string().max(255).optional().describe("Required for Base64; optional safe override for filePath."),fromLang:d.string().max(32).optional().default("auto").describe("Source language code or auto."),targetLang:d.string().min(1).max(32).describe("Target language code."),outputFilePath:d.string().max(32767).optional().describe("New absolute local file path. Existing files and symlink parent directories are rejected."),includeFileByteBase64:d.boolean().optional().default(!1).describe("Return Base64 inline only for translated results up to 2 MB. Mutually exclusive with outputFilePath."),confirmExecution:d.string().optional().describe("Required exact value: TRANSLATE_FILE.")},async({filePath:a,fileByteBase64:s,fileName:c,fromLang:l,targetLang:u,outputFilePath:p,includeFileByteBase64:f,confirmExecution:h})=>{try{if(h!=="TRANSLATE_FILE")return{content:[{type:"text",text:'\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u6587\u4EF6\u4F1A\u53D1\u9001\u5230\u5F53\u524D\u79DF\u6237\u914D\u7F6E\u7684\u7FFB\u8BD1\u670D\u52A1\uFF1B\u786E\u8BA4\u540E\u8BF7\u4F20 confirmExecution="TRANSLATE_FILE"\u3002'}],isError:!0};if(!!p?.trim()==!!f)throw new Error("outputFilePath \u4E0E includeFileByteBase64=true \u5FC5\u987B\u4E14\u53EA\u80FD\u9009\u62E9\u4E00\u79CD\u8F93\u51FA\u65B9\u5F0F\u3002");let m=Vx({filePath:a,fileByteBase64:s,fileName:c,fromLang:l,targetLang:u});if(f&&m.byteLength>jx)throw new Error("\u6E90\u6587\u4EF6\u8D85\u8FC7 2 MB\uFF0C\u8BF7\u4F7F\u7528 outputFilePath\uFF0C\u907F\u514D\u5927 Base64 \u8FDB\u5165 MCP \u4E0A\u4E0B\u6587\u3002");await t.writeAuditLog("microi_translate_file",m.auditFileName,JSON.stringify({byteLength:m.byteLength,sha256:m.sha256,fromLang:m.request.FromLang,targetLang:m.request.Lang,outputMode:p?"local-file":"inline-base64"}));let g=await t.translateFile(m.request);if(g.Code!==1){let _={Code:g.Code,Data:null,Msg:g.Msg||""};return{content:[{type:"text",text:JSON.stringify(_,null,2)}],structuredContent:_,isError:!0}}let y=Bx(g.Data);if(f&&y.length>jx)throw new Error("\u8BD1\u540E\u6587\u4EF6\u8D85\u8FC7 2 MB\uFF0C\u8BF7\u6539\u7528 outputFilePath\u3002");let v=et.default.createHash("sha256").update(y).digest("hex"),x={Provider:g.Data?.Provider,FileName:g.Data?.FileName,ContentType:g.Data?.ContentType,ByteLength:y.length,Sha256:v};p?x.SavedToPath=N4(p,y):x.FileByteBase64=y.toString("base64");let b={Code:1,Data:x,Msg:g.Msg||""};return{content:[{type:"text",text:JSON.stringify(b,null,2)}],structuredContent:b}}catch(m){return{content:[{type:"text",text:`File translation failed: ${m instanceof Error?m.message:String(m)}`}],isError:!0}}}),i.tool("microi_suggest_translation",`Submit a translation improvement suggestion to the current tenant's LibreTranslate-compatible provider. This mutates provider-side suggestion data and requires confirmExecution="TRANSLATE_SUGGEST". Audit logs contain only text lengths and SHA-256 values; source/suggestion text, endpoint, credentials and tenant secrets are never logged or caller-overridable.`,{sourceText:d.string().min(1).max(5e4).describe("Original source text."),suggestedText:d.string().min(1).max(5e4).describe("Proposed translated text."),fromLang:d.string().min(1).max(32).describe("Explicit source language; auto is not accepted."),targetLang:d.string().min(1).max(32).describe("Target language."),confirmExecution:d.string().optional().describe("Required exact value: TRANSLATE_SUGGEST.")},async({sourceText:a,suggestedText:s,fromLang:c,targetLang:l,confirmExecution:u})=>{try{if(u!=="TRANSLATE_SUGGEST")return{content:[{type:"text",text:'\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u5EFA\u8BAE\u4F1A\u5199\u5165\u7FFB\u8BD1\u670D\u52A1\uFF1B\u786E\u8BA4\u540E\u8BF7\u4F20 confirmExecution="TRANSLATE_SUGGEST"\u3002'}],isError:!0};await t.writeAuditLog("microi_suggest_translation",`${c}->${l}`,JSON.stringify({sourceLength:a.length,sourceSha256:et.default.createHash("sha256").update(a,"utf8").digest("hex"),suggestionLength:s.length,suggestionSha256:et.default.createHash("sha256").update(s,"utf8").digest("hex")}));let p=await t.suggestTranslation({SourceText:a,SuggestedText:s,FromLang:c,Lang:l}),f={Code:p.Code,Data:p.Data,Msg:p.Msg||""};return{content:[{type:"text",text:JSON.stringify(f,null,2)}],structuredContent:f,...p.Code!==1?{isError:!0}:{}}}catch(p){return{content:[{type:"text",text:`Translation suggestion failed: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_get_translate_health","Read a safe health/capability summary for the current tenant's translation gateway. It returns provider name, status and supported business operations, but never the internal URL, API key or frontend/metrics settings.",{},async()=>{try{let a=await t.getTranslateHealth(),s={Code:a.Code,Data:a.Data,Msg:a.Msg||""};return{content:[{type:"text",text:JSON.stringify(s,null,2)}],structuredContent:s,...a.Code!==1?{isError:!0}:{}}}catch(a){return{content:[{type:"text",text:`Translation health failed: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}}),i.tool("microi_transition_application_stream_gate","Preview or execute one application-stream gate transition for the exact MCP-bound tenant coordinate. Allowed transitions are LegacyOpen -> Drain, Drain -> V3Only, and the safety rollback Drain -> LegacyOpen; every successful transition must advance the server epoch. V3Only never permits downgrade. The first call never reaches the server and returns ConfirmationSha256. A server call is possible only when confirmExecution=true and confirmationSha256 exactly matches that preview; the server must independently recompute the same hash.",{osClient:d.string().min(1).max(100).describe("Exact OsClient from the active MCP coordinate."),osClientType:d.string().max(100).describe("Exact OsClientType from the active MCP coordinate; pass an explicit empty string when unset."),osClientNetwork:d.string().max(100).describe("Exact OsClientNetwork from the active MCP coordinate; pass an explicit empty string when unset."),expectedMode:d.enum(["LegacyOpen","Drain","V3Only"]).describe("Compare-and-swap source mode."),expectedMinProtocol:d.union([d.literal(2),d.literal(3)]).describe("Compare-and-swap source minimum protocol."),expectedGateEpoch:d.string().describe("Canonical non-negative Int64 decimal string; no leading zeroes."),targetMode:d.enum(["LegacyOpen","Drain","V3Only"]).describe("Target mode. Drain -> LegacyOpen is the only rollback and still advances the gate epoch; V3Only cannot transition."),transitionId:d.string().min(8).max(100).describe("Stable idempotency/audit identifier."),reason:d.string().min(1).max(1e3).describe("Auditable transition reason with no leading/trailing whitespace."),drainProofJson:d.string().min(2).max(1024*1024).describe("Canonical JSON object proving the drain observation."),drainProofHash:d.string().length(64).describe("Lowercase SHA-256 of the exact UTF-8 DrainProofJson bytes."),confirmExecution:d.boolean().optional().describe("Omit/false for preview. Only literal true can execute."),confirmationSha256:d.string().optional().describe("Exact lowercase ConfirmationSha256 returned by the preview of this unchanged payload.")},async({osClient:a,osClientType:s,osClientNetwork:c,expectedMode:l,expectedMinProtocol:u,expectedGateEpoch:p,targetMode:f,transitionId:h,reason:m,drainProofJson:g,drainProofHash:y,confirmExecution:v,confirmationSha256:x})=>{let b=!1;try{let _=OY({osClient:a,osClientType:s,osClientNetwork:c,expectedMode:l,expectedMinProtocol:u,expectedGateEpoch:p,targetMode:f,transitionId:h,reason:m,drainProofJson:g,drainProofHash:y},e),E={Preview:!0,RemoteWriteAttempted:!1,ConfirmationSha256:_.confirmationSha256,Transition:_.payload,Next:"Repeat the unchanged payload with confirmExecution=true and confirmationSha256 exactly equal to ConfirmationSha256."};if(v!==!0)return{content:[{type:"text",text:JSON.stringify(E,null,2)}]};if(x!==_.confirmationSha256)return{content:[{type:"text",text:JSON.stringify({...E,Error:"confirmationSha256 \u4E0E\u5F53\u524D\u89C4\u8303\u5316\u8F6C\u6362\u8F7D\u8377\u4E0D\u5B8C\u5168\u4E00\u81F4\uFF1B\u672A\u8C03\u7528\u670D\u52A1\u5668\u3002"},null,2)}],isError:!0};b=!0;let w=await t.transitionApplicationStreamGate({..._.payload,ConfirmationSha256:_.confirmationSha256,ConfirmExecution:!0});return w.Code!==1?{content:[{type:"text",text:JSON.stringify({Preview:!1,RemoteWriteAttempted:!0,ConfirmationSha256:_.confirmationSha256,Transition:_.payload,Result:w},null,2)}],isError:!0}:{content:[{type:"text",text:JSON.stringify({Preview:!1,RemoteWriteAttempted:!0,ConfirmationSha256:_.confirmationSha256,Transition:_.payload,Result:w},null,2)}]}}catch(_){return{content:[{type:"text",text:JSON.stringify({Preview:!b,RemoteWriteAttempted:b,OutcomeUncertain:b,Error:_ instanceof Error?_.message:String(_)},null,2)}],isError:!0}}}),i.tool("microi_list_my_access_keys",`List the current authenticated user's access keys for OsClient "${r}". The response contains only public metadata and never returns the credential or its hash. Access-key sessions cannot manage keys. Requires confirmExecution="LIST" because key prefixes and usage metadata are security-sensitive.`,{confirmExecution:d.string().optional().describe("Required. Pass LIST.")},async({confirmExecution:a})=>{if(a!=="LIST")return{content:[{type:"text",text:'\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u8BBF\u95EE\u5BC6\u94A5\u5217\u8868\u5305\u542B\u5B89\u5168\u5143\u6570\u636E\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528\u5E76\u4F20 confirmExecution="LIST"\u3002'}],isError:!0};try{let s=await t.listMyUserAccessKeys();return s.Code!==1?{content:[{type:"text",text:`\u8BFB\u53D6\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${s.Msg||`Code=${s.Code}`}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(s.Data||[],null,2)}]}}catch(s){return{content:[{type:"text",text:`\u8BFB\u53D6\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${s instanceof Error?s.message:String(s)}`}],isError:!0}}}),i.tool("microi_create_my_access_key",`Create one revocable, bounded access key for the current authenticated user on OsClient "${r}". This is not a permanent admin/MCP bypass: the backend stores only a SHA-256 hash, returns plaintext exactly once, and exchanges the key for a short scoped session. The MCP surface never creates permanent keys; omitting expiresAt uses the backend's bounded default (currently 90 days). Omit scopes for the minimum page:open + form:read permissions. For a browser kiosk, combine the one-time AccessKey with the Microi.Client frontend origin using /?OsClient=${encodeURIComponent(r)}#/access-login?access_key=<AccessKey>&redirect=<encodeURIComponent(redirectPath)>; do not use the API origin and do not append the key to the destination page. The first call is a dry confirmation step and returns RequiredConfirmationSha256; repeat the exact same payload with confirmExecution equal to that SHA-256.`,{name:d.string().min(1).max(200).describe("Human-readable key name."),allowedRoutes:d.array(d.string().min(1).max(500)).min(1).max(100).describe("Exact allowed routes. Use * only after explicit risk review."),allowedTableNames:d.array(d.string().min(1).max(200)).min(1).max(100).describe("Exact table names. Use * only after explicit risk review."),scopes:d.array(d.enum(["page:open","form:read","api-engine:run","data-source:run","file:read"])).min(1).max(5).optional().describe("Omit for minimum page:open + form:read. MCP does not expose form:write/form:export until the backend path facade supports them."),redirectPath:d.string().max(500).optional().describe("Internal Hash route beginning with /; must be included in allowedRoutes. Example: /mic/data-dashboard/preview/01KK988A0YPHKAM8SF216917HX. MCP URL-encodes the entire value into the browser login redirect parameter."),allowedApiEngineKeys:d.array(d.string().min(1).max(200)).max(100).optional().describe("Exact keys; required only with api-engine:run. Wildcards are rejected."),allowedDataSourceKeys:d.array(d.string().min(1).max(200)).max(100).optional().describe("Exact keys; required only with data-source:run. Wildcards are rejected."),expiresAt:d.string().optional().describe("Optional server-local expiry time, later than now and no more than 365 days. Omit for the bounded default."),remark:d.string().max(1e3).optional(),confirmExecution:d.string().optional().describe("Required for the real create. First omit it; then pass the returned RequiredConfirmationSha256 with the exact same payload.")},async({name:a,allowedRoutes:s,allowedTableNames:c,scopes:l,redirectPath:u,allowedApiEngineKeys:p,allowedDataSourceKeys:f,expiresAt:h,remark:m,confirmExecution:g})=>{let y=eQ({name:a,allowedRoutes:s,allowedTableNames:c,scopes:l,redirectPath:u,allowedApiEngineKeys:p,allowedDataSourceKeys:f,expiresAt:h,remark:m});if(String(g||"").trim().toLowerCase()!==y.sha256)return{content:[{type:"text",text:JSON.stringify({Blocked:!0,Message:"\u521B\u5EFA\u8BBF\u95EE\u5BC6\u94A5\u4F1A\u4EA7\u751F\u65B0\u7684\u767B\u5F55\u51ED\u636E\u3002\u8BF7\u6838\u5BF9\u4EE5\u4E0B\u89C4\u8303\u5316\u6743\u9650\u8F7D\u8377\uFF0C\u5E76\u4F7F\u7528\u5BF9\u5E94 SHA-256 \u786E\u8BA4\u3002",NormalizedGrant:y.normalized,RequiredConfirmationSha256:y.sha256,Next:"\u4FDD\u6301\u5176\u5B83\u53C2\u6570\u5B8C\u5168\u4E0D\u53D8\uFF0C\u5E76\u5C06 confirmExecution \u8BBE\u7F6E\u4E3A RequiredConfirmationSha256\u3002"},null,2)}],isError:!0};try{let v=await t.createMyUserAccessKey({name:y.normalized.name,allowedRoutes:y.normalized.allowedRoutes,allowedTableNames:y.normalized.allowedTableNames,scopes:y.normalized.scopes,redirectPath:y.normalized.redirectPath||void 0,allowedApiEngineKeys:y.normalized.allowedApiEngineKeys,allowedDataSourceKeys:y.normalized.allowedDataSourceKeys,expiresAt:y.normalized.expiresAt||void 0,remark:y.normalized.remark||void 0});if(v.Code!==1||!v.Data?.AccessKey)return{content:[{type:"text",text:`\u521B\u5EFA\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${v.Msg||`Code=${v.Code}`}`}],isError:!0};let x=QY(r,y.normalized.redirectPath);return{content:[{type:"text",text:JSON.stringify({AccessKey:v.Data.AccessKey,Record:v.Data.Record||null,Notice:"\u660E\u6587\u4EC5\u672C\u6B21\u8FD4\u56DE\u3002\u8BF7\u7ACB\u5373\u5B58\u5165\u5B89\u5168\u51ED\u636E\u5E93\uFF1B\u540E\u7EED\u5217\u8868\u548C\u65E5\u5FD7\u4E0D\u4F1A\u518D\u6B21\u663E\u793A\u3002",LoginUrlRelativeTemplate:x.relative,LoginUrlTemplate:x.absolute,LoginUrlNotice:"\u8BF7\u7528 Microi.Client \u524D\u7AEF\u57DF\u540D\u66FF\u6362\u5360\u4F4D\u7B26\uFF0C\u5E76\u7528\u672C\u6B21 AccessKey \u66FF\u6362 <AccessKey>\u3002\u56FA\u5B9A\u7EC8\u7AEF\u5E94\u4FDD\u5B58\u5B8C\u6574 access-login \u542F\u52A8\u94FE\u63A5\uFF1B\u767B\u5F55\u540E\u76EE\u6807\u9875\u9762\u4E0D\u518D\u663E\u793A access_key \u5C5E\u4E8E\u6B63\u5E38\u7684\u5B89\u5168\u6E05\u7406\u3002"},null,2)}]}}catch(v){return{content:[{type:"text",text:`\u521B\u5EFA\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${v instanceof Error?v.message:String(v)}`}],isError:!0}}}),i.tool("microi_revoke_my_access_key",`Revoke one access key owned by the current authenticated user on OsClient "${r}". Revocation is idempotent and invalidates the shared runtime cache. Requires confirmExecution equal to id. For rotation, create a new bounded key first, securely store its one-time plaintext, then revoke the old id.`,{id:d.string().min(1).max(100).describe("Access key record Id from microi_list_my_access_keys."),confirmExecution:d.string().optional().describe("Required. Pass the exact id.")},async({id:a,confirmExecution:s})=>{if(s!==a)return{content:[{type:"text",text:`\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u540A\u9500\u540E\u8BE5\u8BBF\u95EE\u5BC6\u94A5\u5C06\u7ACB\u5373\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528\u5E76\u4F20 confirmExecution="${a}"\u3002`}],isError:!0};try{let c=await t.revokeMyUserAccessKey(a);return c.Code!==1?{content:[{type:"text",text:`\u540A\u9500\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${c.Msg||`Code=${c.Code}`}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify({Id:a,Revoked:!0,Record:c.Data||null,Message:c.Msg||"\u8BBF\u95EE\u5BC6\u94A5\u5DF2\u540A\u9500\u3002"},null,2)}]}}catch(c){return{content:[{type:"text",text:`\u540A\u9500\u8BBF\u95EE\u5BC6\u94A5\u5931\u8D25\uFF1A${c instanceof Error?c.message:String(c)}`}],isError:!0}}}),i.tool("microi_redis_statistics",`Get Redis server/keyspace statistics for OsClient "${r}". Uses the current tenant Redis by default; pass connectionId only for a connection previously saved in mci_redis_connection. Never pass Redis passwords through MCP.`,{database:d.number().int().min(0).max(1023).optional().describe("Redis database index. Default: 0."),connectionId:d.string().optional().describe("Optional saved mci_redis_connection Id. Omit for current tenant Redis.")},async({database:a,connectionId:s})=>{try{let c=await t.getRedisStatistics(a||0,s);return c.Code!==1?{content:[{type:"text",text:`Error: ${c.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(c.Data,null,2)}]}}catch(c){return{content:[{type:"text",text:`Error: ${c instanceof Error?c.message:String(c)}`}],isError:!0}}}),i.tool("microi_redis_list_keys",`SCAN Redis keys for OsClient "${r}" without using blocking KEYS. Returns type, TTL, memory estimate and an opaque next cursor.`,{pattern:d.string().optional().describe("Redis glob pattern. Plain text is treated as a contains search. Default: *."),database:d.number().int().min(0).max(1023).optional().describe("Redis database index. Default: 0."),pageSize:d.number().int().min(10).max(500).optional().describe("Page size. Default: 100."),cursor:d.string().optional().describe("Opaque NextCursor from the previous call."),connectionId:d.string().optional().describe("Optional saved connection Id. Omit for current tenant Redis.")},async({pattern:a,database:s,pageSize:c,cursor:l,connectionId:u})=>{try{let p=await t.getRedisKeys(a||"*",s||0,c||100,l,u);return p.Code!==1?{content:[{type:"text",text:`Error: ${p.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(p.Data,null,2)}]}}catch(p){return{content:[{type:"text",text:`Error: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_redis_get_key",`Read one Redis key for OsClient "${r}". Supports String, Hash, List, Set, Sorted Set and Stream with bounded pagination.`,{key:d.string().describe("Exact Redis key."),database:d.number().int().min(0).max(1023).optional().describe("Redis database index. Default: 0."),pageIndex:d.number().int().min(1).optional().describe("Collection page index. Default: 1."),pageSize:d.number().int().min(10).max(1e3).optional().describe("Collection page size. Default: 500."),connectionId:d.string().optional().describe("Optional saved connection Id. Omit for current tenant Redis.")},async({key:a,database:s,pageIndex:c,pageSize:l,connectionId:u})=>{try{let p=await t.getRedisKey(a,s||0,c||1,l||500,u);return p.Code!==1?{content:[{type:"text",text:`Error: ${p.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(p.Data,null,2)}]}}catch(p){return{content:[{type:"text",text:`Error: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_redis_delete_keys",`Delete up to 500 Redis keys for OsClient "${r}". This is irreversible and requires confirmExecution="DELETE".`,{keys:d.array(d.string()).min(1).max(500).describe("Exact Redis keys to delete."),database:d.number().int().min(0).max(1023).optional().describe("Redis database index. Default: 0."),connectionId:d.string().optional().describe("Optional saved connection Id. Omit for current tenant Redis."),confirmExecution:d.string().optional().describe("Required. Pass DELETE after reviewing the key list.")},async({keys:a,database:s,connectionId:c,confirmExecution:l})=>{if(l!=="DELETE")return{content:[{type:"text",text:JSON.stringify({dryRun:!0,action:"delete",database:s||0,connectionId:c||null,keys:a},null,2)}]};try{let u=await t.deleteRedisKeys(a,s||0,c);return u.Code!==1?{content:[{type:"text",text:`Error: ${u.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(u.Data||{ok:!0},null,2)}]}}catch(u){return{content:[{type:"text",text:`Error: ${u instanceof Error?u.message:String(u)}`}],isError:!0}}}),i.tool("microi_redis_replace_value",`Create or replace a Redis String/Hash/List/Set/Sorted Set for OsClient "${r}". Existing content is replaced; confirmExecution must equal the exact key or EXECUTE.`,{key:d.string().describe("Exact Redis key."),dataType:d.enum(["string","hash","list","set","sortedset"]).describe("Target Redis data type."),value:d.string().describe("String value, or JSON object/array for collection types."),ttlSeconds:d.number().int().min(-1).optional().describe("-1 permanent, 0 delete immediately, positive seconds. Omit to preserve existing TTL."),database:d.number().int().min(0).max(1023).optional().describe("Redis database index. Default: 0."),connectionId:d.string().optional().describe("Optional saved connection Id. Omit for current tenant Redis."),confirmExecution:d.string().optional().describe("Required. Pass the exact key or EXECUTE.")},async({key:a,dataType:s,value:c,ttlSeconds:l,database:u,connectionId:p,confirmExecution:f})=>{if(f!==a&&f!=="EXECUTE")return{content:[{type:"text",text:JSON.stringify({dryRun:!0,key:a,dataType:s,ttlSeconds:l,database:u||0,connectionId:p||null,valueLength:c.length},null,2)}]};try{let h=await t.replaceRedisValue(a,s,c,u||0,l,p);return h.Code!==1?{content:[{type:"text",text:`Error: ${h.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(h.Data||{ok:!0},null,2)}]}}catch(h){return{content:[{type:"text",text:`Error: ${h instanceof Error?h.message:String(h)}`}],isError:!0}}}),i.tool("microi_redis_rename_key",`Rename a Redis key for OsClient "${r}" without overwriting an existing target. Requires confirmExecution equal to the new key or EXECUTE.`,{key:d.string().describe("Existing Redis key."),newKey:d.string().describe("New Redis key."),database:d.number().int().min(0).max(1023).optional(),connectionId:d.string().optional(),confirmExecution:d.string().optional().describe("Required. Pass newKey or EXECUTE.")},async({key:a,newKey:s,database:c,connectionId:l,confirmExecution:u})=>{if(u!==s&&u!=="EXECUTE")return{content:[{type:"text",text:JSON.stringify({dryRun:!0,action:"rename",key:a,newKey:s,database:c||0},null,2)}]};try{let p=await t.renameRedisKey(a,s,c||0,l);return p.Code!==1?{content:[{type:"text",text:`Error: ${p.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(p.Data||{ok:!0},null,2)}]}}catch(p){return{content:[{type:"text",text:`Error: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_redis_set_ttl",`Set Redis TTL for OsClient "${r}". -1 persists, 0 deletes, positive values are seconds. Requires confirmExecution equal to the key or EXECUTE.`,{key:d.string().describe("Exact Redis key."),ttlSeconds:d.number().int().min(-1).describe("-1 permanent, 0 delete, positive seconds."),database:d.number().int().min(0).max(1023).optional(),connectionId:d.string().optional(),confirmExecution:d.string().optional().describe("Required. Pass key or EXECUTE.")},async({key:a,ttlSeconds:s,database:c,connectionId:l,confirmExecution:u})=>{if(u!==a&&u!=="EXECUTE")return{content:[{type:"text",text:JSON.stringify({dryRun:!0,action:"ttl",key:a,ttlSeconds:s,database:c||0},null,2)}]};try{let p=await t.setRedisTtl(a,s,c||0,l);return p.Code!==1?{content:[{type:"text",text:`Error: ${p.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(p.Data||{ok:!0},null,2)}]}}catch(p){return{content:[{type:"text",text:`Error: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_get_db_schema",`Get database table structures for OsClient "${r}". Returns table names, field names, MySQL column types, labels. ALWAYS call this first before creating tables or adding fields to understand the existing data model.`,{tableName:d.string().optional().describe("Filter tables by name (case-insensitive partial match). Omit to get all tables.")},async({tableName:a})=>{try{let s=await t.getDbSchema();if(s.Code!==1)return{content:[{type:"text",text:`Error: ${s.Msg}`}],isError:!0};let c=s.Data?.Tables||[];if(a){let l=a.toLowerCase();c=c.filter(u=>u.Name.toLowerCase().includes(l)||u.Description&&u.Description.toLowerCase().includes(l))}return{content:[{type:"text",text:aQ(c)}]}}catch(s){return{content:[{type:"text",text:`Error: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}}),i.tool("microi_get_table_indexes",`List normalized physical database indexes for one table in OsClient "${r}". Returns one item per index with ordered Columns, IsUnique and IsPrimary. Use this before changing indexes and again for readback verification.`,{tableName:d.string().min(1).describe("Physical table name, e.g. Biz_Order or sys_apiengine.")},async({tableName:a})=>{try{let s=await t.getTableIndexes(a);return s.Code!==1?{content:[{type:"text",text:`Error: ${s.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify({TableName:a,IndexCount:s.Data?.length||0,Indexes:s.Data||[]},null,2)}]}}catch(s){return{content:[{type:"text",text:`Error: ${s instanceof Error?s.message:String(s)}`}],isError:!0}}}),i.tool("microi_create_table_index",`Create an idempotent physical database index for OsClient "${r}". The backend validates the real table/columns, skips an equivalent existing index, and verifies the result by readback. Indexes created on a diy_table are immediately visible in Microi.Client's \u7D22\u5F15\u7BA1\u7406 dialog. Requires confirmExecution equal to tableName or EXECUTE.`,{tableName:d.string().min(1).describe("Physical table name."),columns:d.array(d.string().min(1)).min(1).max(8).describe("Ordered index columns. Put equality/tenant columns first and range/order columns last."),indexName:d.string().optional().describe("Optional index name. Omit for a stable idx_<table>_<columns> name."),unique:d.boolean().optional().describe("Create a UNIQUE index. Default false. Use only when this is a real business invariant."),confirmExecution:d.string().optional().describe("Required. Pass the exact tableName or EXECUTE.")},async({tableName:a,columns:s,indexName:c,unique:l,confirmExecution:u})=>{if(u!==a&&u!=="EXECUTE")return{content:[{type:"text",text:`\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u521B\u5EFA\u6570\u636E\u5E93\u7D22\u5F15\u4F1A\u6267\u884C DDL\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528\u5E76\u4F20 confirmExecution="${a}" \u6216 "EXECUTE"\u3002`}],isError:!0};try{let p=await t.createTableIndex({TableName:a,Columns:s,IndexName:c,Unique:l});return p.Code!==1?{content:[{type:"text",text:`Error: ${p.Msg}
|
|
544
544
|
${JSON.stringify(p.Data||{},null,2)}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(p,null,2)}]}}catch(p){return{content:[{type:"text",text:`Error: ${p instanceof Error?p.message:String(p)}`}],isError:!0}}}),i.tool("microi_drop_table_index",`Drop a non-primary database index from OsClient "${r}". The operation is idempotent, blocks primary-key indexes, and verifies absence by readback. Requires confirmExecution equal to "tableName:indexName" or DROP.`,{tableName:d.string().min(1).describe("Physical table name."),indexName:d.string().min(1).describe("Exact index name returned by microi_get_table_indexes."),confirmExecution:d.string().optional().describe("Required. Pass tableName:indexName or DROP.")},async({tableName:a,indexName:s,confirmExecution:c})=>{let l=`${a}:${s}`;if(c!==l&&c!=="DROP")return{content:[{type:"text",text:`\u6267\u884C\u5DF2\u62E6\u622A\uFF1A\u5220\u9664\u6570\u636E\u5E93\u7D22\u5F15\u4F1A\u6267\u884C\u7834\u574F\u6027 DDL\uFF0C\u8BF7\u91CD\u65B0\u8C03\u7528\u5E76\u4F20 confirmExecution="${l}" \u6216 "DROP"\u3002`}],isError:!0};try{let u=await t.dropTableIndex(a,s);return u.Code!==1?{content:[{type:"text",text:`Error: ${u.Msg}
|
|
545
545
|
${JSON.stringify(u.Data||{},null,2)}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(u,null,2)}]}}catch(u){return{content:[{type:"text",text:`Error: ${u instanceof Error?u.message:String(u)}`}],isError:!0}}}),i.tool("microi_list_database_types","List all database types certified by the current Microi Dos.ORM runtime, including aliases, default ports, and redacted connection-string examples.",{},async()=>{try{let a=await t.getSupportedDatabaseTypes();return a.Code!==1?{content:[{type:"text",text:`Error: ${a.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(a.Data,null,2)}]}}catch(a){return{content:[{type:"text",text:`Error: ${a instanceof Error?a.message:String(a)}`}],isError:!0}}}),i.tool("microi_inspect_external_database",`Connect to an external database through Dos.ORM for OsClient "${r}" and return physical tables, columns, native types, nullability, keys, and comments. Prefer dbKey after saving a connection so credentials are not repeatedly passed to AI tools. This tool never returns the connection string.`,{dbKey:d.string().optional().describe("Saved and enabled microi_database DbKey. Preferred over passing connectionString."),databaseType:d.string().optional().describe("Required only with a temporary connectionString. Call microi_list_database_types for certified values."),connectionString:d.string().optional().describe("Temporary database connection string. Sensitive: never place it in generated code, logs, or narrative output."),tableName:d.string().optional().describe("Optional case-insensitive partial table-name filter."),maxTables:d.number().int().min(1).max(5e3).optional().describe("Maximum returned tables. Default 500."),includeColumns:d.boolean().optional().describe("Whether to load columns for each table. Default true."),commandTimeoutSeconds:d.number().int().min(1).max(600).optional().describe("Metadata query timeout. Default 60 seconds.")},async({dbKey:a,databaseType:s,connectionString:c,tableName:l,maxTables:u,includeColumns:p,commandTimeoutSeconds:f})=>{if(!a&&(!s||!c))return{content:[{type:"text",text:"Error: pass dbKey, or both databaseType and connectionString."}],isError:!0};try{let h=await t.inspectExternalDatabase({DbKey:a,DatabaseType:s,ConnectionString:c,TableName:l,MaxTables:u,IncludeColumns:p,CommandTimeoutSeconds:f});return h.Code!==1?{content:[{type:"text",text:`Error: ${h.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(h.Data,null,2)}]}}catch(h){return{content:[{type:"text",text:`Error: ${h instanceof Error?h.message:String(h)}`}],isError:!0}}}),i.tool("microi_query_external_database",`Run a bounded, parameterized, read-only SELECT/CTE query against an external Dos.ORM database for OsClient "${r}". Use this after schema inspection to read source rows for migration or synchronization. Multi-statement, DML, DDL, procedures, and file-reading SQL are rejected.`,{sql:d.string().min(1).describe("Single read-only SELECT or WITH ... SELECT statement. Use named parameters."),parameters:d.record(d.unknown()).optional().describe("Named SQL parameter values, e.g. { status: 1 }. Never concatenate dynamic values into SQL."),dbKey:d.string().optional().describe("Saved and enabled microi_database DbKey. Preferred."),databaseType:d.string().optional().describe("Required only with a temporary connectionString."),connectionString:d.string().optional().describe("Temporary connection string. Sensitive and never returned."),maxRows:d.number().int().min(1).max(5e3).optional().describe("Maximum returned rows. Default 200."),commandTimeoutSeconds:d.number().int().min(1).max(600).optional().describe("Query timeout. Default 60 seconds.")},async({sql:a,parameters:s,dbKey:c,databaseType:l,connectionString:u,maxRows:p,commandTimeoutSeconds:f})=>{if(!c&&(!l||!u))return{content:[{type:"text",text:"Error: pass dbKey, or both databaseType and connectionString."}],isError:!0};try{let h=await t.queryExternalDatabase({Sql:a,Parameters:s,DbKey:c,DatabaseType:l,ConnectionString:u,MaxRows:p,CommandTimeoutSeconds:f});return h.Code!==1?{content:[{type:"text",text:`Error: ${h.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(h.Data,null,2)}]}}catch(h){return{content:[{type:"text",text:`Error: ${h instanceof Error?h.message:String(h)}`}],isError:!0}}}),i.tool("microi_execute_external_database",`Execute explicitly confirmed administrative SQL against an external Dos.ORM database for OsClient "${r}". This Level >= 9999 control-plane tool intentionally permits DML, DDL, stored procedures, provider-specific commands, and driver-supported multi-statement scripts. The SQL text and connection string are never written to audit logs.`,{sql:d.string().min(1).describe("Raw administrative SQL. It may change schema/data or invoke provider-specific capabilities."),mode:d.enum(["Query","Scalar","NonQuery"]).describe("How Dos.ORM should consume the result. Use NonQuery for DML/DDL/scripts."),parameters:d.record(d.unknown()).optional().describe("Optional named parameters. Use parameters for dynamic values whenever the provider supports them."),dbKey:d.string().optional().describe("Saved and enabled microi_database DbKey. Preferred."),databaseType:d.string().optional().describe("Required only with a temporary connectionString."),connectionString:d.string().optional().describe("Temporary connection string. Sensitive and never returned or audited."),maxRows:d.number().int().min(1).max(1e5).optional().describe("Query response cap only; it does not limit SQL permissions. Default 1000."),commandTimeoutSeconds:d.number().int().min(1).max(86400).optional().describe("Default 600 seconds."),confirmExecution:d.string().optional().describe("Required. Pass EXECUTE or the SHA-256 shown by the dry run.")},async({sql:a,mode:s,parameters:c,dbKey:l,databaseType:u,connectionString:p,maxRows:f,commandTimeoutSeconds:h,confirmExecution:m})=>{if(!l&&(!u||!p))return{content:[{type:"text",text:"Error: pass dbKey, or both databaseType and connectionString."}],isError:!0};let g=et.default.createHash("sha256").update(a,"utf8").digest("hex");if(m!=="EXECUTE"&&m?.toLowerCase()!==g)return{content:[{type:"text",text:JSON.stringify({dryRun:!0,action:"execute_external_database_sql",target:l?`DbKey:${l}`:`temporary:${u}`,mode:s,sqlSha256:g,sqlLength:a.length,parameterNames:Object.keys(c||{}),connectionStringProvided:!!p,requiresConfirmation:"EXECUTE or sqlSha256"},null,2)}]};try{let y=await t.executeExternalDatabaseSql({Sql:a,Mode:s,Parameters:c,DbKey:l,DatabaseType:u,ConnectionString:p,MaxRows:f,CommandTimeoutSeconds:h,ConfirmExecution:m});return y.Code!==1?{content:[{type:"text",text:`Error: ${y.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(y.Data,null,2)}]}}catch(y){return{content:[{type:"text",text:`Error: ${y instanceof Error?y.message:String(y)}`}],isError:!0}}}),i.tool("microi_save_database_connection",`Validate and add or update a connection in the protected microi_database table for OsClient "${r}". The backend tests the connection before writing, never returns the secret, and invalidates the local V8.Dbs cache. Requires explicit confirmation.`,{dbKey:d.string().regex(/^[A-Za-z_][A-Za-z0-9_]{0,49}$/).describe("Stable V8 key used as V8.Dbs.{DbKey}."),dbName:d.string().max(100).optional().describe("Display name. Defaults to dbKey."),databaseType:d.string().describe("Certified type returned by microi_list_database_types."),connectionString:d.string().min(1).describe("Sensitive database connection string. It is validated and never echoed."),dbReadConn:d.string().optional().describe("Optional read-replica connection string of the same database type."),dbVersion:d.string().optional(),remark:d.string().optional(),isEnable:d.number().int().min(0).max(1).optional().describe("Default 1."),commandTimeoutSeconds:d.number().int().min(5).max(120).optional().describe("Connection validation timeout. Default 30 seconds."),confirmExecution:d.string().optional().describe("Required. Pass the exact dbKey or EXECUTE.")},async({dbKey:a,dbName:s,databaseType:c,connectionString:l,dbReadConn:u,dbVersion:p,remark:f,isEnable:h,commandTimeoutSeconds:m,confirmExecution:g})=>{if(g!==a&&g!=="EXECUTE")return{content:[{type:"text",text:JSON.stringify({dryRun:!0,action:"save_database_connection",dbKey:a,dbName:s||a,databaseType:c,connectionStringProvided:!0,requiresConfirmation:a},null,2)}]};try{let y=await t.saveDatabaseConnection({DbKey:a,DbName:s,DatabaseType:c,ConnectionString:l,DbReadConn:u,DbVersion:p,Remark:f,IsEnable:h,CommandTimeoutSeconds:m,ConfirmExecution:g});return y.Code!==1?{content:[{type:"text",text:`Error: ${y.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(y.Data,null,2)}]}}catch(y){return{content:[{type:"text",text:`Error: ${y instanceof Error?y.message:String(y)}`}],isError:!0}}}),i.tool("microi_import_external_attachment",`Stream one attachment from HTTP(S), an absolute server-local path, or a UNC path into Microi storage for OsClient "${r}". This Level >= 9999 control-plane tool intentionally permits private-network and server-filesystem access. It bypasses Base64 buffering and has no fixed MCP size ceiling; MaxBytes is an optional caller safety limit. Requires explicit confirmation and writes a redacted audit record.`,{sourceUrl:d.string().url().refine(a=>/^https?:\/\//i.test(a),"sourceUrl must use http or https").optional().describe("HTTP(S) attachment URL. Provide exactly one of sourceUrl/sourcePath."),sourcePath:d.string().optional().describe("Absolute path visible to the API service account, including Windows UNC paths such as \\\\server\\share\\file.bin. Provide exactly one source."),headers:d.record(d.string()).optional().describe("Optional authentication headers. Sensitive values are never returned."),fileName:d.string().optional(),path:d.string().optional().describe("Target Microi storage directory."),filePathName:d.string().optional().describe("Exact tenant-scoped target path; bucket visibility follows limit."),limit:d.boolean().optional(),preview:d.boolean().optional(),maxBytes:d.number().int().nonnegative().optional().describe("Optional caller limit in bytes. Omit or pass 0 for no MCP-level size cap."),timeoutSeconds:d.number().int().min(5).max(86400).optional().describe("HTTP transfer timeout. Default 3600 seconds."),targetTable:d.string().optional(),targetId:d.string().optional(),targetField:d.string().optional(),confirmExecution:d.string().optional().describe("Required. Pass EXECUTE, the exact source value, or its dry-run SHA-256.")},async({sourceUrl:a,sourcePath:s,headers:c,fileName:l,path:u,filePathName:p,limit:f,preview:h,maxBytes:m,timeoutSeconds:g,targetTable:y,targetId:v,targetField:x,confirmExecution:b})=>{if(!!a==!!s)return{content:[{type:"text",text:"Error: provide exactly one of sourceUrl or sourcePath."}],isError:!0};let _=a||s||"",E=et.default.createHash("sha256").update(_,"utf8").digest("hex");if(b!==_&&b!=="EXECUTE"&&b?.toLowerCase()!==E){let w=s?"[LOCAL_OR_UNC_SOURCE]":"[INVALID_URL]";if(a)try{let T=new URL(a);w=`${T.protocol}//${T.host}/[REDACTED]`}catch{}return{content:[{type:"text",text:JSON.stringify({dryRun:!0,action:"import_external_attachment",source:w,sourceKind:s?"LocalOrUncPath":"Http",sourceSha256:E,headersProvided:!!c&&Object.keys(c).length>0,targetTable:y,targetId:v,targetField:x,requiresConfirmation:"EXECUTE, exact source, or sourceSha256"},null,2)}]}}try{let w=await t.importExternalAttachment({SourceUrl:a,SourcePath:s,Headers:c,FileName:l,Path:u,FilePathName:p,Limit:f,Preview:h,MaxBytes:m,TimeoutSeconds:g,TargetTable:y,TargetId:v,TargetField:x,ConfirmExecution:b});return w.Code!==1?{content:[{type:"text",text:`Error: ${w.Msg}`}],isError:!0}:{content:[{type:"text",text:JSON.stringify(w.Data,null,2)}]}}catch(w){return{content:[{type:"text",text:`Error: ${w instanceof Error?w.message:String(w)}`}],isError:!0}}}),i.tool("microi_get_playwright_context",`Get Playwright E2E testing context for OsClient "${r}". Returns callable API engines, anonymous/public flags, and menu routes for writing browser automation tests.`,{keyword:d.string().optional().describe("Optional keyword to filter engines/modules by name, key, route, category, or table name."),pageSize:d.number().int().min(100).max(2e4).optional().describe("Maximum number of engines/modules returned by the backend context API. Default: 5000.")},async({keyword:a,pageSize:s})=>{try{let c=await t.getPlaywrightContext(a,s);return c.Code!==1||!c.Data?{content:[{type:"text",text:`Error: ${c.Msg||"GetPlaywrightContext failed"}`}],isError:!0}:{content:[{type:"text",text:cQ(c.Data,e.apiBaseUrl)}]}}catch(c){return{content:[{type:"text",text:`Error: ${c instanceof Error?c.message:String(c)}`}],isError:!0}}}),i.tool("microi_plan_playwright_e2e",`Create a Playwright E2E starter plan for a Microi frontend connected to OsClient "${r}". Use this before scaffolding tests in a PC Vue or uni-app H5 project.`,{appType:d.enum(["pc-vue","uniapp-h5","web"]).optional().describe("Frontend type. Default: uniapp-h5."),frontendBaseUrl:d.string().optional().describe("Local frontend URL, e.g. http://127.0.0.1:5180."),homePath:d.string().optional().describe("Home route, e.g. /#/pages/index/index for uni-app H5."),loginEngineKey:d.string().optional().describe("ApiEngineKey used for login."),smokeEngineKey:d.string().optional().describe("Public ApiEngineKey used for API smoke assertion."),keyword:d.string().optional().describe("Keyword to focus context on a module or business area."),pageSize:d.number().int().min(100).max(2e4).optional().describe("Maximum number of engines/modules requested from the backend context API. Default: 5000.")},async({appType:a,frontendBaseUrl:s,homePath:c,loginEngineKey:l,smokeEngineKey:u,keyword:p,pageSize:f})=>{try{let h=await t.getPlaywrightContext(p,f),m=h.Code===1?h.Data:void 0;return{content:[{type:"text",text:lQ({osClient:r,apiBaseUrl:m?.ApiBaseUrl||e.apiBaseUrl,frontendBaseUrl:s,appType:a,homePath:c,loginEngineKey:l,smokeEngineKey:u,pageSize:f,context:m})}]}}catch(h){return{content:[{type:"text",text:`Error: ${h instanceof Error?h.message:String(h)}`}],isError:!0}}}),i.tool("microi_list_engines",`List API engines (\u63A5\u53E3\u5F15\u64CE) for OsClient "${r}". Each engine is a server-side JavaScript function with V8 APIs for database queries, HTTP calls, caching, etc.`,{keyword:d.string().optional().describe("Search keyword to filter engines by name or key")},async({keyword:a})=>{try{let s=await t.getEngineList(a);if(s.Code!==1)return{content:[{type:"text",text:`Error: ${s.Msg}`}],isError:!0};let c=lr(s.Data);if(a&&(c=c.filter(u=>Cn(u.ApiEngineKey,a)||Cn(u.ApiName,a)||Cn(u.Category,a)||Cn(u.ApiRemark,a))),!c.length)return{content:[{type:"text",text:"No engines found."}]};let l=[`# API Engines (${c.length})
|
|
546
546
|
`,"| # | Engine Key | Name | Category | V8 Runtime Limit | Description |","|---|-----------|------|----------|--------------|-------------|"];return c.forEach((u,p)=>{let f=u.V8Limit!==void 0&&u.V8Limit!==null?Number(u.V8Limit||0):u.V8Unlimited!==void 0&&u.V8Unlimited!==null?Number(u.V8Unlimited||0)===1?0:1:0;l.push(`| ${p+1} | ${u.ApiEngineKey||""} | ${u.ApiName||""} | ${u.Category||""} | ${f===1?"ON":"OFF"} | ${u.ApiRemark||u.Description||""} |`)}),{content:[{type:"text",text:l.join(`
|