vault-go 0.22.2 → 0.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/local-dashboard.js +41 -6
- package/dist/local-service.js +17 -0
- package/package.json +1 -1
package/dist/local-dashboard.js
CHANGED
|
@@ -5,7 +5,7 @@ export function dashboardHtml() {
|
|
|
5
5
|
|
|
6
6
|
/* Same identity tokens and glass surfaces as the Vault portal. */
|
|
7
7
|
:root{--c-canvas:8 11 18;--c-surface:24 29 45;--c-surface-2:32 38 56;--c-line:53 61 81;--c-fg:241 243 252;--c-muted:172 180 203;--c-faint:148 159 187;--c-accent:185 182 255;color:rgb(var(--c-fg));background:rgb(var(--c-canvas))}body{background:radial-gradient(ellipse at 85% 8%,#534ca02e,transparent 45%),linear-gradient(145deg,#080b12,#101321 58%,#080b12)}[hidden]{display:none!important}.shell{grid-template-columns:258px 1fr;max-width:1600px}.rail{background:linear-gradient(160deg,#1c2135f5,#101522f5);border-color:#cdd8ff26}.brand{font-size:15px;letter-spacing:-.3px;gap:10px;white-space:nowrap}.brand img,.onboarding-logo{object-fit:contain;filter:drop-shadow(0 5px 12px #7775c533)}.brand-sub{display:block;font-size:9px;letter-spacing:1.7px;color:#acb4cb;margin-top:7px}.card,.panel,.onboarding,.step,.notice{background:linear-gradient(135deg,#272c3ed1,#131724e0);border-color:#cdd8ff26;box-shadow:0 24px 70px -30px #0009,inset 0 1px 0 #ffffff0c;backdrop-filter:blur(28px) saturate(135%)}.nav a.active,.nav a:hover{background:#b9b6ff20;color:#d3d1ff}.eyebrow,.step-number,.empty-symbol{color:#b9b6ff}p,.card-label{color:#acb4cb}.card-note,.row-meta,.rail-footer,.rail-label,.footer{color:#949fbb}.pulse{color:#b9b6ff;border-color:#b9b6ff30;background:#b9b6ff0d}.button{background:#202638;color:#f1f3fc;border-color:#cdd8ff26;text-decoration:none;justify-content:center}.button:hover{border-color:#b9b6ff88}.primary{background:linear-gradient(135deg,#c8c5ff,#9d9bed);color:#15152f;border-color:transparent;font-weight:650;padding:13px 20px;font-size:14px}.primary:hover{background:#d3d1ff}.onboarding{border:1px solid #cdd8ff26;border-radius:20px;overflow:hidden;margin-top:30px;animation:arrive .6s ease both}.onboarding-hero{position:relative;padding:38px;background:radial-gradient(ellipse at 100% 0%,#7370d02c,transparent 62%)}.onboarding-logo{width:86px;height:86px;margin-bottom:24px}.onboarding h1{font-size:36px;max-width:600px;line-height:1.12;margin:12px 0 18px}.onboarding-hero>p{max-width:570px;font-size:14px;line-height:1.8}.actions{display:flex;gap:12px;align-items:center;flex-wrap:wrap;margin-top:25px}.link{color:#d3d1ff;text-decoration:none;font-size:12px}.link:hover{text-decoration:underline}.onboarding-hint{font-size:11px!important;color:#949fbb;margin-top:15px!important}.steps{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));border-top:1px solid #cdd8ff26}.step{padding:25px;background:#080b122b;box-shadow:none;border-right:1px solid #cdd8ff16}.step:last-child{border:0}.step-number{font-family:monospace;font-size:11px;margin-bottom:13px}.step h2{margin-bottom:9px}.step p{font-size:12px}.terminal-fallback{padding:22px 30px;border-top:1px solid #cdd8ff26;background:#080b1233}.terminal-fallback p{font-size:12px}.terminal-fallback code{display:block;margin-top:10px;font-size:12px;color:#d3d1ff;overflow-wrap:anywhere}.connection-message{margin-top:18px;font-size:12px;color:#d3d1ff;min-height:18px}.next-step{display:flex;justify-content:space-between;align-items:center;gap:20px;margin-top:22px;padding:23px;border:1px solid #b9b6ff30;border-radius:14px;background:#b9b6ff09}.next-step h2{margin-bottom:8px}.next-step p{font-size:12px}.next-step .actions{margin:0;flex-shrink:0}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible{outline-color:#b9b6ff}.notice code{color:#d3d1ff}.search{border-color:#cdd8ff26;background:#0307117a}.breadcrumb b{color:#f1f3fc}.rail-footer .dot{background:#b9b6ff}.footer{margin-top:28px}@media(max-width:1100px){.shell{grid-template-columns:225px 1fr}.brand{font-size:13px}.main{padding:25px}.onboarding-hero{padding:30px}.next-step{align-items:flex-start;flex-direction:column}}@media(max-width:680px){.shell{display:block}.brand{font-size:16px}.onboarding{margin-top:22px}.onboarding-hero{padding:26px}.onboarding h1{font-size:30px}.onboarding-logo{width:65px;height:65px;margin-bottom:15px}.steps{grid-template-columns:1fr}.step{padding:20px 26px;border-right:0;border-bottom:1px solid #cdd8ff16}.step-number{margin-bottom:8px}.terminal-fallback{padding:22px 26px}.main{padding:20px}.next-step .actions{flex-shrink:1}.onboarding .actions .button{width:100%}.onboarding .actions .link{padding:8px 0}.card-value{overflow-wrap:anywhere}.nav{padding-bottom:2px}}
|
|
8
|
-
.danger{border-color:#ed9a9a66;color:#ffb5b5;background:#53272d55}.danger:hover{border-color:#ffb5b5}.danger-title{color:#ffb5b5}.pagination{display:flex;gap:9px;align-items:center;flex-wrap:wrap;border-top:1px solid #cdd8ff20;margin-top:15px;padding-top:15px;color:#acb4cb;font-size:11px}.pagination label{display:flex;align-items:center;gap:7px}.pagination .page-summary{flex:1;min-width:95px}.pagination select{padding:7px}.pagination .button{padding:7px 10px}.pagination button:disabled{cursor:default}.row-open{background:transparent;border:0;text-align:left;padding:0;color:#d3d1ff;cursor:pointer;font:inherit}.row-open:hover{text-decoration:underline}.row-actions{padding-top:5px}.detail-dialog{color:#f1f3fc;background:linear-gradient(135deg,#272c3e,#131724);border:1px solid #cdd8ff40;border-radius:18px;max-width:800px;width:calc(100% - 32px);max-height:85vh;padding:26px;box-shadow:0 30px 100px #0009}.detail-dialog::backdrop{background:#050710bd;backdrop-filter:blur(5px)}.detail-dialog h2{font-size:20px;overflow-wrap:anywhere}.detail-fields{margin:0}.detail-fields dt{color:#acb4cb;font-size:11px;margin:20px 0 8px}.detail-fields dd{margin:0;font-size:13px;line-height:1.7;white-space:pre-wrap;overflow-wrap:anywhere}.detail-fields pre{font:inherit;white-space:pre-wrap;margin:0}.engine-options{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-top:18px}.engine-keys{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px;margin-top:16px}.engine-keys label{display:block;font-size:12px;margin-bottom:8px}.engine-keys input{width:100%;background:#0307117a;color:#f1f3fc;border:1px solid #cdd8ff26;border-radius:9px;padding:10px 12px;font:inherit;font-size:13px;margin-bottom:8px}.engine-option{display:block;padding:17px;border:1px solid #cdd8ff26;border-radius:10px;background:#080b1233;cursor:pointer}.engine-option:has(input:checked){border-color:#b9b6ff;background:#b9b6ff12}.engine-option:has(input:disabled){opacity:.7;cursor:default}.engine-option input{accent-color:#b9b6ff;margin-right:8px}.engine-option strong{font-size:12px}.engine-option p{font-size:11px;margin-top:9px}.engine-message{margin-top:13px;font-size:12px;color:#d3d1ff}.context-editor{margin-top:20px}.context-editor label{display:block;font-size:12px;margin-bottom:8px}.context-editor textarea{width:100%;min-height:130px;resize:vertical;background:#0307117a;color:#f1f3fc;border:1px solid #cdd8ff26;border-radius:9px;padding:12px;font:inherit;font-size:13px}.context-editor textarea:focus-visible{outline:2px solid #b9b6ff;outline-offset:3px}@media(max-width:800px){.engine-options{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){.detail-dialog::backdrop{backdrop-filter:none}}</style><script src="/app.js" defer></script></head><body><div class="shell"><aside class="rail"><div class="brand"><img src="/logo.png" alt="" width="46" height="46"><div>AI Vault Memory<span class="brand-sub">LOCAL AGENT</span></div></div><div class="rail-label" data-i18n="workspace">WORKSPACE</div><nav class="nav" aria-label="Navigation"><a class="active" href="#overview"><span class="icon">◈</span><span data-i18n="overview">Overview</span></a><a href="#activity"><span class="icon">⌁</span><span data-i18n="activity">Activity</span></a><a href="#memories"><span class="icon">▤</span><span data-i18n="memories">Memories</span></a><a href="#context"><span class="icon">✧</span><span data-i18n="contextEngine">Context engine</span></a><a href="#projects"><span class="icon">▱</span><span data-i18n="projects">Projects</span></a></nav><div class="rail-footer"><span class="dot"></span><span data-i18n="localWorkspace">Your local workspace</span><br><span data-i18n="privacy">Activity metadata stays local.</span></div></aside><main class="main" id="overview"><header class="top"><div class="breadcrumb">Vault <span aria-hidden="true"> / </span><b data-i18n="localMonitor">Local monitor</b></div><div class="controls"><select id="locale" aria-label="Language"><option value="en">English</option><option value="pt">Português</option><option value="es">Español</option></select><button class="button" id="logout" type="button" hidden data-i18n="logout">Sign out of dashboard</button><button class="button" id="reconnect" type="button" hidden data-i18n="reconnect">Reconnect account</button><button class="button" id="refresh" type="button"><span aria-hidden="true">↻</span><span data-i18n="refresh">Refresh cloud</span></button></div></header><div id="error" class="error" role="status" aria-live="polite"></div><section class="onboarding" id="onboarding"><div class="onboarding-hero"><img class="onboarding-logo" src="/logo.png" alt="" width="86" height="86"><div class="eyebrow" data-i18n="connectEyebrow">AI VAULT MEMORY · LOCAL</div><h1 data-i18n="connectTitle">Your memory. Connected to this machine.</h1><p data-i18n="connectIntro">Connect your Vault account to see your memories, projects and recent activity in one place.</p><div class="actions"><button type="button" class="button primary" id="connect" data-i18n="connect">Connect to Vault</button><a class="link" href="https://vault.resolveup.com.br/app" target="_blank" rel="noopener noreferrer" data-i18n="openPortal">Open Vault portal ↗</a></div><p class="onboarding-hint" data-i18n="connectHint">Sign in securely in a separate window. Your password stays with the Vault portal.</p><div class="connection-message" id="connection-message" role="status" aria-live="polite"></div><a id="auth-fallback" class="button" hidden target="_blank" rel="noopener noreferrer" data-i18n="continueAuth">Continue sign-in ↗</a></div><div class="steps"><article class="step"><div class="step-number">01 / VAULT</div><h2 data-i18n="stepAccount">Connect your account</h2><p data-i18n="stepAccountBody">Sign in to Vault and authorize this local agent.</p></article><article class="step"><div class="step-number">02 / MCP</div><h2 data-i18n="stepClient">Connect your AI client</h2><p data-i18n="stepClientBody">Configure Vault MCP in Codex, Cursor or another compatible client.</p></article><article class="step"><div class="step-number">03 / MEMORY</div><h2 data-i18n="stepMemory">Build your first memory</h2><p data-i18n="stepMemoryBody">Ask your connected client to save useful context, then follow its activity here.</p></article></div><div class="terminal-fallback"><button class="button" id="verify-connection" type="button" data-i18n="verifyConnection">Already signed in? Check connection</button><p style="margin-top:16px" data-i18n="terminalFallback">Already connected through the CLI? Open a secure local session:</p><code>bunx --bun vault-go@latest local open</code></div></section><div id="dashboard" hidden><div class="welcome"><div><div class="eyebrow" data-i18n="eyebrow">YOUR KNOWLEDGE, CONNECTED</div><h1 data-i18n="title">Your local workspace.</h1><p data-i18n="subtitle">Your Vault account, memories and activity on this machine.</p></div><img src="/logo.png" alt="" width="56" height="56"></div><div id="session-notice" hidden></div><section class="cards" aria-label="Status"><article class="card"><div class="card-label"><span data-i18n="localService">Local service</span><span aria-hidden="true">◈</span></div><div class="card-value" id="local-status">—</div><div class="card-note" id="local-note">localhost:38850</div></article><article class="card"><div class="card-label"><span data-i18n="cloudConnection">Cloud connection</span><span aria-hidden="true">↗</span></div><div class="card-value" id="cloud-status">—</div><div class="card-note" id="cloud-note">—</div></article><article class="card"><div class="card-label"><span data-i18n="recentOperations">Recent operations</span><span aria-hidden="true">⌁</span></div><div class="card-value" id="activity-total">—</div><div class="card-note" data-i18n="operationsNote">Recent MCP request metadata</div></article></section><section class="next-step" id="first-memory"><div><h2 data-i18n="firstTitle">Create your first memory</h2><p data-i18n="firstBody">Connect Vault MCP to your AI client, then ask it to save context. Your memories will appear here after a cloud refresh.</p><code id="mcp-command" style="display:block;margin-top:12px;font-size:12px;overflow-wrap:anywhere"></code><p data-i18n="rememberPrompt" style="margin-top:10px"></p></div><div class="actions"><a class="button" href="https://vault.resolveup.com.br/mcp" target="_blank" rel="noopener noreferrer" data-i18n="setupMcp">Set up MCP ↗</a><a class="link" href="https://vault.resolveup.com.br/app/memory" target="_blank" rel="noopener noreferrer" data-i18n="openMemories">Open memories ↗</a></div></section><div class="layout"><section class="panel wide" id="security"><div class="panel-head"><h2 data-i18n="securityTitle">Security on this machine</h2></div><div id="security-facts"></div><div class="actions"><button class="button danger" id="disconnect-device" type="button" data-i18n="disconnectDevice">Disconnect device</button></div></section><section class="panel wide" id="context"><div class="panel-head"><h2 data-i18n="contextEngine">Context engine</h2></div><p data-i18n="engineIntro">Choose how Vault prepares your context.</p><div class="engine-options" id="engine-options" role="radiogroup" aria-label="Context engine"></div><div class="engine-options" id="model-options" role="radiogroup" aria-label="Context model"></div><div class="engine-keys" id="engine-keys"></div><div class="engine-message" id="engine-message" role="status" aria-live="polite"></div><div class="context-editor"><label for="context-text" data-i18n="contextText">Text to prepare</label><textarea id="context-text" maxlength="16000" aria-describedby="context-note"></textarea><p id="context-note" data-i18n="contextNote"></p><div class="actions"><button class="button primary" id="context-preview" type="button" data-i18n="contextPreview"></button><button class="button" id="context-stop" type="button" data-i18n="cancel" hidden></button></div><p id="context-progress" role="status" aria-live="polite"></p></div></section><section class="panel" id="activity"><div class="panel-head"><h2 data-i18n="activity">Activity</h2><span class="count" id="activity-count">0</span></div><input class="search" id="activity-search" type="search" data-placeholder="searchActivity" aria-label="Search activity"><div id="activity-list"></div><div class="pagination" id="activity-pagination"></div></section><section class="panel" id="memories"><div class="panel-head"><h2 data-i18n="memories">Memories</h2><span class="count" id="memory-count">0</span></div><input class="search" id="memory-search" type="search" data-placeholder="searchMemories" aria-label="Search memories"><div id="memory-list"></div><div class="pagination" id="memory-pagination"></div></section><section class="panel wide" id="projects"><div class="panel-head"><h2 data-i18n="projects">Projects</h2><span class="count" id="project-count">0</span></div><input class="search" id="project-search" type="search" data-placeholder="searchProjects" aria-label="Search projects"><div id="project-list"></div><div class="pagination" id="project-pagination"></div></section></div></div><footer class="footer"><span data-i18n="footer">Vault Local · Context with a place to call home.</span><span id="updated" aria-live="off">—</span></footer></main></div><dialog class="detail-dialog" id="detail-dialog" aria-labelledby="detail-title"><div class="panel-head"><h2 id="detail-title"></h2><button class="button" type="button" id="detail-copy" hidden data-i18n="copyResult">Copy result</button><button class="button" type="button" id="detail-close" data-i18n="close">Close</button></div><dl class="detail-fields" id="detail-fields"></dl></dialog><dialog class="detail-dialog" id="logout-dialog" aria-labelledby="logout-title" aria-describedby="logout-description"><h2 id="logout-title" data-i18n="logout"></h2><p id="logout-description" data-i18n="logoutDescription" style="margin-top:16px"></p><div class="actions"><button class="button" type="button" id="logout-cancel" data-i18n="cancel"></button><button class="button primary" type="button" id="logout-confirm" data-i18n="logoutConfirm"></button></div></dialog><dialog class="detail-dialog" id="context-confirm-dialog" aria-labelledby="context-confirm-title" aria-describedby="context-confirm-note"><h2 id="context-confirm-title" data-i18n="contextPreview"></h2><p id="context-confirm-engine" style="margin-top:16px"></p><p id="context-confirm-billing"></p><p id="context-confirm-note" data-i18n="contextConsentNote" style="margin-top:16px"></p><pre id="context-confirm-text" style="white-space:pre-wrap;overflow-wrap:anywhere;max-height:32vh;overflow:auto;font-size:12px;line-height:1.7"></pre><label style="display:flex;gap:10px;align-items:flex-start;font-size:12px"><input id="context-consent" type="checkbox"><span data-i18n="contextConsent"></span></label><div class="actions"><button class="button" id="context-cancel" type="button" data-i18n="cancel"></button><button class="button primary" id="context-generate" type="button" disabled data-i18n="contextGenerate"></button></div></dialog><dialog class="detail-dialog" id="disconnect-dialog" aria-labelledby="disconnect-title" aria-describedby="disconnect-description"><h2 class="danger-title" id="disconnect-title" data-i18n="disconnectDevice"></h2><p id="disconnect-description" data-i18n="disconnectDescription" style="margin-top:16px"></p><p id="disconnect-error" class="error" role="alert"></p><div class="actions"><button class="button" type="button" id="disconnect-cancel" data-i18n="cancel"></button><button class="button danger" type="button" id="disconnect-confirm" data-i18n="disconnectConfirm"></button></div></dialog></body></html>`;
|
|
8
|
+
.danger{border-color:#ed9a9a66;color:#ffb5b5;background:#53272d55}.danger:hover{border-color:#ffb5b5}.danger-title{color:#ffb5b5}.pagination{display:flex;gap:9px;align-items:center;flex-wrap:wrap;border-top:1px solid #cdd8ff20;margin-top:15px;padding-top:15px;color:#acb4cb;font-size:11px}.pagination label{display:flex;align-items:center;gap:7px}.pagination .page-summary{flex:1;min-width:95px}.pagination select{padding:7px}.pagination .button{padding:7px 10px}.pagination button:disabled{cursor:default}.row-open{background:transparent;border:0;text-align:left;padding:0;color:#d3d1ff;cursor:pointer;font:inherit}.row-open:hover{text-decoration:underline}.row-actions{padding-top:5px}.detail-dialog{color:#f1f3fc;background:linear-gradient(135deg,#272c3e,#131724);border:1px solid #cdd8ff40;border-radius:18px;max-width:800px;width:calc(100% - 32px);max-height:85vh;padding:26px;box-shadow:0 30px 100px #0009}.detail-dialog::backdrop{background:#050710bd;backdrop-filter:blur(5px)}.detail-dialog h2{font-size:20px;overflow-wrap:anywhere}.detail-fields{margin:0}.detail-fields dt{color:#acb4cb;font-size:11px;margin:20px 0 8px}.detail-fields dd{margin:0;font-size:13px;line-height:1.7;white-space:pre-wrap;overflow-wrap:anywhere}.detail-fields pre{font:inherit;white-space:pre-wrap;margin:0}.engine-options{display:grid;grid-template-columns:repeat(auto-fit,minmax(180px,1fr));gap:12px;margin-top:18px}.engine-keys{display:grid;grid-template-columns:repeat(auto-fit,minmax(240px,1fr));gap:12px;margin-top:16px}.engine-keys label{display:block;font-size:12px;margin-bottom:8px}.engine-keys input{width:100%;background:#0307117a;color:#f1f3fc;border:1px solid #cdd8ff26;border-radius:9px;padding:10px 12px;font:inherit;font-size:13px;margin-bottom:8px}.engine-option{display:block;padding:17px;border:1px solid #cdd8ff26;border-radius:10px;background:#080b1233;cursor:pointer}.engine-option:has(input:checked){border-color:#b9b6ff;background:#b9b6ff12}.engine-option:has(input:disabled){opacity:.7;cursor:default}.engine-option input{accent-color:#b9b6ff;margin-right:8px}.engine-option strong{font-size:12px}.engine-option p{font-size:11px;margin-top:9px}.engine-message{margin-top:13px;font-size:12px;color:#d3d1ff}.context-editor{margin-top:20px}.context-editor label{display:block;font-size:12px;margin-bottom:8px}.context-editor textarea{width:100%;min-height:130px;resize:vertical;background:#0307117a;color:#f1f3fc;border:1px solid #cdd8ff26;border-radius:9px;padding:12px;font:inherit;font-size:13px}.context-editor textarea:focus-visible{outline:2px solid #b9b6ff;outline-offset:3px}.mcp-clients{display:grid;grid-template-columns:repeat(auto-fit,minmax(210px,1fr));gap:10px;margin-top:14px}.mcp-client{display:flex;align-items:center;justify-content:space-between;gap:10px;border:1px solid #cdd8ff26;border-radius:10px;padding:10px 12px;background:#080b1233;font-size:13px;flex-wrap:wrap}.mcp-client strong{font-size:13px;font-weight:600}.mcp-state{font-size:11px;color:#8edbc8;white-space:nowrap}.mcp-dim{opacity:.75}.mcp-evidence{font-size:10px;color:#949fbb;width:100%}.mcp-note{color:#949fbb;font-size:12px}.mcp-message{color:#ed9a9a;font-size:12px;margin-top:10px}.mcp-message:empty{display:none}.mcp-fallback{color:#949fbb;font-size:11px;margin-top:12px}.mcp-fallback code{font-size:11px;color:#c7d4df;background:#0307117a;border-radius:6px;padding:2px 6px}@media(max-width:800px){.engine-options{grid-template-columns:1fr}}@media(prefers-reduced-motion:reduce){.detail-dialog::backdrop{backdrop-filter:none}}</style><script src="/app.js" defer></script></head><body><div class="shell"><aside class="rail"><div class="brand"><img src="/logo.png" alt="" width="46" height="46"><div>AI Vault Memory<span class="brand-sub">LOCAL AGENT</span></div></div><div class="rail-label" data-i18n="workspace">WORKSPACE</div><nav class="nav" aria-label="Navigation"><a class="active" href="#overview"><span class="icon">◈</span><span data-i18n="overview">Overview</span></a><a href="#activity"><span class="icon">⌁</span><span data-i18n="activity">Activity</span></a><a href="#memories"><span class="icon">▤</span><span data-i18n="memories">Memories</span></a><a href="#context"><span class="icon">✧</span><span data-i18n="contextEngine">Context engine</span></a><a href="#projects"><span class="icon">▱</span><span data-i18n="projects">Projects</span></a></nav><div class="rail-footer"><span class="dot"></span><span data-i18n="localWorkspace">Your local workspace</span><br><span data-i18n="privacy">Activity metadata stays local.</span></div></aside><main class="main" id="overview"><header class="top"><div class="breadcrumb">Vault <span aria-hidden="true"> / </span><b data-i18n="localMonitor">Local monitor</b></div><div class="controls"><select id="locale" aria-label="Language"><option value="en">English</option><option value="pt">Português</option><option value="es">Español</option></select><button class="button" id="logout" type="button" hidden data-i18n="logout">Sign out of dashboard</button><button class="button" id="reconnect" type="button" hidden data-i18n="reconnect">Reconnect account</button><button class="button" id="refresh" type="button"><span aria-hidden="true">↻</span><span data-i18n="refresh">Refresh cloud</span></button></div></header><div id="error" class="error" role="status" aria-live="polite"></div><section class="onboarding" id="onboarding"><div class="onboarding-hero"><img class="onboarding-logo" src="/logo.png" alt="" width="86" height="86"><div class="eyebrow" data-i18n="connectEyebrow">AI VAULT MEMORY · LOCAL</div><h1 data-i18n="connectTitle">Your memory. Connected to this machine.</h1><p data-i18n="connectIntro">Connect your Vault account to see your memories, projects and recent activity in one place.</p><div class="actions"><button type="button" class="button primary" id="connect" data-i18n="connect">Connect to Vault</button><a class="link" href="https://vault.resolveup.com.br/app" target="_blank" rel="noopener noreferrer" data-i18n="openPortal">Open Vault portal ↗</a></div><p class="onboarding-hint" data-i18n="connectHint">Sign in securely in a separate window. Your password stays with the Vault portal.</p><div class="connection-message" id="connection-message" role="status" aria-live="polite"></div><a id="auth-fallback" class="button" hidden target="_blank" rel="noopener noreferrer" data-i18n="continueAuth">Continue sign-in ↗</a></div><div class="steps"><article class="step"><div class="step-number">01 / VAULT</div><h2 data-i18n="stepAccount">Connect your account</h2><p data-i18n="stepAccountBody">Sign in to Vault and authorize this local agent.</p></article><article class="step"><div class="step-number">02 / MCP</div><h2 data-i18n="stepClient">Connect your AI clients</h2><p data-i18n="stepClientBody">After signing in, connect Claude, Codex and other clients with one click, right here.</p></article><article class="step"><div class="step-number">03 / MEMORY</div><h2 data-i18n="stepMemory">Build your first memory</h2><p data-i18n="stepMemoryBody">Ask your connected client to save useful context, then follow its activity here.</p></article></div><div class="terminal-fallback"><button class="button" id="verify-connection" type="button" data-i18n="verifyConnection">Already signed in? Check connection</button><p style="margin-top:16px" data-i18n="terminalFallback">Already connected through the CLI? Open a secure local session:</p><code>bunx --bun vault-go@latest local open</code></div></section><div id="dashboard" hidden><div class="welcome"><div><div class="eyebrow" data-i18n="eyebrow">YOUR KNOWLEDGE, CONNECTED</div><h1 data-i18n="title">Your local workspace.</h1><p data-i18n="subtitle">Your Vault account, memories and activity on this machine.</p></div><img src="/logo.png" alt="" width="56" height="56"></div><div id="session-notice" hidden></div><section class="cards" aria-label="Status"><article class="card"><div class="card-label"><span data-i18n="localService">Local service</span><span aria-hidden="true">◈</span></div><div class="card-value" id="local-status">—</div><div class="card-note" id="local-note">localhost:38850</div></article><article class="card"><div class="card-label"><span data-i18n="cloudConnection">Cloud connection</span><span aria-hidden="true">↗</span></div><div class="card-value" id="cloud-status">—</div><div class="card-note" id="cloud-note">—</div></article><article class="card"><div class="card-label"><span data-i18n="recentOperations">Recent operations</span><span aria-hidden="true">⌁</span></div><div class="card-value" id="activity-total">—</div><div class="card-note" data-i18n="operationsNote">Recent MCP request metadata</div></article></section><section class="next-step" id="first-memory"><div><h2 data-i18n="firstTitle">Connect your AI clients</h2><p data-i18n="firstBody">Connect Claude, Codex and other clients here in one click, then ask them to save context. Memories appear after a cloud refresh.</p><div class="mcp-clients" id="mcp-clients" role="group" aria-label="AI clients"></div><p id="mcp-message" role="status" aria-live="polite" class="mcp-message"></p><p data-i18n="rememberPrompt" style="margin-top:10px"></p><p class="mcp-fallback"><span data-i18n="mcpFallback"></span> <code>bunx --bun vault-go@latest install</code></p></div><div class="actions"><a class="link" href="https://vault.resolveup.com.br/mcp" target="_blank" rel="noopener noreferrer" data-i18n="otherClients">Other clients ↗</a><a class="link" href="https://vault.resolveup.com.br/app/memory" target="_blank" rel="noopener noreferrer" data-i18n="openMemories">Open memories ↗</a></div></section><div class="layout"><section class="panel wide" id="security"><div class="panel-head"><h2 data-i18n="securityTitle">Security on this machine</h2></div><div id="security-facts"></div><div class="actions"><button class="button danger" id="disconnect-device" type="button" data-i18n="disconnectDevice">Disconnect device</button></div></section><section class="panel wide" id="context"><div class="panel-head"><h2 data-i18n="contextEngine">Context engine</h2></div><p data-i18n="engineIntro">Choose how Vault prepares your context.</p><div class="engine-options" id="engine-options" role="radiogroup" aria-label="Context engine"></div><div class="engine-options" id="model-options" role="radiogroup" aria-label="Context model"></div><div class="engine-keys" id="engine-keys"></div><div class="engine-message" id="engine-message" role="status" aria-live="polite"></div><div class="context-editor"><label for="context-text" data-i18n="contextText">Text to prepare</label><textarea id="context-text" maxlength="16000" aria-describedby="context-note"></textarea><p id="context-note" data-i18n="contextNote"></p><div class="actions"><button class="button primary" id="context-preview" type="button" data-i18n="contextPreview"></button><button class="button" id="context-stop" type="button" data-i18n="cancel" hidden></button></div><p id="context-progress" role="status" aria-live="polite"></p></div></section><section class="panel" id="activity"><div class="panel-head"><h2 data-i18n="activity">Activity</h2><span class="count" id="activity-count">0</span></div><input class="search" id="activity-search" type="search" data-placeholder="searchActivity" aria-label="Search activity"><div id="activity-list"></div><div class="pagination" id="activity-pagination"></div></section><section class="panel" id="memories"><div class="panel-head"><h2 data-i18n="memories">Memories</h2><span class="count" id="memory-count">0</span></div><input class="search" id="memory-search" type="search" data-placeholder="searchMemories" aria-label="Search memories"><div id="memory-list"></div><div class="pagination" id="memory-pagination"></div></section><section class="panel wide" id="projects"><div class="panel-head"><h2 data-i18n="projects">Projects</h2><span class="count" id="project-count">0</span></div><input class="search" id="project-search" type="search" data-placeholder="searchProjects" aria-label="Search projects"><div id="project-list"></div><div class="pagination" id="project-pagination"></div></section></div></div><footer class="footer"><span data-i18n="footer">Vault Local · Context with a place to call home.</span><span id="updated" aria-live="off">—</span></footer></main></div><dialog class="detail-dialog" id="detail-dialog" aria-labelledby="detail-title"><div class="panel-head"><h2 id="detail-title"></h2><button class="button" type="button" id="detail-copy" hidden data-i18n="copyResult">Copy result</button><button class="button" type="button" id="detail-close" data-i18n="close">Close</button></div><dl class="detail-fields" id="detail-fields"></dl></dialog><dialog class="detail-dialog" id="logout-dialog" aria-labelledby="logout-title" aria-describedby="logout-description"><h2 id="logout-title" data-i18n="logout"></h2><p id="logout-description" data-i18n="logoutDescription" style="margin-top:16px"></p><div class="actions"><button class="button" type="button" id="logout-cancel" data-i18n="cancel"></button><button class="button primary" type="button" id="logout-confirm" data-i18n="logoutConfirm"></button></div></dialog><dialog class="detail-dialog" id="context-confirm-dialog" aria-labelledby="context-confirm-title" aria-describedby="context-confirm-note"><h2 id="context-confirm-title" data-i18n="contextPreview"></h2><p id="context-confirm-engine" style="margin-top:16px"></p><p id="context-confirm-billing"></p><p id="context-confirm-note" data-i18n="contextConsentNote" style="margin-top:16px"></p><pre id="context-confirm-text" style="white-space:pre-wrap;overflow-wrap:anywhere;max-height:32vh;overflow:auto;font-size:12px;line-height:1.7"></pre><label style="display:flex;gap:10px;align-items:flex-start;font-size:12px"><input id="context-consent" type="checkbox"><span data-i18n="contextConsent"></span></label><div class="actions"><button class="button" id="context-cancel" type="button" data-i18n="cancel"></button><button class="button primary" id="context-generate" type="button" disabled data-i18n="contextGenerate"></button></div></dialog><dialog class="detail-dialog" id="disconnect-dialog" aria-labelledby="disconnect-title" aria-describedby="disconnect-description"><h2 class="danger-title" id="disconnect-title" data-i18n="disconnectDevice"></h2><p id="disconnect-description" data-i18n="disconnectDescription" style="margin-top:16px"></p><p id="disconnect-error" class="error" role="alert"></p><div class="actions"><button class="button" type="button" id="disconnect-cancel" data-i18n="cancel"></button><button class="button danger" type="button" id="disconnect-confirm" data-i18n="disconnectConfirm"></button></div></dialog></body></html>`;
|
|
9
9
|
}
|
|
10
10
|
export function dashboardScript() {
|
|
11
11
|
return `"use strict";
|
|
@@ -19,9 +19,9 @@ export function dashboardScript() {
|
|
|
19
19
|
es: {workspace:'ESPACIO DE TRABAJO',overview:'Resumen',activity:'Actividad',memories:'Memorias',projects:'Proyectos',localWorkspace:'Tu espacio local',privacy:'Los metadatos de actividad quedan locales.',localMonitor:'Monitor local',refresh:'Actualizar nube',eyebrow:'TU CONOCIMIENTO, CONECTADO',title:'Un poco más de contexto.',subtitle:'Una vista clara de tu Vault local y de la conexión con la nube.',session:'Abre una sesión local segura desde tu terminal:',localService:'Servicio local',cloudConnection:'Conexión con la nube',recentOperations:'Operaciones recientes',operationsNote:'Metadatos recientes de llamadas MCP',searchMemories:'Buscar memorias…',searchProjects:'Buscar proyectos…',footer:'Vault Local · Un hogar para tu contexto.',online:'En ejecución',offline:'No disponible',connected:'Conectada',disconnected:'Desconectada',checking:'Comprobando…',signedOut:'Inicia sesión desde la CLI para conectar.',activityEmpty:'Aún no hay operaciones registradas. La actividad aparecerá al usar este servicio local.',memoriesEmpty:'No hay memorias disponibles. Las memorias de tu cuenta en la nube aparecerán aquí.',projectsEmpty:'No hay proyectos disponibles. Los proyectos de tu cuenta en la nube aparecerán aquí.',noResults:'No se encontraron resultados.',updated:'Actualizado',waiting:'Esperando una sesión segura',fetchError:'No se pudo acceder al servicio local. Comprueba que Vault Local esté en ejecución.',syncError:'La actualización de la nube falló. Inténtalo de nuevo en unos momentos.',success:'Completada',failed:'Falló',untitled:'Sin título',unknown:'Desconocido',paused:'Actualizaciones pausadas mientras esta pestaña está oculta'}
|
|
20
20
|
};
|
|
21
21
|
const onboardingCopy = {
|
|
22
|
-
en: {reconnect:'Reconnect account',verifyConnection:'Already signed in? Check connection',rememberPrompt:'Then ask your assistant: “Use vault_go_remember to remember that…”',connectEyebrow:'AI VAULT MEMORY · LOCAL',connectTitle:'Your memory. Connected to this machine.',connectIntro:'Connect your Vault account to see your memories, projects and recent activity in one place.',connect:'Connect to Vault',openPortal:'Open Vault portal ↗',connectHint:'Sign in securely in a separate window. Your password stays with the Vault portal.',continueAuth:'Continue sign-in ↗',stepAccount:'Connect your account',stepAccountBody:'Sign in to Vault and authorize this local agent.',stepClient:'Connect your AI
|
|
23
|
-
pt: {reconnect:'Reconectar conta',verifyConnection:'Já entrei: verificar conexão',rememberPrompt:'Depois peça ao assistente: “Use vault_go_remember para lembrar que…”',connectEyebrow:'AI VAULT MEMORY · LOCAL',connectTitle:'Sua memória. Conectada a esta máquina.',connectIntro:'Conecte sua conta Vault para acompanhar memórias, projetos e atividades recentes em um só lugar.',connect:'Conectar ao Vault',openPortal:'Abrir portal Vault ↗',connectHint:'Entre com segurança em uma janela separada. Sua senha fica no portal Vault.',continueAuth:'Continuar login ↗',stepAccount:'Conecte sua conta',stepAccountBody:'Entre no Vault e autorize este agente local.',stepClient:'Conecte
|
|
24
|
-
es: {reconnect:'Reconectar cuenta',verifyConnection:'Ya inicié sesión: comprobar conexión',rememberPrompt:'Después pide a tu asistente: “Usa vault_go_remember para recordar que…”',connectEyebrow:'AI VAULT MEMORY · LOCAL',connectTitle:'Tu memoria. Conectada a esta máquina.',connectIntro:'Conecta tu cuenta Vault para consultar memorias, proyectos y actividad reciente en un solo lugar.',connect:'Conectar a Vault',openPortal:'Abrir portal Vault ↗',connectHint:'Inicia sesión de forma segura en otra ventana. Tu contraseña permanece en el portal Vault.',continueAuth:'Continuar inicio de sesión ↗',stepAccount:'Conecta tu cuenta',stepAccountBody:'Inicia sesión en Vault y autoriza este agente local.',stepClient:'Conecta
|
|
22
|
+
en: {reconnect:'Reconnect account',verifyConnection:'Already signed in? Check connection',rememberPrompt:'Then ask your assistant: “Use vault_go_remember to remember that…”',connectEyebrow:'AI VAULT MEMORY · LOCAL',connectTitle:'Your memory. Connected to this machine.',connectIntro:'Connect your Vault account to see your memories, projects and recent activity in one place.',connect:'Connect to Vault',openPortal:'Open Vault portal ↗',connectHint:'Sign in securely in a separate window. Your password stays with the Vault portal.',continueAuth:'Continue sign-in ↗',stepAccount:'Connect your account',stepAccountBody:'Sign in to Vault and authorize this local agent.',stepClient:'Connect your AI clients',stepClientBody:'After signing in, connect Claude, Codex and other clients with one click, right here.',stepMemory:'Build your first memory',stepMemoryBody:'Ask your connected client to save useful context, then follow its activity here.',terminalFallback:'Already connected through the CLI? Open a secure local session:',firstTitle:'Connect your AI clients',firstBody:'Connect Claude, Codex and other clients here in one click, then ask them to save context. Memories appear after a cloud refresh.',mcpConnected:'Connected',mcpConnect:'Connect',mcpConnecting:'Connecting…',mcpConnectFailed:'Could not connect this client. Try again, or run bunx --bun vault-go@latest install.',mcpLoadFailed:'Could not check your AI clients. Try refreshing.',mcpNotDetected:'not detected here',mcpFallback:'Client not listed?',otherClients:'Other clients ↗',openMemories:'Open memories ↗',connecting:'Opening secure sign-in…',awaitingAuth:'Complete sign-in in the Vault window. This page will update automatically.',popupBlocked:'Your browser blocked the window. Use the sign-in link below to continue.',connectFailed:'Could not connect to Vault. Try again or open a local session through the terminal.',connectExpired:'Sign-in was not completed. Click Connect to Vault to try again.',title:'Your local workspace.',subtitle:'Your Vault account, memories and activity on this machine.',memoriesEmpty:'No memories yet. Connect an AI client above and ask it to save your first memory.',projectsEmpty:'No projects yet. Projects returned by your Vault account will appear here.',footer:'AI Vault Memory · Local agent'},
|
|
23
|
+
pt: {reconnect:'Reconectar conta',verifyConnection:'Já entrei: verificar conexão',rememberPrompt:'Depois peça ao assistente: “Use vault_go_remember para lembrar que…”',connectEyebrow:'AI VAULT MEMORY · LOCAL',connectTitle:'Sua memória. Conectada a esta máquina.',connectIntro:'Conecte sua conta Vault para acompanhar memórias, projetos e atividades recentes em um só lugar.',connect:'Conectar ao Vault',openPortal:'Abrir portal Vault ↗',connectHint:'Entre com segurança em uma janela separada. Sua senha fica no portal Vault.',continueAuth:'Continuar login ↗',stepAccount:'Conecte sua conta',stepAccountBody:'Entre no Vault e autorize este agente local.',stepClient:'Conecte seus clientes de IA',stepClientBody:'Depois de entrar, conecte Claude, Codex e outros clientes em um clique, aqui mesmo.',stepMemory:'Crie sua primeira memória',stepMemoryBody:'Peça ao cliente conectado para salvar um contexto útil e acompanhe a atividade aqui.',terminalFallback:'Já conectou pela CLI? Abra uma sessão local segura:',firstTitle:'Conecte seus clientes de IA',firstBody:'Conecte Claude, Codex e outros clientes aqui em um clique e peça para salvar contexto. As memórias aparecem após atualizar a nuvem.',mcpConnected:'Conectado',mcpConnect:'Conectar',mcpConnecting:'Conectando…',mcpConnectFailed:'Não foi possível conectar este cliente. Tente novamente ou rode bunx --bun vault-go@latest install.',mcpLoadFailed:'Não foi possível verificar seus clientes de IA. Tente atualizar.',mcpNotDetected:'não detectado aqui',mcpFallback:'Cliente não listado?',otherClients:'Outros clientes ↗',openMemories:'Abrir memórias ↗',connecting:'Abrindo login seguro…',awaitingAuth:'Conclua o login na janela do Vault. Esta página será atualizada automaticamente.',popupBlocked:'O navegador bloqueou a janela. Use o link de login abaixo para continuar.',connectFailed:'Não foi possível conectar ao Vault. Tente novamente ou abra uma sessão local pelo terminal.',connectExpired:'O login não foi concluído. Clique em Conectar ao Vault para tentar novamente.',title:'Seu espaço de trabalho local.',subtitle:'Sua conta Vault, memórias e atividades nesta máquina.',memoriesEmpty:'Ainda não há memórias. Conecte um cliente de IA acima e peça para salvar a primeira.',projectsEmpty:'Ainda não há projetos. Os projetos retornados pela sua conta Vault aparecerão aqui.',footer:'AI Vault Memory · Agente local'},
|
|
24
|
+
es: {reconnect:'Reconectar cuenta',verifyConnection:'Ya inicié sesión: comprobar conexión',rememberPrompt:'Después pide a tu asistente: “Usa vault_go_remember para recordar que…”',connectEyebrow:'AI VAULT MEMORY · LOCAL',connectTitle:'Tu memoria. Conectada a esta máquina.',connectIntro:'Conecta tu cuenta Vault para consultar memorias, proyectos y actividad reciente en un solo lugar.',connect:'Conectar a Vault',openPortal:'Abrir portal Vault ↗',connectHint:'Inicia sesión de forma segura en otra ventana. Tu contraseña permanece en el portal Vault.',continueAuth:'Continuar inicio de sesión ↗',stepAccount:'Conecta tu cuenta',stepAccountBody:'Inicia sesión en Vault y autoriza este agente local.',stepClient:'Conecta tus clientes de IA',stepClientBody:'Tras iniciar sesión, conecta Claude, Codex y otros clientes con un clic, aquí mismo.',stepMemory:'Crea tu primera memoria',stepMemoryBody:'Pide al cliente conectado que guarde contexto útil y sigue su actividad aquí.',terminalFallback:'¿Ya te conectaste mediante la CLI? Abre una sesión local segura:',firstTitle:'Conecta tus clientes de IA',firstBody:'Conecta Claude, Codex y otros clientes aquí con un clic y pídeles que guarden contexto. Las memorias aparecen al actualizar la nube.',mcpConnected:'Conectado',mcpConnect:'Conectar',mcpConnecting:'Conectando…',mcpConnectFailed:'No se pudo conectar este cliente. Inténtalo de nuevo o ejecuta bunx --bun vault-go@latest install.',mcpLoadFailed:'No se pudo comprobar tus clientes de IA. Actualiza la página.',mcpNotDetected:'no detectado aquí',mcpFallback:'¿Cliente no listado?',otherClients:'Otros clientes ↗',openMemories:'Abrir memorias ↗',connecting:'Abriendo inicio de sesión seguro…',awaitingAuth:'Completa el inicio de sesión en la ventana de Vault. Esta página se actualizará automáticamente.',popupBlocked:'El navegador bloqueó la ventana. Usa el enlace de abajo para continuar.',connectFailed:'No se pudo conectar a Vault. Inténtalo de nuevo o abre una sesión local desde el terminal.',connectExpired:'No se completó el inicio de sesión. Pulsa Conectar a Vault para intentarlo de nuevo.',title:'Tu espacio de trabajo local.',subtitle:'Tu cuenta Vault, memorias y actividad en esta máquina.',memoriesEmpty:'Aún no hay memorias. Conecta un cliente de IA arriba y pídele que guarde la primera.',projectsEmpty:'Aún no hay proyectos. Los proyectos de tu cuenta Vault aparecerán aquí.',footer:'AI Vault Memory · Agente local'}
|
|
25
25
|
};
|
|
26
26
|
const detailCopy = {
|
|
27
27
|
en:{disconnectDevice:'Disconnect device',disconnectConfirm:'Revoke access and disconnect',disconnectDescription:'This revokes this agent’s cloud access and removes its local credentials and cache. Your files are preserved. MCP clients stop using this account until you sign in again.',disconnectFailed:'Could not confirm device disconnection. Nothing was cleared from this panel. Check the connection and try again.',disconnectLoginBusy:'Sign-in is in progress. Finish signing in before disconnecting this device.',contextCanceling:'Requesting cancellation…',contextCancelFailed:'Cancellation could not be confirmed. The provider may still be running and usage charges may apply.',securityTitle:'Security on this machine',cacheEncrypted:'Local cache encrypted at rest',cacheUnverified:'Local cache protection not confirmed',credentialProtection:'Account credentials protected by local file permissions',transportProtection:'Local connection: loopback HTTP. Vault cloud connection: HTTPS.',noEndToEnd:'This is not end-to-end encryption. The selected provider processes text you authorize.',device:'Device',deviceOnline:'Online',deviceOffline:'Offline',deviceRevoked:'Revoked',deviceUnregistered:'Not registered',lastSeen:'Last seen',keyStorage:'Encryption key storage',contextCanceled:'Generation canceled. Provider usage already consumed may still be charged.',contextText:'Text to prepare',contextNote:'Up to 16,000 characters. Only this text is sent; no memory is saved automatically.',contextPreview:'Review generation',contextConsentNote:'The following text will be sent to the selected provider. Review it before continuing.',contextConsent:'I authorize sending this text and using the selected engine allowance or applicable credits.',contextGenerate:'Generate context',contextRunning:'Preparing context…',contextComplete:'Context ready. Review or copy the result.',contextFailed:'Could not generate context. Check your engine login and usage limits.',contextTimedOut:'The local wait limit was reached. No further polling will occur.',contextInvalid:'Enter 1–16,000 characters and choose an available engine.',contextBilling:'Provider subscription limits or usage credits may apply.',copyResult:'Copy result',copied:'Result copied.',copyFailed:'Could not copy. Select the result text manually.',logout:'Sign out of dashboard',logoutDescription:'This ends the session in this browser. The local agent remains connected to your Vault account and keeps working.',logoutConfirm:'Sign out',cancel:'Cancel',logoutFailed:'Could not end this session. Please try again.',searchActivity:'Search activity…',previous:'Previous',next:'Next',perPage:'Per page',of:'of',page:'Page',view:'View details',close:'Close',details:'Details',contextEngine:'Context engine',engineIntro:'Choose how Vault prepares your context.',engineLoading:'Checking available engines…',engineUnavailable:'Unavailable on this machine',engineAvailable:'Available',engineSaved:'Context engine updated.',engineFailed:'Could not update the context engine. Try again.',engineLoadFailed:'Could not load context engines. Refresh to retry.'},
|
|
@@ -50,6 +50,8 @@ export function dashboardScript() {
|
|
|
50
50
|
function empty(target, message) { const box = node('div','empty'); box.append(node('span','empty-symbol','◇'),node('p','',message)); target.append(box); }
|
|
51
51
|
const pagination = {activity:{page:1,size:10},memory:{page:1,size:10},project:{page:1,size:10}};
|
|
52
52
|
let detailFocus = '', engines = null, engineBusy = false, engineMessage = '', sessionEpoch = 0, enginesChecked = 0, disconnecting = false;
|
|
53
|
+
let mcpClients = null, mcpChecked = 0, mcpMessage = '';
|
|
54
|
+
const mcpBusy = {};
|
|
53
55
|
let contextPreview=null, contextJob=null, contextTimer=null, contextStarted=0, contextMessage='', contextResult=null, contextStarting=false;
|
|
54
56
|
function showDetails(title,item,trigger) {
|
|
55
57
|
contextResult=null;el('detail-copy').hidden=true;
|
|
@@ -178,6 +180,34 @@ export function dashboardScript() {
|
|
|
178
180
|
el('context-stop').hidden=!contextJob;el('context-stop').disabled=contextStarting;
|
|
179
181
|
text('context-progress',contextMessage?t(contextMessage):'');
|
|
180
182
|
}
|
|
183
|
+
function renderMcpClients() {
|
|
184
|
+
const target=el('mcp-clients');if(!target)return;target.replaceChildren();
|
|
185
|
+
if(!mcpClients){target.append(node('div','mcp-note',sessionRequired?'':t('checking')));return;}
|
|
186
|
+
for(const item of array(mcpClients.clients)) {
|
|
187
|
+
const row=node('div','mcp-client'+(item.detected?'':' mcp-dim')),name=node('strong','',scalar(item.name)||scalar(item.client));
|
|
188
|
+
row.append(name);
|
|
189
|
+
if(item.connected===true)row.append(node('span','mcp-state','✓ '+t('mcpConnected')));
|
|
190
|
+
else {
|
|
191
|
+
const button=node('button','button',mcpBusy[item.client]?t('mcpConnecting'):t('mcpConnect'));
|
|
192
|
+
button.type='button';button.disabled=Boolean(mcpBusy[item.client]);
|
|
193
|
+
button.addEventListener('click',()=>void connectMcp(item.client));
|
|
194
|
+
row.append(button);
|
|
195
|
+
}
|
|
196
|
+
if(item.detected===false)row.append(node('span','mcp-evidence',t('mcpNotDetected')));
|
|
197
|
+
target.append(row);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
async function connectMcp(clientId) {
|
|
201
|
+
if(mcpBusy[clientId])return;
|
|
202
|
+
const epoch=sessionEpoch;mcpBusy[clientId]=true;mcpMessage='';renderMcpClients();
|
|
203
|
+
try {
|
|
204
|
+
const result=await request('/api/mcp/clients',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({client:clientId})});
|
|
205
|
+
if(!result)throw new Error('connect failed');
|
|
206
|
+
const next=await request('/api/mcp/clients');
|
|
207
|
+
if(epoch===sessionEpoch&&!sessionRequired&&next){mcpClients=next;mcpChecked=Date.now();}
|
|
208
|
+
} catch {if(epoch===sessionEpoch)mcpMessage='mcpConnectFailed';}
|
|
209
|
+
finally{delete mcpBusy[clientId];render();}
|
|
210
|
+
}
|
|
181
211
|
function render() {
|
|
182
212
|
document.documentElement.lang = locale; el('locale').value = locale;
|
|
183
213
|
document.querySelectorAll('[data-i18n]').forEach(n => { n.textContent=t(n.dataset.i18n); });
|
|
@@ -186,7 +216,7 @@ export function dashboardScript() {
|
|
|
186
216
|
el('onboarding').hidden = hasSession;
|
|
187
217
|
el('dashboard').hidden = !hasSession;
|
|
188
218
|
if(!hasSession && el('detail-dialog').open)el('detail-dialog').close();
|
|
189
|
-
if(!hasSession){engines=null;enginesChecked=0;clearContext();}
|
|
219
|
+
if(!hasSession){engines=null;enginesChecked=0;mcpClients=null;mcpChecked=0;mcpMessage='';for(const key of Object.keys(mcpBusy))delete mcpBusy[key];clearContext();}
|
|
190
220
|
renderEngines();
|
|
191
221
|
const security=object(state&&state.security),cache=object(security.cache),device=object(state&&state.device),facts=el('security-facts');facts.replaceChildren();
|
|
192
222
|
if(hasSession){
|
|
@@ -208,7 +238,8 @@ export function dashboardScript() {
|
|
|
208
238
|
document.querySelector('.rail-label').hidden = !hasSession;
|
|
209
239
|
el('connect').disabled = connecting;
|
|
210
240
|
el('verify-connection').disabled = busy || connecting;
|
|
211
|
-
|
|
241
|
+
renderMcpClients();
|
|
242
|
+
text('mcp-message',mcpMessage ? t(mcpMessage) : '');
|
|
212
243
|
text('connection-message',connectionMessage ? t(connectionMessage) : '');
|
|
213
244
|
el('first-memory').hidden = array(state && state.memories).length > 0;
|
|
214
245
|
el('refresh').disabled = busy || sessionRequired || disconnecting;
|
|
@@ -241,6 +272,10 @@ export function dashboardScript() {
|
|
|
241
272
|
enginesChecked=Date.now();
|
|
242
273
|
try {const result=await request('/api/context/engines');if(result&&epoch===sessionEpoch&&!sessionRequired){engines=result;if(engineMessage==='engineLoadFailed')engineMessage='';}} catch {if(!engines&&epoch===sessionEpoch&&!sessionRequired)engineMessage='engineLoadFailed';}
|
|
243
274
|
}
|
|
275
|
+
if(state && state.authenticated && !sessionRequired && (!mcpChecked||Date.now()-mcpChecked>60000)) {
|
|
276
|
+
mcpChecked=Date.now();
|
|
277
|
+
try {const result=await request('/api/mcp/clients');if(result&&epoch===sessionEpoch&&!sessionRequired)mcpClients=result;} catch {if(!mcpClients&&epoch===sessionEpoch&&!sessionRequired)mcpMessage='mcpLoadFailed';}
|
|
278
|
+
}
|
|
244
279
|
} catch { if(epoch===sessionEpoch&&!disconnecting){failure=sync ? 'syncError' : 'fetchError'; if (!sync) state=null;} }
|
|
245
280
|
finally { busy=false; render(); if(pendingRefresh) {pendingRefresh=false; void refresh(true);} }
|
|
246
281
|
}
|
package/dist/local-service.js
CHANGED
|
@@ -15,6 +15,8 @@ import { localDevice } from "./local-device.js";
|
|
|
15
15
|
import { processGenerationQueue } from "./hook-queue.js";
|
|
16
16
|
import { startTranscriptWatchers } from './transcript-watchers.js';
|
|
17
17
|
import { transcriptStatus } from './transcript-config.js';
|
|
18
|
+
import { connectMcpClient, listMcpClients } from "./mcp-clients.js";
|
|
19
|
+
import { MCP_CLIENTS } from "./installer.js";
|
|
18
20
|
import { generateContext, isApiEngine, isContextEngine, listContextEngines, parseEngineModel, saveEngineKey, selectContextEngine, selectEngineModel, selectedContextEngine, } from "./context-engines.js";
|
|
19
21
|
export const LOCAL_PORT = 38850;
|
|
20
22
|
const safeEqual = (a, b) => a.length === b.length &&
|
|
@@ -462,6 +464,21 @@ export async function startLocalService(options = {}) {
|
|
|
462
464
|
json(200, { ok: true });
|
|
463
465
|
return;
|
|
464
466
|
}
|
|
467
|
+
if (url.pathname === "/api/mcp/clients" && req.method === "GET") {
|
|
468
|
+
json(200, { clients: listMcpClients(home) });
|
|
469
|
+
return;
|
|
470
|
+
}
|
|
471
|
+
if (url.pathname === "/api/mcp/clients" && req.method === "POST") {
|
|
472
|
+
const data = (await readBody(req));
|
|
473
|
+
if (typeof data.client !== "string" ||
|
|
474
|
+
!MCP_CLIENTS.includes(data.client)) {
|
|
475
|
+
json(400, { error: "invalid_client" });
|
|
476
|
+
return;
|
|
477
|
+
}
|
|
478
|
+
const result = connectMcpClient(data.client, home);
|
|
479
|
+
json(200, { ok: true, ...result, connected: true });
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
465
482
|
if (url.pathname === "/api/context/engines" && req.method === "GET") {
|
|
466
483
|
json(200, await engines());
|
|
467
484
|
return;
|