micro-models-agent 2.26.0 → 2.28.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/CHANGELOG.md +47 -0
- package/dist/assets/js/feed/core.js +1 -1
- package/dist/assets/js/feed/history.js +1 -1
- package/dist/assets/js/feed/image-card.js +1 -0
- package/dist/assets/js/feed/stream.js +1 -1
- package/dist/assets/js/feed/turn.js +4 -4
- package/dist/assets/js/format.js +2 -2
- package/dist/assets/js/lightbox.js +1 -0
- package/dist/assets/js/settings/controls.js +1 -1
- package/dist/assets/js/settings/editors.js +1 -1
- package/dist/assets/js/settings/panels.js +1 -1
- package/dist/assets/styles.css +1 -1
- package/dist/i18n/en.json +1 -1
- package/dist/i18n/ru.json +1 -1
- package/dist/main.js +321 -321
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,53 @@ All notable changes to Micro Models Agent (MMA) will be documented in this file.
|
|
|
4
4
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/), and this project adheres to [Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## [2.28.0] - 2026-10-07
|
|
8
|
+
|
|
9
|
+
Tool-produced images (browser screenshots, `attach_image`) are now visible in the
|
|
10
|
+
`mma web` feed — a thumbnail with a full-screen lightbox — and survive reload via
|
|
11
|
+
per-session persistence with rotation. The old static placeholder card that never
|
|
12
|
+
filled is gone.
|
|
13
|
+
|
|
14
|
+
### Added
|
|
15
|
+
|
|
16
|
+
- **Tool images in the web feed** (`src/modules/webui/assets/js/lightbox.ts`, `feed/image-card.ts`, `feed/turn.ts`, `feed/history.ts`): `browser` screenshots and `attach_image` render as lazy thumbnails; click opens a lightbox (Esc/backdrop close, "open in a new tab", "copy link"). Shown in every verbosity, including quiet.
|
|
17
|
+
- **Persistence + replay** (`src/modules/session/image-store.ts`, `src/core/session-logger.ts`): full-size assets are written to `<sessionDir>/images/` and served via `GET /api/sessions/:id/images/:name`; history replay renders the same thumbnails. When a file was evicted by rotation, the card shows a muted "image removed (rotation)".
|
|
18
|
+
- **Rotation** (`images.maxCount` default 30, `images.maxBytes` default 100 MB in `src/config/registry-extra.ts`): oldest images are evicted first; both keys in `/config` and Web UI settings (UI → Tool images). Labels `config.key.images.*` (en+ru).
|
|
19
|
+
- **Delivery contract** (`src/tools/types.ts`, `src/core/types.ts`): `ToolResult.imageFiles`/`imageRefs`, `ToolEvent.imageRefs`/`images`, and `tool_result.images` in `session.jsonl`.
|
|
20
|
+
|
|
21
|
+
### Changed
|
|
22
|
+
|
|
23
|
+
- **`attach_image`** (`src/tools/attach-image.ts`): returns the image via `result.images` (unified path with the browser tool) instead of queueing it directly on the context manager.
|
|
24
|
+
- **SSE `tool_end`** (`src/modules/webui/session/forward.ts`): carries an `images` URL list; for an encrypted session (no disk write) it falls back to inline data URLs for live view.
|
|
25
|
+
- **Browser screenshots for text-only models** (`src/tools/browser.ts`): the screenshot is always produced and delivered to the web feed; a non-vision model still receives the text note.
|
|
26
|
+
|
|
27
|
+
### Removed
|
|
28
|
+
|
|
29
|
+
- **Static screenshot placeholder** (`src/modules/webui/assets/js/feed/turn.ts`): the misleading "screenshot" card that was created on every `browser`/`attach_image` call and never filled.
|
|
30
|
+
|
|
31
|
+
## [2.27.0] - 2026-10-07
|
|
32
|
+
|
|
33
|
+
MoE is now usable out of the box: `moe.enabled: true` starts on the active
|
|
34
|
+
model instead of silently falling back when no planner model is set, the
|
|
35
|
+
planner keys are configurable from `/config` and Web UI, and model/provider
|
|
36
|
+
references render as dropdowns instead of free-text/JSON fields.
|
|
37
|
+
|
|
38
|
+
### Added
|
|
39
|
+
|
|
40
|
+
- **Orchestrator config keys** (`src/config/registry-extra.ts`): `orchestrator.model`, `orchestrator.provider`, `orchestrator.contextWindow` (domain `provider`). Previously reachable only by hand-editing `config.json`; now in `/config`, `mma config set` and Web UI settings (Agent → Mixture of experts).
|
|
41
|
+
- **Dynamic `select` editor** (`src/config/registry.ts`, `src/modules/webui/assets/js/settings/{controls,editors}.ts`): `ConfigEditorSpec.kind: "select"` with `optionsSource: "models" | "providers"` renders a dropdown fed by the live model/provider lists, with text-input fallback when the list is unavailable. Applied to `critic.model`, `orchestrator.model` and the `experts[*].model` table column.
|
|
42
|
+
- **`resolveProviderRef`** (`src/modules/providers/resolve-ref.ts`): resolves a provider name (`provider.entries[]` label/type) to its entry.
|
|
43
|
+
- **Per-expert models** (`src/modules/execution/expert-provider.ts`): `experts[*].model` now takes effect — an expert whose model differs from the active one runs on a dedicated provider built on the active provider (`buildManagedProvider`); a matching/empty model reuses the shared provider, a build error fails open. Applies both to MoE subtasks and to the `subagent` tool called directly with `expert_tag`.
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- **Shared managed-provider builder** (`src/modules/providers/managed.ts`): the ProviderManager-based builder (per-entry contextWindow/retry/rateLimits + failover) is extracted and reused by the MoE orchestrator, the critic and per-expert providers instead of being duplicated in three places.
|
|
48
|
+
|
|
49
|
+
- **MoE default-model fallback** (`src/llm/orchestrator.ts`, `src/core/agent-moe.ts`): `OrchestratorClient` reuses the active agent provider when `orchestrator.model` is unset, and builds a dedicated provider on the active provider when `orchestrator.model` differs — so enabling MoE no longer requires hand-configuring a planner model.
|
|
50
|
+
- **`critic.provider` / `orchestrator.provider`** (`src/config/types.ts`, `src/modules/critic/provider.ts`): accept a provider name string (reference) as well as a full `ProviderConfig`; the Web UI shows a provider dropdown.
|
|
51
|
+
- **`ConfigKeyDef.allowEmpty`** (`src/config/registry.ts`): optional string keys accept an empty value (clears to unset), so a dropdown can restore "use active".
|
|
52
|
+
- **Cert MoE scenarios** (`src/modules/certification/scenarios.ts`): dropped the `orchestrator: { model: "" }` override that disabled MoE and let the file-level checks pass without ever exercising the MoE path.
|
|
53
|
+
|
|
7
54
|
## [2.26.0] - 2026-10-07
|
|
8
55
|
|
|
9
56
|
Web UI polish: the sidebar now has a fixed width with the detail panel on the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{msgs as s,el as i,setIcon as C}from"../dom.js";import{t as l,pluralCount as w}from"../i18n.js";import{feed as o,tabs as a}from"../store.js";import{formatMs as x,verbosity as T}from"../format.js";import{copyText as v}from"../../md.js";export function mdOpts(t){return{copyLabel:l("web.code.copy"),copiedLabel:l("web.code.copied"),copyFailedLabel:l("web.code.copy_failed"),animate:t===!0}}export function buildThinkBlock(t,e){const n=i("div","think"+(e===!1?"":" live")),r=i("button","think-h");r.type="button",r.setAttribute("aria-expanded","false"),r.appendChild(i("span","g","✦")),r.appendChild(i("span","lab",l("web.action.thinking"))),t&&r.appendChild(i("span","dur",""));const d=i("span","tog");C(d,"chevron-right",l("web.action.show")),r.appendChild(d);const p=i("div","think-body hidden");return n.appendChild(r),n.appendChild(p),{wrap:n,head:r,body:p}}export function copyAction(t,e){const n=i("button","act-btn",l(e));return n.type="button",n.addEventListener("click",()=>{v(t).then(r=>{n.textContent=r?"✓ "+l("web.code.copied"):"⚠ "+l("web.code.copy_failed"),window.setTimeout(()=>{n.textContent=l(e)},1400)})}),n}export function appendActionsRow(t,e,n){const r=String(e??""),d=String(n??"");if(!t||!r.trim()&&!d.trim())return;const p=i("div","msg-actions");r.trim()&&p.appendChild(copyAction(r,"web.msg.copy")),d.trim()&&p.appendChild(copyAction(d,"web.msg.copy_md")),appendTo(t,p)}export function insertAfter(t,e){t&&t.parentNode?t.parentNode.insertBefore(e,t.nextSibling):appendTo(liveFeed(),e)}function b(){const t=i("div","empty");return t.appendChild(i("span","g","✦")),t.appendChild(document.createTextNode(" "+l("web.empty.title"))),t.appendChild(document.createElement("br")),t.appendChild(i("span","hint",l("web.empty.hint"))),t}export function makeFeed(){const t=i("div","feed");return t.appendChild(b()),t}export function showEmptyFeed(){s.replaceChildren(b()),u=!0,f(),syncUrl()}export function clearFeed(t){if(!t)return;t.replaceChildren(b()),u=!0,f();const e=a.tabs.find(n=>n.feed===t);e&&(e.planCard=null),t===activeFeed()&&scroll()}export function activeFeed(){const t=a.tabs.find(e=>e.id===a.activeTabId);return t?t.feed:null}export function liveFeed(){const t=a.tabs.find(e=>e.id===a.liveTabId)||a.tabs.find(e=>e.id===a.activeTabId);return t?t.feed:null}export function feedForEvent(t){if(t){const e=a.tabs.find(n=>n.id===t);if(e)return e.feed}return liveFeed()}function h(){return s.scrollHeight-s.scrollTop-s.clientHeight<140}let u=!0;export function scroll(t){t||u||h()?(s.scrollTop=s.scrollHeight,u=!0,f()):m()}export function scrollToBottom(t){if(u=!0,f(),t&&typeof s.scrollTo=="function")try{s.scrollTo({top:s.scrollHeight,behavior:"smooth"});return}catch{}s.scrollTop=s.scrollHeight}export function isFollowing(){return u}export function feedHasContent(t){return!!t.querySelector(".u, .md, .ans, .code, .act, .think, .metaln, .errline, .sysline, .detail")}export function syncUrl(){const t=new URL(location.href),e=a.tabs.find(n=>n.id===a.activeTabId);e&&e.kind==="session"?t.searchParams.set("session",e.id):t.searchParams.delete("session"),history.replaceState(null,"",t)}let c=null;function g(){if(c)return c;const t=document.querySelector(".chat");return t?(c=i("button","to-latest"),c.type="button",c.hidden=!0,c.addEventListener("click",()=>scrollToBottom(!0)),t.appendChild(c),c):null}function m(){const t=g();t&&(t.textContent="↓ "+l("web.scroll.latest"),t.hidden=!1,s.classList.add("unfollowed"))}function f(){c&&(c.hidden=!0),s.classList.remove("unfollowed")}s
|
|
1
|
+
import{msgs as s,el as i,setIcon as C}from"../dom.js";import{t as l,pluralCount as w}from"../i18n.js";import{feed as o,tabs as a}from"../store.js";import{formatMs as x,verbosity as T}from"../format.js";import{copyText as v}from"../../md.js";export function mdOpts(t){return{copyLabel:l("web.code.copy"),copiedLabel:l("web.code.copied"),copyFailedLabel:l("web.code.copy_failed"),animate:t===!0}}export function buildThinkBlock(t,e){const n=i("div","think"+(e===!1?"":" live")),r=i("button","think-h");r.type="button",r.setAttribute("aria-expanded","false"),r.appendChild(i("span","g","✦")),r.appendChild(i("span","lab",l("web.action.thinking"))),t&&r.appendChild(i("span","dur",""));const d=i("span","tog");C(d,"chevron-right",l("web.action.show")),r.appendChild(d);const p=i("div","think-body hidden");return n.appendChild(r),n.appendChild(p),{wrap:n,head:r,body:p}}export function copyAction(t,e){const n=i("button","act-btn",l(e));return n.type="button",n.addEventListener("click",()=>{v(t).then(r=>{n.textContent=r?"✓ "+l("web.code.copied"):"⚠ "+l("web.code.copy_failed"),window.setTimeout(()=>{n.textContent=l(e)},1400)})}),n}export function appendActionsRow(t,e,n){const r=String(e??""),d=String(n??"");if(!t||!r.trim()&&!d.trim())return;const p=i("div","msg-actions");r.trim()&&p.appendChild(copyAction(r,"web.msg.copy")),d.trim()&&p.appendChild(copyAction(d,"web.msg.copy_md")),appendTo(t,p)}export function insertAfter(t,e){t&&t.parentNode?t.parentNode.insertBefore(e,t.nextSibling):appendTo(liveFeed(),e)}function b(){const t=i("div","empty");return t.appendChild(i("span","g","✦")),t.appendChild(document.createTextNode(" "+l("web.empty.title"))),t.appendChild(document.createElement("br")),t.appendChild(i("span","hint",l("web.empty.hint"))),t}export function makeFeed(){const t=i("div","feed");return t.appendChild(b()),t}export function showEmptyFeed(){s.replaceChildren(b()),u=!0,f(),syncUrl()}export function clearFeed(t){if(!t)return;t.replaceChildren(b()),u=!0,f();const e=a.tabs.find(n=>n.feed===t);e&&(e.planCard=null),t===activeFeed()&&scroll()}export function activeFeed(){const t=a.tabs.find(e=>e.id===a.activeTabId);return t?t.feed:null}export function liveFeed(){const t=a.tabs.find(e=>e.id===a.liveTabId)||a.tabs.find(e=>e.id===a.activeTabId);return t?t.feed:null}export function feedForEvent(t){if(t){const e=a.tabs.find(n=>n.id===t);if(e)return e.feed}return liveFeed()}function h(){return s.scrollHeight-s.scrollTop-s.clientHeight<140}let u=!0;export function scroll(t){t||u||h()?(s.scrollTop=s.scrollHeight,u=!0,f()):m()}export function scrollToBottom(t){if(u=!0,f(),t&&typeof s.scrollTo=="function")try{s.scrollTo({top:s.scrollHeight,behavior:"smooth"});return}catch{}s.scrollTop=s.scrollHeight}export function isFollowing(){return u}export function feedHasContent(t){return!!t.querySelector(".u, .md, .ans, .code, .act, .think, .metaln, .errline, .sysline, .detail")}export function syncUrl(){const t=new URL(location.href),e=a.tabs.find(n=>n.id===a.activeTabId);e&&e.kind==="session"?t.searchParams.set("session",e.id):t.searchParams.delete("session"),history.replaceState(null,"",t)}let c=null;function g(){if(c)return c;const t=document.querySelector(".chat");return t?(c=i("button","to-latest"),c.type="button",c.hidden=!0,c.addEventListener("click",()=>scrollToBottom(!0)),t.appendChild(c),c):null}function m(){const t=g();t&&(t.textContent="↓ "+l("web.scroll.latest"),t.hidden=!1,s.classList.add("unfollowed"))}function f(){c&&(c.hidden=!0),s.classList.remove("unfollowed")}s?.addEventListener("scroll",()=>{const t=h();u=t,s.classList.toggle("scrolled",s.scrollTop>24),t?f():liveFeed()&&feedHasContent(liveFeed())&&m()});export function appendTo(t,e){return t&&(t.appendChild(e),t===activeFeed()&&scroll()),e}export function clearEmpty(t){const e=t&&t.querySelector(".empty");e&&e.remove()}export function clearBusy(t){if(o.busyTimer&&(clearInterval(o.busyTimer),o.busyTimer=null),t=t||liveFeed(),!t)return;const e=t.querySelector(".busy");e&&e.remove()}export function showBusy(t){if(t=t||liveFeed(),!t||o.curMd||o.curThink||(clearEmpty(t),t.querySelector(".busy")))return;o.busyTimer&&(clearInterval(o.busyTimer),o.busyTimer=null);const e=i("div","busy");e.appendChild(i("span","spin","✦")),e.appendChild(i("span","lab",l("web.action.thinking")));const n=i("span","busytime","· 0s");e.appendChild(n),e.appendChild(i("span","","· "+l("web.input.esc"))),appendTo(t,e);const r=Date.now();o.busyTimer=setInterval(()=>{if(!e.parentNode){clearInterval(o.busyTimer),o.busyTimer=null;return}n.textContent="· "+Math.round((Date.now()-r)/1e3)+"s"},1e3)}export function flushRun(){if(o.runCount<=0){y();return}if(T()==="quiet"&&o.runReconOnly&&o.runFails===0&&o.runCount>1){const t=o.runNodes.slice();t.forEach(r=>r.classList.add("fold-out")),window.setTimeout(()=>t.forEach(r=>r.remove()),160);const e=i("div","grouped");e.appendChild(i("span","pipe","│"));const n=x(o.runDuration);e.appendChild(document.createTextNode(" "+w("web.action.actions",o.runCount)+" ✓"+(n?" · "+n:""))),appendTo(liveFeed(),e)}y()}function y(){o.runCount=0,o.runFails=0,o.runReconOnly=!0,o.runNodes=[],o.runDuration=0}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{el as
|
|
1
|
+
import{el as a}from"../dom.js";import{t as n}from"../i18n.js";import{categoryOf as c,labelOf as f,argText as u,formatMs as C}from"../format.js";import{renderMarkdown as m}from"../../md.js";import{api as g}from"../api.js";import{imageCard as k}from"./image-card.js";import{feedHasContent as r,clearEmpty as x,scrollToBottom as h,activeFeed as v,liveFeed as w,mdOpts as A,buildThinkBlock as I,appendActionsRow as L}from"./core.js";function T(i,e){const s=String(e??"");if(!s.trim())return;const o=m(i,s,A());L(i,o.innerText||o.textContent||"",s)}function H(i,e){const{wrap:s,body:o}=I(!1,!1);o.textContent=e==null?"":String(e),i.appendChild(s)}function F(i,e,s){const o=a("div","act "+c(e.name));o.appendChild(a("span","g","◇")),o.appendChild(a("span","lab",f(e.name)));const l=u(e.args);l&&(o.appendChild(a("span","sep","·")),o.appendChild(a("span","args",l)));const t=a("span","ok","");o.appendChild(t),i.appendChild(o),e.toolCallId&&s.set(e.toolCallId,t)}function S(i,e,s){const o=C(e.duration),l=(e.success?" ✓":" ✗")+(o?" "+o:""),t=e.toolCallId?s.get(e.toolCallId):null;if(t)t.textContent=l,e.success||t.classList.add("fail"),s.delete(e.toolCallId);else{const d=a("div","act "+c(e.tool));d.appendChild(a("span","g","↳")),d.appendChild(a("span","lab",f(e.tool))),d.appendChild(a("span","ok"+(e.success?"":" fail"),l)),i.appendChild(d)}if(e.success&&Array.isArray(e.images)&&e.images.length)for(const d of e.images){const p=k(String(e.tool||""),String(d));p&&i.appendChild(p)}}function B(i,e){const s=new Map;e.forEach(o=>{if(!(!o||typeof o.kind!="string"))switch(o.kind){case"user":i.appendChild(a("div","u",o.text||""));break;case"assistant":T(i,o.text||"");break;case"reasoning":H(i,o.text||"");break;case"tool_call":F(i,o,s);break;case"tool_result":S(i,o,s);break;case"plan":o.text&&i.appendChild(a("div","sysline","▸ "+o.text));break;case"context":o.text&&i.appendChild(a("div","detail","↳ "+o.text));break;case"error":i.appendChild(a("div","errline","✗ "+(o.text||"")));break;case"system":o.text&&i.appendChild(a("div","sysline",o.text));break}})}export async function loadHistory(i){if(!i||i.historyLoaded||i.historyLoading)return{gone:!!i.dead};i.historyLoading=!0;const e=a("div","detail",n("web.history.loading"));r(i.feed)||(x(i.feed),i.feed.appendChild(e));const s=await g("/api/sessions/"+encodeURIComponent(i.id)+"/history");if(i.historyLoading=!1,e.remove(),i.historyLoaded=!0,i.historyFailed=!1,!s.ok||!s.data||!Array.isArray(s.data.history))return s.status===404?{gone:!0}:(i.historyFailed=!0,r(i.feed)||i.feed.appendChild(a("div","detail",n("web.history.unavailable"))),{gone:!1});r(i.feed)||(B(i.feed,s.data.history),s.data.history.length||i.feed.appendChild(a("div","detail",n("web.history.empty"))),i.feed===v()?h():i.feed===w()&&h())}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as r}from"../dom.js";import{t as d}from"../i18n.js";import{openLightbox as o}from"../lightbox.js";function c(e){return e==="attach_image"?d("web.card.attached_image"):d("web.card.browser_viewport")}function m(e,t){e.className="imgcard-missing",e.replaceChildren(),e.appendChild(document.createTextNode("◧ "+d("web.card.image_removed"))),e.appendChild(r("div","cap",t))}export function imageCard(e,t){if(!t)return null;const a=c(e),n=r("div","imgcard"),i=document.createElement("img");return i.className="imgthumb",i.alt="",i.loading="lazy",i.src=t,i.addEventListener("error",()=>m(n,a)),i.addEventListener("click",()=>o(t,a)),n.appendChild(i),n.appendChild(r("div","cap",a)),n}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{msgs as g,el as w,setIcon as k}from"../dom.js";import{t as v}from"../i18n.js";import{feed as t}from"../store.js";import{verbosity as y}from"../format.js";import{mountMarkdown as b}from"../../md.js";import{activeFeed as l,feedForEvent as d,clearBusy as f,clearEmpty as x,flushRun as M,showBusy as R,appendTo as m,scroll as a,mdOpts as A,buildThinkBlock as F}from"./core.js";let s="",c=null,p=!1;function h(){if(p=!1,!s||!t.curMd){s="",c=null;return}const n=s,o=c;s="",c=null,t.curMd.write(n),o&&o===l()&&a()}function L(){p||(p=!0,typeof window<"u"&&typeof window.requestAnimationFrame=="function"?window.requestAnimationFrame(h):h())}export function finishMd(){h(),t.curMd&&(t.curMd.root.classList.remove("streaming"),t.curMd.end(),t.curMd=null),t.curText=null}export function onText(n,o){const e=d(o);f(e),e&&(x(e),t.curThink&&finishThink(),t.curText==null&&(M(),t.curText="",t.curMd=b(e,A(!0)),t.curMd.root.classList.add("streaming"),t.turnRoots.push(t.curMd.root)),t.curText+=n,t.turnMd+=n,c&&c!==e&&h(),c=e,s+=n,L())}export function finishThink(){if(t.curThink&&(t.curThink.wrap&&t.curThink.wrap.classList.remove("live"),t.curThink.startedAt)){const n=t.curThink.head.querySelector(".dur");n&&(n.textContent="· "+((Date.now()-t.curThink.startedAt)/1e3).toFixed(1)+"s")}t.curThink=null}export function onReasoning(n,o){const e=d(o);if(f(e),!!e){if(x(e),finishMd(),!t.curThink){M();const{wrap:r,head:i,body:u}=F(!0);m(e,r),t.curThink={wrap:r,head:i,body:u,startedAt:Date.now()}}t.curThink.body.textContent+=n,e===l()&&a()}}export function onMeta(n,o,e){if(e==="tool"&&y()==="quiet")return;const r=d(o);f(r);const i=(n||"").trim();if(!r||!i)return;x(r),finishMd();const u=i.indexOf("⚠")!==-1||i.indexOf("✗")!==-1;m(r,w("div",u?"metaln warn":"metaln",i)),r===l()&&a()}export function onRetract(n,o){const e=d(o);if(!e)return;f(e);const r=t.curMd?t.curMd.root:null,i=!!r||t.curText!=null&&t.curText!=="",u=t.curText?t.curText.length:0;if(finishMd(),finishThink(),r){const T=t.turnRoots.indexOf(r);T!==-1&&t.turnRoots.splice(T,1),r.remove()}u>0&&(t.turnMd=t.turnMd.slice(0,Math.max(0,t.turnMd.length-u))),i&&(n&&m(e,w("div","metaln",n)),e===l()&&a())}export function onPhase(n,o){const e=d(o);n==="thinking"?R(e):f(e)}g
|
|
1
|
+
import{msgs as g,el as w,setIcon as k}from"../dom.js";import{t as v}from"../i18n.js";import{feed as t}from"../store.js";import{verbosity as y}from"../format.js";import{mountMarkdown as b}from"../../md.js";import{activeFeed as l,feedForEvent as d,clearBusy as f,clearEmpty as x,flushRun as M,showBusy as R,appendTo as m,scroll as a,mdOpts as A,buildThinkBlock as F}from"./core.js";let s="",c=null,p=!1;function h(){if(p=!1,!s||!t.curMd){s="",c=null;return}const n=s,o=c;s="",c=null,t.curMd.write(n),o&&o===l()&&a()}function L(){p||(p=!0,typeof window<"u"&&typeof window.requestAnimationFrame=="function"?window.requestAnimationFrame(h):h())}export function finishMd(){h(),t.curMd&&(t.curMd.root.classList.remove("streaming"),t.curMd.end(),t.curMd=null),t.curText=null}export function onText(n,o){const e=d(o);f(e),e&&(x(e),t.curThink&&finishThink(),t.curText==null&&(M(),t.curText="",t.curMd=b(e,A(!0)),t.curMd.root.classList.add("streaming"),t.turnRoots.push(t.curMd.root)),t.curText+=n,t.turnMd+=n,c&&c!==e&&h(),c=e,s+=n,L())}export function finishThink(){if(t.curThink&&(t.curThink.wrap&&t.curThink.wrap.classList.remove("live"),t.curThink.startedAt)){const n=t.curThink.head.querySelector(".dur");n&&(n.textContent="· "+((Date.now()-t.curThink.startedAt)/1e3).toFixed(1)+"s")}t.curThink=null}export function onReasoning(n,o){const e=d(o);if(f(e),!!e){if(x(e),finishMd(),!t.curThink){M();const{wrap:r,head:i,body:u}=F(!0);m(e,r),t.curThink={wrap:r,head:i,body:u,startedAt:Date.now()}}t.curThink.body.textContent+=n,e===l()&&a()}}export function onMeta(n,o,e){if(e==="tool"&&y()==="quiet")return;const r=d(o);f(r);const i=(n||"").trim();if(!r||!i)return;x(r),finishMd();const u=i.indexOf("⚠")!==-1||i.indexOf("✗")!==-1;m(r,w("div",u?"metaln warn":"metaln",i)),r===l()&&a()}export function onRetract(n,o){const e=d(o);if(!e)return;f(e);const r=t.curMd?t.curMd.root:null,i=!!r||t.curText!=null&&t.curText!=="",u=t.curText?t.curText.length:0;if(finishMd(),finishThink(),r){const T=t.turnRoots.indexOf(r);T!==-1&&t.turnRoots.splice(T,1),r.remove()}u>0&&(t.turnMd=t.turnMd.slice(0,Math.max(0,t.turnMd.length-u))),i&&(n&&m(e,w("div","metaln",n)),e===l()&&a())}export function onPhase(n,o){const e=d(o);n==="thinking"?R(e):f(e)}g?.addEventListener("click",n=>{const e=n.target.closest(".think-h");if(!e)return;const r=e.nextElementSibling;if(!r)return;const i=r.classList.toggle("hidden");e.setAttribute("aria-expanded",i?"false":"true");const u=e.querySelector(".tog");u&&k(u,i?"chevron-right":"chevron-down",v(i?"web.action.show":"web.action.hide"))});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{el as r,icon as w,announce as g}from"../dom.js";import{t as
|
|
2
|
-
`).length>12){
|
|
1
|
+
import{el as r,icon as w,announce as g}from"../dom.js";import{t as d,pluralCount as _}from"../i18n.js";import{feed as c,tabs as k,session as m}from"../store.js";import{FILE_TOOLS as x,OPENABLE_TOOLS as F,LINK_TOOLS as B,categoryOf as y,labelOf as I,argText as U,formatMs as S,verbosity as b,firstOutputLine as L}from"../format.js";import{copyText as q}from"../../md.js";import{imageCard as P}from"./image-card.js";import{activeFeed as O,liveFeed as j,feedForEvent as a,clearBusy as T,clearEmpty as N,appendTo as h,insertAfter as E,appendActionsRow as D,flushRun as $}from"./core.js";import{finishMd as M,finishThink as R}from"./stream.js";export function onToolStart(e){const n=a(e.sessionId);if(T(n),!n)return;N(n),M(),R(),c.pendingArgs.set(e.toolCallId,e.args||{});const o=r("div","act "+y(e.name));o.appendChild(r("span","g","◇")),o.appendChild(r("span","lab",I(e.name)));const s=U(e.args);s&&(o.appendChild(r("span","sep","·")),o.appendChild(r("span","args",s)));const i=r("span","ok","");o.appendChild(i),o.classList.add("running"),h(n,o),c.toolNodes.set(e.toolCallId,{status:i,line:o}),y(e.name)!=="recon"&&(c.runReconOnly=!1),c.runCount++}function A(e,n){if(typeof n!="string"||!n)return;const o=r("div","toolout"),s=r("div","code");if(s.textContent=n,o.appendChild(s),n.length>600||n.split(`
|
|
2
|
+
`).length>12){o.classList.add("collapsed");const p="▸ "+_("web.tool.output",n.length),l=r("span","more",p);l.addEventListener("click",()=>{const u=o.classList.toggle("collapsed");l.textContent=u?p:"▾ "+d("web.tool.collapse")}),o.appendChild(l)}const t=e&&e.parentNode?null:j();e&&e.parentNode?e.parentNode.insertBefore(o,e.nextSibling):h(t,o)}function K(e){if(typeof e!="string"||!e)return null;try{const n=new URL(e,location.href);if(n.protocol==="http:"||n.protocol==="https:"||n.protocol==="file:")return n.href}catch{return null}return null}function z(e){const n=String(e??"").replace(/\\/g,"/");try{const o=m&&m.host&&m.host.workspace?String(m.host.workspace).replace(/\\/g,"/").replace(/\/+$/,""):"";if(o&&(n===o||n.indexOf(o+"/")===0)){const s=n===o?"":n.slice(o.length+1);if(s)return s}}catch{}return n}function C(e,n,o,s){const i=a(o);if(!i)return null;if(x.indexOf(e)!==-1){const t=n.path||n.file||n.dir;if(!t)return null;const p=z(t),l=r("div","filerow "+y(e));if(l.appendChild(r("span","g","◇")),l.appendChild(r("span","lab",I(e))),l.appendChild(r("span","sep"," · ")),F.indexOf(e)!==-1){const f=r("a","path",p||String(t));f.href="/api/file?path="+encodeURIComponent(String(t)),f.target="_blank",f.rel="noopener noreferrer",f.title=d("web.card.open_title")+" · "+String(t),l.appendChild(f)}else{const f=r("span","tail",p||String(t));f.title=String(t),l.appendChild(f)}const u=r("button","copy-btn");return u.type="button",u.title=d("web.card.copy_title"),u.setAttribute("aria-label",d("web.card.copy_title")),u.appendChild(w("copy")),u.addEventListener("click",()=>{q(String(t)).then(f=>{if(u.replaceChildren(w(f?"check":"copy")),!f){const v=l.querySelector(".st");v&&(v.textContent=" ⚠")}window.setTimeout(()=>u.replaceChildren(w("copy")),1400)})}),l.appendChild(u),l.appendChild(r("span","st",s===!1?" ✗":s===!0?" ✓":"")),s===!1&&(l.dataset.fail="1"),/\.drawio(\.xml)?$/i.test(String(t))&&b()==="verbose"&&l.appendChild(r("span","detail","↳ "+d("web.card.drawio_hint"))),h(i,l),l}if(B.indexOf(e)!==-1&&n.url){const t=r("div","linkline");t.appendChild(document.createTextNode("↳ "));const p=K(n.url);if(p){const l=r("a","",n.url);l.href=p,l.target="_blank",l.rel="noopener noreferrer",t.appendChild(l);try{const u=new URL(p).hostname;u&&t.appendChild(r("span","dom"," · "+u))}catch{}}else t.appendChild(r("span","",n.url));return h(i,t),t}return null}function G(e){if(!e.success||!Array.isArray(e.images)||!e.images.length)return;const n=a(e.sessionId);if(n)for(const o of e.images){const s=P(String(e.name||""),String(o));s&&h(n,s)}}export function onToolEnd(e){H(e),G(e)}function H(e){const n=c.toolNodes.get(e.toolCallId),o=n?n.line:null;if(n){n.line.classList.remove("running");const t=S(e.durationMs);n.status.textContent=e.success?" ✓"+(t?" "+t:""):" ✗"+(t?" "+t:""),e.success||(n.status.classList.add("fail"),c.runFails++,c.runReconOnly=!1)}c.toolNodes.delete(e.toolCallId);const s=c.pendingArgs.get(e.toolCallId)||{};c.pendingArgs.delete(e.toolCallId);const i=s.path||s.file||s.dir;if(x.indexOf(e.name)!==-1&&i){if(o&&o.parentNode&&o.remove(),b()==="quiet"){if(e.success){const p=C(e.name,s,e.sessionId,e.success);p&&c.runNodes.push(p),c.runDuration+=typeof e.durationMs=="number"?e.durationMs:0}else{const p=C(e.name,s,e.sessionId,e.success),l=L(e.output);l&&E(p||o,r("div","detail","↳ "+l)),p&&c.runNodes.push(p)}return}const t=C(e.name,s,e.sessionId,e.success);A(t||o,e.output);return}if(b()==="quiet"){if(e.success){o&&c.runNodes.push(o);const t=C(e.name,s,e.sessionId,e.success);t&&c.runNodes.push(t),c.runDuration+=typeof e.durationMs=="number"?e.durationMs:0}else{const t=L(e.output);t&&E(o,r("div","detail","↳ "+t))}return}e.success&&C(e.name,s,e.sessionId,e.success),A(o,e.output)}export function onTurnEnd(e){m.busy=!1;const n=a(e.sessionId);T(n),R(),M(),$(),c.toolNodes.forEach(i=>{i&&i.line&&n&&i.line.parentNode===n&&i.line.classList.remove("running")});const o=k.tabs.find(i=>i.id===e.sessionId);if(o&&(o.planCard=null),!n){resetTurnText();return}if(e.success===!1)e.interrupted?(h(n,r("div","warnline","⚠ "+d("web.turn.stopped"))),g(d("web.turn.stopped"))):(h(n,r("div","errline","✗ "+d("web.turn.failed"))),g(d("web.turn.failed")));else{const i=[];typeof e.toolCalls=="number"&&e.toolCalls>0&&i.push(d("web.turn.tools",{count:e.toolCalls})),typeof e.durationMs=="number"&&i.push(S(e.durationMs)),i.length&&h(n,r("div","metric","⟡ "+i.join(" · "))),g(d("web.turn.end",{count:e.toolCalls||0}))}const s=c.turnRoots.map(i=>i.innerText||i.textContent||"").join(`
|
|
3
3
|
|
|
4
|
-
`);D(n,s,c.turnMd),resetTurnText()}export function resetTurnText(){c.turnMd="",c.turnRoots=[]}export function onErrorEvent(e){if(!e||!e.error)return;const n=
|
|
5
|
-
`).forEach(s=>
|
|
4
|
+
`);D(n,s,c.turnMd),resetTurnText()}export function resetTurnText(){c.turnMd="",c.turnRoots=[]}export function onErrorEvent(e){if(!e||!e.error)return;const n=a(e.sessionId);n&&h(n,r("div","errline","✗ "+e.error)),g(String(e.error))}export function onCommandOutput(e,n){const o=a(n)||O();o&&(N(o),String(e).split(`
|
|
5
|
+
`).forEach(s=>h(o,r("div","cmdout",s))))}export function onLog(e){if(!e||typeof e.text!="string"||!e.text||e.diagnostic&&b()!=="verbose")return;const n=a(e.sessionId)||O();if(!n)return;const o=e.level,s=o==="error"?"errline":o==="warn"?"warnline":"detail",i=o==="error"?"✗ ":o==="warn"?"⚠ ":"↳ ",t=r("div",s);t.textContent=i+e.text,h(n,t),(o==="error"||o==="warn")&&g(e.text)}
|
package/dist/assets/js/format.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{t as c}from"./i18n.js";import{settings as f}from"./store.js";export const CATEGORIES={recon:["read_file","list_dir","glob","grep","file_info","project_map","chunk_query","web_search","web_fetch","history","recall","process_list","process_log"],mutate:["write_file","edit_file","create_dir","delete_file","move_file","attach_image"],execute:["bash","process_kill","pipeline_run","browser","download_file","subagent","mcp_call"],meta:["plan","plan_step","todo","verify","lsp_check","enable_tools","set_thinking","load_skill","remember"]},FILE_TOOLS=["read_file","write_file","edit_file","list_dir","delete_file","move_file","file_info"],OPENABLE_TOOLS=["read_file","write_file","edit_file","file_info"],
|
|
2
|
-
`)){const r=t.trim();if(r)return r.length>200?r.slice(0,197)+"…":r}return""}export function matchesQuery(e,t){const r=String(t??"").trim().toLowerCase();return r?String(e??"").toLowerCase().indexOf(r)!==-1:!0}export function relTime(e){if(!e)return"";const t=Date.now()-new Date(e).getTime();if(!isFinite(t)||t<0)return"";const r=Math.floor(t/6e4);if(r<1)return"now";if(r<60)return r+"m";const
|
|
1
|
+
import{t as c}from"./i18n.js";import{settings as f}from"./store.js";export const CATEGORIES={recon:["read_file","list_dir","glob","grep","file_info","project_map","chunk_query","web_search","web_fetch","history","recall","process_list","process_log"],mutate:["write_file","edit_file","create_dir","delete_file","move_file","attach_image"],execute:["bash","process_kill","pipeline_run","browser","download_file","subagent","mcp_call"],meta:["plan","plan_step","todo","verify","lsp_check","enable_tools","set_thinking","load_skill","remember"]},FILE_TOOLS=["read_file","write_file","edit_file","list_dir","delete_file","move_file","file_info"],OPENABLE_TOOLS=["read_file","write_file","edit_file","file_info"],LINK_TOOLS=["web_fetch","download_file"];export function categoryOf(e){for(const t of Object.keys(CATEGORIES))if(CATEGORIES[t].indexOf(e)!==-1)return t;return"meta"}export function labelOf(e){const t="tool.friendly."+e,r=c(t);if(r!==t)return r;const n=String(e).replace(/_/g," ");return n.charAt(0).toUpperCase()+n.slice(1)}export function argText(e){if(!e||typeof e!="object")return"";const t=e,r=["path","file","dir","command","query","url","pattern","name","id","text","prompt"];for(const i of r)if(typeof t[i]=="string"&&t[i])return t[i];const n=Object.keys(t);if(!n.length)return"";const o=t[n[0]];if(typeof o=="string")return o;if(typeof o=="number"||typeof o=="boolean")return String(o);try{const i=JSON.stringify(e);return i==="{}"?"":i.slice(0,120)}catch{return""}}export function formatMs(e){return typeof e!="number"||!isFinite(e)?"":e>=1e3?(e/1e3).toFixed(1)+"s":Math.round(e)+"ms"}export function verbosity(){const e=f.config&&f.config.ui||{};return e.verbosity?e.verbosity:e.verbose?"verbose":"quiet"}export function firstOutputLine(e){if(typeof e!="string"||!e)return"";for(const t of e.split(`
|
|
2
|
+
`)){const r=t.trim();if(r)return r.length>200?r.slice(0,197)+"…":r}return""}export function matchesQuery(e,t){const r=String(t??"").trim().toLowerCase();return r?String(e??"").toLowerCase().indexOf(r)!==-1:!0}export function relTime(e){if(!e)return"";const t=Date.now()-new Date(e).getTime();if(!isFinite(t)||t<0)return"";const r=Math.floor(t/6e4);if(r<1)return"now";if(r<60)return r+"m";const n=Math.floor(r/60);return n<24?n+"h":Math.floor(n/24)+"d"}export function fmtTokens(e){return e>=1e3?(e/1e3).toFixed(1)+"K":String(e)}export function contextLabel(){const e=f.config&&f.config.contextWindow||0;return e?Math.round(e/1024)+"K":"—"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{el as r}from"./dom.js";import{t as c}from"./i18n.js";import{setIndicator as f,trapTab as h}from"./dialog.js";import{copyText as g}from"../md.js";let t=null,n=null,p=null,l=null,a=null,u=null;function m(){const e=r("div","lightbox");e.hidden=!0,e.setAttribute("role","dialog"),e.setAttribute("aria-modal","true");const o=r("button","lb-close","✕");o.type="button",o.title=c("web.lightbox.close"),o.setAttribute("aria-label",c("web.lightbox.close"));const d=r("figure","lb-figure");n=document.createElement("img"),n.className="lb-img",n.alt="",d.appendChild(n),p=r("figcaption","lb-cap"),d.appendChild(p);const b=r("div","lb-actions");return l=r("a","lb-open"),l.textContent=c("web.lightbox.open_tab"),l.target="_blank",l.rel="noopener noreferrer",a=r("button","lb-copy",c("web.lightbox.copy")),a.type="button",b.appendChild(l),b.appendChild(a),e.appendChild(o),e.appendChild(d),e.appendChild(b),o.addEventListener("click",closeLightbox),e.addEventListener("click",i=>{i.target===e&&closeLightbox()}),e.addEventListener("keydown",i=>{if(i.key==="Escape"){i.stopPropagation(),closeLightbox();return}h(e,i)}),a.addEventListener("click",()=>{const i=l?.href||"";g(i).then(s=>f(c("web.lightbox.copied"),!s))}),document.body.appendChild(e),e}export function openLightbox(e,o){if(!e||(t||(t=m()),!n||!p||!l||!a))return;n.src=e,p.textContent=o||"",p.hidden=!o,l.href=e,a.textContent=c("web.lightbox.copy"),u=document.activeElement,t.hidden=!1,t.classList.add("open");const d=t.querySelector(".lb-close");d&&d.focus()}export function closeLightbox(){!t||t.hidden||(t.hidden=!0,t.classList.remove("open"),n&&n.removeAttribute("src"),u&&u.focus&&u.focus(),u=null)}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{el as c,makeToggle as y}from"../dom.js";import{tagsEditor as u,checkboxEditor as g,tableEditor as b}from"./editors.js";export function validateJson(i){const e=String(i??"").trim();if(!e)return{ok:!1,error:"required"};try{return JSON.parse(e),{ok:!0}}catch(s){return{ok:!1,error:s instanceof Error?s.message:"invalid JSON"}}}function l(i,e){const s=c("input");return s.setAttribute("aria-label",i),s.value=e,s}export function controlFor(i,e,s){if(i.readOnly){const t=c("span","val dim",e==null?"—":String(e));return e!=null&&(t.title=String(e)),t}if(i.valueType==="bool")return y(!!e,t=>(s.post(t),!0));if(i.valueType==="enum"){const t=c("select");return t.setAttribute("aria-label",s.label),(i.enum||[]).forEach(n=>{const o=c("option","",s.enumLabel(n));o.value=n,n===e&&(o.selected=!0),t.appendChild(o)}),t.addEventListener("change",()=>s.post(t.value)),t}if(i.valueType==="int"){const t=l(s.label,e==null?"":String(e));return t.type="number",i.min!=null&&(t.min=String(i.min)),i.max!=null&&(t.max=String(i.max)),i.step!=null&&(t.step=String(i.step)),t.addEventListener("change",()=>s.post(t.value)),t}if(i.valueType==="share"){const t=l(s.label,e==null?"":Math.round(Number(e)*100)+"%");return t.addEventListener("change",()=>s.post(t.value)),t}const r=i.editor;if(r&&r.kind==="tags"&&(i.valueType==="list"||i.valueType==="json"))return u(e,s,r);if(r&&r.kind==="checkboxes")return g(e,s,r);if(r&&r.kind==="table")return b(e,s,r);if(i.valueType==="list"){const t=Array.isArray(e)?e.join(", "):e==null?"":String(e),n=l(s.label,t);return n.placeholder="a, b, c",n.addEventListener("change",()=>s.post(n.value)),n}if(i.valueType==="json"){const t=c("div","jsonctl"),n=c("textarea");n.setAttribute("aria-label",s.label),n.rows=3,n.value=e==null?"":JSON.stringify(e,null,2);const o=c("div","json-err");return o.hidden=!0,n.addEventListener("input",()=>{const d=validateJson(n.value);o.hidden=d.ok,o.textContent=d.ok?"":String(d.error||"invalid JSON")}),n.addEventListener("change",()=>{validateJson(n.value).ok?s.post(n.value.trim()):n.focus()}),t.appendChild(n),t.appendChild(o),t}const a=l(s.label,e==null?"":String(e));return a.addEventListener("change",()=>s.post(a.value)),a}export const PANEL_SECTIONS={general:[{id:"general.interface",titleKey:"web.settings.sec.general.interface",keys:["locale","ui.verbosity"]},{id:"general.agent",titleKey:"web.settings.sec.general.agent",descKey:"web.settings.sec.general.agent.desc",keys:["maxToolIterations","stuckThreshold","autoPlan","execution.autoAdvance"]},{id:"general.provider",titleKey:"web.settings.sec.general.provider",keys:["provider.fallback"]}],model:[{id:"model.tuning",titleKey:"web.settings.sec.model.tuning",descKey:"web.settings.sec.model.tuning.desc",keys:["provider.maxCompletionTokens","modelLoad.autoLoad","modelLoad.flashAttention","modelLoad.evalBatchSize","modelLoad.offloadKvCacheToGpu"]},{id:"model.capabilities",titleKey:"web.settings.sec.model.capabilities",descKey:"web.settings.sec.model.capabilities.desc",keys:["modelCapabilities"]}],context:[{id:"context.window",titleKey:"web.settings.sec.context.window",descKey:"web.settings.sec.context.window.desc",keys:["contextWindow","contextBudget.systemPrompt","contextBudget.responseReserve"]},{id:"context.compaction",titleKey:"web.settings.sec.context.compaction",descKey:"web.settings.sec.context.compaction.desc",keys:["contextBudget.compactionThreshold","contextBudget.compactionMinLoad","contextBudget.policy","contextBudget.compactionSummary","contextBudget.overflowCooldown","contextBudget.toolResultKeep","contextBudget.calibrationWarmup","contextBudget.ratioFloor"]},{id:"context.instructions",titleKey:"web.settings.sec.context.instructions",descKey:"web.settings.sec.context.instructions.desc",keys:["instructions.summarize"]},{id:"context.indexer",titleKey:"web.settings.sec.context.indexer",descKey:"web.settings.sec.context.indexer.desc",keys:["indexer.maxFiles","indexer.respectGitignore","indexer.mapTokenBudget"]},{id:"context.log",titleKey:"web.settings.sec.context.log",descKey:"web.settings.sec.context.log.desc",keys:["contextLog.enabled","contextLog.redact"]}],reasoning:[{id:"reasoning.display",titleKey:"web.settings.sec.reasoning.display",keys:["showReasoning"]},{id:"reasoning.effort",titleKey:"web.settings.sec.reasoning.effort",descKey:"web.settings.sec.reasoning.effort.desc",keys:["reasoning.mode","reasoning.min","reasoning.max","reasoning.baseline","reasoning.overrideCooldown"]}],agent:[{id:"agent.moe",titleKey:"web.settings.sec.agent.moe",descKey:"web.settings.sec.agent.moe.desc",keys:["moe.enabled","moe.maxReplanCycles","experts"]},{id:"agent.critic",titleKey:"web.settings.sec.agent.critic",descKey:"web.settings.sec.agent.critic.desc",keys:["critic.enabled","critic.model","critic.provider","critic.tools","critic.maxCalls","critic.maxRepairCycles","critic.timeoutMs"]},{id:"agent.tools",titleKey:"web.settings.sec.agent.tools",descKey:"web.settings.sec.agent.tools.desc",keys:["tools.enableOnDemand","tools.defaultTags","tools.grepEngine","skills.budget"]},{id:"agent.subagent",titleKey:"web.settings.sec.agent.subagent",descKey:"web.settings.sec.agent.subagent.desc",keys:["subagent.resultMode","subagent.maxSummaryChars","subagent.maxParallelChunkQueries","subagent.stableSystemPrompt","subagent.timeoutMs"]},{id:"agent.hallucination",titleKey:"web.settings.sec.agent.hallucination",descKey:"web.settings.sec.agent.hallucination.desc",keys:["hallucination.judge.enabled"]}],network:[{id:"network.web",titleKey:"web.settings.sec.network.web",descKey:"web.settings.sec.network.web.desc",keys:["webSearch.enabled"]},{id:"network.error",titleKey:"web.settings.sec.network.error",descKey:"web.settings.sec.network.error.desc",keys:["errorWebSearch.enabled","errorWebSearch.threshold","errorWebSearch.maxResults","errorWebSearch.maxQueryChars","errorWebSearch.maxSearchesPerSession","errorWebSearch.requestTimeoutMs"]}],browser:[{id:"browser.main",titleKey:"web.settings.sec.browser.main",keys:["browser.enabled","browser.headless"]},{id:"browser.limits",titleKey:"web.settings.sec.browser.limits",descKey:"web.settings.sec.browser.limits.desc",keys:["browser.maxElements","browser.maxContentChars","browser.maxConsoleEntries","browser.maxConsoleLineChars"]},{id:"browser.viewport",titleKey:"web.settings.sec.browser.viewport",keys:["browser.viewportWidth","browser.viewportHeight","browser.navigationTimeout"]}],sessions:[{id:"sessions.main",titleKey:"web.settings.sec.sessions.main",descKey:"web.settings.sec.sessions.main.desc",keys:["session.autoSave","session.autoName","session.maxSessions","session.isolateMemory"]},{id:"sessions.isolation",titleKey:"web.settings.sec.sessions.isolation",descKey:"web.settings.sec.sessions.isolation.desc",keys:["sessionIsolation.enabled","sessionIsolation.isolatePlugins","sessionIsolation.isolateTempFiles"]}],ui:[{id:"ui.chat",titleKey:"web.settings.sec.ui.chat",descKey:"web.settings.sec.ui.chat.desc",keys:["ui.fontSize","ui.activityRail","ui.spinner","ui.showContextStats","ui.showCompaction"]}],security:[{id:"security.switches",titleKey:"web.settings.sec.security.switches",descKey:"web.settings.sec.security.switches.desc",keys:["security.enabled","security.bash.enabled","security.bash.blockDangerousFlags","security.paths.enabled","security.contentScan.enabled","security.network.enabled","security.sessionEncryption.enabled"]},{id:"security.limits",titleKey:"web.settings.sec.security.limits",descKey:"web.settings.sec.security.limits.desc",keys:["security.maxRecursionDepth","security.maxFileOperations","security.rateLimits.maxRequestsPerMinute","security.rateLimits.maxParallelTasks","security.network.requestTimeout","security.network.maxResponseSize"]},{id:"security.bash",titleKey:"web.settings.sec.security.bash",descKey:"web.settings.sec.security.bash.desc",keys:["security.bash.blacklist","security.bash.whitelist","security.bash.dangerousFlags","security.bash.dangerousOperators"]},{id:"security.paths",titleKey:"web.settings.sec.security.paths",descKey:"web.settings.sec.security.paths.desc",keys:["security.paths.denied","security.paths.allowed"]},{id:"security.network",titleKey:"web.settings.sec.security.network",descKey:"web.settings.sec.security.network.desc",keys:["security.network.deniedDomains","security.network.allowedDomains"]},{id:"security.scan",titleKey:"web.settings.sec.security.scan",descKey:"web.settings.sec.security.scan.desc",keys:["security.contentScan.dangerousPatterns"]},{id:"security.audit",titleKey:"web.settings.sec.security.audit",descKey:"web.settings.sec.security.audit.desc",keys:["security.auditNotifier.enabled","security.auditNotifier.filePath","security.auditNotifier.webhookUrl","security.auditNotifier.webhookTimeout","security.auditNotifier.minSeverity","security.auditNotifier.maxRetries","security.auditNotifier.eventTypes"]},{id:"security.encryption",titleKey:"web.settings.sec.security.encryption",descKey:"web.settings.sec.security.encryption.desc",keys:["security.sessionEncryption.encryptHistory","security.sessionEncryption.encryptSessionLog","security.sessionEncryption.keyPath"]}],advanced:[{id:"advanced.diagnostics",titleKey:"web.settings.sec.advanced.diagnostics",descKey:"web.settings.sec.advanced.diagnostics.desc",keys:["logLevel","version"]},{id:"advanced.retry",titleKey:"web.settings.sec.advanced.retry",descKey:"web.settings.sec.advanced.retry.desc",keys:["retry.maxRetries","retry.baseDelay","retry.maxDelay","retry.maxStreamRetries","retry.noDataTimeoutMs"]},{id:"advanced.service",titleKey:"web.settings.sec.advanced.service",descKey:"web.settings.sec.advanced.service.desc",keys:["pricing.enabled","pricing.overrides","updater.enabled","updater.checkOnStart","updater.autoInstall","updater.intervalMs"]}],plugins:[{id:"plugins.lsp",titleKey:"web.settings.sec.plugins.lsp",descKey:"web.settings.sec.plugins.lsp.desc",keys:["lsp.enabled","lsp.offline"]}]};export function keyToPanel(){const i=new Map;for(const[e,s]of Object.entries(PANEL_SECTIONS))for(const r of s)for(const a of r.keys)i.set(a,e);return i}
|
|
1
|
+
import{el as a,makeToggle as g}from"../dom.js";import{tagsEditor as b,checkboxEditor as p,tableEditor as w}from"./editors.js";export function validateJson(i){const e=String(i??"").trim();if(!e)return{ok:!1,error:"required"};try{return JSON.parse(e),{ok:!0}}catch(s){return{ok:!1,error:s instanceof Error?s.message:"invalid JSON"}}}function u(i,e){const s=a("input");return s.setAttribute("aria-label",i),s.value=e,s}function m(i,e,s){const l=s.optionsSource==="providers"?e.providerOptions||[]:e.modelOptions||[],t=typeof i=="string"?i:"";if(!l.length){const o=u(e.label,t);return o.addEventListener("change",()=>e.post(o.value)),o}const n=a("select");n.setAttribute("aria-label",e.label);const c=a("option","",e.emptyLabel||"—");c.value="",n.appendChild(c);const d=new Set([""]);if(l.forEach(o=>{if(d.has(o))return;d.add(o);const y=a("option","",o);y.value=o,o===t&&(y.selected=!0),n.appendChild(y)}),t&&!d.has(t)){const o=a("option","",t);o.value=t,o.selected=!0,n.appendChild(o)}return n.value=t||"",n.addEventListener("change",()=>e.post(n.value)),n}export function controlFor(i,e,s){if(i.readOnly){const t=a("span","val dim",e==null?"—":String(e));return e!=null&&(t.title=String(e)),t}if(i.valueType==="bool")return g(!!e,t=>(s.post(t),!0));if(i.valueType==="enum"){const t=a("select");return t.setAttribute("aria-label",s.label),(i.enum||[]).forEach(n=>{const c=a("option","",s.enumLabel(n));c.value=n,n===e&&(c.selected=!0),t.appendChild(c)}),t.addEventListener("change",()=>s.post(t.value)),t}if(i.valueType==="int"){const t=u(s.label,e==null?"":String(e));return t.type="number",i.min!=null&&(t.min=String(i.min)),i.max!=null&&(t.max=String(i.max)),i.step!=null&&(t.step=String(i.step)),t.addEventListener("change",()=>s.post(t.value)),t}if(i.valueType==="share"){const t=u(s.label,e==null?"":Math.round(Number(e)*100)+"%");return t.addEventListener("change",()=>s.post(t.value)),t}const r=i.editor;if(r&&r.kind==="select")return m(e,s,r);if(r&&r.kind==="tags"&&(i.valueType==="list"||i.valueType==="json"))return b(e,s,r);if(r&&r.kind==="checkboxes")return p(e,s,r);if(r&&r.kind==="table")return w(e,s,r);if(i.valueType==="list"){const t=Array.isArray(e)?e.join(", "):e==null?"":String(e),n=u(s.label,t);return n.placeholder="a, b, c",n.addEventListener("change",()=>s.post(n.value)),n}if(i.valueType==="json"){const t=a("div","jsonctl"),n=a("textarea");n.setAttribute("aria-label",s.label),n.rows=3,n.value=e==null?"":JSON.stringify(e,null,2);const c=a("div","json-err");return c.hidden=!0,n.addEventListener("input",()=>{const d=validateJson(n.value);c.hidden=d.ok,c.textContent=d.ok?"":String(d.error||"invalid JSON")}),n.addEventListener("change",()=>{validateJson(n.value).ok?s.post(n.value.trim()):n.focus()}),t.appendChild(n),t.appendChild(c),t}const l=u(s.label,e==null?"":String(e));return l.addEventListener("change",()=>s.post(l.value)),l}export const PANEL_SECTIONS={general:[{id:"general.interface",titleKey:"web.settings.sec.general.interface",keys:["locale","ui.verbosity"]},{id:"general.agent",titleKey:"web.settings.sec.general.agent",descKey:"web.settings.sec.general.agent.desc",keys:["maxToolIterations","stuckThreshold","autoPlan","execution.autoAdvance"]},{id:"general.provider",titleKey:"web.settings.sec.general.provider",keys:["provider.fallback"]}],model:[{id:"model.tuning",titleKey:"web.settings.sec.model.tuning",descKey:"web.settings.sec.model.tuning.desc",keys:["provider.maxCompletionTokens","modelLoad.autoLoad","modelLoad.flashAttention","modelLoad.evalBatchSize","modelLoad.offloadKvCacheToGpu"]},{id:"model.capabilities",titleKey:"web.settings.sec.model.capabilities",descKey:"web.settings.sec.model.capabilities.desc",keys:["modelCapabilities"]}],context:[{id:"context.window",titleKey:"web.settings.sec.context.window",descKey:"web.settings.sec.context.window.desc",keys:["contextWindow","contextBudget.systemPrompt","contextBudget.responseReserve"]},{id:"context.compaction",titleKey:"web.settings.sec.context.compaction",descKey:"web.settings.sec.context.compaction.desc",keys:["contextBudget.compactionThreshold","contextBudget.compactionMinLoad","contextBudget.policy","contextBudget.compactionSummary","contextBudget.overflowCooldown","contextBudget.toolResultKeep","contextBudget.calibrationWarmup","contextBudget.ratioFloor"]},{id:"context.instructions",titleKey:"web.settings.sec.context.instructions",descKey:"web.settings.sec.context.instructions.desc",keys:["instructions.summarize"]},{id:"context.indexer",titleKey:"web.settings.sec.context.indexer",descKey:"web.settings.sec.context.indexer.desc",keys:["indexer.maxFiles","indexer.respectGitignore","indexer.mapTokenBudget"]},{id:"context.log",titleKey:"web.settings.sec.context.log",descKey:"web.settings.sec.context.log.desc",keys:["contextLog.enabled","contextLog.redact"]}],reasoning:[{id:"reasoning.display",titleKey:"web.settings.sec.reasoning.display",keys:["showReasoning"]},{id:"reasoning.effort",titleKey:"web.settings.sec.reasoning.effort",descKey:"web.settings.sec.reasoning.effort.desc",keys:["reasoning.mode","reasoning.min","reasoning.max","reasoning.baseline","reasoning.overrideCooldown"]}],agent:[{id:"agent.moe",titleKey:"web.settings.sec.agent.moe",descKey:"web.settings.sec.agent.moe.desc",keys:["moe.enabled","moe.maxReplanCycles","orchestrator.model","orchestrator.provider","orchestrator.contextWindow","experts"]},{id:"agent.critic",titleKey:"web.settings.sec.agent.critic",descKey:"web.settings.sec.agent.critic.desc",keys:["critic.enabled","critic.model","critic.provider","critic.tools","critic.maxCalls","critic.maxRepairCycles","critic.timeoutMs"]},{id:"agent.tools",titleKey:"web.settings.sec.agent.tools",descKey:"web.settings.sec.agent.tools.desc",keys:["tools.enableOnDemand","tools.defaultTags","tools.grepEngine","skills.budget"]},{id:"agent.subagent",titleKey:"web.settings.sec.agent.subagent",descKey:"web.settings.sec.agent.subagent.desc",keys:["subagent.resultMode","subagent.maxSummaryChars","subagent.maxParallelChunkQueries","subagent.stableSystemPrompt","subagent.timeoutMs"]},{id:"agent.hallucination",titleKey:"web.settings.sec.agent.hallucination",descKey:"web.settings.sec.agent.hallucination.desc",keys:["hallucination.judge.enabled"]}],network:[{id:"network.web",titleKey:"web.settings.sec.network.web",descKey:"web.settings.sec.network.web.desc",keys:["webSearch.enabled"]},{id:"network.error",titleKey:"web.settings.sec.network.error",descKey:"web.settings.sec.network.error.desc",keys:["errorWebSearch.enabled","errorWebSearch.threshold","errorWebSearch.maxResults","errorWebSearch.maxQueryChars","errorWebSearch.maxSearchesPerSession","errorWebSearch.requestTimeoutMs"]}],browser:[{id:"browser.main",titleKey:"web.settings.sec.browser.main",keys:["browser.enabled","browser.headless"]},{id:"browser.limits",titleKey:"web.settings.sec.browser.limits",descKey:"web.settings.sec.browser.limits.desc",keys:["browser.maxElements","browser.maxContentChars","browser.maxConsoleEntries","browser.maxConsoleLineChars"]},{id:"browser.viewport",titleKey:"web.settings.sec.browser.viewport",keys:["browser.viewportWidth","browser.viewportHeight","browser.navigationTimeout"]}],sessions:[{id:"sessions.main",titleKey:"web.settings.sec.sessions.main",descKey:"web.settings.sec.sessions.main.desc",keys:["session.autoSave","session.autoName","session.maxSessions","session.isolateMemory"]},{id:"sessions.isolation",titleKey:"web.settings.sec.sessions.isolation",descKey:"web.settings.sec.sessions.isolation.desc",keys:["sessionIsolation.enabled","sessionIsolation.isolatePlugins","sessionIsolation.isolateTempFiles"]}],ui:[{id:"ui.chat",titleKey:"web.settings.sec.ui.chat",descKey:"web.settings.sec.ui.chat.desc",keys:["ui.fontSize","ui.activityRail","ui.spinner","ui.showContextStats","ui.showCompaction"]},{id:"ui.images",titleKey:"web.settings.sec.ui.images",descKey:"web.settings.sec.ui.images.desc",keys:["images.maxCount","images.maxBytes"]}],security:[{id:"security.switches",titleKey:"web.settings.sec.security.switches",descKey:"web.settings.sec.security.switches.desc",keys:["security.enabled","security.bash.enabled","security.bash.blockDangerousFlags","security.paths.enabled","security.contentScan.enabled","security.network.enabled","security.sessionEncryption.enabled"]},{id:"security.limits",titleKey:"web.settings.sec.security.limits",descKey:"web.settings.sec.security.limits.desc",keys:["security.maxRecursionDepth","security.maxFileOperations","security.rateLimits.maxRequestsPerMinute","security.rateLimits.maxParallelTasks","security.network.requestTimeout","security.network.maxResponseSize"]},{id:"security.bash",titleKey:"web.settings.sec.security.bash",descKey:"web.settings.sec.security.bash.desc",keys:["security.bash.blacklist","security.bash.whitelist","security.bash.dangerousFlags","security.bash.dangerousOperators"]},{id:"security.paths",titleKey:"web.settings.sec.security.paths",descKey:"web.settings.sec.security.paths.desc",keys:["security.paths.denied","security.paths.allowed"]},{id:"security.network",titleKey:"web.settings.sec.security.network",descKey:"web.settings.sec.security.network.desc",keys:["security.network.deniedDomains","security.network.allowedDomains"]},{id:"security.scan",titleKey:"web.settings.sec.security.scan",descKey:"web.settings.sec.security.scan.desc",keys:["security.contentScan.dangerousPatterns"]},{id:"security.audit",titleKey:"web.settings.sec.security.audit",descKey:"web.settings.sec.security.audit.desc",keys:["security.auditNotifier.enabled","security.auditNotifier.filePath","security.auditNotifier.webhookUrl","security.auditNotifier.webhookTimeout","security.auditNotifier.minSeverity","security.auditNotifier.maxRetries","security.auditNotifier.eventTypes"]},{id:"security.encryption",titleKey:"web.settings.sec.security.encryption",descKey:"web.settings.sec.security.encryption.desc",keys:["security.sessionEncryption.encryptHistory","security.sessionEncryption.encryptSessionLog","security.sessionEncryption.keyPath"]}],advanced:[{id:"advanced.diagnostics",titleKey:"web.settings.sec.advanced.diagnostics",descKey:"web.settings.sec.advanced.diagnostics.desc",keys:["logLevel","version"]},{id:"advanced.retry",titleKey:"web.settings.sec.advanced.retry",descKey:"web.settings.sec.advanced.retry.desc",keys:["retry.maxRetries","retry.baseDelay","retry.maxDelay","retry.maxStreamRetries","retry.noDataTimeoutMs"]},{id:"advanced.service",titleKey:"web.settings.sec.advanced.service",descKey:"web.settings.sec.advanced.service.desc",keys:["pricing.enabled","pricing.overrides","updater.enabled","updater.checkOnStart","updater.autoInstall","updater.intervalMs"]}],plugins:[{id:"plugins.lsp",titleKey:"web.settings.sec.plugins.lsp",descKey:"web.settings.sec.plugins.lsp.desc",keys:["lsp.enabled","lsp.offline"]}]};export function keyToPanel(){const i=new Map;for(const[e,s]of Object.entries(PANEL_SECTIONS))for(const r of s)for(const l of r.keys)i.set(l,e);return i}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{el as l}from"../dom.js";import{t as
|
|
1
|
+
import{el as l}from"../dom.js";import{t as q}from"../i18n.js";export function tagsEditor(f,i,A){const r=Array.isArray(f)?f.map(String):[],u=l("div","tagsctl ctl-block"),d=l("div","tags-list"),k=()=>i.post(JSON.stringify(r)),s=()=>{d.textContent="",r.forEach((o,O)=>{const $=l("span","tag-chip"),g=l("span","tag-text",o);g.title=o,$.appendChild(g);const E=l("button","tag-rm linkbtn","✕");E.type="button",E.setAttribute("aria-label",`${i.label}: remove ${o}`),E.addEventListener("click",()=>{r.splice(O,1),k(),s()}),$.appendChild(E),d.appendChild($)}),r.length||d.appendChild(l("span","tags-empty",i.emptyLabel||"—"))};s(),u.appendChild(d);const y=l("div","tags-add"),c=l("input");c.type="text",c.placeholder=A.placeholder||"…",c.setAttribute("aria-label",i.label);const C=()=>{const o=c.value.trim();if(!o||r.includes(o)){c.select();return}r.push(o),k(),s(),c.value="",c.focus()};c.addEventListener("keydown",o=>{o.key==="Enter"&&(o.preventDefault(),C())}),y.appendChild(c);const b=l("button","tags-plus linkbtn","+");return b.type="button",b.setAttribute("aria-label",`${i.label}: add`),b.addEventListener("click",C),y.appendChild(b),u.appendChild(y),u}export function checkboxEditor(f,i,A){const r=new Set(Array.isArray(f)?f.map(String):[]),u=l("div","checksctl ctl-block");return(A.options||[]).forEach(d=>{const k=l("label","check-line"),s=l("input");s.type="checkbox",s.checked=r.has(d),s.addEventListener("change",()=>{s.checked?r.add(d):r.delete(d),i.post(JSON.stringify([...r]))}),k.appendChild(s),k.appendChild(l("span","",i.enumLabel?i.enumLabel(d):d)),u.appendChild(k)}),u}export function tableEditor(f,i,A){const r=A.columns||[],u=r[0],d=r.slice(1),k=f&&typeof f=="object"&&!Array.isArray(f)?f:{},s=Object.entries(k).map(([e,t])=>({name:e,val:t&&typeof t=="object"?{...t}:{},error:""})),y=l("div","tablectl ctl-block"),c=l("div","table-head");r.forEach(e=>c.appendChild(l("span","table-th",i.fieldLabel(e.key)))),y.appendChild(c);const C=l("div","table-body"),b=l("div","json-err");b.hidden=!0;const o=e=>e.array===!0,O=e=>e===void 0||e===""||Array.isArray(e)&&e.length===0,$=()=>{const e={};for(const t of s){if(!t.name)return{ok:!1,reason:"empty name"};if(e[t.name]!==void 0)return{ok:!1,reason:`duplicate: ${t.name}`};const a={};for(const n of d){const p=t.val[n.key];if(!(n.optional&&O(p))){if(!n.optional&&O(p))return{ok:!1,reason:`${t.name}: ${i.fieldLabel(n.key)}`};if(n.type==="number"){const S=Number(p);if(!Number.isFinite(S)||S<0)return{ok:!1,reason:`${t.name}: ${i.fieldLabel(n.key)}`};a[n.key]=S}else n.type==="bool"?p===!0&&(a[n.key]=!0):a[n.key]=o(n)?p:String(p)}}e[t.name]=a}return{ok:!0,value:e}},g=()=>{const e=$();return e.ok?(b.hidden=!0,b.textContent="",i.post(JSON.stringify(e.value)),!0):(b.hidden=!1,b.textContent=q("web.settings.table_invalid",{field:e.reason||""}),!1)},E=(e,t,a)=>{if(t.type==="bool")a.checked?e.val[t.key]=!0:delete e.val[t.key];else if(t.type==="number"){const n=a.value.trim();n===""?delete e.val[t.key]:e.val[t.key]=Number(n)}else{const n=a.value.trim();n===""?delete e.val[t.key]:e.val[t.key]=o(t)?n.split(",").map(p=>p.trim()).filter(Boolean):n}},F=(e,t)=>{const a=e.val[t.key];if(t.optionsSource){const S=t.optionsSource==="providers"?i.providerOptions||[]:i.modelOptions||[],L=a==null?"":String(a),h=l("select"),D=l("option","","—");D.value="",h.appendChild(D);const J=new Set([""]);if(S.forEach(m=>{if(J.has(m))return;J.add(m);const w=l("option","",m);w.value=m,m===L&&(w.selected=!0),h.appendChild(w)}),L&&!J.has(L)){const m=l("option","",L);m.value=L,m.selected=!0,h.appendChild(m)}return h.value=L||"",h.setAttribute("aria-label",`${e.name}: ${i.fieldLabel(t.key)}`),h.addEventListener("change",()=>{h.value?e.val[t.key]=h.value:delete e.val[t.key],g()}),h}const n=l("input");return t.type==="bool"?(n.type="checkbox",n.checked=a===!0):t.type==="number"?(n.type="number",n.value=a==null?"":String(a)):(n.type="text",n.value=Array.isArray(a)?a.join(", "):a==null?"":String(a)),n.setAttribute("aria-label",`${e.name}: ${i.fieldLabel(t.key)}`),n.addEventListener("change",()=>{E(e,t,n),g()}),n},j=()=>{C.textContent="",s.forEach(e=>{const t=l("div","table-row");t.dataset.key=e.name;const a=l("input");a.type="text",a.value=e.name,a.placeholder=i.fieldLabel(u.key),a.setAttribute("aria-label",i.fieldLabel(u.key)),a.addEventListener("change",()=>{e.name=a.value.trim(),g()&&(t.dataset.key=e.name)}),t.appendChild(a),d.forEach(p=>t.appendChild(F(e,p)));const n=l("button","table-rm linkbtn","✕");n.type="button",n.setAttribute("aria-label",`${i.label}: remove ${e.name}`),n.addEventListener("click",()=>{s.splice(s.indexOf(e),1),g()&&j()}),t.appendChild(n),C.appendChild(t)})};j(),y.appendChild(C),y.appendChild(b);const I=l("div","table-add"),v=l("input");v.type="text",v.placeholder=i.fieldLabel(u.key),v.setAttribute("aria-label",`${i.label}: new ${i.fieldLabel(u.key)}`);const B=()=>{const e=v.value.trim();if(!e||s.some(p=>p.name===e)){v.select();return}const t={};s.push({name:e,val:t,error:""}),v.value="",j();const a=C.lastElementChild,n=a&&a.querySelectorAll("input,select")[1];n&&n.focus()};v.addEventListener("keydown",e=>{e.key==="Enter"&&(e.preventDefault(),B())}),I.appendChild(v);const N=l("button","table-plus linkbtn","+");return N.type="button",N.setAttribute("aria-label",`${i.label}: add`),N.addEventListener("click",B),I.appendChild(N),y.appendChild(I),y}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{el as i,icon as O,link as k,inlineTextNodes as q,makeToggle as J}from"../dom.js";import{api as w}from"../api.js";import{t as s}from"../i18n.js";import{settings as l,getPath as D,THEME_KEY as N}from"../store.js";import{setIndicator as C}from"../dialog.js";import{controlFor as U,PANEL_SECTIONS as E}from"./controls.js";import{postConfig as j}from"./write.js";import{openSubDialog as F,closeSubDialog as x}from"./subdialog.js";import{mcpLiteralField as v,providerInput as _,providerSelect as H,providerCheck as P}from"./form.js";export function configLabel(e){const n="config.key."+e.key,t=s(n);return t===n?e.key:t}export function enumLabel(e){const n="config.enum."+e,t=s(n);return t===n?e:t}export function defFor(e){return l.registry.find(n=>n.key===e)||null}export function row(e,n,t){const a=i("div","row"),o=i("div","row-label");if(o.appendChild(i("span","row-name",e)),t&&o.appendChild(i("span","row-desc",t)),a.appendChild(o),typeof n=="string"){const d=i("span","val",n);d.title=n,a.appendChild(d)}else n&&a.appendChild(n);return a}export function descFor(e){const n="config.desc."+e,t=s(n);return t===n?"":t}function B(e,n){const t=e.readOnly&&e.value!==void 0?e.value:l.config?D(l.config,n):void 0;return U(e,t,{label:configLabel(e),enumLabel,emptyLabel:s("config.enum.none"),fieldLabel:a=>{const o="config.field."+a,d=s(o);return d===o?a:d},post:a=>{j(n,a,!1)}})}function Y(e){const n=i("div","settings-section"),t=i("div","sec-head");if(t.appendChild(i("span","sec-title",s(e.titleKey))),n.appendChild(t),e.descKey){const o=s(e.descKey);o!==e.descKey&&n.appendChild(i("div","sec-desc",o))}const a=i("div","sec-body");return e.keys.forEach(o=>{const d=defFor(o);d&&a.appendChild(row(configLabel(d),B(d,o),descFor(d.key)))}),n.appendChild(a),n}export function renderSections(e,n){const t=document.querySelector('[data-panel="'+e+'"]');t&&n.forEach(a=>t.appendChild(Y(a)))}export function renderPanel(e){const n=document.querySelector('[data-panel="'+e+'"]');n&&(n.textContent="",renderSections(e,E[e]||[]))}export function settingsSection(e){const n=i("div","settings-section"),t=i("div","sec-head");t.appendChild(i("span","sec-title",s(e))),n.appendChild(t);const a=i("div","sec-body");return n.appendChild(a),{el:n,head:t,body:a}}export function chip(e,n,t){const a=i("button","chip"+(n?" "+n:""),e);return a.type="button",a.addEventListener("click",t),a}export function placeholderFor(e,n){const t=i("div","placeholder");return e===void 0?t.textContent=s("web.settings.loading"):t.textContent=n,t}export function groupHeader(e,n){const t=i("div","row");return t.appendChild(i("span","val accent",e)),n!=null&&t.appendChild(i("span","val dim",String(n))),t}export function currentTheme(){return localStorage.getItem(N)||"auto"}function I(){const e=document.querySelector('[data-panel="ui"]');if(!e)return;e.textContent="";const n=i("span","seg");["dark","light","auto"].forEach(r=>{const p=i("button",currentTheme()===r?"on":"",r);p.type="button",p.setAttribute("aria-pressed",currentTheme()===r?"true":"false"),p.addEventListener("click",()=>{n.querySelectorAll("button").forEach(u=>{u.classList.remove("on"),u.setAttribute("aria-pressed","false")}),p.classList.add("on"),p.setAttribute("aria-pressed","true"),applyTheme(r)}),n.appendChild(p)});const t=i("div","settings-section"),a=i("div","sec-head");a.appendChild(i("span","sec-title",s("web.settings.sec.ui.theme"))),t.appendChild(a);const o=s("web.settings.sec.ui.theme.desc");o!=="web.settings.sec.ui.theme.desc"&&t.appendChild(i("div","sec-desc",o));const d=i("div","sec-body");d.appendChild(row(s("web.settings.theme"),n)),t.appendChild(d),e.appendChild(t),renderSections("ui",E.ui||[])}export function applyTheme(e){localStorage.setItem(N,e);const n=e==="light"||e==="auto"&&window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").matches;document.body.classList.toggle("light",!!n),I()}window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").addEventListener("change",()=>{currentTheme()==="auto"&&applyTheme("auto")});function z(){const e=document.querySelector('[data-panel="security"]');if(!e)return;e.textContent="",renderSections("security",E.security||[]);const n=i("div","settings-section"),t=i("div","sec-head");t.appendChild(i("span","sec-title",s("web.settings.sec.security.access"))),n.appendChild(t);const a=i("div","sec-body");a.appendChild(row(s("web.settings.web_token"),i("span","val dim",l.webToken||s("web.settings.web_token_none")),s("config.desc.webToken")));const o=i("div","placeholder");o.appendChild(i("span","tag",s("web.settings.terminal_tag"))),o.appendChild(document.createTextNode(" "+s("web.settings.security_note"))),a.appendChild(o),n.appendChild(a),e.appendChild(n)}const G=["conventions","decisions","errors","facts"];function Q(){const e=i("div","pform"),n=i("div","pform-grid"),t=i("select");t.setAttribute("aria-label",s("web.settings.memory_category")),G.forEach(d=>t.appendChild(i("option","",d))),t.value="facts",n.appendChild(v(s("web.settings.memory_category"),t)),e.appendChild(n);const a=i("textarea");a.rows=5,a.placeholder=s("web.settings.new_memory"),a.value="",e.appendChild(v(s("web.settings.new_memory"),a));const o=i("div","pform-actions");o.appendChild(k(s("web.settings.save"),"",async()=>{const d=a.value.trim();if(!d){a.focus();return}const r=await w("/api/memory",{method:"POST",body:{category:t.value,text:d}});r.ok&&r.data&&r.data.ok?(x(),await loadMemory()):C(s("web.settings.add_failed"),!0)})),o.appendChild(k(s("web.settings.cancel"),"dim",()=>x())),e.appendChild(o),F(s("web.settings.memory_add_title"),e,()=>L())}function L(){const e=document.querySelector('[data-panel="memory"]');if(!e)return;if(e.textContent="",l.memory===void 0||l.memory===null){e.appendChild(placeholderFor(l.memory,s("web.settings.memory_unavailable")));return}const n=l.memory,t=i("button","sec-add");t.type="button",t.appendChild(O("plus")),t.appendChild(i("span","",s("web.settings.add"))),t.addEventListener("click",()=>Q());const a=i("div","sec-head");a.appendChild(i("span","sec-title",s("web.settings.sec.memory.add"))),a.appendChild(t);const o=i("div","settings-section");o.appendChild(a),e.appendChild(o);const d=i("input","searchbox");d.placeholder=s("web.settings.search_memory"),d.setAttribute("aria-label",s("web.settings.search_memory")),e.appendChild(d);const r=i("div","settings-list");e.appendChild(r);const p=(h,g)=>{const c=i("div","mem-cat");return c.appendChild(i("span","",h)),g!=null&&c.appendChild(i("span","n",String(g))),c},u=(h,g)=>{const c=i("div","mem-entry"),m=i("span","mem-text");return m.appendChild(q(String(h??""))),m.title=String(h??""),c.appendChild(m),g&&c.appendChild(k(s("web.settings.forget"),"mem-del",g)),c},b=()=>{r.textContent="";const h=d.value.trim().toLowerCase();let g=!1;(n.categories||[]).forEach(m=>{const f=(m.entries||[]).filter(y=>!h||String(y.text).toLowerCase().indexOf(h)!==-1);f.length&&(g=!0,r.appendChild(p(m.name,f.length)),f.forEach(y=>{r.appendChild(u(y.text,async()=>{(await w("/api/memory/"+encodeURIComponent(m.name)+"/"+y.n,{method:"DELETE"})).ok?await loadMemory():C(s("web.settings.forget_failed"),!0)}))}))});const c=Object.entries(n.preferences||{});if(c.length&&!h&&(g=!0,r.appendChild(p(s("web.settings.preferences"),c.length)),c.forEach(([m,f])=>{r.appendChild(u(m+" = "+f))})),!g){const m=i("div","placeholder");m.textContent=h?s("web.settings.no_matches"):s("web.settings.no_memory"),r.appendChild(m)}};d.addEventListener("input",b),b()}function M(){const e=document.querySelector('[data-panel="skills"]');if(!e)return;if(e.textContent="",l.skills===void 0||l.skills===null){e.appendChild(placeholderFor(l.skills,s("web.settings.skills_unavailable")));return}if(!l.skills.length){const t=i("div","placeholder");t.textContent=s("web.settings.no_skills"),e.appendChild(t);return}const n=i("div","settings-list");l.skills.forEach(t=>{const a=i("div","skill-item"),o=i("div","skill-head");o.appendChild(i("span",t.enabled?"g":"dim",t.enabled?"✓":"○"));const d=i("span","name",t.name);if(d.title=t.name,o.appendChild(d),o.appendChild(i("span","st",t.enabled?s("web.settings.enabled"):s("web.settings.available"))),a.appendChild(o),t.source){const r=i("div","skill-src",t.source);r.title=t.source,a.appendChild(r)}n.appendChild(a)}),e.appendChild(n)}function S(){const e=document.querySelector('[data-panel="plugins"]');if(!e)return;if(e.textContent="",l.pluginsData===void 0||l.pluginsData===null){e.appendChild(placeholderFor(l.pluginsData,s("web.settings.plugins_unavailable")));return}const n=l.pluginsData,t=i("div","settings-list");if(t.appendChild(groupHeader(s("web.settings.plugins_header"),(n.plugins||[]).length)),!(n.plugins||[]).length){const d=i("div","placeholder");d.textContent=s("web.settings.no_plugins"),t.appendChild(d)}(n.plugins||[]).forEach(d=>{const r=i("div","list-line");r.appendChild(i("span","g","✓"));const p=i("span","name",d.name);if(p.title=d.name,r.appendChild(p),d.version&&r.appendChild(i("span","src","v"+d.version)),d.source){const u=i("span","src",d.source);u.title=d.source,r.appendChild(u)}d.builtin&&r.appendChild(i("span","src",s("web.settings.builtin"))),r.appendChild(i("span","st",d.enabled===!1?s("web.settings.disabled"):s("web.settings.enabled"))),t.appendChild(r)});const a=i("div","settings-note");a.textContent=s("web.settings.plugins_note"),t.appendChild(a),t.appendChild(groupHeader(s("web.settings.mcp_servers"),(n.mcp||[]).length));const o=i("button","sec-add");if(o.type="button",o.appendChild(O("plus")),o.appendChild(i("span","",s("web.settings.mcp_add"))),o.addEventListener("click",()=>R("add",null)),t.appendChild(o),!(n.mcp||[]).length){const d=i("div","placeholder");d.textContent=s("web.settings.no_mcp"),t.appendChild(d)}if((n.mcp||[]).forEach(d=>{const r=i("div","list-line"),p=d.status!=="disabled",u=J(p,h=>{w("/api/mcp/"+encodeURIComponent(d.id||d.name),{method:"POST",body:{enabled:h}}).then(async g=>{g.ok&&g.data&&g.data.ok?(C(s("web.settings.mcp_saved"),!1),await loadPlugins()):C(s("web.settings.save_failed"),!0)})});u.title=p?s("web.settings.mcp_disable"):s("web.settings.mcp_enable"),u.setAttribute("aria-label",u.title),r.appendChild(u);const b=i("span","name",d.name);b.title=d.name,r.appendChild(b),r.appendChild(i("span","st",d.status||"—")),r.appendChild(chip(s("web.settings.edit"),"",()=>R("edit",d))),r.appendChild(chip(s("web.settings.delete"),"danger",async()=>{const h=await w("/api/mcp/"+encodeURIComponent(d.id||d.name),{method:"DELETE"});h.ok&&h.data&&h.data.ok?(C(s("web.settings.mcp_saved"),!1),await loadPlugins()):C(h.data&&h.data.error||s("web.settings.delete_failed"),!0)})),t.appendChild(r)}),l.mcpForm&&t.appendChild(K()),(n.mcp||[]).length){const d=i("div","settings-note");d.textContent=s("web.settings.mcp_note"),t.appendChild(d)}X(t),e.appendChild(t),renderSections("plugins",E.plugins||[])}function K(){const e=l.mcpForm&&l.mcpForm.mode||"add",n=l.mcpForm&&l.mcpForm.entry||{},t=i("div","pform"),a=i("div","pform-grid"),o=_(n.name||"","text","my-server"),d=H(["stdio","sse","http"],n.transport||"stdio"),r=_(n.command||"","text","npx"),p=_(n.url||"","text","https://…");a.appendChild(v("name",o)),a.appendChild(v("transport",d)),a.appendChild(v("command",r)),a.appendChild(v("url",p)),t.appendChild(a);const u=i("details","pform-adv");u.appendChild(i("summary","",s("web.settings.provider_advanced")));const b=_(n.args?JSON.stringify(n.args):"","text",'["--stdio"]'),h=_(n.timeout!=null?String(n.timeout):"","number","30000"),g=P(n.enabled!==!1);u.appendChild(v("args (JSON)",b)),u.appendChild(v("timeout (ms)",h));const c=Array.isArray(n.envKeys)?n.envKeys:[],m=Array.isArray(n.headerKeys)?n.headerKeys:[],f=i("textarea");f.placeholder=c.length?"stored: "+c.join(", ")+" — blank keeps":'{"TOKEN": "…"}';const y=i("textarea");y.placeholder=m.length?"stored: "+m.join(", ")+" — blank keeps":'{"Authorization": "…"}',u.appendChild(v("env (JSON)",f)),u.appendChild(v("headers (JSON)",y)),u.appendChild(v("enabled",g)),t.appendChild(u);const T={name:o,transport:d,command:r,url:p,args:b,timeout:h,env:f,headers:y,enabled:g},A=i("div","pform-actions");return A.appendChild(k(s("web.settings.save"),"",()=>{W(T,e,n)})),A.appendChild(k(s("web.settings.cancel"),"dim",()=>x())),t.appendChild(A),t}function R(e,n){l.mcpForm={mode:e,entry:n||null},F(s(e==="edit"?"web.settings.mcp_edit_title":"web.settings.mcp_add"),K(),()=>{l.mcpForm=null,S(),loadPlugins()})}function V(e){const n=e.trim();if(!n)return{present:!1,value:null};let t=null;try{t=JSON.parse(n)}catch{return{present:!0,value:null}}return!t||typeof t!="object"||Array.isArray(t)?{present:!0,value:null}:Object.values(t).every(a=>typeof a=="string")?{present:!0,value:t}:{present:!0,value:null}}async function W(e,n,t){const a=e.name.value.trim(),o=e.transport.value||"stdio",d=e.command.value.trim(),r=e.url.value.trim();if(!a||(o==="stdio"?!d:!r)){C(s("web.settings.mcp_required"),!0);return}const p={name:a,transport:o};d&&(p.command=d),r&&(p.url=r);const u=e.args.value.trim();if(u){let c=null;try{c=JSON.parse(u)}catch{c=null}if(!Array.isArray(c)||!c.every(m=>typeof m=="string")){C(s("web.settings.mcp_invalid"),!0);return}p.args=c}for(const c of["env","headers"]){const m=V(e[c].value);if(m.present&&!m.value){C(s("web.settings.mcp_invalid"),!0);return}m.present&&(p[c]=m.value)}const b=e.timeout.value.trim();if(b){const c=Number(b);if(!Number.isInteger(c)||c<1e3||c>3e5){C(s("web.settings.mcp_invalid"),!0);return}p.timeout=c}p.enabled=e.enabled.checked;const h=n==="edit"?"/api/mcp/"+encodeURIComponent(t.id||t.name):"/api/mcp",g=await w(h,{method:n==="edit"?"PUT":"POST",body:p});g.ok&&g.data&&g.data.ok?(C(s("web.settings.mcp_saved"),!1),x()):C(g.data&&g.data.error||s("web.settings.save_failed"),!0)}function X(e){const n=l.lsp;if(e.appendChild(groupHeader(s("web.settings.lsp_servers"),Array.isArray(n)?n.length:null)),n==null){e.appendChild(placeholderFor(n,s("web.settings.lsp_unavailable")));return}if(!n.length){const t=i("div","placeholder");t.textContent=s("web.settings.no_lsp"),e.appendChild(t)}if(n.forEach(t=>{const a=i("div","list-line");a.appendChild(i("span",t.enabled?"g":"dim",t.enabled?"✓":"○"));const o=i("span","name",t.lang);o.title=t.lang,a.appendChild(o);const d=[t.command,t.timeout!=null?t.timeout+" ms":null].filter(Boolean).join(" · ");d&&a.appendChild(i("span","src",d)),a.appendChild(i("span","st",t.enabled?s("web.settings.enabled"):s("web.settings.disabled"))),a.appendChild(chip(s("web.settings.edit"),"",()=>Z(t))),e.appendChild(a)}),n.length){const t=i("div","settings-note");t.textContent=s("web.settings.lsp_note"),e.appendChild(t)}}function Z(e){l.lspForm={lang:e.lang,entry:e},F(e.lang,$(),()=>{l.lspForm=null,S(),loadLsp()})}function $(){const e=l.lspForm&&l.lspForm.entry||{},n=l.lspForm&&l.lspForm.lang||e.lang||"",t=i("div","pform"),a=i("div","pform-grid"),o=_(e.command||"","text","npx"),d=_(e.timeout!=null?String(e.timeout):"","number","30000"),r=P(e.enabled!==!1);a.appendChild(v("command",o)),a.appendChild(v("timeout (ms)",d)),a.appendChild(v("enabled",r)),t.appendChild(a);const p=i("textarea");p.value=e.args?JSON.stringify(e.args):"",p.placeholder='["--stdio"]',t.appendChild(v("args (JSON)",p));const u=i("div","pform-actions");return u.appendChild(k(s("web.settings.save"),"",async()=>{const b={},h=o.value.trim();h&&(b.command=h);const g=d.value.trim();if(g){const f=Number(g);if(!Number.isInteger(f)||f<1e3||f>3e5){C(s("web.settings.provider_invalid"),!0);return}b.timeout=f}const c=p.value.trim();if(c){let f=null;try{f=JSON.parse(c)}catch{f=null}if(!Array.isArray(f)||!f.every(y=>typeof y=="string")){C(s("web.settings.provider_invalid"),!0);return}b.args=f}b.enabled=r.checked;const m=await w("/api/lsp/"+encodeURIComponent(n),{method:"PUT",body:b});m.ok&&m.data&&m.data.ok?(C(s("web.settings.mcp_saved"),!1),x()):C(m.data&&m.data.error||s("web.settings.save_failed"),!0)})),u.appendChild(k(s("web.settings.cancel"),"dim",()=>x())),t.appendChild(u),t}export async function loadLsp(){const e=await w("/api/lsp");l.lsp=e.ok&&e.data&&Array.isArray(e.data.servers)?e.data.servers:null,S()}export async function loadMemory(){const e=await w("/api/memory");l.memory=e.ok&&e.data?e.data:null,L()}export async function loadSkills(){const e=await w("/api/skills");l.skills=e.ok&&e.data&&Array.isArray(e.data.skills)?e.data.skills:null,M()}export async function loadPlugins(){const e=await w("/api/plugins");l.pluginsData=e.ok&&e.data?{plugins:e.data.plugins||[],mcp:e.data.mcp||[]}:null,S()}export{I as renderUiPanel,L as renderMemoryPanel,M as renderSkillsPanel,S as renderPluginsPanel,z as renderSecurityPanel};
|
|
1
|
+
import{el as i,icon as T,link as k,inlineTextNodes as q,makeToggle as J}from"../dom.js";import{api as w}from"../api.js";import{t as s}from"../i18n.js";import{settings as l,getPath as D,THEME_KEY as N}from"../store.js";import{setIndicator as C}from"../dialog.js";import{controlFor as U,PANEL_SECTIONS as E}from"./controls.js";import{postConfig as j}from"./write.js";import{openSubDialog as O,closeSubDialog as _}from"./subdialog.js";import{mcpLiteralField as v,providerInput as x,providerSelect as H,providerCheck as P}from"./form.js";export function configLabel(e){const n="config.key."+e.key,t=s(n);return t===n?e.key:t}export function enumLabel(e){const n="config.enum."+e,t=s(n);return t===n?e:t}export function defFor(e){return l.registry.find(n=>n.key===e)||null}export function row(e,n,t){const d=i("div","row"),o=i("div","row-label");if(o.appendChild(i("span","row-name",e)),t&&o.appendChild(i("span","row-desc",t)),d.appendChild(o),typeof n=="string"){const a=i("span","val",n);a.title=n,d.appendChild(a)}else n&&d.appendChild(n);return d}export function descFor(e){const n="config.desc."+e,t=s(n);return t===n?"":t}function B(){const e=l.providers||{},n=l.config&&l.config.provider||{},d=(Array.isArray(e.entries)&&e.entries.length?e.entries:Array.isArray(n.entries)?n.entries:[]).map(a=>a.label||a.type).filter(a=>!!a),o=e.active||n.active;return o&&d.indexOf(o)===-1&&d.unshift(o),d}function Y(e,n){const t=e.readOnly&&e.value!==void 0?e.value:l.config?D(l.config,n):void 0;return U(e,t,{label:configLabel(e),enumLabel,emptyLabel:s("config.enum.none"),modelOptions:l.models,providerOptions:B(),fieldLabel:d=>{const o="config.field."+d,a=s(o);return a===o?d:a},post:d=>{j(n,d,!1)}})}function z(e){const n=i("div","settings-section"),t=i("div","sec-head");if(t.appendChild(i("span","sec-title",s(e.titleKey))),n.appendChild(t),e.descKey){const o=s(e.descKey);o!==e.descKey&&n.appendChild(i("div","sec-desc",o))}const d=i("div","sec-body");return e.keys.forEach(o=>{const a=defFor(o);a&&d.appendChild(row(configLabel(a),Y(a,o),descFor(a.key)))}),n.appendChild(d),n}export function renderSections(e,n){const t=document.querySelector('[data-panel="'+e+'"]');t&&n.forEach(d=>t.appendChild(z(d)))}export function renderPanel(e){const n=document.querySelector('[data-panel="'+e+'"]');n&&(n.textContent="",renderSections(e,E[e]||[]))}export function settingsSection(e){const n=i("div","settings-section"),t=i("div","sec-head");t.appendChild(i("span","sec-title",s(e))),n.appendChild(t);const d=i("div","sec-body");return n.appendChild(d),{el:n,head:t,body:d}}export function chip(e,n,t){const d=i("button","chip"+(n?" "+n:""),e);return d.type="button",d.addEventListener("click",t),d}export function placeholderFor(e,n){const t=i("div","placeholder");return e===void 0?t.textContent=s("web.settings.loading"):t.textContent=n,t}export function groupHeader(e,n){const t=i("div","row");return t.appendChild(i("span","val accent",e)),n!=null&&t.appendChild(i("span","val dim",String(n))),t}export function currentTheme(){return localStorage.getItem(N)||"auto"}function I(){const e=document.querySelector('[data-panel="ui"]');if(!e)return;e.textContent="";const n=i("span","seg");["dark","light","auto"].forEach(r=>{const p=i("button",currentTheme()===r?"on":"",r);p.type="button",p.setAttribute("aria-pressed",currentTheme()===r?"true":"false"),p.addEventListener("click",()=>{n.querySelectorAll("button").forEach(u=>{u.classList.remove("on"),u.setAttribute("aria-pressed","false")}),p.classList.add("on"),p.setAttribute("aria-pressed","true"),applyTheme(r)}),n.appendChild(p)});const t=i("div","settings-section"),d=i("div","sec-head");d.appendChild(i("span","sec-title",s("web.settings.sec.ui.theme"))),t.appendChild(d);const o=s("web.settings.sec.ui.theme.desc");o!=="web.settings.sec.ui.theme.desc"&&t.appendChild(i("div","sec-desc",o));const a=i("div","sec-body");a.appendChild(row(s("web.settings.theme"),n)),t.appendChild(a),e.appendChild(t),renderSections("ui",E.ui||[])}export function applyTheme(e){localStorage.setItem(N,e);const n=e==="light"||e==="auto"&&window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").matches;document.body.classList.toggle("light",!!n),I()}window.matchMedia&&window.matchMedia("(prefers-color-scheme: light)").addEventListener("change",()=>{currentTheme()==="auto"&&applyTheme("auto")});function G(){const e=document.querySelector('[data-panel="security"]');if(!e)return;e.textContent="",renderSections("security",E.security||[]);const n=i("div","settings-section"),t=i("div","sec-head");t.appendChild(i("span","sec-title",s("web.settings.sec.security.access"))),n.appendChild(t);const d=i("div","sec-body");d.appendChild(row(s("web.settings.web_token"),i("span","val dim",l.webToken||s("web.settings.web_token_none")),s("config.desc.webToken")));const o=i("div","placeholder");o.appendChild(i("span","tag",s("web.settings.terminal_tag"))),o.appendChild(document.createTextNode(" "+s("web.settings.security_note"))),d.appendChild(o),n.appendChild(d),e.appendChild(n)}const Q=["conventions","decisions","errors","facts"];function V(){const e=i("div","pform"),n=i("div","pform-grid"),t=i("select");t.setAttribute("aria-label",s("web.settings.memory_category")),Q.forEach(a=>t.appendChild(i("option","",a))),t.value="facts",n.appendChild(v(s("web.settings.memory_category"),t)),e.appendChild(n);const d=i("textarea");d.rows=5,d.placeholder=s("web.settings.new_memory"),d.value="",e.appendChild(v(s("web.settings.new_memory"),d));const o=i("div","pform-actions");o.appendChild(k(s("web.settings.save"),"",async()=>{const a=d.value.trim();if(!a){d.focus();return}const r=await w("/api/memory",{method:"POST",body:{category:t.value,text:a}});r.ok&&r.data&&r.data.ok?(_(),await loadMemory()):C(s("web.settings.add_failed"),!0)})),o.appendChild(k(s("web.settings.cancel"),"dim",()=>_())),e.appendChild(o),O(s("web.settings.memory_add_title"),e,()=>F())}function F(){const e=document.querySelector('[data-panel="memory"]');if(!e)return;if(e.textContent="",l.memory===void 0||l.memory===null){e.appendChild(placeholderFor(l.memory,s("web.settings.memory_unavailable")));return}const n=l.memory,t=i("button","sec-add");t.type="button",t.appendChild(T("plus")),t.appendChild(i("span","",s("web.settings.add"))),t.addEventListener("click",()=>V());const d=i("div","sec-head");d.appendChild(i("span","sec-title",s("web.settings.sec.memory.add"))),d.appendChild(t);const o=i("div","settings-section");o.appendChild(d),e.appendChild(o);const a=i("input","searchbox");a.placeholder=s("web.settings.search_memory"),a.setAttribute("aria-label",s("web.settings.search_memory")),e.appendChild(a);const r=i("div","settings-list");e.appendChild(r);const p=(h,g)=>{const c=i("div","mem-cat");return c.appendChild(i("span","",h)),g!=null&&c.appendChild(i("span","n",String(g))),c},u=(h,g)=>{const c=i("div","mem-entry"),m=i("span","mem-text");return m.appendChild(q(String(h??""))),m.title=String(h??""),c.appendChild(m),g&&c.appendChild(k(s("web.settings.forget"),"mem-del",g)),c},b=()=>{r.textContent="";const h=a.value.trim().toLowerCase();let g=!1;(n.categories||[]).forEach(m=>{const f=(m.entries||[]).filter(y=>!h||String(y.text).toLowerCase().indexOf(h)!==-1);f.length&&(g=!0,r.appendChild(p(m.name,f.length)),f.forEach(y=>{r.appendChild(u(y.text,async()=>{(await w("/api/memory/"+encodeURIComponent(m.name)+"/"+y.n,{method:"DELETE"})).ok?await loadMemory():C(s("web.settings.forget_failed"),!0)}))}))});const c=Object.entries(n.preferences||{});if(c.length&&!h&&(g=!0,r.appendChild(p(s("web.settings.preferences"),c.length)),c.forEach(([m,f])=>{r.appendChild(u(m+" = "+f))})),!g){const m=i("div","placeholder");m.textContent=h?s("web.settings.no_matches"):s("web.settings.no_memory"),r.appendChild(m)}};a.addEventListener("input",b),b()}function M(){const e=document.querySelector('[data-panel="skills"]');if(!e)return;if(e.textContent="",l.skills===void 0||l.skills===null){e.appendChild(placeholderFor(l.skills,s("web.settings.skills_unavailable")));return}if(!l.skills.length){const t=i("div","placeholder");t.textContent=s("web.settings.no_skills"),e.appendChild(t);return}const n=i("div","settings-list");l.skills.forEach(t=>{const d=i("div","skill-item"),o=i("div","skill-head");o.appendChild(i("span",t.enabled?"g":"dim",t.enabled?"✓":"○"));const a=i("span","name",t.name);if(a.title=t.name,o.appendChild(a),o.appendChild(i("span","st",t.enabled?s("web.settings.enabled"):s("web.settings.available"))),d.appendChild(o),t.source){const r=i("div","skill-src",t.source);r.title=t.source,d.appendChild(r)}n.appendChild(d)}),e.appendChild(n)}function S(){const e=document.querySelector('[data-panel="plugins"]');if(!e)return;if(e.textContent="",l.pluginsData===void 0||l.pluginsData===null){e.appendChild(placeholderFor(l.pluginsData,s("web.settings.plugins_unavailable")));return}const n=l.pluginsData,t=i("div","settings-list");if(t.appendChild(groupHeader(s("web.settings.plugins_header"),(n.plugins||[]).length)),!(n.plugins||[]).length){const a=i("div","placeholder");a.textContent=s("web.settings.no_plugins"),t.appendChild(a)}(n.plugins||[]).forEach(a=>{const r=i("div","list-line");r.appendChild(i("span","g","✓"));const p=i("span","name",a.name);if(p.title=a.name,r.appendChild(p),a.version&&r.appendChild(i("span","src","v"+a.version)),a.source){const u=i("span","src",a.source);u.title=a.source,r.appendChild(u)}a.builtin&&r.appendChild(i("span","src",s("web.settings.builtin"))),r.appendChild(i("span","st",a.enabled===!1?s("web.settings.disabled"):s("web.settings.enabled"))),t.appendChild(r)});const d=i("div","settings-note");d.textContent=s("web.settings.plugins_note"),t.appendChild(d),t.appendChild(groupHeader(s("web.settings.mcp_servers"),(n.mcp||[]).length));const o=i("button","sec-add");if(o.type="button",o.appendChild(T("plus")),o.appendChild(i("span","",s("web.settings.mcp_add"))),o.addEventListener("click",()=>R("add",null)),t.appendChild(o),!(n.mcp||[]).length){const a=i("div","placeholder");a.textContent=s("web.settings.no_mcp"),t.appendChild(a)}if((n.mcp||[]).forEach(a=>{const r=i("div","list-line"),p=a.status!=="disabled",u=J(p,h=>{w("/api/mcp/"+encodeURIComponent(a.id||a.name),{method:"POST",body:{enabled:h}}).then(async g=>{g.ok&&g.data&&g.data.ok?(C(s("web.settings.mcp_saved"),!1),await loadPlugins()):C(s("web.settings.save_failed"),!0)})});u.title=p?s("web.settings.mcp_disable"):s("web.settings.mcp_enable"),u.setAttribute("aria-label",u.title),r.appendChild(u);const b=i("span","name",a.name);b.title=a.name,r.appendChild(b),r.appendChild(i("span","st",a.status||"—")),r.appendChild(chip(s("web.settings.edit"),"",()=>R("edit",a))),r.appendChild(chip(s("web.settings.delete"),"danger",async()=>{const h=await w("/api/mcp/"+encodeURIComponent(a.id||a.name),{method:"DELETE"});h.ok&&h.data&&h.data.ok?(C(s("web.settings.mcp_saved"),!1),await loadPlugins()):C(h.data&&h.data.error||s("web.settings.delete_failed"),!0)})),t.appendChild(r)}),l.mcpForm&&t.appendChild(K()),(n.mcp||[]).length){const a=i("div","settings-note");a.textContent=s("web.settings.mcp_note"),t.appendChild(a)}Z(t),e.appendChild(t),renderSections("plugins",E.plugins||[])}function K(){const e=l.mcpForm&&l.mcpForm.mode||"add",n=l.mcpForm&&l.mcpForm.entry||{},t=i("div","pform"),d=i("div","pform-grid"),o=x(n.name||"","text","my-server"),a=H(["stdio","sse","http"],n.transport||"stdio"),r=x(n.command||"","text","npx"),p=x(n.url||"","text","https://…");d.appendChild(v("name",o)),d.appendChild(v("transport",a)),d.appendChild(v("command",r)),d.appendChild(v("url",p)),t.appendChild(d);const u=i("details","pform-adv");u.appendChild(i("summary","",s("web.settings.provider_advanced")));const b=x(n.args?JSON.stringify(n.args):"","text",'["--stdio"]'),h=x(n.timeout!=null?String(n.timeout):"","number","30000"),g=P(n.enabled!==!1);u.appendChild(v("args (JSON)",b)),u.appendChild(v("timeout (ms)",h));const c=Array.isArray(n.envKeys)?n.envKeys:[],m=Array.isArray(n.headerKeys)?n.headerKeys:[],f=i("textarea");f.placeholder=c.length?"stored: "+c.join(", ")+" — blank keeps":'{"TOKEN": "…"}';const y=i("textarea");y.placeholder=m.length?"stored: "+m.join(", ")+" — blank keeps":'{"Authorization": "…"}',u.appendChild(v("env (JSON)",f)),u.appendChild(v("headers (JSON)",y)),u.appendChild(v("enabled",g)),t.appendChild(u);const L={name:o,transport:a,command:r,url:p,args:b,timeout:h,env:f,headers:y,enabled:g},A=i("div","pform-actions");return A.appendChild(k(s("web.settings.save"),"",()=>{X(L,e,n)})),A.appendChild(k(s("web.settings.cancel"),"dim",()=>_())),t.appendChild(A),t}function R(e,n){l.mcpForm={mode:e,entry:n||null},O(s(e==="edit"?"web.settings.mcp_edit_title":"web.settings.mcp_add"),K(),()=>{l.mcpForm=null,S(),loadPlugins()})}function W(e){const n=e.trim();if(!n)return{present:!1,value:null};let t=null;try{t=JSON.parse(n)}catch{return{present:!0,value:null}}return!t||typeof t!="object"||Array.isArray(t)?{present:!0,value:null}:Object.values(t).every(d=>typeof d=="string")?{present:!0,value:t}:{present:!0,value:null}}async function X(e,n,t){const d=e.name.value.trim(),o=e.transport.value||"stdio",a=e.command.value.trim(),r=e.url.value.trim();if(!d||(o==="stdio"?!a:!r)){C(s("web.settings.mcp_required"),!0);return}const p={name:d,transport:o};a&&(p.command=a),r&&(p.url=r);const u=e.args.value.trim();if(u){let c=null;try{c=JSON.parse(u)}catch{c=null}if(!Array.isArray(c)||!c.every(m=>typeof m=="string")){C(s("web.settings.mcp_invalid"),!0);return}p.args=c}for(const c of["env","headers"]){const m=W(e[c].value);if(m.present&&!m.value){C(s("web.settings.mcp_invalid"),!0);return}m.present&&(p[c]=m.value)}const b=e.timeout.value.trim();if(b){const c=Number(b);if(!Number.isInteger(c)||c<1e3||c>3e5){C(s("web.settings.mcp_invalid"),!0);return}p.timeout=c}p.enabled=e.enabled.checked;const h=n==="edit"?"/api/mcp/"+encodeURIComponent(t.id||t.name):"/api/mcp",g=await w(h,{method:n==="edit"?"PUT":"POST",body:p});g.ok&&g.data&&g.data.ok?(C(s("web.settings.mcp_saved"),!1),_()):C(g.data&&g.data.error||s("web.settings.save_failed"),!0)}function Z(e){const n=l.lsp;if(e.appendChild(groupHeader(s("web.settings.lsp_servers"),Array.isArray(n)?n.length:null)),n==null){e.appendChild(placeholderFor(n,s("web.settings.lsp_unavailable")));return}if(!n.length){const t=i("div","placeholder");t.textContent=s("web.settings.no_lsp"),e.appendChild(t)}if(n.forEach(t=>{const d=i("div","list-line");d.appendChild(i("span",t.enabled?"g":"dim",t.enabled?"✓":"○"));const o=i("span","name",t.lang);o.title=t.lang,d.appendChild(o);const a=[t.command,t.timeout!=null?t.timeout+" ms":null].filter(Boolean).join(" · ");a&&d.appendChild(i("span","src",a)),d.appendChild(i("span","st",t.enabled?s("web.settings.enabled"):s("web.settings.disabled"))),d.appendChild(chip(s("web.settings.edit"),"",()=>$(t))),e.appendChild(d)}),n.length){const t=i("div","settings-note");t.textContent=s("web.settings.lsp_note"),e.appendChild(t)}}function $(e){l.lspForm={lang:e.lang,entry:e},O(e.lang,ee(),()=>{l.lspForm=null,S(),loadLsp()})}function ee(){const e=l.lspForm&&l.lspForm.entry||{},n=l.lspForm&&l.lspForm.lang||e.lang||"",t=i("div","pform"),d=i("div","pform-grid"),o=x(e.command||"","text","npx"),a=x(e.timeout!=null?String(e.timeout):"","number","30000"),r=P(e.enabled!==!1);d.appendChild(v("command",o)),d.appendChild(v("timeout (ms)",a)),d.appendChild(v("enabled",r)),t.appendChild(d);const p=i("textarea");p.value=e.args?JSON.stringify(e.args):"",p.placeholder='["--stdio"]',t.appendChild(v("args (JSON)",p));const u=i("div","pform-actions");return u.appendChild(k(s("web.settings.save"),"",async()=>{const b={},h=o.value.trim();h&&(b.command=h);const g=a.value.trim();if(g){const f=Number(g);if(!Number.isInteger(f)||f<1e3||f>3e5){C(s("web.settings.provider_invalid"),!0);return}b.timeout=f}const c=p.value.trim();if(c){let f=null;try{f=JSON.parse(c)}catch{f=null}if(!Array.isArray(f)||!f.every(y=>typeof y=="string")){C(s("web.settings.provider_invalid"),!0);return}b.args=f}b.enabled=r.checked;const m=await w("/api/lsp/"+encodeURIComponent(n),{method:"PUT",body:b});m.ok&&m.data&&m.data.ok?(C(s("web.settings.mcp_saved"),!1),_()):C(m.data&&m.data.error||s("web.settings.save_failed"),!0)})),u.appendChild(k(s("web.settings.cancel"),"dim",()=>_())),t.appendChild(u),t}export async function loadLsp(){const e=await w("/api/lsp");l.lsp=e.ok&&e.data&&Array.isArray(e.data.servers)?e.data.servers:null,S()}export async function loadMemory(){const e=await w("/api/memory");l.memory=e.ok&&e.data?e.data:null,F()}export async function loadSkills(){const e=await w("/api/skills");l.skills=e.ok&&e.data&&Array.isArray(e.data.skills)?e.data.skills:null,M()}export async function loadPlugins(){const e=await w("/api/plugins");l.pluginsData=e.ok&&e.data?{plugins:e.data.plugins||[],mcp:e.data.mcp||[]}:null,S()}export{I as renderUiPanel,F as renderMemoryPanel,M as renderSkillsPanel,S as renderPluginsPanel,G as renderSecurityPanel};
|