@numa-tech/numa 1.12.6 → 1.12.8
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/README.md +141 -43
- package/dist/ai-registry/bridge.d.ts +8 -0
- package/dist/ai-registry/bridge.js +63 -0
- package/dist/ai-registry/bridge.js.map +1 -0
- package/dist/ai-registry/client.d.ts +29 -3
- package/dist/ai-registry/client.js +112 -8
- package/dist/ai-registry/client.js.map +1 -1
- package/dist/ai-registry/commands.js +367 -112
- package/dist/ai-registry/commands.js.map +1 -1
- package/dist/ai-registry/errors.d.ts +2 -1
- package/dist/ai-registry/errors.js +12 -1
- package/dist/ai-registry/errors.js.map +1 -1
- package/dist/ai-registry/mcp-installer.d.ts +1 -0
- package/dist/ai-registry/mcp-installer.js +4 -0
- package/dist/ai-registry/mcp-installer.js.map +1 -1
- package/dist/ai-registry/namespace.d.ts +17 -0
- package/dist/ai-registry/namespace.js +53 -0
- package/dist/ai-registry/namespace.js.map +1 -0
- package/dist/ai-registry/schemas.d.ts +127 -2
- package/dist/ai-registry/schemas.js +42 -2
- package/dist/ai-registry/schemas.js.map +1 -1
- package/dist/ai-registry/sync.d.ts +23 -0
- package/dist/ai-registry/sync.js +276 -0
- package/dist/ai-registry/sync.js.map +1 -0
- package/dist/ai-registry/tui.d.ts +2 -0
- package/dist/ai-registry/tui.js +140 -0
- package/dist/ai-registry/tui.js.map +1 -0
- package/dist/ai-registry/workspace.d.ts +191 -0
- package/dist/ai-registry/workspace.js +167 -0
- package/dist/ai-registry/workspace.js.map +1 -0
- package/dist/app-config.d.ts +3 -2
- package/dist/app-config.js +5 -3
- package/dist/app-config.js.map +1 -1
- package/dist/chatgpt-desktop.d.ts +7 -0
- package/dist/chatgpt-desktop.js +95 -0
- package/dist/chatgpt-desktop.js.map +1 -1
- package/dist/cli.js +25 -3
- package/dist/cli.js.map +1 -1
- package/dist/command-catalog.d.ts +1 -0
- package/dist/command-catalog.js +97 -10
- package/dist/command-catalog.js.map +1 -1
- package/dist/config-page.js +2 -0
- package/dist/config-page.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/pipeline/client.d.ts +10 -6
- package/dist/pipeline/client.js +7 -4
- package/dist/pipeline/client.js.map +1 -1
- package/dist/pipeline/commands.d.ts +5 -1
- package/dist/pipeline/commands.js +89 -18
- package/dist/pipeline/commands.js.map +1 -1
- package/dist/pipeline/schemas.d.ts +7 -7
- package/dist/pipeline/schemas.js +2 -2
- package/dist/pipeline/schemas.js.map +1 -1
- package/dist/platform-profile.d.ts +8 -2
- package/dist/platform-profile.js +5 -2
- package/dist/platform-profile.js.map +1 -1
- package/dist/web-console-page.d.ts +3 -3
- package/dist/web-console-page.js +75 -20
- package/dist/web-console-page.js.map +1 -1
- package/dist/web-console.d.ts +1 -1
- package/dist/web-console.js +46 -0
- package/dist/web-console.js.map +1 -1
- package/package.json +8 -5
- package/skills/numa-ai-registry/SKILL.md +25 -19
- package/skills/numa-ai-registry/evals/evals.json +10 -10
- package/skills/numa-ai-registry/references/command-contract.md +41 -6
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export declare const CONSOLE_HTML = "<!doctype html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n <title>Numa CLI \u63A7\u5236\u53F0</title>\n <link rel=\"stylesheet\" href=\"/assets/console.css\">\n</head>\n<body>\n <div id=\"app\" class=\"boot\"><div class=\"boot-mark\">N</div><p>\u6B63\u5728\u8FDE\u63A5\u672C\u5730\u63A7\u5236\u53F0\u2026</p></div>\n <script type=\"module\" src=\"/assets/console.js\"></script>\n</body>\n</html>";
|
|
2
|
-
export declare const CONSOLE_CSS = "\n:root{color-scheme:light;--ink:#0b1728;--navy:#07182b;--navy-2:#102943;--cyan:#0eb7bf;--cyan-soft:#dff7f6;--mist:#eef4f8;--paper:#fbfdff;--line:#d7e2ea;--muted:#64778c;--amber:#e99a32;--red:#d94b58;--green:#198a68;--shadow:0 18px 50px rgba(12,38,62,.1)}\n*{box-sizing:border-box}html,body,#app{min-height:100%}body{min-height:100vh;margin:0;background:var(--mist);color:var(--ink);font-family:\"Avenir Next\",\"Segoe UI\",system-ui,sans-serif}button,input,select,textarea{font:inherit}.mono,code,pre{font-family:\"SFMono-Regular\",Consolas,\"Liberation Mono\",monospace}.boot{min-height:100vh;display:grid;place-content:center;justify-items:center;gap:14px;color:var(--muted)}.boot-mark,.brand-mark{display:grid;place-items:center;background:var(--cyan);color:#00262a;font-weight:900}.boot-mark{width:50px;height:50px;border-radius:15px;box-shadow:0 0 0 8px rgba(14,183,191,.12)}\n.shell{min-height:100vh;display:grid;grid-template-columns:260px 1fr}.rail{position:sticky;top:0;height:100vh;padding:24px 18px;background:var(--navy);color:#d7e6f3;display:flex;flex-direction:column}.brand{display:flex;align-items:center;gap:12px;padding:8px 8px 26px}.brand-mark{width:38px;height:38px;border-radius:12px}.brand strong{display:block;letter-spacing:.04em}.brand small{display:block;margin-top:4px;color:#708aa3;font-size:10px;letter-spacing:.18em;text-transform:uppercase}.nav{display:grid;gap:7px}.nav button{border:0;background:transparent;color:#8da4b8;border-radius:11px;text-align:left;padding:11px 13px;cursor:pointer;display:flex;justify-content:space-between}.nav button:hover,.nav button.active{background:var(--navy-2);color:white}.nav button.active{box-shadow:inset 3px 0 var(--cyan)}.rail-foot{margin-top:auto;border:1px solid #203b55;border-radius:14px;padding:14px}.rail-foot .pulse{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--cyan);box-shadow:0 0 12px var(--cyan);margin-right:7px}.rail-foot p{margin:7px 0 0;color:#7791a8;font-size:11px;line-height:1.5}\n.main{min-width:0;min-height:100vh;display:flex;flex-direction:column}.topbar{height:76px;padding:0 34px;background:rgba(251,253,255,.94);border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:3;backdrop-filter:blur(12px)}.topbar h1{font-size:17px;margin:0}.eyebrow{font:700 10px/1.2 \"SFMono-Regular\",monospace;text-transform:uppercase;letter-spacing:.16em;color:var(--cyan)}.user-chip{display:flex;align-items:center;gap:10px}.avatar{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;background:var(--cyan-soft);color:#087d84;font-weight:800}.user-chip small{color:var(--muted)}.content{width:100%;max-width:1420px;flex:1;margin:0 auto;padding:30px 34px 56px}.hero{background:var(--navy);color:white;border-radius:22px;padding:28px 30px;display:grid;grid-template-columns:1fr auto;gap:24px;position:relative;overflow:hidden;box-shadow:var(--shadow)}.hero:after{content:\"\";position:absolute;right:-45px;top:-90px;width:320px;height:240px;border:34px solid rgba(14,183,191,.09);transform:rotate(-18deg);border-radius:48px}.hero h2{font-size:32px;line-height:1.08;margin:10px 0}.hero p{max-width:720px;color:#91aac0;margin:0;line-height:1.6}.session-track{align-self:center;display:flex;gap:0;position:relative;z-index:1}.track-node{min-width:112px;border:1px solid #2a4661;padding:13px 15px;background:#0b1e33}.track-node:first-child{border-radius:13px 0 0 13px}.track-node:last-child{border-radius:0 13px 13px 0}.track-node span{display:block;color:#7690a7;font-size:9px;text-transform:uppercase;letter-spacing:.12em}.track-node strong{display:block;margin-top:6px;font-size:13px}.track-node.live strong{color:#58e0df}\n.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:18px;margin-top:20px}.card{grid-column:span 4;background:var(--paper);border:1px solid var(--line);border-radius:17px;padding:20px;box-shadow:0 10px 30px rgba(25,54,79,.05)}.card.wide{grid-column:span 8}.card.full{grid-column:1/-1}.card h3{margin:0;font-size:15px}.card p{color:var(--muted);font-size:12px;line-height:1.6}.metric{font-size:28px;font-weight:750;margin-top:16px}.metric small{font-size:11px;color:var(--muted);font-weight:500}.tag{display:inline-flex;border-radius:999px;padding:5px 8px;font:700 9px/1 \"SFMono-Regular\",monospace;text-transform:uppercase;letter-spacing:.05em;background:var(--cyan-soft);color:#087d84}.tag.public{background:#edf1f5;color:#5d7082}.tag.role{background:#fff0d9;color:#9c5c09}.actions{display:flex;gap:8px;flex-wrap:wrap}.button{border:1px solid var(--line);border-radius:10px;background:white;color:var(--ink);padding:9px 12px;cursor:pointer;font-weight:700;font-size:12px}.button:hover{border-color:#9ab6c9;background:#f7fbfd}.button.primary{background:#0b949b;border-color:#0b949b;color:white}.button.danger{color:var(--red);border-color:#f0bec4}.button:disabled{opacity:.45;cursor:not-allowed}.field{display:grid;gap:6px}.field label{font-size:11px;color:var(--muted);font-weight:700}.field input,.field select,.field textarea{width:100%;border:1px solid var(--line);border-radius:10px;background:white;padding:10px 11px;color:var(--ink);outline:none}.field input:focus,.field textarea:focus{border-color:var(--cyan);box-shadow:0 0 0 3px rgba(14,183,191,.12)}.field textarea{min-height:110px;resize:vertical}.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}.form-grid .span-2{grid-column:1/-1}.command-toolbar{display:flex;gap:10px;margin-bottom:15px}.grow{flex:1}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-14{margin-top:14px}.command-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:11px}.command{border:1px solid var(--line);border-radius:13px;padding:14px;background:white}.command-head{display:flex;gap:8px;align-items:center;justify-content:space-between}.command code{font-size:11px;color:#0b6f76}.command p{margin:9px 0}.command small{display:block;color:#8a9bab;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.output{background:#071522;color:#b8d1e2;border-radius:13px;padding:15px;min-height:170px;max-height:420px;overflow:auto;white-space:pre-wrap;font-size:11px;line-height:1.65}.notice{margin-top:14px;border-radius:11px;padding:11px 13px;font-size:12px}.notice.error{background:#fff0f2;color:#a52c3b;border:1px solid #f1c4ca}.notice.success{background:#e8f7f1;color:#176c54;border:1px solid #bce4d5}.login-gate{min-height:calc(100vh - 76px);display:grid;place-content:center;padding:30px}.login-card{width:min(520px,90vw);background:white;border:1px solid var(--line);border-radius:22px;padding:32px;box-shadow:var(--shadow)}.login-card h2{font-size:28px;margin:14px 0 9px}.login-card p{color:var(--muted);line-height:1.65}.hidden{display:none!important}\n.sync-board{display:grid;grid-template-columns:1fr 56px 1fr;align-items:stretch;margin-top:20px}.sync-stage{background:var(--paper);border:1px solid var(--line);border-radius:17px;padding:18px 20px;box-shadow:0 10px 30px rgba(25,54,79,.05)}.sync-stage strong{display:block;margin-top:8px;font-size:18px}.sync-stage p{margin:7px 0 0;color:var(--muted);font-size:11px}.sync-link{display:grid;place-items:center;color:var(--cyan);font-size:22px}.sync-link:before{content:\"\";height:2px;width:100%;background:linear-gradient(90deg,var(--cyan),#bad8dc)}.table-card{margin-top:18px;background:var(--paper);border:1px solid var(--line);border-radius:17px;box-shadow:0 10px 30px rgba(25,54,79,.05);overflow:hidden}.table-head{padding:18px 20px;display:flex;align-items:center;justify-content:space-between;gap:16px;border-bottom:1px solid var(--line)}.table-head h3{margin:0}.table-head p{margin:5px 0 0;color:var(--muted);font-size:11px}.account-table-wrap{overflow:auto}.account-table{width:100%;border-collapse:collapse;min-width:920px}.account-table th,.account-table td{text-align:left;padding:14px 16px;border-bottom:1px solid #e7eef3;vertical-align:middle}.account-table th{background:#f5f9fb;color:#6c8094;font-size:10px;text-transform:uppercase;letter-spacing:.08em}.account-table tr:last-child td{border-bottom:0}.account-name strong{display:block;font-size:13px}.account-name small{display:block;margin-top:4px;color:var(--muted);font-size:10px}.quota-stack{min-width:210px;display:grid;gap:8px}.quota-line{display:grid;grid-template-columns:42px 1fr 38px;align-items:center;gap:7px;font-size:10px;color:var(--muted)}progress{width:100%;height:7px;border:0;border-radius:99px;overflow:hidden;background:#e7eef3}progress::-webkit-progress-bar{background:#e7eef3;border-radius:99px}progress::-webkit-progress-value{background:var(--cyan);border-radius:99px}progress::-moz-progress-bar{background:var(--cyan);border-radius:99px}.status-stack{display:flex;gap:6px;flex-wrap:wrap}.tag.success{background:#e8f7f1;color:var(--green)}.tag.failed{background:#fff0f2;color:var(--red)}.tag.waiting{background:#fff0d9;color:#9c5c09}.tag.local{background:#e8f1fa;color:#32658f}.empty-state{padding:48px 20px;text-align:center;color:var(--muted)}.empty-state.account-request{margin:24px;border:2px solid #f0b5bd;border-radius:16px;background:#fff2f4;color:#8d2334;box-shadow:0 12px 30px rgba(167,44,64,.1)}.empty-state.account-request strong{display:block;margin-bottom:9px;font-size:16px}.empty-state.account-request span{display:block;font-size:13px;line-height:1.7}.table-meta{color:var(--muted);font-size:10px;line-height:1.55}.spin{display:inline-block;animation:turn 1s linear infinite}@keyframes turn{to{transform:rotate(360deg)}}\n.registry-hero{background:linear-gradient(118deg,#06172a 0%,#0b2d42 67%,#0a4c55 100%)}.lifecycle{display:grid;grid-template-columns:repeat(3,84px);align-items:center;position:relative;z-index:1}.life-node{position:relative;text-align:center;color:#7293a7;font:700 9px/1.2 \"SFMono-Regular\",monospace;text-transform:uppercase;letter-spacing:.08em}.life-node:before{content:\"\";display:block;width:11px;height:11px;margin:0 auto 9px;border:2px solid #58e0df;border-radius:50%;background:#0a2638;box-shadow:0 0 0 5px rgba(88,224,223,.08)}.life-node:not(:last-child):after{content:\"\";position:absolute;height:1px;width:calc(100% - 24px);top:6px;left:calc(50% + 12px);background:linear-gradient(90deg,#58e0df,#31546a)}.life-node.live{color:#d5ffff}.life-node.live:before{background:#58e0df;box-shadow:0 0 15px #58e0df}.registry-toolbar{display:grid;grid-template-columns:minmax(190px,1fr) auto minmax(190px,1fr) auto;gap:10px;align-items:end;margin-top:20px}.segment{display:flex;padding:3px;background:#dfe9ef;border-radius:11px}.segment button{border:0;background:transparent;padding:8px 13px;border-radius:8px;color:var(--muted);font-weight:750;font-size:11px;cursor:pointer}.segment button.active{background:white;color:#087d84;box-shadow:0 3px 12px rgba(7,24,43,.1)}.registry-board{display:grid;grid-template-columns:minmax(260px,32%) 1fr;min-height:560px;margin-top:14px;background:var(--paper);border:1px solid var(--line);border-radius:18px;overflow:hidden;box-shadow:var(--shadow)}.registry-list{border-right:1px solid var(--line);background:#f4f8fa}.registry-list-head{padding:15px 17px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center}.registry-items{padding:9px;display:grid;gap:6px;max-height:680px;overflow:auto}.registry-item{width:100%;border:1px solid transparent;background:transparent;border-radius:12px;padding:12px;text-align:left;cursor:pointer;display:grid;grid-template-columns:12px 1fr;gap:10px;color:var(--ink)}.registry-item:hover,.registry-item.active{background:white;border-color:var(--line);box-shadow:0 6px 20px rgba(18,49,71,.07)}.registry-dot{width:8px;height:8px;margin-top:4px;border-radius:50%;background:var(--amber);box-shadow:0 0 0 4px rgba(233,154,50,.1)}.registry-dot.online{background:var(--green);box-shadow:0 0 0 4px rgba(25,138,104,.1)}.registry-item strong,.registry-item small{display:block}.registry-item strong{font-size:12px}.registry-item small{margin-top:5px;color:var(--muted);font-size:10px}.registry-detail{min-width:0;padding:22px;display:flex;flex-direction:column}.registry-detail-head{display:flex;justify-content:space-between;align-items:start;gap:16px}.registry-detail h3{margin:5px 0 3px;font-size:20px}.registry-detail pre{flex:1;margin:16px 0;min-height:270px}.registry-actions{border-top:1px solid var(--line);padding-top:15px;display:grid;gap:12px}.install-row{display:grid;grid-template-columns:1fr 1fr auto;gap:9px}.registry-error{margin-top:14px}.button:focus-visible,.nav button:focus-visible,.registry-item:focus-visible,.segment button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid rgba(14,183,191,.3);outline-offset:2px}\n@media(max-width:980px){.shell{grid-template-columns:78px 1fr}.rail{padding:18px 10px}.brand div:last-child,.nav button span:first-child,.rail-foot p,.rail-foot strong{display:none}.brand{justify-content:center}.nav button{justify-content:center}.card,.card.wide{grid-column:span 6}.hero{grid-template-columns:1fr}.session-track,.lifecycle{display:none}.registry-toolbar{grid-template-columns:1fr 1fr}.registry-board{grid-template-columns:1fr}.registry-list{border-right:0;border-bottom:1px solid var(--line)}.registry-items{max-height:260px}}\n@media(max-width:680px){.shell{display:block}.rail{height:auto;position:static;flex-direction:row;align-items:center;padding:10px 14px;overflow-x:auto}.brand{padding:0;margin-right:auto;flex:0 0 auto}.nav{display:flex}.nav button{padding:9px;flex:0 0 auto}.rail-foot{display:none}.topbar{padding:0 18px}.content{padding:20px 14px}.hero{padding:23px}.hero h2{font-size:25px}.card,.card.wide{grid-column:1/-1}.form-grid,.command-list,.registry-toolbar,.install-row{grid-template-columns:1fr}.form-grid .span-2{grid-column:auto}.user-chip div:not(.avatar){display:none}.sync-board{grid-template-columns:1fr}.sync-link{height:32px;transform:rotate(90deg)}.table-head{align-items:flex-start;flex-direction:column}.registry-detail{padding:17px}}\n@media(prefers-reduced-motion:no-preference){.card,.hero{animation:arrive .35s ease both}@keyframes arrive{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}}\n";
|
|
3
|
-
export declare const CONSOLE_JS = "\nconst app=document.getElementById('app');let state=null;let csrf='';let active='overview';let output='\u9009\u62E9\u4E00\u6761\u547D\u4EE4\u6216\u8F93\u5165\u53C2\u6570\u540E\u8FD0\u884C\u3002';let chatgptLocal=null;let chatgptRemote=null;let chatgptLoading=false;let registryNamespaces=[];let registryItems=[];let registryDetail=null;let registryMode='skill';let registryNamespaceId=null;let registryName='';let registrySearch='';let registryLoading=false;let registryError='';const noAvailableAccountGuidance='\u5F53\u524D\u7528\u6237\u6CA1\u6709\u7ED1\u5B9A\u53EF\u7528\u7684 ChatGPT \u8D26\u53F7\u3002\u8BF7\u524D\u5F80 OA \u7CFB\u7EDF\u63D0\u4EA4 IT11 \u5DE5\u5355\uFF0C\u7533\u8BF7\u72EC\u4EAB\u6216\u5171\u4EAB\u7684 ChatGPT \u4E2A\u4EBA\u8D26\u53F7\u3002';\nconst esc=(v)=>String(v??'').replace(/[&<>\"']/g,(c)=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nasync function api(path,init={}){const headers={'Accept':'application/json',...(init.body?{'Content-Type':'application/json'}:{}),...(csrf?{'x-numa-console-csrf':csrf}:{})};const response=await fetch(path,{...init,headers:{...headers,...(init.headers||{})},credentials:'same-origin'});const body=await response.json().catch(()=>({error:{message:'\u54CD\u5E94\u4E0D\u662F JSON'}}));if(!response.ok)throw new Error(body.error?.message||body.stderr||body.stdout||('HTTP '+response.status));return body}\nasync function bootstrap(attempt=0){try{state=await api('/api/bootstrap');csrf=state.csrfToken;const callbackState=new URLSearchParams(location.search).get('login');const waitingForSuccess=callbackState==='complete'&&!state.loggedIn&&attempt<40;const waitingForFailure=callbackState==='failed'&&!state.loginError&&attempt<8;if(waitingForSuccess||waitingForFailure){app.innerHTML='<div class=\"boot\"><div class=\"boot-mark\">N</div><p>'+(callbackState==='complete'?'\u767B\u5F55\u6210\u529F\uFF0C\u6B63\u5728\u5EFA\u7ACB\u672C\u673A\u4F1A\u8BDD\u2026':'\u6B63\u5728\u8BFB\u53D6\u767B\u5F55\u5931\u8D25\u4FE1\u606F\u2026')+'</p></div>';setTimeout(()=>bootstrap(attempt+1),250);return}if(callbackState==='complete'&&!state.loggedIn&&!state.loginError)state.loginError='\u767B\u5F55\u51ED\u636E\u4EA4\u6362\u5C1A\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5\u767B\u5F55\u3002';if(callbackState==='failed'&&!state.loginError)state.loginError='Keycloak \u767B\u5F55\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5\u3002';if(callbackState)history.replaceState({},'',location.pathname);render()}catch(error){app.innerHTML='<div class=\"login-gate\"><div class=\"login-card\"><span class=\"tag role\">\u8FDE\u63A5\u5931\u8D25</span><h2>\u672C\u5730\u63A7\u5236\u53F0\u4E0D\u53EF\u7528</h2><p>'+esc(error.message)+'</p></div></div>'}}\nfunction navButton(id,label,mark){return '<button data-nav=\"'+id+'\" class=\"'+(active===id?'active':'')+'\"><span>'+label+'</span><span class=\"mono\">'+mark+'</span></button>'}\nfunction shell(content){const user=state.user||{};const label=user.username||user.email||'\u672A\u767B\u5F55';return '<div class=\"shell\"><aside class=\"rail\"><div class=\"brand\"><div class=\"brand-mark\">N</div><div><strong>Numa CLI</strong><small>Local control plane</small></div></div><nav class=\"nav\">'+navButton('overview','\u8FD0\u884C\u6982\u89C8','01')+navButton('registry','AI Registry','02')+navButton('chatgpt','ChatGPT \u8D26\u53F7','03')+navButton('config','\u57FA\u7840\u914D\u7F6E','04')+navButton('commands','\u547D\u4EE4\u80FD\u529B','05')+navButton('runner','\u6267\u884C\u5668','06')+'</nav><div class=\"rail-foot\"><strong><span class=\"pulse\"></span>\u4EC5\u76D1\u542C\u672C\u673A</strong><p>Token \u4E0D\u4F1A\u53D1\u9001\u7ED9\u7F51\u9875\u811A\u672C\uFF0C\u4E5F\u4E0D\u4F1A\u51FA\u73B0\u5728\u547D\u4EE4\u8F93\u51FA\u4E2D\u3002</p></div></aside><main class=\"main\"><header class=\"topbar\"><div><div class=\"eyebrow\">Numa / Web console</div><h1>'+sectionTitle()+'</h1></div><div class=\"user-chip\"><div class=\"avatar\">'+esc(label.slice(0,1).toUpperCase())+'</div><div><strong>'+esc(label)+'</strong><br><small>'+esc(state.loggedIn?'Keycloak \u4F1A\u8BDD\u6709\u6548':'\u9700\u8981\u767B\u5F55')+'</small></div></div></header>'+content+'</main></div>'}\nfunction sectionTitle(){return {overview:'\u8FD0\u884C\u6982\u89C8',registry:'AI Registry',chatgpt:'ChatGPT \u8D26\u53F7',config:'\u57FA\u7840\u914D\u7F6E',commands:'\u547D\u4EE4\u80FD\u529B',runner:'\u5B89\u5168\u6267\u884C\u5668'}[active]||'\u63A7\u5236\u53F0'}\nfunction loginGate(){const error=state?.loginError?'<div class=\"notice error\">'+esc(state.loginError)+'</div>':'';return '<div class=\"login-gate\"><div class=\"login-card\"><span class=\"tag role\">Keycloak PKCE</span><h2>\u767B\u5F55\u540E\u8FDB\u5165\u672C\u5730\u63A7\u5236\u53F0</h2><p>\u6D4F\u89C8\u5668\u53EA\u8D1F\u8D23\u5B8C\u6210\u8BA4\u8BC1\u548C\u64CD\u4F5C\u672C\u673A API\u3002\u8BBF\u95EE\u4EE4\u724C\u4FDD\u5B58\u5728 CLI \u7684\u79C1\u6709\u7F13\u5B58\u4E2D\uFF0C\u4E0D\u5199\u5165 localStorage\uFF0C\u4E5F\u4E0D\u8FD4\u56DE\u7ED9\u9875\u9762\u3002</p><div class=\"actions\"><button class=\"button primary\" data-action=\"login\">\u4F7F\u7528 Keycloak \u767B\u5F55</button></div><div id=\"notice\">'+error+'</div></div></div>'}\nfunction overview(){const u=state.user||{};const roles=[...(u.realmRoles||[]),...Object.values(u.clientRoles||{}).flat()];return '<div class=\"content\"><section class=\"hero\"><div><div class=\"eyebrow\">Authenticated workstation</div><h2>\u672C\u673A\u4F1A\u8BDD\u5DF2\u63A5\u5165\u7814\u53D1\u63A7\u5236\u9762</h2><p>\u4ECE\u540C\u4E00\u5904\u68C0\u67E5\u8EAB\u4EFD\u3001\u8C03\u6574 CLI \u914D\u7F6E\uFF0C\u5E76\u4EE5\u7ED3\u6784\u5316\u53C2\u6570\u8FD0\u884C\u53D7\u652F\u6301\u547D\u4EE4\u3002\u6240\u6709\u7F51\u7EDC\u8BF7\u6C42\u7EE7\u7EED\u7531 CLI \u6CE8\u5165 Bearer Token\u3002</p></div><div class=\"session-track\"><div class=\"track-node live\"><span>\u8EAB\u4EFD</span><strong>'+esc(u.username||'\u5DF2\u767B\u5F55')+'</strong></div><div class=\"track-node\"><span>API</span><strong>'+esc(state.config.apiBaseUrl?'\u5DF2\u914D\u7F6E':'\u672A\u914D\u7F6E')+'</strong></div><div class=\"track-node\"><span>\u89D2\u8272</span><strong>'+roles.length+'</strong></div></div></section><section class=\"grid\"><article class=\"card\"><div class=\"eyebrow\">Session</div><div class=\"metric\">'+esc(state.expiresAt?new Date(state.expiresAt*1000).toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'}):'\u2014')+' <small>\u8BBF\u95EE\u4EE4\u724C\u5230\u671F</small></div><p>\u9700\u8981\u65F6\u7531 CLI \u4F7F\u7528 refresh token \u81EA\u52A8\u7EED\u671F\u3002</p></article><article class=\"card\"><div class=\"eyebrow\">Commands</div><div class=\"metric\">'+state.commands.length+' <small>\u6761\u80FD\u529B\u5951\u7EA6</small></div><p>\u7F51\u9875\u6267\u884C\u5668\u53EA\u63A5\u53D7\u76EE\u5F55\u4E2D\u58F0\u660E\u7684\u547D\u4EE4\u3002</p></article><article class=\"card\"><div class=\"eyebrow\">Endpoint</div><div class=\"metric\">'+(state.config.apiBaseUrl?'READY':'SETUP')+'</div><p>'+esc(state.config.apiBaseUrl||'\u8BF7\u5728\u57FA\u7840\u914D\u7F6E\u4E2D\u586B\u5199\u5E73\u53F0 API \u5730\u5740')+'</p></article><article class=\"card wide\"><h3>\u5F53\u524D\u8EAB\u4EFD</h3><p>'+esc(u.displayName||u.username||'-')+' \u00B7 '+esc(u.email||'-')+'</p><div class=\"actions\">'+roles.slice(0,8).map((r)=>'<span class=\"tag\">'+esc(r)+'</span>').join('')+(roles.length>8?'<span class=\"tag public\">+'+(roles.length-8)+'</span>':'')+'</div></article><article class=\"card\"><h3>\u4F1A\u8BDD\u64CD\u4F5C</h3><p>\u5F3A\u5236\u5237\u65B0\u8EAB\u4EFD\u8D44\u6599\uFF0C\u6216\u6E05\u9664\u672C\u673A Keycloak \u7F13\u5B58\u3002</p><div class=\"actions\"><button class=\"button\" data-action=\"reload\">\u5237\u65B0\u72B6\u6001</button><button class=\"button danger\" data-action=\"logout\">\u9000\u51FA\u767B\u5F55</button></div></article></section></div>'}\nfunction instant(value){if(!value)return null;const number=typeof value==='number'?(value<1000000000000?value*1000:value):Date.parse(value);return Number.isFinite(number)?number:null}\nfunction timeText(value){const at=instant(value);return at?new Date(at).toLocaleString('zh-CN',{month:'2-digit',day:'2-digit',hour:'2-digit',minute:'2-digit'}):'\u2014'}\nfunction windowName(window,fallback){const minutes=window?.windowMinutes;if(!minutes)return fallback;if(minutes%1440===0)return (minutes/1440)+'d';if(minutes%60===0)return (minutes/60)+'h';return minutes+'m'}\nfunction quotaWindowHasData(window){if(!window)return false;const minutes=window.windowMinutes;const reset=window.resetAt;const hasMinutes=typeof minutes==='number'&&Number.isFinite(minutes)&&minutes>0;const hasReset=(typeof reset==='number'&&Number.isFinite(reset)&&reset>0)||(typeof reset==='string'&&Number.isFinite(Date.parse(reset)));const hasUsage=typeof window.usedPercent==='number'&&Number.isFinite(window.usedPercent)&&window.usedPercent>0;return hasMinutes||hasReset||hasUsage}\nfunction quotaLine(window,fallback){if(!quotaWindowHasData(window)||typeof window.usedPercent!=='number')return '';const remain=Math.max(0,Math.min(100,100-window.usedPercent));return '<div class=\"quota-line\" title=\"\u989D\u5EA6\u91CD\u7F6E\u65F6\u95F4 '+esc(timeText(window.resetAt))+'\"><span>'+esc(windowName(window,fallback))+'</span><progress max=\"100\" value=\"'+remain.toFixed(1)+'\"></progress><strong>'+remain.toFixed(0)+'%</strong></div>'}\nfunction quotaCell(quota){if(!quota)return '<span class=\"table-meta\">\u6682\u65E0\u989D\u5EA6\u91C7\u6837</span>';const lines=quotaLine(quota.primary,'\u4E3B\u7A97\u53E3')+quotaLine(quota.secondary,'\u6B21\u7A97\u53E3');const detail=[quota.planType,quota.model,quota.activeLimit!=null?'limit '+quota.activeLimit:null].filter(Boolean).join(' \u00B7 ');return '<div class=\"quota-stack\">'+(lines||'<span class=\"table-meta\">\u989D\u5EA6\u7A97\u53E3\u6682\u65E0\u6570\u636E</span>')+'<div class=\"table-meta\">'+esc(detail||'\u5DF2\u91C7\u6837')+'<br>\u91C7\u6837 '+esc(timeText(quota.updatedAt))+'</div></div>'}\nfunction newerQuota(localQuota,remoteQuota){if(!localQuota)return remoteQuota;if(!remoteQuota)return localQuota;return (instant(remoteQuota.updatedAt)||0)>=(instant(localQuota.updatedAt)||0)?remoteQuota:localQuota}\nfunction mergedChatgptAccounts(){const local=chatgptLocal?.accounts||[];const remote=chatgptRemote?.accounts||[];const used=new Set();const rows=local.map((item)=>{const index=remote.findIndex((candidate,i)=>!used.has(i)&&item.accountId&&candidate.accountId===item.accountId);const match=index>=0?remote[index]:null;if(index>=0)used.add(index);return {key:item.id,local:item,remote:match,label:item.label,email:item.email,accountId:item.accountId||match?.accountId,enabled:item.enabled,selected:item.selected,quota:newerQuota(item.quota,match?.quota)}});remote.forEach((item,index)=>{if(!used.has(index))rows.push({key:'remote_'+item.id,local:null,remote:item,label:item.label,email:null,accountId:item.accountId,enabled:true,selected:item.isDefault,quota:item.quota})});return rows}\nfunction syncTag(row){if(chatgptRemote?.status==='LOADING')return '<span class=\"tag waiting\">\u6B63\u5728\u540C\u6B65</span>';if(chatgptRemote?.status==='FAILED')return '<span class=\"tag failed\">\u8FDC\u7A0B\u540C\u6B65\u5931\u8D25</span>';if(chatgptRemote?.status==='NOT_CONFIGURED')return '<span class=\"tag waiting\">\u672A\u914D\u7F6E\u5E73\u53F0</span>';if(row.local&&row.remote)return '<span class=\"tag success\">\u5DF2\u540C\u6B65</span>';if(row.local)return '<span class=\"tag local\">\u4EC5\u672C\u5730</span>';return '<span class=\"tag success\">\u5E73\u53F0\u53EF\u7528</span>'}\nfunction remoteStage(){const remote=chatgptRemote;if(!remote||remote.status==='LOADING')return {tag:'<span class=\"tag waiting\"><span class=\"spin\">\u21BB</span> \u8FDE\u63A5\u4E2D</span>',title:'\u6B63\u5728\u8FDE\u63A5\u5E73\u53F0',detail:'\u672C\u5730\u8D26\u53F7\u5DF2\u7ECF\u53EF\u89C1\uFF0C\u6B63\u5728\u8BFB\u53D6\u8FDC\u7A0B\u53EF\u7528\u8D26\u53F7\u3002'};if(remote.status==='SUCCESS')return {tag:'<span class=\"tag success\">\u540C\u6B65\u6210\u529F</span>',title:remote.accounts.length+' \u4E2A\u5E73\u53F0\u8D26\u53F7',detail:'\u5B8C\u6210\u4E8E '+timeText(remote.syncedAt)};if(remote.status==='FAILED')return {tag:'<span class=\"tag failed\">\u8FDC\u7A0B\u540C\u6B65\u5931\u8D25</span>',title:'\u4FDD\u7559\u672C\u5730\u7ED3\u679C',detail:remote.error?.message||'\u65E0\u6CD5\u8FDE\u63A5\u8FDC\u7A0B\u8D26\u53F7\u670D\u52A1'};return {tag:'<span class=\"tag waiting\">\u672A\u914D\u7F6E</span>',title:'\u672A\u914D\u7F6E\u5E73\u53F0\u5730\u5740',detail:'\u53EF\u5728\u57FA\u7840\u914D\u7F6E\u4E2D\u586B\u5199\u5E73\u53F0 API \u5730\u5740\u3002'}}\nfunction accountRows(rows){return rows.map((row)=>'<tr><td><div class=\"account-name\"><strong>'+esc(row.label)+'</strong><small>'+esc(row.email||row.accountId||row.key)+'</small></div></td><td><div class=\"status-stack\">'+(row.enabled?'<span class=\"tag success\">\u53EF\u7528</span>':'<span class=\"tag failed\">\u5DF2\u505C\u7528</span>')+(row.selected?'<span class=\"tag role\">\u5BA2\u6237\u7AEF\u5DF2\u9009</span>':'')+'</div></td><td>'+quotaCell(row.quota)+'</td><td><div class=\"table-meta\">Token '+esc(row.local?'\u672C\u5730\u53EF\u7528':'\u6309\u9700\u4ECE\u5E73\u53F0\u83B7\u53D6')+'<br>\u5230\u671F '+esc(timeText(row.local?.accessExpiresAt||row.remote?.accessExpiresAt))+'</div></td><td><div class=\"status-stack\">'+syncTag(row)+'</div></td></tr>').join('')}\nfunction chatgptPage(){const rows=mergedChatgptAccounts();const remote=remoteStage();const localReady=chatgptLocal?.status==='READY';const localCount=chatgptLocal?.available??0;const failure=chatgptRemote?.status==='FAILED'?'<div class=\"notice error\"><strong>\u8FDC\u7A0B\u540C\u6B65\u5931\u8D25\u3002</strong> '+esc(chatgptRemote.error?.message||'\u5E73\u53F0\u6682\u65F6\u4E0D\u53EF\u7528')+'\uFF1B\u672C\u5730\u8D26\u53F7\u6570\u636E\u4ECD\u53EF\u6B63\u5E38\u67E5\u770B\u3002</div>':'';return '<div class=\"content\"><section class=\"hero\"><div><div class=\"eyebrow\">Local first / Remote second</div><h2>ChatGPT \u8D26\u53F7\u8FD0\u884C\u89C6\u56FE</h2><p>\u5148\u8BFB\u53D6 codex-multi-auth \u672C\u5730\u8D26\u53F7\u4E0E\u989D\u5EA6\u7F13\u5B58\uFF0C\u518D\u8FDE\u63A5\u5E73\u53F0\u8865\u5145\u5F53\u524D\u7528\u6237\u53EF\u7528\u8D26\u53F7\u3002\u9875\u9762\u6C38\u4E0D\u63A5\u6536 access token \u6216 refresh token\u3002</p></div><div class=\"session-track\"><div class=\"track-node live\"><span>\u672C\u5730\u53EF\u7528</span><strong>'+localCount+'</strong></div><div class=\"track-node\"><span>\u6C47\u603B\u8D26\u53F7</span><strong>'+rows.length+'</strong></div><div class=\"track-node\"><span>\u8FDC\u7A0B</span><strong>'+esc(chatgptRemote?.status||'WAITING')+'</strong></div></div></section><section class=\"sync-board\"><article class=\"sync-stage\"><div class=\"eyebrow\">01 / Local pool</div><strong>'+(localReady?localCount+' \u4E2A\u672C\u5730\u53EF\u7528\u8D26\u53F7':'\u6B63\u5728\u8BFB\u53D6\u672C\u5730\u8D26\u53F7')+'</strong><p>'+(localReady?'\u8BFB\u53D6\u5B8C\u6210\u4E8E '+timeText(chatgptLocal.readAt):'\u4F18\u5148\u8BFB\u53D6 codex-multi-auth \u5B89\u5168\u6458\u8981\u3002')+'</p></article><div class=\"sync-link\" aria-label=\"\u7136\u540E\u8FDE\u63A5\u8FDC\u7A0B\"></div><article class=\"sync-stage\"><div class=\"eyebrow\">02 / Platform service</div>'+remote.tag+'<strong>'+esc(remote.title)+'</strong><p>'+esc(remote.detail)+'</p></article></section>'+failure+'<section class=\"table-card\"><header class=\"table-head\"><div><h3>\u53EF\u7528\u8D26\u53F7\u4E0E\u5269\u4F59\u989D\u5EA6</h3><p>\u989D\u5EA6\u4F18\u5148\u5C55\u793A\u672C\u5730\u6216\u670D\u52A1\u5668\u7AEF\u66F4\u65B0\u8F83\u65B0\u7684\u5B89\u5168\u5FEB\u7167\u3002</p></div><button class=\"button\" data-action=\"chatgpt-refresh\" '+(chatgptLoading?'disabled':'')+'>'+(chatgptLoading?'<span class=\"spin\">\u21BB</span> \u540C\u6B65\u4E2D':'\u21BB \u91CD\u65B0\u540C\u6B65')+'</button></header>'+(rows.length?'<div class=\"account-table-wrap\"><table class=\"account-table\"><thead><tr><th>\u8D26\u53F7</th><th>\u53EF\u7528\u72B6\u6001</th><th>\u5269\u4F59 limit</th><th>\u51ED\u636E\u65F6\u6548</th><th>\u540C\u6B65\u72B6\u6001</th></tr></thead><tbody>'+accountRows(rows)+'</tbody></table></div>':'<div class=\"empty-state'+(chatgptLoading?'':' account-request')+'\">'+(chatgptLoading?'\u6B63\u5728\u8BFB\u53D6\u672C\u5730\u8D26\u53F7\u2026':'<strong>\u9700\u8981\u7533\u8BF7 ChatGPT \u8D26\u53F7</strong><span>'+esc(noAvailableAccountGuidance)+'</span>')+'</div>')+'</section></div>'}\nfunction registryPageItems(payload){if(Array.isArray(payload))return payload.filter((item)=>item&&typeof item==='object');for(const key of ['pageItems','items','records','list','data']){const value=payload?.[key];if(Array.isArray(value))return value.filter((item)=>item&&typeof item==='object');if(value&&typeof value==='object'){const nested=registryPageItems(value);if(nested.length)return nested}}return []}\nfunction registryItemName(item,index){return String(item?.name??item?.skillName??item?.mcpName??((registryMode==='skill'?'skill-':'mcp-')+(index+1)))}\nfunction registryItemStatus(item){return String(item?.status??item?.releaseStatus??item?.state??item?.version??'registered')}\nfunction registryCanEdit(){const u=state.user||{};const roles=[...(u.realmRoles||[]),...Object.values(u.clientRoles||{}).flat()].map(String);return roles.includes('mci-devops-platform-ai-registry-admin')||roles.some((role)=>role.endsWith('-ops-admin'))}\nfunction registryNamespaceOptions(){return registryNamespaces.map((namespace)=>'<option value=\"'+namespace.id+'\" '+(Number(namespace.id)===Number(registryNamespaceId)?'selected':'')+'>'+esc(namespace.displayName)+' \u00B7 '+esc(namespace.namespaceKey)+' \u00B7 '+esc(namespace.instanceCode)+(namespace.isDefault?' \u00B7 default':'')+'</option>').join('')}\nfunction registryItemButtons(){return registryItems.map((item,index)=>{const name=registryItemName(item,index);const status=registryItemStatus(item);const online=/online|published|release/i.test(status);return '<button class=\"registry-item '+(name===registryName?'active':'')+'\" data-registry-name=\"'+esc(name)+'\"><span class=\"registry-dot '+(online?'online':'')+'\"></span><span><strong>'+esc(name)+'</strong><small>'+esc(status)+(item.scope?' \u00B7 '+esc(item.scope):'')+'</small></span></button>'}).join('')||'<div class=\"empty-state\">\u6CA1\u6709\u5339\u914D\u7684 '+(registryMode==='skill'?'Skill':'MCP Server')+'</div>'}\nfunction registryTargets(){const targets=registryMode==='skill'?['chatgpt','codex','claude','cursor','workbuddy','openclaw','agents']:['chatgpt','codex','claude','cursor','workbuddy','openclaw'];return targets.map((target)=>'<option value=\"'+target+'\">'+target+'</option>').join('')}\nfunction registryDetailPanel(){if(registryLoading)return '<div class=\"empty-state\"><span class=\"spin\">\u21BB</span> \u6B63\u5728\u8BFB\u53D6\u79C1\u6709 Registry\u2026</div>';if(!registryName)return '<div class=\"empty-state\">\u4ECE\u5DE6\u4FA7\u9009\u62E9\u4E00\u9879\u67E5\u770B\u8BE6\u60C5\u4E0E\u64CD\u4F5C\u3002</div>';const canEdit=registryCanEdit();const mutating=registryMode==='skill'?'<button class=\"button\" data-registry-action=\"submit\" '+(canEdit?'':'disabled')+'>\u63D0\u4EA4\u5BA1\u6838</button><button class=\"button\" data-registry-action=\"publish\" '+(canEdit?'':'disabled')+'>\u53D1\u5E03\u7248\u672C</button><button class=\"button\" data-registry-action=\"online\" '+(canEdit?'':'disabled')+'>\u4E0A\u7EBF</button><button class=\"button\" data-registry-action=\"offline\" '+(canEdit?'':'disabled')+'>\u4E0B\u7EBF</button>':'';return '<div class=\"registry-detail-head\"><div><div class=\"eyebrow\">'+esc(registryMode==='skill'?'Skill package':'MCP definition')+'</div><h3>'+esc(registryName)+'</h3><span class=\"tag '+(canEdit?'role':'public')+'\">'+(canEdit?'registry admin':'reader')+'</span></div><button class=\"button\" data-action=\"registry-refresh\">\u21BB \u5237\u65B0</button></div><pre class=\"output\">'+esc(JSON.stringify(registryDetail??{},null,2))+'</pre><div class=\"registry-actions\"><div class=\"install-row\"><label class=\"field\"><span>\u5B89\u88C5\u76EE\u6807</span><select id=\"registry-target\">'+registryTargets()+'</select></label><label class=\"field\"><span>\u5B89\u88C5\u8303\u56F4</span><select id=\"registry-scope\"><option value=\"project\">\u5F53\u524D\u9879\u76EE</option><option value=\"user\">\u5F53\u524D\u7528\u6237</option></select></label><button class=\"button primary\" data-registry-action=\"install\">\u5B89\u88C5</button></div><div class=\"actions\">'+mutating+'</div><small class=\"table-meta\">\u53D1\u5E03\u7C7B\u6309\u94AE\u53EA\u662F\u6743\u9650\u63D0\u793A\uFF1B\u6700\u7EC8\u6388\u6743\u4ECD\u7531\u5E73\u53F0 Keycloak Policy Enforcer \u6267\u884C\u3002</small><div id=\"registry-notice\"></div></div>'}\nfunction registryPage(){const error=registryError?'<div class=\"notice error registry-error\">'+esc(registryError)+'</div>':'';return '<div class=\"content\"><section class=\"hero registry-hero\"><div><div class=\"eyebrow\">Nacos private AI registry</div><h2>\u53D1\u73B0\u3001\u6CBB\u7406\u5E76\u5B89\u88C5\u56E2\u961F\u80FD\u529B</h2><p>Nacos \u5B9E\u4F8B\u3001OIDC \u914D\u7F6E\u4E0E namespace \u8DEF\u7531\u7531\u5E73\u53F0\u6570\u636E\u5E93\u7BA1\u7406\uFF1B\u6D4F\u89C8\u5668\u4E0E CLI \u53EA\u643A\u5E26\u5F53\u524D\u7528\u6237\u7684 Keycloak \u8EAB\u4EFD\u3002</p></div><div class=\"lifecycle\" aria-label=\"Skill \u751F\u547D\u5468\u671F\"><div class=\"life-node live\">draft</div><div class=\"life-node\">review</div><div class=\"life-node\">online</div></div></section>'+error+'<section class=\"registry-toolbar\"><label class=\"field\"><span>Nacos namespace</span><select id=\"registry-namespace\">'+registryNamespaceOptions()+'</select></label><div class=\"segment\" role=\"group\" aria-label=\"\u8D44\u6E90\u7C7B\u578B\"><button data-registry-mode=\"skill\" class=\"'+(registryMode==='skill'?'active':'')+'\">Skills</button><button data-registry-mode=\"mcp\" class=\"'+(registryMode==='mcp'?'active':'')+'\">MCP</button></div><label class=\"field\"><span>\u8FC7\u6EE4</span><input id=\"registry-search\" value=\"'+esc(registrySearch)+'\" placeholder=\"\u540D\u79F0\u6216\u63CF\u8FF0\"></label><button class=\"button\" data-load=\"'+esc(JSON.stringify(['registry','namespaces','list']))+'\">\u5B9E\u4F8B/namespace \u547D\u4EE4</button></section><section class=\"registry-board\"><aside class=\"registry-list\"><div class=\"registry-list-head\"><strong>'+(registryMode==='skill'?'Skill track':'MCP track')+'</strong><span class=\"tag public\">'+registryItems.length+'</span></div><div class=\"registry-items\">'+registryItemButtons()+'</div></aside><article class=\"registry-detail\">'+registryDetailPanel()+'</article></section></div>'}\nasync function loadRegistry(resetNamespaces=false){if(registryLoading)return;registryLoading=true;registryError='';render();try{if(resetNamespaces||!registryNamespaces.length){registryNamespaces=await api('/api/registry/namespaces');if(!Array.isArray(registryNamespaces))throw new Error('namespace \u54CD\u5E94\u683C\u5F0F\u65E0\u6548');if(!registryNamespaceId||!registryNamespaces.some((namespace)=>Number(namespace.id)===Number(registryNamespaceId)))registryNamespaceId=registryNamespaces.find((namespace)=>namespace.status==='ACTIVE'&&namespace.instanceStatus==='ACTIVE'&&namespace.isDefault)?.id??registryNamespaces.find((namespace)=>namespace.status==='ACTIVE'&&namespace.instanceStatus==='ACTIVE')?.id??registryNamespaces[0]?.id??null}if(!registryNamespaceId){registryItems=[];registryDetail=null;return}const endpoint=registryMode==='skill'?'/api/registry/skills':'/api/registry/mcp';const payload=await api(endpoint+'?namespaceId='+encodeURIComponent(registryNamespaceId)+(registrySearch?'&search='+encodeURIComponent(registrySearch):''));registryItems=registryPageItems(payload);if(registryName&&!registryItems.some((item,index)=>registryItemName(item,index)===registryName)){registryName='';registryDetail=null}}catch(error){registryError=error.message;registryItems=[];registryDetail=null}finally{registryLoading=false;render()}}\nasync function selectRegistryItem(name){registryName=name;registryLoading=true;registryError='';render();try{const endpoint=registryMode==='skill'?'/api/registry/skill':'/api/registry/mcp-detail';registryDetail=await api(endpoint+'?namespaceId='+encodeURIComponent(registryNamespaceId)+'&name='+encodeURIComponent(name))}catch(error){registryError=error.message;registryDetail=null}finally{registryLoading=false;render()}}\nasync function runRegistryCommand(argv,successMessage){const target=document.getElementById('registry-notice');if(target)target.innerHTML='<div class=\"notice success\">\u6B63\u5728\u6267\u884C\u2026</div>';try{const result=await api('/api/commands/run',{method:'POST',body:JSON.stringify({argv,confirm:false})});if(result.exitCode!==0)throw new Error(result.stderr||result.stdout||'\u547D\u4EE4\u6267\u884C\u5931\u8D25');if(registryMode==='skill'&®istryName&&argv[2]!=='install')await selectRegistryItem(registryName);const current=document.getElementById('registry-notice');if(current)current.innerHTML='<div class=\"notice success\">'+esc(successMessage)+'</div>'}catch(error){const current=document.getElementById('registry-notice');if(current)current.innerHTML='<div class=\"notice error\">'+esc(error.message)+'</div>'}}\nasync function registryAction(action){if(!registryNamespaceId||!registryName)return;const selected=registryNamespaces.find((namespace)=>Number(namespace.id)===Number(registryNamespaceId));if(!selected)throw new Error('\u672A\u9009\u62E9 namespace');const targetArgs=['--namespace',String(selected.namespaceKey),'--instance',String(selected.instanceCode)];if(action==='install'){const agent=document.getElementById('registry-target').value;let scope=document.getElementById('registry-scope').value;if(registryMode==='mcp'&&(agent==='codex'||agent==='openclaw'))scope='user';const argv=['registry',registryMode,'install',registryName,...targetArgs,'--agent',agent,'--scope',scope];if(registryMode==='skill')argv.push('--label','latest');await runRegistryCommand(argv,'\u5DF2\u5B8C\u6210\u672C\u673A\u5B89\u88C5');return}if(!confirm('\u786E\u8BA4\u5BF9 '+registryName+' \u6267\u884C '+action+'\uFF1F'))return;const argv=['registry','skill',action,registryName,...targetArgs];if(action==='publish'){const version=prompt('\u8F93\u5165\u8981\u53D1\u5E03\u7684 SemVer');if(!version)return;argv.push('--version',version)}await runRegistryCommand(argv,action+' \u5B8C\u6210')}\nfunction configPage(){const c=state.config;return '<div class=\"content\"><section class=\"grid\"><article class=\"card full\"><div class=\"eyebrow\">Configuration file</div><h3>\u57FA\u7840\u914D\u7F6E</h3><p>\u4E0E <code>numa config --set</code> \u4F7F\u7528\u540C\u4E00\u4EFD\u914D\u7F6E\u548C\u6821\u9A8C\u903B\u8F91\u3002</p><form id=\"config-form\" class=\"form-grid\"><div class=\"field\"><label>\u754C\u9762\u8BED\u8A00</label><select name=\"locale\"><option '+(c.locale==='zh-CN'?'selected':'')+'>zh-CN</option><option '+(c.locale==='en-US'?'selected':'')+'>en-US</option></select></div><div class=\"field\"><label>\u9ED8\u8BA4\u8F93\u51FA</label><select name=\"output\"><option '+(c.output==='text'?'selected':'')+'>text</option><option '+(c.output==='json'?'selected':'')+'>json</option></select></div><div class=\"field span-2\"><label>\u5E73\u53F0 API \u5730\u5740</label><input name=\"apiBaseUrl\" value=\"'+esc(c.apiBaseUrl)+'\" placeholder=\"https://platform.example/api\"></div><div class=\"field span-2\"><label>npm registry</label><input name=\"registryUrl\" value=\"'+esc(c.registryUrl)+'\"></div><label class=\"field span-2\"><span>\u66F4\u65B0\u68C0\u67E5</span><select name=\"checkUpdates\"><option value=\"true\" '+(c.checkUpdates?'selected':'')+'>\u542F\u7528</option><option value=\"false\" '+(!c.checkUpdates?'selected':'')+'>\u5173\u95ED</option></select></label><div class=\"actions span-2\"><button class=\"button primary\" type=\"submit\">\u4FDD\u5B58\u914D\u7F6E</button></div></form><div id=\"notice\"></div></article></section></div>'}\nfunction commandsPage(){return '<div class=\"content\"><section class=\"card full\"><div class=\"command-toolbar\"><div class=\"field grow\"><label>\u8FC7\u6EE4\u547D\u4EE4</label><input id=\"command-search\" placeholder=\"\u4F8B\u5982 codex\u3001media\u3001auth\"></div></div><div id=\"command-list\" class=\"command-list\">'+commandCards('')+'</div></section></div>'}\nfunction commandCards(query){const q=query.toLowerCase();return state.commands.filter((c)=>(c.command+' '+c.summary).toLowerCase().includes(q)).map((c)=>'<article class=\"command\"><div class=\"command-head\"><code>'+esc(c.command)+'</code><span class=\"tag '+esc(c.access)+'\">'+esc(c.access)+'</span></div><p>'+esc(c.summary)+'</p><small>'+esc(c.examples[0]||'')+'</small><div class=\"actions mt-10\"><button class=\"button\" data-load=\"'+esc(JSON.stringify(commandPrefix(c.command)))+'\">\u8F7D\u5165\u6267\u884C\u5668</button></div></article>').join('')||'<p>\u6CA1\u6709\u5339\u914D\u547D\u4EE4\u3002</p>'}\nfunction commandPrefix(command){return command.split(/s+/).filter((part)=>!part.startsWith('[')&&!part.startsWith('<')&&!part.startsWith('--'))}\nfunction runnerPage(){return '<div class=\"content\"><section class=\"grid\"><article class=\"card\"><div class=\"eyebrow\">Structured argv</div><h3>\u5B89\u5168\u6267\u884C\u5668</h3><p>\u4F7F\u7528 JSON \u6570\u7EC4\u4F20\u5165\u53C2\u6570\uFF0C\u4E0D\u7ECF\u8FC7 shell\u3002\u957F\u9A7B\u6216\u4EA4\u4E92\u547D\u4EE4\u9700\u8981\u5728\u7EC8\u7AEF\u8FD0\u884C\u3002</p><form id=\"runner-form\"><div class=\"field\"><label>\u547D\u4EE4\u53C2\u6570</label><textarea id=\"argv\" class=\"mono\">[\"doctor\"]</textarea></div><label class=\"field mt-12\"><span>\u5371\u9669\u64CD\u4F5C\u786E\u8BA4</span><select id=\"confirm\"><option value=\"false\">\u672A\u786E\u8BA4</option><option value=\"true\">\u786E\u8BA4\u6267\u884C\u5220\u9664/\u91CD\u7F6E</option></select></label><div class=\"actions mt-14\"><button class=\"button primary\" type=\"submit\">\u8FD0\u884C\u547D\u4EE4</button></div></form></article><article class=\"card wide\"><div class=\"eyebrow\">Result stream</div><h3>\u7ED3\u6784\u5316\u8F93\u51FA</h3><pre id=\"output\" class=\"output\">'+esc(output)+'</pre></article></section></div>'}\nasync function loadChatgpt(){if(chatgptLoading)return;chatgptLoading=true;chatgptLocal=null;chatgptRemote={status:'LOADING',accounts:[]};render();try{chatgptLocal=await api('/api/chatgpt/local')}catch(error){chatgptLocal={status:'FAILED',accounts:[],available:0,total:0,error:{message:error.message}}}render();try{chatgptRemote=await api('/api/chatgpt/remote')}catch(error){chatgptRemote={status:'FAILED',accounts:[],syncedAt:Date.now(),error:{message:error.message}}}finally{chatgptLoading=false;render()}}\nfunction render(){if(!state.loggedIn){app.innerHTML=loginGate();bind();return}const page=active==='overview'?overview():active==='registry'?registryPage():active==='chatgpt'?chatgptPage():active==='config'?configPage():active==='commands'?commandsPage():runnerPage();app.innerHTML=shell(page);bind()}\nfunction notice(message,type='success'){const target=document.getElementById('notice');if(target)target.innerHTML='<div class=\"notice '+type+'\">'+esc(message)+'</div>'}\nfunction bindCommandLoaders(){document.querySelectorAll('[data-load]').forEach((b)=>b.addEventListener('click',()=>{const argv=JSON.parse(b.dataset.load);active='runner';render();document.getElementById('argv').value=JSON.stringify(argv)}))}\nfunction bind(){document.querySelectorAll('[data-nav]').forEach((b)=>b.addEventListener('click',()=>{active=b.dataset.nav;render();if(active==='chatgpt'&&!chatgptLocal&&!chatgptLoading)void loadChatgpt();if(active==='registry'&&!registryNamespaces.length&&!registryLoading)void loadRegistry(true)}));document.querySelector('[data-action=\"chatgpt-refresh\"]')?.addEventListener('click',()=>void loadChatgpt());document.querySelector('[data-action=\"registry-refresh\"]')?.addEventListener('click',()=>registryName?void selectRegistryItem(registryName):void loadRegistry());document.querySelectorAll('[data-registry-mode]').forEach((button)=>button.addEventListener('click',()=>{registryMode=button.dataset.registryMode;registryName='';registryDetail=null;void loadRegistry()}));document.querySelectorAll('[data-registry-name]').forEach((button)=>button.addEventListener('click',()=>void selectRegistryItem(button.dataset.registryName)));document.querySelectorAll('[data-registry-action]').forEach((button)=>button.addEventListener('click',()=>void registryAction(button.dataset.registryAction)));document.getElementById('registry-namespace')?.addEventListener('change',(event)=>{registryNamespaceId=Number(event.target.value);registryName='';registryDetail=null;void loadRegistry()});document.getElementById('registry-search')?.addEventListener('change',(event)=>{registrySearch=event.target.value.trim();registryName='';registryDetail=null;void loadRegistry()});document.getElementById('registry-search')?.addEventListener('keydown',(event)=>{if(event.key==='Enter'){event.preventDefault();registrySearch=event.target.value.trim();registryName='';registryDetail=null;void loadRegistry()}});document.querySelector('[data-action=\"login\"]')?.addEventListener('click',async()=>{try{notice('\u6B63\u5728\u542F\u52A8\u767B\u5F55\u2026');const result=await api('/api/auth/login',{method:'POST',body:'{}'});location.href=result.authorizationUrl}catch(e){notice(e.message,'error')}});document.querySelector('[data-action=\"reload\"]')?.addEventListener('click',()=>bootstrap());document.querySelector('[data-action=\"logout\"]')?.addEventListener('click',async()=>{if(!confirm('\u6E05\u9664\u672C\u673A Keycloak \u767B\u5F55\u7F13\u5B58\uFF1F'))return;await api('/api/auth/logout',{method:'POST',body:'{}'});location.reload()});document.getElementById('config-form')?.addEventListener('submit',async(e)=>{e.preventDefault();const data=Object.fromEntries(new FormData(e.currentTarget));data.checkUpdates=data.checkUpdates==='true';try{const result=await api('/api/config',{method:'PUT',body:JSON.stringify(data)});state.config=result.config;notice('\u914D\u7F6E\u5DF2\u4FDD\u5B58')}catch(err){notice(err.message,'error')}});document.getElementById('command-search')?.addEventListener('input',(e)=>{document.getElementById('command-list').innerHTML=commandCards(e.target.value);bindCommandLoaders()});bindCommandLoaders();document.getElementById('runner-form')?.addEventListener('submit',async(e)=>{e.preventDefault();try{const argv=JSON.parse(document.getElementById('argv').value);const confirmed=document.getElementById('confirm')?.value==='true';output='\u8FD0\u884C\u4E2D\u2026';render();const result=await api('/api/commands/run',{method:'POST',body:JSON.stringify({argv,confirm:confirmed})});output=result.stdout||result.stderr||JSON.stringify(result,null,2);render()}catch(err){output='\u9519\u8BEF: '+err.message;render()}})}\nbootstrap();\n";
|
|
1
|
+
export declare const CONSOLE_HTML = "<!doctype html>\n<html lang=\"zh-CN\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width,initial-scale=1\">\n <title>Numa CLI \u63A7\u5236\u53F0</title>\n <link rel=\"stylesheet\" href=\"/assets/console.css\">\n</head>\n<body>\n <!--\n THESIS: A namespace-scoped operations ledger owns the release boundary and refuses a generic dashboard of disconnected cards.\n OWN-WORLD: Deep navy frame, mist work surface, paper records, cyan state signals, compact operational type, and flat control-plane materials.\n STORY: The operator sees their authorized boundary, understands resource and release state, then performs one capability-gated next action.\n FIRST VIEWPORT: Persistent rail and header frame a wide registry hero, six visible workspaces, namespace context, then a list-detail operating board with actions beside their record.\n FORM: Code-led control-room ledger, first choice; seed control-plane-ledger-v1.\n FINISH: unreviewed and undocumented is unfinished; this build ends with the finish review, the verdict, DESIGN.md, and every shipping raster carrying its provenance\n -->\n <div id=\"app\" class=\"boot\"><div class=\"boot-mark\">N</div><p>\u6B63\u5728\u8FDE\u63A5\u672C\u5730\u63A7\u5236\u53F0\u2026</p></div>\n <script type=\"module\" src=\"/assets/console.js\"></script>\n</body>\n</html>";
|
|
2
|
+
export declare const CONSOLE_CSS = "\n:root{color-scheme:light;--ink:#0b1728;--navy:#07182b;--navy-2:#102943;--cyan:#0a9fa7;--cyan-soft:#d7f2f1;--mist:#eef4f8;--paper:#fbfdff;--line:#d7e2ea;--muted:#536b82;--amber:#e99a32;--red:#d94b58;--green:#147a5d;--shadow:0 18px 50px rgba(12,38,62,.1)}\n*{box-sizing:border-box}html,body,#app{min-height:100%}body{min-height:100vh;margin:0;background:var(--mist);color:var(--ink);font-family:\"Avenir Next\",\"Segoe UI\",system-ui,sans-serif}button,input,select,textarea{font:inherit}.mono,code,pre{font-family:\"SFMono-Regular\",Consolas,\"Liberation Mono\",monospace}.boot{min-height:100vh;display:grid;place-content:center;justify-items:center;gap:14px;color:var(--muted)}.boot-mark,.brand-mark{display:grid;place-items:center;background:var(--cyan);color:#00262a;font-weight:900}.boot-mark{width:50px;height:50px;border-radius:15px;box-shadow:0 0 0 8px rgba(14,183,191,.12)}\n.shell{min-height:100vh;display:grid;grid-template-columns:260px 1fr}.rail{position:sticky;top:0;height:100vh;padding:24px 18px;background:var(--navy);color:#d7e6f3;display:flex;flex-direction:column}.brand{display:flex;align-items:center;gap:12px;padding:8px 8px 26px}.brand-mark{width:38px;height:38px;border-radius:12px}.brand strong{display:block;letter-spacing:.04em}.brand small{display:block;margin-top:4px;color:#708aa3;font-size:10px;letter-spacing:.18em;text-transform:uppercase}.nav{display:grid;gap:7px}.nav button{border:0;background:transparent;color:#8da4b8;border-radius:11px;text-align:left;padding:11px 13px;cursor:pointer;display:flex;justify-content:space-between}.nav button:hover,.nav button.active{background:var(--navy-2);color:white}.nav button.active{box-shadow:inset 3px 0 var(--cyan)}.rail-foot{margin-top:auto;border:1px solid #203b55;border-radius:14px;padding:14px}.rail-foot .pulse{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--cyan);box-shadow:0 0 12px var(--cyan);margin-right:7px}.rail-foot p{margin:7px 0 0;color:#7791a8;font-size:11px;line-height:1.5}\n.main{min-width:0;min-height:100vh;display:flex;flex-direction:column}.topbar{height:76px;padding:0 34px;background:rgba(251,253,255,.94);border-bottom:1px solid var(--line);display:flex;align-items:center;justify-content:space-between;position:sticky;top:0;z-index:3;backdrop-filter:blur(12px)}.topbar h1{font-size:17px;margin:0}.eyebrow{font:700 10px/1.2 \"SFMono-Regular\",monospace;text-transform:uppercase;letter-spacing:.16em;color:var(--cyan)}.user-chip{display:flex;align-items:center;gap:10px}.avatar{width:34px;height:34px;border-radius:50%;display:grid;place-items:center;background:var(--cyan-soft);color:#066b70;font-weight:800}.user-chip small{color:var(--muted)}.content{width:100%;max-width:1420px;flex:1;margin:0 auto;padding:30px 34px 56px}.hero{background:var(--navy);color:white;border-radius:22px;padding:28px 30px;display:grid;grid-template-columns:1fr auto;gap:24px;position:relative;overflow:hidden;box-shadow:var(--shadow)}.hero:after{content:\"\";position:absolute;right:-45px;top:-90px;width:320px;height:240px;border:34px solid rgba(14,183,191,.09);transform:rotate(-18deg);border-radius:48px}.hero h2{font-size:32px;line-height:1.08;margin:10px 0}.hero p{max-width:720px;color:#91aac0;margin:0;line-height:1.6}.session-track{align-self:center;display:flex;gap:0;position:relative;z-index:1}.track-node{min-width:112px;border:1px solid #2a4661;padding:13px 15px;background:#0b1e33}.track-node:first-child{border-radius:13px 0 0 13px}.track-node:last-child{border-radius:0 13px 13px 0}.track-node span{display:block;color:#7690a7;font-size:9px;text-transform:uppercase;letter-spacing:.12em}.track-node strong{display:block;margin-top:6px;font-size:13px}.track-node.live strong{color:#58e0df}\n.grid{display:grid;grid-template-columns:repeat(12,1fr);gap:18px;margin-top:20px}.card{grid-column:span 4;background:var(--paper);border:1px solid var(--line);border-radius:17px;padding:20px;box-shadow:0 10px 30px rgba(25,54,79,.05)}.card.wide{grid-column:span 8}.card.full{grid-column:1/-1}.card h3{margin:0;font-size:15px}.card p{color:var(--muted);font-size:12px;line-height:1.6}.metric{font-size:28px;font-weight:750;margin-top:16px}.metric small{font-size:11px;color:var(--muted);font-weight:500}.tag{display:inline-flex;border-radius:999px;padding:5px 8px;font:700 9px/1 \"SFMono-Regular\",monospace;text-transform:uppercase;letter-spacing:.05em;background:var(--cyan-soft);color:#066b70}.tag.public{background:#edf1f5;color:#5d7082}.tag.role{background:#fff0d9;color:#9c5c09}.actions{display:flex;gap:8px;flex-wrap:wrap}.button{border:1px solid var(--line);border-radius:10px;background:white;color:var(--ink);padding:9px 12px;cursor:pointer;font-weight:700;font-size:12px}.button:hover{border-color:#9ab6c9;background:#f7fbfd}.button.primary{background:#0b949b;border-color:#0b949b;color:white}.button.danger{color:var(--red);border-color:#f0bec4}.button:disabled{opacity:.45;cursor:not-allowed}.field{display:grid;gap:6px}.field label{font-size:11px;color:var(--muted);font-weight:700}.field input,.field select,.field textarea{width:100%;border:1px solid var(--line);border-radius:10px;background:white;padding:10px 11px;color:var(--ink);outline:none}.field input:focus,.field textarea:focus{border-color:var(--cyan);box-shadow:0 0 0 3px rgba(14,183,191,.12)}.field textarea{min-height:110px;resize:vertical}.form-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px}.form-grid .span-2{grid-column:1/-1}.command-toolbar{display:flex;gap:10px;margin-bottom:15px}.grow{flex:1}.mt-10{margin-top:10px}.mt-12{margin-top:12px}.mt-14{margin-top:14px}.command-list{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:11px}.command{border:1px solid var(--line);border-radius:13px;padding:14px;background:white}.command-head{display:flex;gap:8px;align-items:center;justify-content:space-between}.command code{font-size:11px;color:#0b6f76}.command p{margin:9px 0}.command small{display:block;color:#8a9bab;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.output{background:#071522;color:#b8d1e2;border-radius:13px;padding:15px;min-height:170px;max-height:420px;overflow:auto;white-space:pre-wrap;font-size:11px;line-height:1.65}.notice{margin-top:14px;border-radius:11px;padding:11px 13px;font-size:12px}.notice.error{background:#fff0f2;color:#a52c3b;border:1px solid #f1c4ca}.notice.success{background:#e8f7f1;color:#176c54;border:1px solid #bce4d5}.login-gate{min-height:calc(100vh - 76px);display:grid;place-content:center;padding:30px}.login-card{width:min(520px,90vw);background:white;border:1px solid var(--line);border-radius:22px;padding:32px;box-shadow:var(--shadow)}.login-card h2{font-size:28px;margin:14px 0 9px}.login-card p{color:var(--muted);line-height:1.65}.hidden{display:none!important}\n.sync-board{display:grid;grid-template-columns:1fr 56px 1fr;align-items:stretch;margin-top:20px}.sync-stage{background:var(--paper);border:1px solid var(--line);border-radius:17px;padding:18px 20px;box-shadow:0 10px 30px rgba(25,54,79,.05)}.sync-stage strong{display:block;margin-top:8px;font-size:18px}.sync-stage p{margin:7px 0 0;color:var(--muted);font-size:11px}.sync-link{display:grid;place-items:center;color:var(--cyan);font-size:22px}.sync-link:before{content:\"\";height:2px;width:100%;background:linear-gradient(90deg,var(--cyan),#bad8dc)}.table-card{margin-top:18px;background:var(--paper);border:1px solid var(--line);border-radius:17px;box-shadow:0 10px 30px rgba(25,54,79,.05);overflow:hidden}.table-head{padding:18px 20px;display:flex;align-items:center;justify-content:space-between;gap:16px;border-bottom:1px solid var(--line)}.table-head h3{margin:0}.table-head p{margin:5px 0 0;color:var(--muted);font-size:11px}.account-table-wrap{overflow:auto}.account-table{width:100%;border-collapse:collapse;min-width:920px}.account-table th,.account-table td{text-align:left;padding:14px 16px;border-bottom:1px solid #e7eef3;vertical-align:middle}.account-table th{background:#f5f9fb;color:#536b82;font-size:10px;text-transform:uppercase;letter-spacing:.08em}.account-table tr:last-child td{border-bottom:0}.account-name strong{display:block;font-size:13px}.account-name small{display:block;margin-top:4px;color:var(--muted);font-size:10px}.quota-stack{min-width:210px;display:grid;gap:8px}.quota-line{display:grid;grid-template-columns:42px 1fr 38px;align-items:center;gap:7px;font-size:10px;color:var(--muted)}progress{width:100%;height:7px;border:0;border-radius:99px;overflow:hidden;background:#e7eef3}progress::-webkit-progress-bar{background:#e7eef3;border-radius:99px}progress::-webkit-progress-value{background:var(--cyan);border-radius:99px}progress::-moz-progress-bar{background:var(--cyan);border-radius:99px}.status-stack{display:flex;gap:6px;flex-wrap:wrap}.tag.success{background:#e8f7f1;color:var(--green)}.tag.failed{background:#fff0f2;color:var(--red)}.tag.waiting{background:#fff0d9;color:#8c5005}.tag.local{background:#e8f1fa;color:#32658f}.empty-state{padding:48px 20px;text-align:center;color:var(--muted)}.empty-state.account-request{margin:24px;border:2px solid #f0b5bd;border-radius:16px;background:#fff2f4;color:#8d2334;box-shadow:0 12px 30px rgba(167,44,64,.1)}.empty-state.account-request strong{display:block;margin-bottom:9px;font-size:16px}.empty-state.account-request span{display:block;font-size:13px;line-height:1.7}.table-meta{color:var(--muted);font-size:10px;line-height:1.55}.spin{animation:turn 1s linear infinite}.refresh-icon{display:inline-block;width:12px;height:12px;border:2px solid currentColor;border-left-color:transparent;border-radius:50%;vertical-align:-2px;position:relative}.refresh-icon:after{content:\"\";position:absolute;right:-3px;top:-2px;border-width:3px 0 3px 4px;border-style:solid;border-color:transparent transparent transparent currentColor;transform:rotate(-18deg)}@keyframes turn{to{transform:rotate(360deg)}}\n.registry-hero{background:linear-gradient(118deg,#06172a 0%,#0b2d42 67%,#0a4c55 100%)}.lifecycle{display:grid;grid-template-columns:repeat(5,70px);align-items:center;position:relative;z-index:1;margin-top:12px}.life-node{position:relative;text-align:center;color:#8ba7b8;font:700 8px/1.2 \"SFMono-Regular\",monospace;text-transform:uppercase;letter-spacing:.05em}.life-node:before{content:\"\";display:block;width:10px;height:10px;margin:0 auto 9px;border:2px solid #58e0df;border-radius:50%;background:#0a2638;box-shadow:0 0 0 4px rgba(88,224,223,.08)}.life-node:not(:last-child):after{content:\"\";position:absolute;height:1px;width:calc(100% - 22px);top:6px;left:calc(50% + 11px);background:linear-gradient(90deg,#58e0df,#31546a)}.registry-toolbar{display:grid;grid-template-columns:minmax(190px,1fr) auto minmax(190px,1fr) auto;gap:10px;align-items:end;margin-top:20px}.segment{display:flex;padding:3px;background:#dfe9ef;border-radius:11px}.segment button{border:0;background:transparent;padding:8px 13px;border-radius:8px;color:var(--muted);font-weight:750;font-size:11px;cursor:pointer}.segment button.active{background:white;color:#087d84;box-shadow:0 3px 12px rgba(7,24,43,.1)}.registry-board{display:grid;grid-template-columns:minmax(260px,32%) 1fr;min-height:560px;margin-top:14px;background:var(--paper);border:1px solid var(--line);border-radius:18px;overflow:hidden;box-shadow:var(--shadow)}.registry-list{border-right:1px solid var(--line);background:#f4f8fa}.registry-list-head{padding:15px 17px;border-bottom:1px solid var(--line);display:flex;justify-content:space-between;align-items:center}.registry-items{padding:9px;display:grid;gap:6px;max-height:680px;overflow:auto}.registry-item{width:100%;border:1px solid transparent;background:transparent;border-radius:12px;padding:12px;text-align:left;cursor:pointer;display:grid;grid-template-columns:12px 1fr;gap:10px;color:var(--ink)}.registry-item:hover,.registry-item.active{background:white;border-color:var(--line);box-shadow:0 6px 20px rgba(18,49,71,.07)}.registry-dot{width:8px;height:8px;margin-top:4px;border-radius:50%;background:var(--amber);box-shadow:0 0 0 4px rgba(233,154,50,.1)}.registry-dot.online{background:var(--green);box-shadow:0 0 0 4px rgba(25,138,104,.1)}.registry-item strong,.registry-item small{display:block}.registry-item strong{font-size:12px}.registry-item small{margin-top:5px;color:var(--muted);font-size:10px}.registry-detail{min-width:0;padding:22px;display:flex;flex-direction:column}.registry-detail-head{display:flex;justify-content:space-between;align-items:start;gap:16px}.registry-detail h3{margin:5px 0 3px;font-size:20px}.registry-detail pre{flex:1;margin:16px 0;min-height:270px}.registry-actions{border-top:1px solid var(--line);padding-top:15px;display:grid;gap:12px}.install-row{display:grid;grid-template-columns:1fr 1fr auto;gap:9px}.registry-error{margin-top:14px}.button:focus-visible,.nav button:focus-visible,.registry-item:focus-visible,.segment button:focus-visible,input:focus-visible,select:focus-visible,textarea:focus-visible{outline:3px solid rgba(14,183,191,.3);outline-offset:2px}\n.registry-workspaces{display:flex;gap:2px;margin-top:22px;border-bottom:1px solid var(--line)}.registry-workspaces button{flex:1 1 auto;border:0;border-bottom:2px solid transparent;background:transparent;color:#536b82;padding:12px 10px;cursor:pointer;font-weight:720;font-size:12px}.registry-workspaces button:hover{color:var(--ink);background:#e4f0f3}.registry-workspaces button.active{color:#066f75;border-bottom-color:#0b949b}.registry-context{min-width:0;display:flex;flex-direction:column;justify-content:center;padding:7px 2px}.registry-context strong,.registry-context span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.registry-context span{margin-top:4px;color:var(--muted);font-size:11px}.registry-simple{margin-top:14px;min-height:430px;background:var(--paper);border:1px solid var(--line);border-radius:16px;padding:26px;box-shadow:0 12px 34px rgba(25,54,79,.08)}.registry-simple>h3{margin:0 0 8px;font-size:20px}.registry-simple>p{max-width:72ch;color:var(--muted);line-height:1.65}.governance-strip{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));margin:26px 0;border-block:1px solid var(--line)}.governance-strip>div{min-width:0;padding:20px}.governance-strip>div+div{border-inline-start:1px solid var(--line)}.governance-strip strong,.governance-strip span{display:block;overflow-wrap:anywhere}.governance-strip strong{font-size:13px}.governance-strip span{margin-top:7px;color:var(--muted);font-size:11px}.registry-facts{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;margin:24px 0;background:var(--line)}.registry-facts>div{min-width:0;background:white;padding:18px}.registry-facts dt{color:var(--muted);font-size:11px}.registry-facts dd{margin:7px 0 0;overflow-wrap:anywhere;font-weight:700}.record-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:12px;margin:18px 0}.record-card{border:1px solid var(--line);border-radius:13px;background:white;padding:16px}.record-card h4{margin:0;font-size:14px}.record-card dl{display:grid;grid-template-columns:minmax(90px,.45fr) 1fr;gap:8px 12px;margin:14px 0 0;font-size:11px}.record-card dt{color:var(--muted)}.record-card dd{margin:0;overflow-wrap:anywhere;font-weight:650}.summary-grid{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:10px;margin:16px 0}.summary-cell{border:1px solid var(--line);border-radius:12px;padding:14px;background:#f8fbfc}.summary-cell span,.summary-cell strong{display:block}.summary-cell span{color:var(--muted);font-size:10px}.summary-cell strong{margin-top:7px;overflow-wrap:anywhere;font-size:13px}.raw-disclosure{margin:14px 0}.raw-disclosure summary{cursor:pointer;color:#3e6078;font-size:11px;font-weight:700}.raw-disclosure .output{margin:9px 0 0;min-height:120px;max-height:280px}.permission-grid{display:flex;flex-wrap:wrap;gap:8px;margin:16px 0 22px}.permission-grid .tag{font-size:10px;padding:7px 9px}.wrap{overflow-wrap:anywhere;white-space:pre-wrap}.sr-only{position:absolute!important;width:1px!important;height:1px!important;padding:0!important;margin:-1px!important;overflow:hidden!important;clip:rect(0,0,0,0)!important;white-space:nowrap!important;border:0!important}::selection{background:#0b949b;color:white}*{scrollbar-color:#8eb5c0 #e7eef3}input,textarea{caret-color:#0b949b}.output{font-variant-numeric:tabular-nums}\n@media(max-width:980px){.shell{grid-template-columns:78px 1fr}.rail{padding:18px 10px}.brand div:last-child,.nav button span:first-child,.rail-foot p,.rail-foot strong{display:none}.brand{justify-content:center}.nav button{justify-content:center}.card,.card.wide{grid-column:span 6}.hero{grid-template-columns:1fr}.session-track,.lifecycle{display:none}.registry-toolbar{grid-template-columns:1fr 1fr}.registry-board{grid-template-columns:1fr}.registry-list{border-right:0;border-bottom:1px solid var(--line)}.registry-items{max-height:260px}}\n@media(max-width:680px){.shell{display:block}.rail{height:auto;position:static;flex-direction:row;align-items:center;padding:10px 14px;overflow-x:auto}.brand{padding:0;margin-right:auto;flex:0 0 auto}.nav{display:flex}.nav button{padding:9px;flex:0 0 auto}.rail-foot{display:none}.topbar{padding:0 18px}.content{padding:20px 14px}.hero{padding:23px}.hero h2{font-size:25px}.card,.card.wide{grid-column:1/-1}.form-grid,.command-list,.registry-toolbar,.install-row{grid-template-columns:1fr}.form-grid .span-2{grid-column:auto}.user-chip div:not(.avatar){display:none}.sync-board{grid-template-columns:1fr}.sync-link{height:32px;transform:rotate(90deg)}.table-head{align-items:flex-start;flex-direction:column}.registry-detail{padding:17px}}\n@media(max-width:680px){.field input,.field select,.field textarea{font-size:16px}.governance-strip,.registry-facts,.record-grid,.summary-grid{grid-template-columns:1fr}.governance-strip>div+div{border-inline-start:0;border-block-start:1px solid var(--line)}.registry-simple{padding:19px}.registry-workspaces{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));border:1px solid var(--line);border-radius:13px;overflow:hidden}.registry-workspaces button{width:100%;border-bottom:1px solid var(--line);border-radius:0;padding:11px 8px}.registry-workspaces button.active{box-shadow:inset 3px 0 #0b949b;border-bottom-color:var(--line)}}\n@media(prefers-reduced-motion:reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;scroll-behavior:auto!important}}\n@media(prefers-reduced-motion:no-preference){.card,.hero{animation:arrive .35s ease both}@keyframes arrive{from{opacity:0;transform:translateY(7px)}to{opacity:1;transform:none}}}\n";
|
|
3
|
+
export declare const CONSOLE_JS = "\nconst app=document.getElementById('app');let state=null;let csrf='';let active='overview';let output='\u9009\u62E9\u4E00\u6761\u547D\u4EE4\u6216\u8F93\u5165\u53C2\u6570\u540E\u8FD0\u884C\u3002';let chatgptLocal=null;let chatgptRemote=null;let chatgptLoading=false;let registryCapabilities=null;let registryNamespaces=[];let registryItems=[];let registryDetail=null;let registryAux=null;let registryMode='skill';let registryWorkspace='catalog';let registryNamespaceId=null;let registryName='';let registrySearch='';let registryLoading=false;let registryError='';let registryNotice='';const noAvailableAccountGuidance='\u5F53\u524D\u7528\u6237\u6CA1\u6709\u7ED1\u5B9A\u53EF\u7528\u7684 ChatGPT \u8D26\u53F7\u3002\u8BF7\u524D\u5F80 OA \u7CFB\u7EDF\u63D0\u4EA4 IT11 \u5DE5\u5355\uFF0C\u7533\u8BF7\u72EC\u4EAB\u6216\u5171\u4EAB\u7684 ChatGPT \u4E2A\u4EBA\u8D26\u53F7\u3002';\nconst esc=(v)=>String(v??'').replace(/[&<>\"']/g,(c)=>({'&':'&','<':'<','>':'>','\"':'"',\"'\":'''}[c]));\nasync function api(path,init={}){const headers={'Accept':'application/json',...(init.body?{'Content-Type':'application/json'}:{}),...(csrf?{'x-numa-console-csrf':csrf}:{})};const response=await fetch(path,{...init,headers:{...headers,...(init.headers||{})},credentials:'same-origin'});const body=await response.json().catch(()=>({error:{message:'\u54CD\u5E94\u4E0D\u662F JSON'}}));if(!response.ok)throw new Error(body.error?.message||body.stderr||body.stdout||('HTTP '+response.status));return body}\nasync function bootstrap(attempt=0){try{state=await api('/api/bootstrap');csrf=state.csrfToken;const callbackState=new URLSearchParams(location.search).get('login');const waitingForSuccess=callbackState==='complete'&&!state.loggedIn&&attempt<40;const waitingForFailure=callbackState==='failed'&&!state.loginError&&attempt<8;if(waitingForSuccess||waitingForFailure){app.innerHTML='<div class=\"boot\"><div class=\"boot-mark\">N</div><p>'+(callbackState==='complete'?'\u767B\u5F55\u6210\u529F\uFF0C\u6B63\u5728\u5EFA\u7ACB\u672C\u673A\u4F1A\u8BDD\u2026':'\u6B63\u5728\u8BFB\u53D6\u767B\u5F55\u5931\u8D25\u4FE1\u606F\u2026')+'</p></div>';setTimeout(()=>bootstrap(attempt+1),250);return}if(callbackState==='complete'&&!state.loggedIn&&!state.loginError)state.loginError='\u767B\u5F55\u51ED\u636E\u4EA4\u6362\u5C1A\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5\u767B\u5F55\u3002';if(callbackState==='failed'&&!state.loginError)state.loginError='Keycloak \u767B\u5F55\u672A\u5B8C\u6210\uFF0C\u8BF7\u91CD\u8BD5\u3002';if(callbackState)history.replaceState({},'',location.pathname);render()}catch(error){app.innerHTML='<div class=\"login-gate\"><div class=\"login-card\"><span class=\"tag role\">\u8FDE\u63A5\u5931\u8D25</span><h2>\u672C\u5730\u63A7\u5236\u53F0\u4E0D\u53EF\u7528</h2><p>'+esc(error.message)+'</p></div></div>'}}\nfunction navButton(id,label,mark){return '<button data-nav=\"'+id+'\" class=\"'+(active===id?'active':'')+'\"><span>'+label+'</span><span class=\"mono\">'+mark+'</span></button>'}\nfunction shell(content){const user=state.user||{};const label=user.username||user.email||'\u672A\u767B\u5F55';return '<div class=\"shell\"><aside class=\"rail\"><div class=\"brand\"><div class=\"brand-mark\">N</div><div><strong>Numa CLI</strong><small>Local control plane</small></div></div><nav class=\"nav\">'+navButton('overview','\u8FD0\u884C\u6982\u89C8','01')+navButton('registry','AI Registry','02')+navButton('chatgpt','ChatGPT \u8D26\u53F7','03')+navButton('config','\u57FA\u7840\u914D\u7F6E','04')+navButton('commands','\u547D\u4EE4\u80FD\u529B','05')+navButton('runner','\u6267\u884C\u5668','06')+'</nav><div class=\"rail-foot\"><strong><span class=\"pulse\"></span>\u4EC5\u76D1\u542C\u672C\u673A</strong><p>Token \u4E0D\u4F1A\u53D1\u9001\u7ED9\u7F51\u9875\u811A\u672C\uFF0C\u4E5F\u4E0D\u4F1A\u51FA\u73B0\u5728\u547D\u4EE4\u8F93\u51FA\u4E2D\u3002</p></div></aside><main class=\"main\"><header class=\"topbar\"><h1>'+sectionTitle()+'</h1><div class=\"user-chip\"><div class=\"avatar\">'+esc(label.slice(0,1).toUpperCase())+'</div><div><strong>'+esc(label)+'</strong><br><small>'+esc(state.loggedIn?'Keycloak \u4F1A\u8BDD\u6709\u6548':'\u9700\u8981\u767B\u5F55')+'</small></div></div></header>'+content+'</main></div>'}\nfunction sectionTitle(){return {overview:'\u8FD0\u884C\u6982\u89C8',registry:'AI Registry',chatgpt:'ChatGPT \u8D26\u53F7',config:'\u57FA\u7840\u914D\u7F6E',commands:'\u547D\u4EE4\u80FD\u529B',runner:'\u5B89\u5168\u6267\u884C\u5668'}[active]||'\u63A7\u5236\u53F0'}\nfunction loginGate(){const error=state?.loginError?'<div class=\"notice error\">'+esc(state.loginError)+'</div>':'';return '<div class=\"login-gate\"><div class=\"login-card\"><span class=\"tag role\">Keycloak PKCE</span><h2>\u767B\u5F55\u540E\u8FDB\u5165\u672C\u5730\u63A7\u5236\u53F0</h2><p>\u6D4F\u89C8\u5668\u53EA\u8D1F\u8D23\u5B8C\u6210\u8BA4\u8BC1\u548C\u64CD\u4F5C\u672C\u673A API\u3002\u8BBF\u95EE\u4EE4\u724C\u4FDD\u5B58\u5728 CLI \u7684\u79C1\u6709\u7F13\u5B58\u4E2D\uFF0C\u4E0D\u5199\u5165 localStorage\uFF0C\u4E5F\u4E0D\u8FD4\u56DE\u7ED9\u9875\u9762\u3002</p><div class=\"actions\"><button class=\"button primary\" data-action=\"login\">\u4F7F\u7528 Keycloak \u767B\u5F55</button></div><div id=\"notice\">'+error+'</div></div></div>'}\nfunction overview(){const u=state.user||{};const roles=[...(u.realmRoles||[]),...Object.values(u.clientRoles||{}).flat()];return '<div class=\"content\"><section class=\"hero\"><div><div class=\"eyebrow\">Authenticated workstation</div><h2>\u672C\u673A\u4F1A\u8BDD\u5DF2\u63A5\u5165\u7814\u53D1\u63A7\u5236\u9762</h2><p>\u4ECE\u540C\u4E00\u5904\u68C0\u67E5\u8EAB\u4EFD\u3001\u8C03\u6574 CLI \u914D\u7F6E\uFF0C\u5E76\u4EE5\u7ED3\u6784\u5316\u53C2\u6570\u8FD0\u884C\u53D7\u652F\u6301\u547D\u4EE4\u3002\u6240\u6709\u7F51\u7EDC\u8BF7\u6C42\u7EE7\u7EED\u7531 CLI \u6CE8\u5165 Bearer Token\u3002</p></div><div class=\"session-track\"><div class=\"track-node live\"><span>\u8EAB\u4EFD</span><strong>'+esc(u.username||'\u5DF2\u767B\u5F55')+'</strong></div><div class=\"track-node\"><span>API</span><strong>'+esc(state.config.apiBaseUrl?'\u5DF2\u914D\u7F6E':'\u672A\u914D\u7F6E')+'</strong></div><div class=\"track-node\"><span>\u89D2\u8272</span><strong>'+roles.length+'</strong></div></div></section><section class=\"grid\"><article class=\"card\"><div class=\"eyebrow\">Session</div><div class=\"metric\">'+esc(state.expiresAt?new Date(state.expiresAt*1000).toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'}):'\u2014')+' <small>\u8BBF\u95EE\u4EE4\u724C\u5230\u671F</small></div><p>\u9700\u8981\u65F6\u7531 CLI \u4F7F\u7528 refresh token \u81EA\u52A8\u7EED\u671F\u3002</p></article><article class=\"card\"><div class=\"eyebrow\">Commands</div><div class=\"metric\">'+state.commands.length+' <small>\u6761\u80FD\u529B\u5951\u7EA6</small></div><p>\u7F51\u9875\u6267\u884C\u5668\u53EA\u63A5\u53D7\u76EE\u5F55\u4E2D\u58F0\u660E\u7684\u547D\u4EE4\u3002</p></article><article class=\"card\"><div class=\"eyebrow\">Endpoint</div><div class=\"metric\">'+(state.config.apiBaseUrl?'READY':'SETUP')+'</div><p>'+esc(state.config.apiBaseUrl||'\u8BF7\u5728\u57FA\u7840\u914D\u7F6E\u4E2D\u586B\u5199\u5E73\u53F0 API \u5730\u5740')+'</p></article><article class=\"card wide\"><h3>\u5F53\u524D\u8EAB\u4EFD</h3><p>'+esc(u.displayName||u.username||'-')+' \u00B7 '+esc(u.email||'-')+'</p><div class=\"actions\">'+roles.slice(0,8).map((r)=>'<span class=\"tag\">'+esc(r)+'</span>').join('')+(roles.length>8?'<span class=\"tag public\">+'+(roles.length-8)+'</span>':'')+'</div></article><article class=\"card\"><h3>\u4F1A\u8BDD\u64CD\u4F5C</h3><p>\u5F3A\u5236\u5237\u65B0\u8EAB\u4EFD\u8D44\u6599\uFF0C\u6216\u6E05\u9664\u672C\u673A Keycloak \u7F13\u5B58\u3002</p><div class=\"actions\"><button class=\"button\" data-action=\"reload\">\u5237\u65B0\u72B6\u6001</button><button class=\"button danger\" data-action=\"logout\">\u9000\u51FA\u767B\u5F55</button></div></article></section></div>'}\nfunction instant(value){if(!value)return null;const number=typeof value==='number'?(value<1000000000000?value*1000:value):Date.parse(value);return Number.isFinite(number)?number:null}\nfunction timeText(value){const at=instant(value);return at?new Date(at).toLocaleString('zh-CN',{month:'2-digit',day:'2-digit',hour:'2-digit',minute:'2-digit'}):'\u2014'}\nfunction windowName(window,fallback){const minutes=window?.windowMinutes;if(!minutes)return fallback;if(minutes%1440===0)return (minutes/1440)+'d';if(minutes%60===0)return (minutes/60)+'h';return minutes+'m'}\nfunction quotaWindowHasData(window){if(!window)return false;const minutes=window.windowMinutes;const reset=window.resetAt;const hasMinutes=typeof minutes==='number'&&Number.isFinite(minutes)&&minutes>0;const hasReset=(typeof reset==='number'&&Number.isFinite(reset)&&reset>0)||(typeof reset==='string'&&Number.isFinite(Date.parse(reset)));const hasUsage=typeof window.usedPercent==='number'&&Number.isFinite(window.usedPercent)&&window.usedPercent>0;return hasMinutes||hasReset||hasUsage}\nfunction quotaLine(window,fallback){if(!quotaWindowHasData(window)||typeof window.usedPercent!=='number')return '';const remain=Math.max(0,Math.min(100,100-window.usedPercent));return '<div class=\"quota-line\" title=\"\u989D\u5EA6\u91CD\u7F6E\u65F6\u95F4 '+esc(timeText(window.resetAt))+'\"><span>'+esc(windowName(window,fallback))+'</span><progress max=\"100\" value=\"'+remain.toFixed(1)+'\"></progress><strong>'+remain.toFixed(0)+'%</strong></div>'}\nfunction quotaCell(quota){if(!quota)return '<span class=\"table-meta\">\u6682\u65E0\u989D\u5EA6\u91C7\u6837</span>';const lines=quotaLine(quota.primary,'\u4E3B\u7A97\u53E3')+quotaLine(quota.secondary,'\u6B21\u7A97\u53E3');const detail=[quota.planType,quota.model,quota.activeLimit!=null?'limit '+quota.activeLimit:null].filter(Boolean).join(' \u00B7 ');return '<div class=\"quota-stack\">'+(lines||'<span class=\"table-meta\">\u989D\u5EA6\u7A97\u53E3\u6682\u65E0\u6570\u636E</span>')+'<div class=\"table-meta\">'+esc(detail||'\u5DF2\u91C7\u6837')+'<br>\u91C7\u6837 '+esc(timeText(quota.updatedAt))+'</div></div>'}\nfunction newerQuota(localQuota,remoteQuota){if(!localQuota)return remoteQuota;if(!remoteQuota)return localQuota;return (instant(remoteQuota.updatedAt)||0)>=(instant(localQuota.updatedAt)||0)?remoteQuota:localQuota}\nfunction mergedChatgptAccounts(){const local=chatgptLocal?.accounts||[];const remote=chatgptRemote?.accounts||[];const used=new Set();const rows=local.map((item)=>{const index=remote.findIndex((candidate,i)=>!used.has(i)&&item.accountId&&candidate.accountId===item.accountId);const match=index>=0?remote[index]:null;if(index>=0)used.add(index);return {key:item.id,local:item,remote:match,label:item.label,email:item.email,accountId:item.accountId||match?.accountId,enabled:item.enabled,selected:item.selected,quota:newerQuota(item.quota,match?.quota)}});remote.forEach((item,index)=>{if(!used.has(index))rows.push({key:'remote_'+item.id,local:null,remote:item,label:item.label,email:null,accountId:item.accountId,enabled:true,selected:item.isDefault,quota:item.quota})});return rows}\nfunction syncTag(row){if(chatgptRemote?.status==='LOADING')return '<span class=\"tag waiting\">\u6B63\u5728\u540C\u6B65</span>';if(chatgptRemote?.status==='FAILED')return '<span class=\"tag failed\">\u8FDC\u7A0B\u540C\u6B65\u5931\u8D25</span>';if(chatgptRemote?.status==='NOT_CONFIGURED')return '<span class=\"tag waiting\">\u672A\u914D\u7F6E\u5E73\u53F0</span>';if(row.local&&row.remote)return '<span class=\"tag success\">\u5DF2\u540C\u6B65</span>';if(row.local)return '<span class=\"tag local\">\u4EC5\u672C\u5730</span>';return '<span class=\"tag success\">\u5E73\u53F0\u53EF\u7528</span>'}\nfunction remoteStage(){const remote=chatgptRemote;if(!remote||remote.status==='LOADING')return {tag:'<span class=\"tag waiting\"><span class=\"refresh-icon spin\" aria-hidden=\"true\"></span> \u8FDE\u63A5\u4E2D</span>',title:'\u6B63\u5728\u8FDE\u63A5\u5E73\u53F0',detail:'\u672C\u5730\u8D26\u53F7\u5DF2\u7ECF\u53EF\u89C1\uFF0C\u6B63\u5728\u8BFB\u53D6\u8FDC\u7A0B\u53EF\u7528\u8D26\u53F7\u3002'};if(remote.status==='SUCCESS')return {tag:'<span class=\"tag success\">\u540C\u6B65\u6210\u529F</span>',title:remote.accounts.length+' \u4E2A\u5E73\u53F0\u8D26\u53F7',detail:'\u5B8C\u6210\u4E8E '+timeText(remote.syncedAt)};if(remote.status==='FAILED')return {tag:'<span class=\"tag failed\">\u8FDC\u7A0B\u540C\u6B65\u5931\u8D25</span>',title:'\u4FDD\u7559\u672C\u5730\u7ED3\u679C',detail:remote.error?.message||'\u65E0\u6CD5\u8FDE\u63A5\u8FDC\u7A0B\u8D26\u53F7\u670D\u52A1'};return {tag:'<span class=\"tag waiting\">\u672A\u914D\u7F6E</span>',title:'\u672A\u914D\u7F6E\u5E73\u53F0\u5730\u5740',detail:'\u53EF\u5728\u57FA\u7840\u914D\u7F6E\u4E2D\u586B\u5199\u5E73\u53F0 API \u5730\u5740\u3002'}}\nfunction accountRows(rows){return rows.map((row)=>'<tr><td><div class=\"account-name\"><strong>'+esc(row.label)+'</strong><small>'+esc(row.email||row.accountId||row.key)+'</small></div></td><td><div class=\"status-stack\">'+(row.enabled?'<span class=\"tag success\">\u53EF\u7528</span>':'<span class=\"tag failed\">\u5DF2\u505C\u7528</span>')+(row.selected?'<span class=\"tag role\">\u5BA2\u6237\u7AEF\u5DF2\u9009</span>':'')+'</div></td><td>'+quotaCell(row.quota)+'</td><td><div class=\"table-meta\">Token '+esc(row.local?'\u672C\u5730\u53EF\u7528':'\u6309\u9700\u4ECE\u5E73\u53F0\u83B7\u53D6')+'<br>\u5230\u671F '+esc(timeText(row.local?.accessExpiresAt||row.remote?.accessExpiresAt))+'</div></td><td><div class=\"status-stack\">'+syncTag(row)+'</div></td></tr>').join('')}\nfunction chatgptPage(){const rows=mergedChatgptAccounts();const remote=remoteStage();const localReady=chatgptLocal?.status==='READY';const localCount=chatgptLocal?.available??0;const failure=chatgptRemote?.status==='FAILED'?'<div class=\"notice error\"><strong>\u8FDC\u7A0B\u540C\u6B65\u5931\u8D25\u3002</strong> '+esc(chatgptRemote.error?.message||'\u5E73\u53F0\u6682\u65F6\u4E0D\u53EF\u7528')+'\uFF1B\u672C\u5730\u8D26\u53F7\u6570\u636E\u4ECD\u53EF\u6B63\u5E38\u67E5\u770B\u3002</div>':'';return '<div class=\"content\"><section class=\"hero\"><div><div class=\"eyebrow\">Local first / Remote second</div><h2>ChatGPT \u8D26\u53F7\u8FD0\u884C\u89C6\u56FE</h2><p>\u5148\u8BFB\u53D6 codex-multi-auth \u672C\u5730\u8D26\u53F7\u4E0E\u989D\u5EA6\u7F13\u5B58\uFF0C\u518D\u8FDE\u63A5\u5E73\u53F0\u8865\u5145\u5F53\u524D\u7528\u6237\u53EF\u7528\u8D26\u53F7\u3002\u9875\u9762\u6C38\u4E0D\u63A5\u6536 access token \u6216 refresh token\u3002</p></div><div class=\"session-track\"><div class=\"track-node live\"><span>\u672C\u5730\u53EF\u7528</span><strong>'+localCount+'</strong></div><div class=\"track-node\"><span>\u6C47\u603B\u8D26\u53F7</span><strong>'+rows.length+'</strong></div><div class=\"track-node\"><span>\u8FDC\u7A0B</span><strong>'+esc(chatgptRemote?.status||'WAITING')+'</strong></div></div></section><section class=\"sync-board\"><article class=\"sync-stage\"><div class=\"eyebrow\">01 / Local pool</div><strong>'+(localReady?localCount+' \u4E2A\u672C\u5730\u53EF\u7528\u8D26\u53F7':'\u6B63\u5728\u8BFB\u53D6\u672C\u5730\u8D26\u53F7')+'</strong><p>'+(localReady?'\u8BFB\u53D6\u5B8C\u6210\u4E8E '+timeText(chatgptLocal.readAt):'\u4F18\u5148\u8BFB\u53D6 codex-multi-auth \u5B89\u5168\u6458\u8981\u3002')+'</p></article><div class=\"sync-link\" aria-label=\"\u7136\u540E\u8FDE\u63A5\u8FDC\u7A0B\"></div><article class=\"sync-stage\"><div class=\"eyebrow\">02 / Platform service</div>'+remote.tag+'<strong>'+esc(remote.title)+'</strong><p>'+esc(remote.detail)+'</p></article></section>'+failure+'<section class=\"table-card\"><header class=\"table-head\"><div><h3>\u53EF\u7528\u8D26\u53F7\u4E0E\u5269\u4F59\u989D\u5EA6</h3><p>\u989D\u5EA6\u4F18\u5148\u5C55\u793A\u672C\u5730\u6216\u670D\u52A1\u5668\u7AEF\u66F4\u65B0\u8F83\u65B0\u7684\u5B89\u5168\u5FEB\u7167\u3002</p></div><button class=\"button\" data-action=\"chatgpt-refresh\" '+(chatgptLoading?'disabled':'')+'><span class=\"refresh-icon '+(chatgptLoading?'spin':'')+'\" aria-hidden=\"true\"></span> '+(chatgptLoading?'\u540C\u6B65\u4E2D':'\u91CD\u65B0\u540C\u6B65')+'</button></header>'+(rows.length?'<div class=\"account-table-wrap\"><table class=\"account-table\"><thead><tr><th>\u8D26\u53F7</th><th>\u53EF\u7528\u72B6\u6001</th><th>\u5269\u4F59 limit</th><th>\u51ED\u636E\u65F6\u6548</th><th>\u540C\u6B65\u72B6\u6001</th></tr></thead><tbody>'+accountRows(rows)+'</tbody></table></div>':'<div class=\"empty-state'+(chatgptLoading?'':' account-request')+'\">'+(chatgptLoading?'\u6B63\u5728\u8BFB\u53D6\u672C\u5730\u8D26\u53F7\u2026':'<strong>\u9700\u8981\u7533\u8BF7 ChatGPT \u8D26\u53F7</strong><span>'+esc(noAvailableAccountGuidance)+'</span>')+'</div>')+'</section></div>'}\nfunction registryPageItems(payload){if(Array.isArray(payload))return payload.filter((item)=>item&&typeof item==='object');for(const key of ['pageItems','items','records','list','data']){const value=payload?.[key];if(Array.isArray(value))return value.filter((item)=>item&&typeof item==='object');if(value&&typeof value==='object'){const nested=registryPageItems(value);if(nested.length)return nested}}return []}\nfunction registryItemName(item,index){return String(item?.name??item?.skillName??item?.mcpName??item?.requestId??item?.eventType??item?.bindingId??((registryMode==='skill'?'skill-':'mcp-')+(index+1)))}\nfunction registryItemStatus(item){return String(item?.status??item?.releaseStatus??item?.state??item?.version??'registered')}\nfunction currentRegistryCapability(){const selected=registryNamespaces.find((namespace)=>Number(namespace.id)===Number(registryNamespaceId));return registryCapabilities?.namespaces?.find((candidate)=>candidate.namespaceKey===selected?.namespaceKey&&(!candidate.instanceCode||candidate.instanceCode===selected?.instanceCode))||null}\nfunction registryCan(action){const actions=currentRegistryCapability()?.actions||[];return actions.some((value)=>value===action||value.endsWith(':'+action)||value.endsWith('.'+action))}\nfunction registryWorkspaceTabs(){const tabs=[['catalog','\u76EE\u5F55'],['approvals','\u53D1\u5E03\u6536\u4EF6\u7BB1'],['instances','\u5B9E\u4F8B / \u51ED\u636E'],['namespace','Namespace / Profile'],['router','Router'],['audit','\u6743\u9650 / \u5BA1\u8BA1']];return '<div class=\"registry-workspaces\" role=\"tablist\" aria-label=\"AI Registry \u5DE5\u4F5C\u533A\">'+tabs.map(([id,label])=>'<button role=\"tab\" aria-selected=\"'+(registryWorkspace===id)+'\" data-registry-workspace=\"'+id+'\" class=\"'+(registryWorkspace===id?'active':'')+'\">'+label+'</button>').join('')+'</div>'}\nfunction registryNamespaceOptions(){return registryNamespaces.map((namespace)=>'<option value=\"'+namespace.id+'\" '+(Number(namespace.id)===Number(registryNamespaceId)?'selected':'')+'>'+esc(namespace.displayName)+' \u00B7 '+esc(namespace.namespaceKey)+' \u00B7 '+esc(namespace.instanceCode)+(namespace.isDefault?' \u00B7 default':'')+'</option>').join('')}\nfunction registryItemButtons(){return registryItems.map((item,index)=>{const name=registryItemName(item,index);const status=registryItemStatus(item);const online=/online|published|release/i.test(status);return '<button class=\"registry-item '+(name===registryName?'active':'')+'\" data-registry-name=\"'+esc(name)+'\"><span class=\"registry-dot '+(online?'online':'')+'\"></span><span><strong>'+esc(name)+'</strong><small>'+esc(status)+(item.scope?' \u00B7 '+esc(item.scope):'')+'</small></span></button>'}).join('')||'<div class=\"empty-state\">\u6CA1\u6709\u5339\u914D\u7684 '+(registryMode==='skill'?'Skill':'MCP Server')+'</div>'}\nfunction registryTargets(){const targets=registryMode==='skill'?['chatgpt','codex','claude','cursor','workbuddy','openclaw','agents']:['chatgpt','codex','claude','cursor','workbuddy','openclaw'];return targets.map((target)=>'<option value=\"'+target+'\">'+target+'</option>').join('')}\nfunction compactValue(value){if(value==null||value==='')return '\u2014';if(Array.isArray(value))return value.length?value.map((item)=>typeof item==='object'?(item.name??item.id??'record'):item).join(', '):'\u2014';if(typeof value==='object')return value.displayName??value.name??value.status??Object.keys(value).length+' fields';return String(value)}\nfunction summaryCells(entries){return '<div class=\"summary-grid\">'+entries.map(([label,value])=>'<div class=\"summary-cell\"><span>'+esc(label)+'</span><strong>'+esc(compactValue(value))+'</strong></div>').join('')+'</div>'}\nfunction rawDisclosure(value,label='\u67E5\u770B\u539F\u59CB\u54CD\u5E94'){return '<details class=\"raw-disclosure\"><summary>'+esc(label)+'</summary><pre class=\"output wrap\">'+esc(JSON.stringify(value??{},null,2))+'</pre></details>'}\nfunction registryDetailSummary(detail){const tags=detail?.tags??detail?.labels;const owner=detail?.ownerTeamCode??detail?.ownerTeam??detail?.teamCode;const entries=registryMode==='skill'?[['\u7CBE\u786E\u7248\u672C',detail?.version??detail?.latestVersion],['\u6CBB\u7406\u72B6\u6001',detail?.status??detail?.state],['\u53EF\u89C1\u6027',detail?.visibility??detail?.scope],['\u8D23\u4EFB\u56E2\u961F',owner],['\u6807\u7B7E',tags],['\u626B\u63CF',detail?.scanStatus??detail?.pipelineStatus]]:[['\u7CBE\u786E\u7248\u672C',detail?.version??detail?.latestVersion],['\u6CBB\u7406\u72B6\u6001',detail?.status??detail?.state],['\u534F\u8BAE',detail?.protocol??detail?.transport],['\u8D23\u4EFB\u56E2\u961F',owner],['\u5DE5\u5177\u6570\u91CF',Array.isArray(detail?.tools)?detail.tools.length:detail?.toolCount],['Endpoint \u5065\u5EB7',detail?.health??detail?.endpointStatus]];return summaryCells(entries)+rawDisclosure(detail)}\nfunction registryDetailPanel(){if(registryLoading)return '<div class=\"empty-state\" role=\"status\"><span class=\"refresh-icon spin\" aria-hidden=\"true\"></span> \u6B63\u5728\u8BFB\u53D6\u79C1\u6709 Registry\u2026</div>';if(!registryName)return '<div class=\"empty-state\">\u4ECE\u5217\u8868\u9009\u62E9\u4E00\u9879\u67E5\u770B\u7248\u672C\u3001\u6807\u7B7E\u548C\u6CBB\u7406\u72B6\u6001\u3002</div>';const canSubmit=registryCan('submit');const mutating='<button class=\"button\" data-registry-action=\"submit\" '+(canSubmit?'':'disabled')+'>\u63D0\u4EA4\u5BA1\u6838</button>';return '<div class=\"registry-detail-head\"><div><h3>'+esc(registryName)+'</h3><span class=\"tag '+(canSubmit?'role':'public')+'\">'+(canSubmit?'\u53EF\u63D0\u4EA4\u8349\u7A3F':'\u53EA\u8BFB')+'</span></div><button class=\"button\" data-action=\"registry-refresh\"><span class=\"refresh-icon\" aria-hidden=\"true\"></span> \u5237\u65B0\u8BE6\u60C5</button></div>'+registryDetailSummary(registryDetail)+'<div class=\"registry-actions\"><div class=\"install-row\"><label class=\"field\"><span>\u5B89\u88C5\u76EE\u6807</span><select id=\"registry-target\">'+registryTargets()+'</select></label><label class=\"field\"><span>\u5B89\u88C5\u8303\u56F4</span><select id=\"registry-scope\"><option value=\"project\">\u5F53\u524D\u9879\u76EE</option><option value=\"user\">\u5F53\u524D\u7528\u6237</option></select></label><button class=\"button primary\" data-registry-action=\"install\" '+(registryCan('install')||registryCan('use')?'':'disabled')+'>\u5B89\u88C5\u5E76\u9501\u5B9A</button></div><div class=\"actions\">'+mutating+'</div><small class=\"table-meta\">\u76EE\u5F55\u53EA\u5141\u8BB8\u5B89\u88C5\u4E0E\u63D0\u4EA4 release request\u3002\u6279\u51C6\u548C\u53D1\u5E03\u53EA\u5728\u53D1\u5E03\u6536\u4EF6\u7BB1\u51FA\u73B0\uFF0C\u6700\u7EC8\u6388\u6743\u548C\u4E24\u4EBA\u5236\u6821\u9A8C\u7531\u5E73\u53F0\u6267\u884C\u3002</small><div id=\"registry-notice\" aria-live=\"polite\">'+registryNotice+'</div></div>'}\nfunction instanceCards(){if(!registryItems.length)return '<div class=\"empty-state\">\u6CA1\u6709\u53EF\u89C1\u7684 Registry \u5B9E\u4F8B\u3002</div>';return '<div class=\"record-grid\">'+registryItems.map((item)=>{const credentials=item.credentials||{};return '<article class=\"record-card\"><div class=\"registry-detail-head\"><h4>'+esc(item.displayName||item.code||'\u5B9E\u4F8B')+'</h4><span class=\"tag '+(item.status==='ACTIVE'?'success':'waiting')+'\">'+esc(item.status||'UNKNOWN')+'</span></div><dl><dt>\u5B9E\u4F8B\u4EE3\u7801</dt><dd>'+esc(item.code||'\u2014')+'</dd><dt>\u8BA4\u8BC1\u65B9\u5F0F</dt><dd>'+esc(item.authenticationType||'\u2014')+'</dd><dt>READER</dt><dd>'+esc(credentials.readerConfigured??item.credentialConfigured?'\u5DF2\u9A8C\u8BC1':'\u672A\u5C31\u7EEA')+'</dd><dt>MAINTAINER</dt><dd>'+esc(credentials.maintainerConfigured??item.credentialConfigured?'\u5DF2\u9A8C\u8BC1':'\u672A\u5C31\u7EEA')+'</dd><dt>LEGACY_BOTH</dt><dd>'+esc(credentials.legacyBothConfigured?'\u8FC1\u79FB\u4E2D':'\u672A\u542F\u7528')+'</dd><dt>\u4E50\u89C2\u9501\u7248\u672C</dt><dd>'+esc(item.version??'\u2014')+'</dd></dl></article>'}).join('')+'</div>'}\nfunction registrySimplePanel(title,description){\nif(registryLoading)return '<section class=\"registry-simple\"><div class=\"empty-state\" role=\"status\">\u6B63\u5728\u8BFB\u53D6 '+esc(title)+'\u2026</div></section>';\nif(registryError)return '<section class=\"registry-simple\"><div class=\"notice error\" role=\"alert\"><strong>'+esc(title)+'\u52A0\u8F7D\u5931\u8D25\u3002</strong> '+esc(registryError)+' <button class=\"button\" data-action=\"registry-retry\">\u91CD\u8BD5</button></div></section>';\nif(registryWorkspace==='instances')return '<section class=\"registry-simple\"><h3>'+esc(title)+'</h3><p>'+esc(description)+'</p>'+instanceCards()+'<small class=\"table-meta\">\u6D4F\u89C8\u5668\u53EA\u63A5\u6536\u201C\u662F\u5426\u5DF2\u914D\u7F6E/\u9A8C\u8BC1\u201D\u7684\u5E03\u5C14\u72B6\u6001\uFF1BNacos \u5730\u5740\u4E0E credential \u6C38\u4E0D\u8FDB\u5165 capability\u3002</small></section>';\nif(registryWorkspace==='namespace'){\nconst cap=currentRegistryCapability()||{};const selected=registryNamespaces.find((item)=>Number(item.id)===Number(registryNamespaceId));\nreturn '<section class=\"registry-simple\"><h3>'+esc(title)+'</h3><p>'+esc(description)+'</p><dl class=\"registry-facts\"><div><dt>\u73AF\u5883</dt><dd>'+esc(cap.environment||selected?.environment||'\u672A\u58F0\u660E')+'</dd></div><div><dt>\u8BBF\u95EE\u7B56\u7565</dt><dd>'+esc(selected?.accessPolicy||'\u7531 capability \u51B3\u5B9A')+'</dd></div><div><dt>\u8D23\u4EFB\u56E2\u961F</dt><dd>'+esc(selected?.ownerTeamCode||'\u5171\u4EAB\u9ED8\u8BA4 namespace')+'</dd></div><div><dt>\u5F53\u524D\u7528\u6237\u9ED8\u8BA4\u503C</dt><dd>'+esc(state.config.aiRegistryDefaultNamespaceKey||'\u672A\u8BBE\u7F6E')+'</dd></div><div><dt>Profile \u9ED8\u8BA4\u503C</dt><dd>'+esc(state.config.aiRegistryDefaultNamespaceKey?'\u88AB\u7528\u6237\u504F\u597D\u8986\u76D6':'\u89E3\u6790\u65F6\u7531 profile \u63D0\u4F9B')+'</dd></div><div><dt>Namespace \u72B6\u6001</dt><dd>'+esc(registryAux?.status||selected?.status||'UNKNOWN')+'</dd></div></dl><form id=\"registry-default-form\" class=\"form-grid\"><label class=\"field\"><span>\u5C06\u6388\u6743 namespace \u8BBE\u4E3A\u7528\u6237\u9ED8\u8BA4\u503C</span><select name=\"namespaceKey\">'+registryNamespaces.map((item)=>'<option value=\"'+esc(item.namespaceKey)+'\" '+(item.namespaceKey===state.config.aiRegistryDefaultNamespaceKey?'selected':'')+'>'+esc(item.displayName)+' \u00B7 '+esc(item.namespaceKey)+'</option>').join('')+'</select></label><div class=\"actions\"><button class=\"button primary\" type=\"submit\">\u4FDD\u5B58\u9ED8\u8BA4\u503C</button><button class=\"button\" type=\"button\" data-registry-action=\"namespace-check\">\u91CD\u65B0\u68C0\u67E5</button></div></form><small class=\"table-meta\">\u89E3\u6790\u987A\u5E8F\u4FDD\u6301\u4E3A\u547D\u4EE4\u53C2\u6570 \u2192 \u9879\u76EE manifest \u2192 \u7528\u6237\u504F\u597D \u2192 profile \u9ED8\u8BA4\u503C\uFF1B\u65E0\u6548\u9ED8\u8BA4\u503C\u4F1A\u660E\u786E\u5931\u8D25\u3002</small><div id=\"registry-notice\" aria-live=\"polite\">'+registryNotice+'</div></section>';\n}\nif(registryWorkspace==='router'){\nconst router=registryDetail||currentRegistryCapability()?.router||{};const canConnect=registryCan('router.connect')||registryCan('connect');\nreturn '<section class=\"registry-simple\"><div class=\"registry-detail-head\"><div><h3>'+esc(title)+'</h3><span class=\"tag '+(router.status==='READY'?'success':'waiting')+'\">'+esc(router.status||'UNAVAILABLE')+'</span></div><button class=\"button\" data-action=\"registry-refresh\"><span class=\"refresh-icon\" aria-hidden=\"true\"></span> \u5237\u65B0\u5065\u5EB7</button></div><p>'+esc(description)+'</p>'+summaryCells([['\u7ED1\u5B9A',router.bindingId],['\u534F\u8BAE',router.protocol],['\u7B56\u7565 revision',router.policyRevision],['\u5065\u5EB7',registryAux?.status??router.health],['Endpoint',router.endpoint],['OAuth resource',router.oauthResource]])+rawDisclosure({router:router,health:registryAux})+'<div class=\"actions\"><button class=\"button\" data-load=\"'+esc(JSON.stringify(['registry','router','connect']))+'\" '+(canConnect?'':'disabled')+'>\u8FDE\u63A5\u9002\u914D\u5668</button></div></section>';\n}\nif(registryWorkspace==='audit'){const cap=currentRegistryCapability()||{};const detail=registryDetail?'<div class=\"registry-detail-head\"><h3>'+esc(registryName)+'</h3><button class=\"button\" data-action=\"registry-refresh\"><span class=\"refresh-icon\" aria-hidden=\"true\"></span> \u5237\u65B0</button></div>'+summaryCells([['\u4E8B\u4EF6',registryDetail.eventType??registryDetail.action],['Request ID',registryDetail.requestId],['\u64CD\u4F5C\u8005',registryDetail.actor??registryDetail.subject],['\u7ED3\u679C',registryDetail.result??registryDetail.status],['\u53D1\u751F\u65F6\u95F4',registryDetail.createdAt??registryDetail.occurredAt],['\u7B56\u7565 revision',registryDetail.policyRevision]])+rawDisclosure(registryDetail):'<div class=\"empty-state\">\u9009\u62E9\u5BA1\u8BA1\u4E8B\u4EF6\u67E5\u770B\u5173\u8054 requestId \u4E0E\u7ED3\u679C\u3002</div>';return '<section class=\"registry-simple\"><h3>'+esc(title)+'</h3><p>'+esc(description)+'</p><div class=\"permission-grid\">'+(cap.actions||[]).map((action)=>'<span class=\"tag role\">'+esc(action)+'</span>').join('')+(!(cap.actions||[]).length?'<span class=\"tag public\">\u53EA\u8BFB</span>':'')+'</div>'+summaryCells([['Policy revision',registryCapabilities?.policyRevision],['\u73AF\u5883',cap.environment],['Router',cap.router?.status],['\u53EF\u7528\u52A8\u4F5C',(cap.actions||[]).length]])+'<section class=\"registry-board\"><aside class=\"registry-list\"><div class=\"registry-list-head\"><strong>\u8FFD\u52A0\u5F0F\u5BA1\u8BA1</strong><span class=\"tag public\">'+registryItems.length+'</span></div><div class=\"registry-items\">'+registryItemButtons()+'</div></aside><article class=\"registry-detail\">'+detail+'</article></section></section>'}\nconst requestState=String(registryDetail?.state??registryDetail?.status??'').toUpperCase();const canReview=requestState==='SUBMITTED'&®istryCan('review');const canPublish=requestState==='APPROVED'&®istryCan('publish');const approvalActions=registryWorkspace==='approvals'&®istryDetail?'<div class=\"registry-actions\"><div class=\"actions\"><button class=\"button\" data-registry-action=\"approval-approve\" '+(canReview?'':'disabled')+'>\u6279\u51C6</button><button class=\"button danger\" data-registry-action=\"approval-reject\" '+(canReview?'':'disabled')+'>\u62D2\u7EDD</button><button class=\"button primary\" data-registry-action=\"approval-publish\" '+(canPublish?'':'disabled')+'>\u53D1\u5E03\u5DF2\u6279\u51C6\u7533\u8BF7</button></div><small class=\"table-meta\">\u63D0\u4EA4\u4EBA\u4E0D\u80FD\u5BA1\u6838\u6216\u53D1\u5E03\u81EA\u5DF1\u7684\u7533\u8BF7\uFF1B\u72B6\u6001\u548C capability \u5FC5\u987B\u540C\u65F6\u5141\u8BB8\uFF0C\u670D\u52A1\u7AEF\u4F1A\u518D\u6B21\u6821\u9A8C\u3002</small><div id=\"registry-notice\" aria-live=\"polite\">'+registryNotice+'</div></div>':'';\nconst detail=registryDetail?'<div class=\"registry-detail-head\"><h3>'+esc(registryName)+'</h3><button class=\"button\" data-action=\"registry-refresh\"><span class=\"refresh-icon\" aria-hidden=\"true\"></span> \u5237\u65B0</button></div>'+summaryCells([['\u8D44\u6E90\u7C7B\u578B',registryDetail.resourceType],['\u8D44\u6E90',registryDetail.resourceName??registryDetail.name],['\u7CBE\u786E\u7248\u672C',registryDetail.resourceVersion],['\u72B6\u6001',registryDetail.state??registryDetail.status],['\u63D0\u4EA4\u4EBA',registryDetail.submitter??registryDetail.createdBy],['\u4E50\u89C2\u9501\u7248\u672C',registryDetail.version]])+rawDisclosure(registryDetail)+approvalActions:'<div class=\"empty-state\">\u9009\u62E9 release request \u67E5\u770B\u72B6\u6001\u548C\u53EF\u6267\u884C\u64CD\u4F5C\u3002</div>';\nreturn '<section class=\"registry-board\"><aside class=\"registry-list\"><div class=\"registry-list-head\"><strong>'+esc(title)+'</strong><span class=\"tag public\">'+registryItems.length+'</span></div><div class=\"registry-items\">'+registryItemButtons()+'</div></aside><article class=\"registry-detail\">'+detail+'</article></section>';\n}\nfunction registryContent(){if(registryWorkspace==='catalog')return '<section class=\"registry-board\"><aside class=\"registry-list\"><div class=\"registry-list-head\"><strong>'+(registryMode==='skill'?'Skills':'MCP Servers')+'</strong><span class=\"tag public\">'+registryItems.length+'</span></div><div class=\"registry-items\">'+registryItemButtons()+'</div></aside><article class=\"registry-detail\">'+registryDetailPanel()+'</article></section>';const labels={approvals:['\u53D1\u5E03\u6536\u4EF6\u7BB1','\u5BA1\u6838\u8005\u4E0E\u53D1\u5E03\u8005\u5728\u8FD9\u91CC\u5904\u7406\u4E24\u4EBA\u5236 release request\u3002'],instances:['\u5B9E\u4F8B\u4E0E\u53CC\u51ED\u636E','\u5E73\u53F0\u53EA\u663E\u793A\u51ED\u636E\u662F\u5426\u5C31\u7EEA\uFF0C\u4E0D\u628A secret \u8FD4\u56DE\u6D4F\u89C8\u5668\u3002'],namespace:['Namespace \u4E0E Profile \u9ED8\u8BA4\u503C','\u5F53\u524D\u73AF\u5883\u3001\u6388\u6743\u52A8\u4F5C\u548C namespace \u89E3\u6790\u6765\u6E90\u4FDD\u6301\u53EF\u89C1\u3002'],router:['\u4F01\u4E1A Router','\u53EA\u6709 READY \u7684 Streamable HTTP Endpoint \u624D\u4F1A\u8FDB\u5165 capability\u3002'],audit:['\u6743\u9650\u4E0E\u8FFD\u52A0\u5F0F\u5BA1\u8BA1','\u6309 requestId \u8FFD\u8E2A\u62D2\u7EDD\u3001\u5BA1\u6279\u3001\u53D1\u5E03\u548C\u5BF9\u8D26\u4E8B\u4EF6\u3002']};return registrySimplePanel(...labels[registryWorkspace])}\nfunction registryPage(){const selected=registryNamespaces.find((namespace)=>Number(namespace.id)===Number(registryNamespaceId));const cap=currentRegistryCapability();const error=registryError&®istryWorkspace==='catalog'?'<div class=\"notice error registry-error\" role=\"alert\"><strong>\u76EE\u5F55\u52A0\u8F7D\u5931\u8D25\u3002</strong> '+esc(registryError)+' <button class=\"button\" data-action=\"registry-retry\">\u91CD\u8BD5</button></div>':'';return '<div class=\"content\"><section class=\"hero registry-hero\"><div><h2>\u56E2\u961F\u80FD\u529B\u7684\u53D1\u5E03\u4E0E\u8FD0\u884C\u8FB9\u754C</h2><p>\u76EE\u5F55\u3001\u5BA1\u6279\u548C Router \u5171\u4EAB\u4E00\u4E2A namespace \u9009\u62E9\uFF1BNuma \u53EA\u63A5\u6536 capability \u548C\u6CBB\u7406\u5143\u6570\u636E\uFF0C\u4E0D\u63A5\u89E6 Nacos \u51ED\u636E\u3002</p></div><div><small class=\"table-meta\">\u751F\u547D\u5468\u671F\u5951\u7EA6 \u00B7 rejected / failed / offline \u4E3A\u5206\u652F\u72B6\u6001</small><div class=\"lifecycle\" aria-label=\"\u751F\u547D\u5468\u671F\u56FE\u4F8B\uFF0C\u4E0D\u8868\u793A\u5F53\u524D\u72B6\u6001\"><div class=\"life-node\">draft</div><div class=\"life-node\">submitted</div><div class=\"life-node\">approved</div><div class=\"life-node\">publishing</div><div class=\"life-node\">published</div></div></div></section>'+registryWorkspaceTabs()+'<section class=\"registry-toolbar\"><label class=\"field\"><span>Namespace</span><select id=\"registry-namespace\">'+registryNamespaceOptions()+'</select></label>'+(registryWorkspace==='catalog'?'<div class=\"segment\" role=\"group\" aria-label=\"\u8D44\u6E90\u7C7B\u578B\"><button data-registry-mode=\"skill\" class=\"'+(registryMode==='skill'?'active':'')+'\">Skills</button><button data-registry-mode=\"mcp\" class=\"'+(registryMode==='mcp'?'active':'')+'\">MCP</button></div><label class=\"field\"><span>\u8FC7\u6EE4</span><input id=\"registry-search\" maxlength=\"80\" value=\"'+esc(registrySearch)+'\" placeholder=\"\u540D\u79F0\u6216\u63CF\u8FF0\"></label>':'<div class=\"registry-context\"><strong>'+esc(selected?.displayName||'\u672A\u9009\u62E9')+'</strong><span>'+esc(cap?.environment||'unknown')+' \u00B7 '+esc(cap?.router?.status||'NO ROUTER')+'</span></div>')+'<button class=\"button\" data-action=\"registry-refresh\" '+(registryLoading?'disabled':'')+'><span class=\"refresh-icon '+(registryLoading?'spin':'')+'\" aria-hidden=\"true\"></span> '+(registryLoading?'\u8BFB\u53D6\u4E2D\u2026':'\u5237\u65B0')+'</button></section>'+error+registryContent()+'<div class=\"sr-only\" aria-live=\"polite\">'+esc(registryLoading?'\u6B63\u5728\u52A0\u8F7D':registryError||registryNotice||'\u52A0\u8F7D\u5B8C\u6210')+'</div></div>'}\nasync function loadRegistry(resetNamespaces=false){if(registryLoading)return;registryLoading=true;registryError='';render();try{if(resetNamespaces||!registryNamespaces.length||!registryCapabilities){[registryCapabilities,registryNamespaces]=await Promise.all([api('/api/registry/capabilities'),api('/api/registry/namespaces')]);if(!Array.isArray(registryNamespaces)||!Array.isArray(registryCapabilities?.namespaces))throw new Error('capability \u6216 namespace \u54CD\u5E94\u683C\u5F0F\u65E0\u6548');const visible=registryNamespaces.filter((namespace)=>registryCapabilities.namespaces.some((candidate)=>candidate.namespaceKey===namespace.namespaceKey&&(!candidate.instanceCode||candidate.instanceCode===namespace.instanceCode)));registryNamespaces=visible;if(!registryNamespaceId||!registryNamespaces.some((namespace)=>Number(namespace.id)===Number(registryNamespaceId))){const preferred=state.config.aiRegistryDefaultNamespaceKey;const preferredNamespace=preferred?registryNamespaces.find((namespace)=>namespace.namespaceKey===preferred):null;if(preferred&&!preferredNamespace)throw new Error('\u7528\u6237\u9ED8\u8BA4 namespace '+preferred+' \u4E0D\u5728 capability \u6388\u6743\u5217\u8868\u4E2D\uFF1B\u8BF7\u663E\u5F0F\u4FEE\u6539\u9ED8\u8BA4\u503C\u3002');registryNamespaceId=preferredNamespace?.id??registryNamespaces[0]?.id??null}}if(!registryNamespaceId){registryItems=[];registryDetail=null;throw new Error('\u5F53\u524D\u7528\u6237\u6CA1\u6709\u53EF\u89C1\u7684 Registry namespace\u3002\u8BF7\u8054\u7CFB\u8D23\u4EFB\u56E2\u961F\u6216\u7BA1\u7406\u5458\u6388\u6743\u3002')}registryAux=null;if(registryWorkspace==='catalog'){const endpoint=registryMode==='skill'?'/api/registry/skills':'/api/registry/mcp';const payload=await api(endpoint+'?namespaceId='+encodeURIComponent(registryNamespaceId)+(registrySearch?'&search='+encodeURIComponent(registrySearch):''));registryItems=registryPageItems(payload);if(registryName&&!registryItems.some((item,index)=>registryItemName(item,index)===registryName)){registryName='';registryDetail=null}}else if(registryWorkspace==='approvals'||registryWorkspace==='audit'){const endpoint=registryWorkspace==='approvals'?'/api/registry/approvals':'/api/registry/audit';const payload=await api(endpoint+'?namespaceId='+encodeURIComponent(registryNamespaceId));registryItems=registryPageItems(payload);registryDetail=null;registryName=''}else if(registryWorkspace==='instances'){registryItems=registryPageItems(await api('/api/registry/instances'));registryDetail=null;registryName=''}else if(registryWorkspace==='namespace'){registryAux=await api('/api/registry/namespace-health?namespaceId='+encodeURIComponent(registryNamespaceId));registryItems=[];registryDetail=null;registryName=''}else if(registryWorkspace==='router'){[registryDetail,registryAux]=await Promise.all([api('/api/registry/router?namespaceId='+encodeURIComponent(registryNamespaceId)),api('/api/registry/router-health?namespaceId='+encodeURIComponent(registryNamespaceId))]);registryItems=[];registryName=''}else{registryItems=[];registryDetail=null;registryName=''}}catch(error){registryError=error.message;registryItems=[];registryDetail=null;registryAux=null}finally{registryLoading=false;render()}}\nasync function selectRegistryItem(name){registryName=name;if(registryWorkspace!=='catalog'){registryDetail=registryItems.find((item,index)=>registryItemName(item,index)===name)||null;render();return}registryLoading=true;registryError='';render();try{const endpoint=registryMode==='skill'?'/api/registry/skill':'/api/registry/mcp-detail';registryDetail=await api(endpoint+'?namespaceId='+encodeURIComponent(registryNamespaceId)+'&name='+encodeURIComponent(name))}catch(error){registryError=error.message;registryDetail=null}finally{registryLoading=false;render()}}\nasync function runRegistryCommand(argv,successMessage){const selectedName=registryName;registryNotice='<div class=\"notice success\">\u6B63\u5728\u6267\u884C\u2026</div>';render();try{const result=await api('/api/commands/run',{method:'POST',body:JSON.stringify({argv,confirm:false})});if(result.exitCode!==0)throw new Error(result.stderr||result.stdout||'\u547D\u4EE4\u6267\u884C\u5931\u8D25');await loadRegistry();if(selectedName&®istryItems.some((item,index)=>registryItemName(item,index)===selectedName))await selectRegistryItem(selectedName);registryNotice='<div class=\"notice success\">'+esc(successMessage)+'</div>';render()}catch(error){registryNotice='<div class=\"notice error\">'+esc(error.message)+'</div>';render()}}\nasync function registryAction(action){if(!registryNamespaceId)return;const selected=registryNamespaces.find((namespace)=>Number(namespace.id)===Number(registryNamespaceId));if(!selected)throw new Error('\u672A\u9009\u62E9 namespace');if(action==='namespace-check'){registryNotice='<div class=\"notice success\">\u6B63\u5728\u68C0\u67E5 namespace\u2026</div>';render();try{registryAux=await api('/api/registry/namespace-health?namespaceId='+encodeURIComponent(registryNamespaceId));registryNotice='<div class=\"notice success\">\u68C0\u67E5\u5B8C\u6210\uFF1A'+esc(registryAux?.status||'\u5DF2\u54CD\u5E94')+'</div>'}catch(error){registryNotice='<div class=\"notice error\">'+esc(error.message)+'</div>'}render();return}if(!registryName)return;const targetArgs=['--namespace',String(selected.namespaceKey),'--instance',String(selected.instanceCode)];if(action==='install'){const agent=document.getElementById('registry-target').value;let scope=document.getElementById('registry-scope').value;if(registryMode==='mcp'&&(agent==='codex'||agent==='openclaw'))scope='user';const argv=['registry',registryMode,'install',registryName,...targetArgs,'--agent',agent,'--scope',scope];if(registryMode==='skill')argv.push('--label','latest');await runRegistryCommand(argv,'\u5DF2\u5B8C\u6210\u672C\u673A\u5B89\u88C5');return}if(action==='submit'){const version=prompt('\u8F93\u5165\u8981\u63D0\u4EA4\u5BA1\u6838\u7684\u7CBE\u786E\u7248\u672C');if(!version)return;const reason=prompt('\u8F93\u5165\u53D1\u5E03\u8BF4\u660E');if(!reason)return;await runRegistryCommand(['registry','approvals','submit',registryMode,registryName,...targetArgs,'--resource-version',version,'--reason',reason],'\u5DF2\u63D0\u4EA4\u53D1\u5E03\u7533\u8BF7');return}if(action.startsWith('approval-')){const operation=action.slice('approval-'.length);if(!confirm('\u786E\u8BA4\u5BF9\u7533\u8BF7 '+registryName+' \u6267\u884C '+operation+'\uFF1F'))return;const optimisticVersion=registryDetail?.version;const versionArgs=Number.isInteger(optimisticVersion)?['--version',String(optimisticVersion)]:[];if(operation==='publish'){await runRegistryCommand(['registry','approvals','publish',registryName,...versionArgs],'\u53D1\u5E03\u5DF2\u5F00\u59CB');return}const reason=prompt(operation==='approve'?'\u8F93\u5165\u6279\u51C6\u539F\u56E0':'\u8F93\u5165\u62D2\u7EDD\u539F\u56E0');if(!reason)return;await runRegistryCommand(['registry','approvals','review',registryName,'--decision',operation==='approve'?'APPROVED':'REJECTED','--reason',reason,...versionArgs],operation==='approve'?'\u5DF2\u6279\u51C6':'\u5DF2\u62D2\u7EDD');return}}\nfunction configPage(){const c=state.config;return '<div class=\"content\"><section class=\"grid\"><article class=\"card full\"><h3>\u57FA\u7840\u914D\u7F6E</h3><p>\u4E0E <code>numa config --set</code> \u4F7F\u7528\u540C\u4E00\u4EFD\u914D\u7F6E\u548C\u6821\u9A8C\u903B\u8F91\u3002</p><form id=\"config-form\" class=\"form-grid\"><div class=\"field\"><label>\u754C\u9762\u8BED\u8A00</label><select name=\"locale\"><option '+(c.locale==='zh-CN'?'selected':'')+'>zh-CN</option><option '+(c.locale==='en-US'?'selected':'')+'>en-US</option></select></div><div class=\"field\"><label>\u9ED8\u8BA4\u8F93\u51FA</label><select name=\"output\"><option '+(c.output==='text'?'selected':'')+'>text</option><option '+(c.output==='json'?'selected':'')+'>json</option></select></div><div class=\"field span-2\"><label>\u5E73\u53F0 API \u5730\u5740</label><input name=\"apiBaseUrl\" value=\"'+esc(c.apiBaseUrl)+'\" placeholder=\"https://platform.example/api\"></div><div class=\"field\"><label>AI Registry \u7528\u6237\u9ED8\u8BA4 namespace</label><input name=\"aiRegistryDefaultNamespaceKey\" maxlength=\"160\" value=\"'+esc(c.aiRegistryDefaultNamespaceKey||'')+'\" placeholder=\"\u7531\u9879\u76EE\u6216 profile \u63D0\u4F9B\u65F6\u53EF\u7559\u7A7A\"></div><div class=\"field\"><label>npm registry</label><input name=\"registryUrl\" value=\"'+esc(c.registryUrl)+'\"></div><label class=\"field span-2\"><span>\u66F4\u65B0\u68C0\u67E5</span><select name=\"checkUpdates\"><option value=\"true\" '+(c.checkUpdates?'selected':'')+'>\u542F\u7528</option><option value=\"false\" '+(!c.checkUpdates?'selected':'')+'>\u5173\u95ED</option></select></label><div class=\"actions span-2\"><button class=\"button primary\" type=\"submit\">\u4FDD\u5B58\u914D\u7F6E</button></div></form><div id=\"notice\" aria-live=\"polite\"></div></article></section></div>'}\nfunction commandsPage(){return '<div class=\"content\"><section class=\"card full\"><div class=\"command-toolbar\"><div class=\"field grow\"><label>\u8FC7\u6EE4\u547D\u4EE4</label><input id=\"command-search\" placeholder=\"\u4F8B\u5982 codex\u3001media\u3001auth\"></div></div><div id=\"command-list\" class=\"command-list\">'+commandCards('')+'</div></section></div>'}\nfunction commandCards(query){const q=query.toLowerCase();return state.commands.filter((c)=>(c.command+' '+c.summary).toLowerCase().includes(q)).map((c)=>'<article class=\"command\"><div class=\"command-head\"><code>'+esc(c.command)+'</code><span class=\"tag '+esc(c.access)+'\">'+esc(c.access)+'</span></div><p>'+esc(c.summary)+'</p><small>'+esc(c.examples[0]||'')+'</small><div class=\"actions mt-10\"><button class=\"button\" data-load=\"'+esc(JSON.stringify(commandPrefix(c.command)))+'\">\u8F7D\u5165\u6267\u884C\u5668</button></div></article>').join('')||'<p>\u6CA1\u6709\u5339\u914D\u547D\u4EE4\u3002</p>'}\nfunction commandPrefix(command){return command.split(/\\s+/).filter((part)=>!part.startsWith('[')&&!part.startsWith('<')&&!part.startsWith('--'))}\nfunction runnerPage(){return '<div class=\"content\"><section class=\"grid\"><article class=\"card\"><div class=\"eyebrow\">Structured argv</div><h3>\u5B89\u5168\u6267\u884C\u5668</h3><p>\u4F7F\u7528 JSON \u6570\u7EC4\u4F20\u5165\u53C2\u6570\uFF0C\u4E0D\u7ECF\u8FC7 shell\u3002\u957F\u9A7B\u6216\u4EA4\u4E92\u547D\u4EE4\u9700\u8981\u5728\u7EC8\u7AEF\u8FD0\u884C\u3002</p><form id=\"runner-form\"><div class=\"field\"><label>\u547D\u4EE4\u53C2\u6570</label><textarea id=\"argv\" class=\"mono\">[\"doctor\"]</textarea></div><label class=\"field mt-12\"><span>\u5371\u9669\u64CD\u4F5C\u786E\u8BA4</span><select id=\"confirm\"><option value=\"false\">\u672A\u786E\u8BA4</option><option value=\"true\">\u786E\u8BA4\u6267\u884C\u5220\u9664/\u91CD\u7F6E</option></select></label><div class=\"actions mt-14\"><button class=\"button primary\" type=\"submit\">\u8FD0\u884C\u547D\u4EE4</button></div></form></article><article class=\"card wide\"><div class=\"eyebrow\">Result stream</div><h3>\u7ED3\u6784\u5316\u8F93\u51FA</h3><pre id=\"output\" class=\"output\">'+esc(output)+'</pre></article></section></div>'}\nasync function loadChatgpt(){if(chatgptLoading)return;chatgptLoading=true;chatgptLocal=null;chatgptRemote={status:'LOADING',accounts:[]};render();try{chatgptLocal=await api('/api/chatgpt/local')}catch(error){chatgptLocal={status:'FAILED',accounts:[],available:0,total:0,error:{message:error.message}}}render();try{chatgptRemote=await api('/api/chatgpt/remote')}catch(error){chatgptRemote={status:'FAILED',accounts:[],syncedAt:Date.now(),error:{message:error.message}}}finally{chatgptLoading=false;render()}}\nfunction render(){if(!state.loggedIn){app.innerHTML=loginGate();bind();return}const page=active==='overview'?overview():active==='registry'?registryPage():active==='chatgpt'?chatgptPage():active==='config'?configPage():active==='commands'?commandsPage():runnerPage();app.innerHTML=shell(page);bind()}\nfunction notice(message,type='success'){const target=document.getElementById('notice');if(target)target.innerHTML='<div class=\"notice '+type+'\">'+esc(message)+'</div>'}\nfunction bindCommandLoaders(){document.querySelectorAll('[data-load]').forEach((b)=>b.addEventListener('click',()=>{const argv=JSON.parse(b.dataset.load);active='runner';render();document.getElementById('argv').value=JSON.stringify(argv)}))}\nfunction bind(){\ndocument.querySelectorAll('[data-nav]').forEach((b)=>b.addEventListener('click',()=>{active=b.dataset.nav;render();if(active==='chatgpt'&&!chatgptLocal&&!chatgptLoading)void loadChatgpt();if(active==='registry'&&!registryNamespaces.length&&!registryLoading)void loadRegistry(true)}));\ndocument.querySelector('[data-action=\"chatgpt-refresh\"]')?.addEventListener('click',()=>void loadChatgpt());\ndocument.querySelectorAll('[data-action=\"registry-refresh\"],[data-action=\"registry-retry\"]')?.forEach((button)=>button.addEventListener('click',()=>registryWorkspace==='catalog'&®istryName?void selectRegistryItem(registryName):void loadRegistry()));\ndocument.querySelectorAll('[data-registry-workspace]').forEach((button)=>button.addEventListener('click',()=>{registryWorkspace=button.dataset.registryWorkspace;registryName='';registryDetail=null;registryAux=null;registryError='';registryNotice='';void loadRegistry()}));\ndocument.querySelectorAll('[data-registry-mode]').forEach((button)=>button.addEventListener('click',()=>{registryMode=button.dataset.registryMode;registryName='';registryDetail=null;void loadRegistry()}));\ndocument.querySelectorAll('[data-registry-name]').forEach((button)=>button.addEventListener('click',()=>void selectRegistryItem(button.dataset.registryName)));\ndocument.querySelectorAll('[data-registry-action]').forEach((button)=>button.addEventListener('click',()=>void registryAction(button.dataset.registryAction)));\ndocument.getElementById('registry-namespace')?.addEventListener('change',(event)=>{registryNamespaceId=Number(event.target.value);registryName='';registryDetail=null;registryAux=null;void loadRegistry()});\ndocument.getElementById('registry-search')?.addEventListener('change',(event)=>{registrySearch=event.target.value.trim();registryName='';registryDetail=null;void loadRegistry()});\ndocument.getElementById('registry-search')?.addEventListener('keydown',(event)=>{if(event.key==='Enter'){event.preventDefault();registrySearch=event.target.value.trim();registryName='';registryDetail=null;void loadRegistry()}});\ndocument.getElementById('registry-default-form')?.addEventListener('submit',async(event)=>{event.preventDefault();const namespaceKey=String(new FormData(event.currentTarget).get('namespaceKey')||'');if(!registryNamespaces.some((item)=>item.namespaceKey===namespaceKey)){registryNotice='<div class=\"notice error\">\u53EA\u80FD\u9009\u62E9 capability \u4E2D\u6388\u6743\u7684 namespace\u3002</div>';render();return}registryNotice='<div class=\"notice success\">\u6B63\u5728\u4FDD\u5B58\u9ED8\u8BA4\u503C\u2026</div>';render();try{const data={...state.config,aiRegistryDefaultNamespaceKey:namespaceKey};const result=await api('/api/config',{method:'PUT',body:JSON.stringify(data)});state.config=result.config;registryNotice='<div class=\"notice success\">\u7528\u6237\u9ED8\u8BA4 namespace \u5DF2\u4FDD\u5B58\u3002</div>'}catch(error){registryNotice='<div class=\"notice error\">'+esc(error.message)+'</div>'}render()});\ndocument.querySelector('[data-action=\"login\"]')?.addEventListener('click',async()=>{try{notice('\u6B63\u5728\u542F\u52A8\u767B\u5F55\u2026');const result=await api('/api/auth/login',{method:'POST',body:'{}'});location.href=result.authorizationUrl}catch(e){notice(e.message,'error')}});\ndocument.querySelector('[data-action=\"reload\"]')?.addEventListener('click',()=>bootstrap());\ndocument.querySelector('[data-action=\"logout\"]')?.addEventListener('click',async()=>{if(!confirm('\u6E05\u9664\u672C\u673A Keycloak \u767B\u5F55\u7F13\u5B58\uFF1F'))return;await api('/api/auth/logout',{method:'POST',body:'{}'});location.reload()});\ndocument.getElementById('config-form')?.addEventListener('submit',async(e)=>{e.preventDefault();const submit=e.currentTarget.querySelector('button[type=\"submit\"]');if(submit)submit.disabled=true;const data=Object.fromEntries(new FormData(e.currentTarget));data.checkUpdates=data.checkUpdates==='true';try{const result=await api('/api/config',{method:'PUT',body:JSON.stringify(data)});state.config=result.config;notice('\u914D\u7F6E\u5DF2\u4FDD\u5B58')}catch(err){notice(err.message,'error')}finally{if(submit)submit.disabled=false}});\ndocument.getElementById('command-search')?.addEventListener('input',(e)=>{document.getElementById('command-list').innerHTML=commandCards(e.target.value);bindCommandLoaders()});\nbindCommandLoaders();\ndocument.getElementById('runner-form')?.addEventListener('submit',async(e)=>{e.preventDefault();try{const argv=JSON.parse(document.getElementById('argv').value);const confirmed=document.getElementById('confirm')?.value==='true';output='\u8FD0\u884C\u4E2D\u2026';render();const result=await api('/api/commands/run',{method:'POST',body:JSON.stringify({argv,confirm:confirmed})});output=result.stdout||result.stderr||JSON.stringify(result,null,2);render()}catch(err){output='\u9519\u8BEF: '+err.message;render()}})\n}\nbootstrap();\n";
|