micro-models-agent 2.23.0 → 2.26.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 +54 -0
- package/dist/assets/app.js +1 -1
- package/dist/assets/js/core/store/index.js +1 -1
- package/dist/assets/js/session/tabs.js +1 -1
- package/dist/assets/js/sidebar/files.js +1 -1
- package/dist/assets/js/sidebar/trace.js +5 -5
- package/dist/assets/js/state-sync.js +1 -0
- 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 +319 -319
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,60 @@ 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.26.0] - 2026-10-07
|
|
8
|
+
|
|
9
|
+
Web UI polish: the sidebar now has a fixed width with the detail panel on the
|
|
10
|
+
left, and message attachments can be up to 50 MB each (up to 10 per message).
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Up to 10 attachments of 50 MB each** (`src/modules/webui`): `MAX_IMAGE_BYTES` 6 MB → 50 MB (client per file), `MAX_IMAGE_DATA_URL_BYTES` 6 MB → 70 MB (server, base64 of a 50 MB file + header), `MAX_IMAGES` 3 → 10 (client, server and the `web-ui` example plugin), `MAX_BODY_BYTES` 24 MB → 768 MB so ten base64 images fit in a single request. i18n `web.attach.too_large` updated.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- **Fixed-width sidebar, detail on the left** (`src/modules/webui/assets`): `.sb` is a constant 679 px and the auto-expanding `.sb-expanded` width transition is gone, so the sidebar no longer resizes itself on external events. The Trace detail opens to the left of the list (`flex-direction: row-reverse`); the Files viewer takes the full sidebar width with wrapped lines. The now-unused `sb-expanded` class was removed from CSS/JS.
|
|
19
|
+
|
|
20
|
+
## [2.25.0] - 2026-10-07
|
|
21
|
+
|
|
22
|
+
Multiple subagent calls emitted in one assistant turn now actually run in
|
|
23
|
+
parallel, instead of strictly one after another. The batch executor gains a
|
|
24
|
+
generic "parallelizable tool" capability; every hook, UI event and `role:"tool"`
|
|
25
|
+
message stays serial and ordered.
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **Parallelizable tool capability** (`src/tools/types.ts`): `ToolDefinition.parallelizable` opts a tool into concurrent batch execution. `subagent` sets it.
|
|
30
|
+
- **`ToolExecutor.fork()`** (`src/tools/executor.ts`): isolated executor for one concurrent call — clones the `ToolContext` by descriptors (live getters preserved), gives it its own `scope`/`recursionDepth`/`cleanup`/`activeCallId`, and shares the memo/registry/plugin manager so a subagent's mutation still invalidates the parent's cached reads.
|
|
31
|
+
- **Parallel run in `ToolBatchExecutor`** (`src/core/agent/tool-batch.ts`): consecutive `parallelizable` calls (≥2) are prepared serially, executed concurrently — each on `toolExecutor.fork()`, capped by `security.rateLimits.maxParallelTasks` (default 5) — then finalized serially in original call order. The per-call lifecycle is split into `prepareCall`/`executeCall`/`finalizeCall` so the serial and parallel paths share all bookkeeping.
|
|
32
|
+
- **Plugin-hook serialization** (`src/tools/executor.ts`): `onBeforeTool`/`onAfterTool` dispatch runs under a shared FIFO lock (one per root executor, inherited by forks), so stateful plugins (execution stuck-detector, lint-on-write, LSP) never run concurrently across sibling forks; the tool handler itself stays concurrent.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- **`subagent` runs in parallel** (`src/tools/subagent.ts`): sibling subagents no longer clobber each other's workspace scope or recursion depth (each runs on its own fork).
|
|
37
|
+
- **MoE subtasks get isolated executors** (`src/modules/execution/moe-executor.ts`): each subtask runs against its own `fork()`, removing the scope/recursion-depth race between concurrent wave tasks.
|
|
38
|
+
- **Live session footgun closed**: the tool description's "use for parallel work" is now true; the harness no longer implies concurrency it does not provide.
|
|
39
|
+
|
|
40
|
+
## [2.24.0] - 2026-10-07
|
|
41
|
+
|
|
42
|
+
The `mma web` sidebar is now event-sourced: the SSE `state` event carries the full
|
|
43
|
+
session snapshot, each tab owns its snapshot, and the client-side poll timers are
|
|
44
|
+
gone.
|
|
45
|
+
|
|
46
|
+
### Added
|
|
47
|
+
|
|
48
|
+
- **Full snapshot in the `state` event** (`src/modules/webui/session/session-status.ts`): the new `pushState(s, sessionId?)` helper broadcasts the `HostStateSnapshot` (built from the existing `Host.getState`) with the owning `sessionId`; every state change (turn start/end, queue, plan, reconfigure, re-index) goes through it.
|
|
49
|
+
- **`sessions` SSE event** (`src/modules/webui/session/sessions-api.ts`): create/activate/delete broadcast the sessions list; the client renders it directly.
|
|
50
|
+
- **Per-tab snapshot store** (`src/modules/webui/assets/js/state-sync.ts`): pure routing of `state`/`usage` payloads into `tab.state` (active-only render, `sessionId` guard, usage merge); the switched-to tab renders instantly from memory.
|
|
51
|
+
|
|
52
|
+
### Changed
|
|
53
|
+
|
|
54
|
+
- **Client no longer polls** (`src/modules/webui/assets/app.ts`): the `state` event applies the snapshot via `applyState`, `ensureTabState` renders a tab from cache or one REST fetch, and the `2s /api/state` + `15s /api/sessions` intervals are removed; reconnect re-fetches every open session tab.
|
|
55
|
+
- **Accent toggles** (`src/modules/webui/assets/styles.css`): on/off switches now fill with the theme accent color instead of a muted gray, in both dark and light themes.
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- **Auto-advance blocked by timestamp skew** (`src/modules/execution/module.ts`): `provablyStale` compares a step file's mtime against the plan's `createdAt`; the filesystem can record a file written right after plan creation a fraction of a millisecond *earlier* than `createdAt`, which falsely marked the file "pre-existing" and silently suppressed step auto-advance. A small tolerance now absorbs the skew (real stale files stay stale).
|
|
60
|
+
|
|
7
61
|
## [2.23.0] - 2026-10-07
|
|
8
62
|
|
|
9
63
|
A new **Files** sidebar tab in `mma web`: browse the workspace as a lazy tree,
|
package/dist/assets/app.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{msgs as
|
|
1
|
+
import{msgs as D,inp as g,connStatus as L,setIcon as x,icon as T}from"./js/dom.js";import{api as z,token as A}from"./js/api.js";import{I18N as J,t as i,loadI18n as Q}from"./js/i18n.js";import{tabs as l,session as f,settings as u,hooks as C}from"./js/store.js";import{routeState as X,mergeUsage as G,storeSnapshot as k,applyCounters as R}from"./js/state-sync.js";import{onText as K,onReasoning as V,onMeta as Y,onPhase as Z,onToolStart as $,onToolEnd as ee,onTurnEnd as te,onErrorEvent as se,onCommandOutput as ne,onLog as oe,onPlan as ae,onQuestion as ie,onRetract as re,showEmptyFeed as w,renderPlan as de,renderUsage as _,renderEnvironment as ce,renderWorkspace as le,feedHasContent as fe,loadHistory as ue}from"./js/feed.js";import{openTab as P,updateTabName as pe,renderSessionsDropdown as h,reflectBusy as be,loadSessions as q,loadCommands as me,setTabStatus as p,reconcileTabStatuses as ge}from"./js/session/tabs.js";import{renderSelectors as S,renderSettings as we,loadConfig as he,loadModels as Se,loadProviders as ve,loadMemory as ye,loadSkills as Ie,loadPlugins as Ee,applyTheme as Le,currentTheme as xe,applyFontSize as Te,setConnStatus as v,setStaleBar as B}from"./js/settings.js";import{initRail as Ae,setPlan as N,railEvent as Ce,applyRailI18n as ke}from"./js/rail.js";import{initSidebar as Re,sidebarSessionChanged as _e,sidebarMapState as Pe,sidebarTraceEvent as y,sidebarTurnEnd as qe,sidebarBusy as M,sidebarMapIndicator as Be,sidebarPullLog as Ne,sidebarSessionId as Me,setSessionLoading as He,sidebarLspState as Ue,sidebarLspEvent as Fe,applySidebarI18n as H,initFiles as We,sidebarFilesState as Oe,sidebarFilesChanged as U}from"./js/sidebar.js";import{insertIntoDraft as je}from"./js/session/composer.js";document.querySelectorAll("[data-collapse]").forEach(s=>{const e=s.querySelector(".arrow");e&&(e.textContent="",e.appendChild(T("chevron-down"))),s.addEventListener("click",()=>{const o=s.nextElementSibling;if(!o)return;const a=o.classList.toggle("collapsed");s.setAttribute("aria-expanded",a?"false":"true");const r=s.querySelector(".arrow");r&&(r.textContent="",r.appendChild(T(a?"chevron-right":"chevron-down")))})});const b=document.getElementById("toggleSidebar");b&&(b.addEventListener("click",()=>{const s=document.body.classList.toggle("sb-open");b.setAttribute("aria-expanded",s?"true":"false")}),document.addEventListener("keydown",s=>{if(s.key!=="Escape"||!document.body.classList.contains("sb-open"))return;const e=document.activeElement?String(document.activeElement.tagName):"";e==="TEXTAREA"||e==="INPUT"||(document.body.classList.remove("sb-open"),b.setAttribute("aria-expanded","false"))}));let I=-1;function m(){const s=l.tabs.find(r=>r.id===l.activeTabId)||null,e=s&&s.state||{};f.host=e;const o=e.sessionId||s&&s.id||null;f.activeSessionId=o,l.tabs.length||w(),de(e.plan),N(f.busy&&e?e.plan:null),_(e),typeof e.contextWindow=="number"&&u.config&&u.config.contextWindow!==e.contextWindow&&(u.config.contextWindow=e.contextWindow,S()),ce(e),Pe(e),Be(e),Ue(),Oe(e);const a=typeof e.filesRevision=="number"?e.filesRevision:void 0;if(a!==void 0&&a!==I){const r=I===-1;I=a,!r&&a>0&&U()}_e(o),le(e),h(),He(!1),B(!!e.i18nStale)}function De(s){const e=X(s);be(),ge(),s.state&&typeof s.state.sessionId=="string"&&pe(s.state.sessionId,s.state.sessionName),e&&m()}async function F(s){const e=s?"/api/state?session="+encodeURIComponent(s):"/api/state",o=await z(e);return o.ok&&o.data?o.data:null}async function W(s){const e=l.tabs.find(a=>a.id===s);if(!e)return;if(e.state){l.activeTabId===s&&m();return}const o=await F(s);o&&(k(o.state),l.activeTabId===s&&(R(o),m()))}async function O(){const s=l.activeTabId,e=await F(s);if(!e||l.activeTabId!==s)return;const o=e.state;!s&&o&&o.sessionId&&!l.tabs.some(a=>a.id===o.sessionId)&&P(o.sessionId,o.sessionName||String(o.sessionId),"session",!1),k(o),R(e),m()}C.ensureTabState=W;function ze(){for(const e of l.tabs)e.kind==="session"&&(e.state=null,W(e.id));O(),q();const s=l.tabs.find(e=>e.id===l.activeTabId);s&&s.kind==="session"&&!fe(s.feed)&&(s.historyLoaded=!1,ue(s))}function Je(){const s="/events"+(A?"?token="+encodeURIComponent(A):""),e=new EventSource(s);let o=!1;e.onopen=()=>{o&&(o=!1,v(!1),ze())},e.onerror=t=>{t&&typeof t.data=="string"||(o=!0,v(!0))};const a=t=>{try{return JSON.parse(t.data)}catch{return null}},r=t=>!t.sessionId||t.sessionId===Me(),c=[["text",t=>K(t.chunk||"",t.sessionId)],["meta",t=>Y(t.chunk||"",t.sessionId,t.kind)],["reasoning",t=>V(t.chunk||"",t.sessionId)],["phase",t=>Z(t.phase,t.sessionId)],["tool_start",$],["tool_end",ee],["plan",ae],["question",ie],["turn_end",t=>{te(t),r(t)&&(qe(t.turnSeq),M(!1),Ne())}],["log",oe],["retract",t=>re(t.reason||"",t.sessionId)]];for(const[t,n]of c)e.addEventListener(t,d=>{const E=a(d);E&&n(E)});for(const t of["tool_start","tool_end","text","plan"])e.addEventListener(t,n=>{const d=a(n);d&&(t==="plan"?N(d):Ce(t,d.name))});for(const t of["text","reasoning","phase","tool_start","plan"])e.addEventListener(t,n=>{const d=a(n);d&&d.sessionId&&p(d.sessionId,"working")});e.addEventListener("question",t=>{const n=a(t);n&&n.sessionId&&p(n.sessionId,"waiting")}),e.addEventListener("turn_end",t=>{const n=a(t);n&&n.sessionId&&p(n.sessionId,n.success===!1?"failed":"idle")});for(const t of["tool_start","tool_end","phase","plan","question","meta","log","retract","index"])e.addEventListener(t,n=>{const d=a(n);d&&r(d)&&y(t,d)});e.addEventListener("text",t=>{const n=a(t);n&&r(n)&&y("text",n)}),e.addEventListener("lsp",t=>{const n=a(t);n&&Fe(n)}),e.addEventListener("files",()=>U()),e.addEventListener("command",t=>{const n=a(t);n&&typeof n.text=="string"&&ne(n.text,n.sessionId)}),e.addEventListener("state",t=>{const n=a(t);n&&(M(!!n.busy),De(n))}),e.addEventListener("sessions",t=>{const n=a(t);n&&Array.isArray(n.sessions)&&(f.sessions=n.sessions,h())}),e.addEventListener("usage",t=>{const n=a(t);if(!n||!n.usage||typeof n.usage!="object")return;const d=n.usageSessionId||n.sessionId||null;G(d,n.usage)&&_(f.host)}),e.addEventListener("error",t=>{if(!t.data)return;const n=a(t);n&&(n.sessionId&&p(n.sessionId,"failed"),se(n),y("error",n))})}function j(){document.documentElement.lang=J.locale;const s=(r,c)=>{const t=document.getElementById(r);t&&(t.textContent=c)};s("planHeaderLabel",i("web.sidebar.plan")),s("usageHeaderLabel",i("web.sidebar.session")+" · "+i("web.sidebar.usage")),s("envHeaderLabel",i("web.sidebar.env")),s("settingsTitle",i("web.settings.title")),s("sessActiveHeader",i("web.sessions.active")),s("sessRecentHeader",i("web.sessions.recent")),s("hintEnter",i("web.input.enter")),s("hintShift",i("web.input.shift_enter")),s("hintEsc",i("web.input.esc")),s("hintAttach",i("web.input.attach"));const e={newChat:["plus",i("web.topbar.new_chat")],sessBtn:["menu",i("web.topbar.all_sessions")],toggleSidebar:["panel",i("web.topbar.sidebar")],openSettings:["settings",i("web.topbar.settings")],attachBtn:["image",i("web.attach.title")],closeSettings:["x",i("web.topbar.close")],sessNew:["plus",i("web.sessions.new")],sessRefresh:["refresh",i("web.sessions.refresh")],sessPrev:["chevron-left",i("web.sessbar.prev")],sessNext:["chevron-right",i("web.sessbar.next")],sessClose:["x",i("web.topbar.close")]};Object.keys(e).forEach(r=>{const c=document.getElementById(r);if(!c)return;const[t,n]=e[r];x(c,t,r==="closeSettings"||r==="sessNew"||r==="sessRefresh"?n:null),c.title=n,c.setAttribute("aria-label",n)});const o=document.getElementById("settingsIcon");o&&x(o,"settings",null),g&&(g.placeholder=i("web.input.placeholder"),g.setAttribute("aria-label",i("web.input.placeholder"))),document.querySelectorAll("#setMenu .mi").forEach(r=>{const c=r.dataset.p;c&&(r.textContent=i("web.settings."+c))});const a=document.getElementById("setSearch");a&&(a.setAttribute("placeholder",i("web.settings.search_placeholder")),a.setAttribute("aria-label",i("web.settings.search_placeholder"))),document.querySelectorAll(".content-col .panel").forEach(r=>{const c=r.querySelector("h3"),t=r.id.replace(/^p-/,"");c&&t&&(c.textContent=i("web.settings."+t))}),S(),h(),ke(),H(),D.querySelector(".empty")&&w(),L&&!L.hidden&&v(!0),B(void 0,!0)}async function Qe(){const s=new URLSearchParams(location.search).get("session");if(window.MmaSetup)try{if(await window.MmaSetup.maybeOpen())return}catch{}await Q(),await me(),Le(xe()),Te(),j(),w(),S(),we(),await he(),Ae(u.config&&u.config.ui?u.config.ui.activityRail:void 0),Re(),H(),We({insertPath:e=>je("`"+e+"` ")}),await Se(),await ve(),await q(),await ye(),await Ie(),await Ee();try{await O()}catch(e){console.error("initial refresh failed",e)}if(s){const e=f.sessions.find(o=>o.id===s);e&&P(s,e.name||String(s),"session",!0)}Je()}C.applyStaticI18n=j,Qe();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{feed as s}from"./feed.js";import{tabs as c}from"./tabs.js";import{settings as f}from"./settings.js";import{session as i}from"./session.js";export{s as feed,c as tabs,f as settings,i as session};export const THEME_KEY="mma-theme",MAX_IMAGES=
|
|
1
|
+
import{feed as s}from"./feed.js";import{tabs as c}from"./tabs.js";import{settings as f}from"./settings.js";import{session as i}from"./session.js";export{s as feed,c as tabs,f as settings,i as session};export const THEME_KEY="mma-theme",MAX_IMAGES=10,MAX_IMAGE_BYTES=50*1024*1024,hooks={applyStaticI18n:null};export function setPath(r,n,p){const t=n.split(".");let o=r;for(let e=0;e<t.length-1;e++)(o[t[e]]==null||typeof o[t[e]]!="object")&&(o[t[e]]={}),o=o[t[e]];o[t[t.length-1]]=p}export function getPath(r,n){const p=n.split(".");let t=r;for(const o of p){if(t==null||typeof t!="object")return;t=t[o]}return t}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{msgs as k,inp as S,tabstripEl as l,el as u,icon as
|
|
1
|
+
import{msgs as k,inp as S,tabstripEl as l,el as u,icon as I,link as E}from"../dom.js";import{api as m}from"../api.js";import{t as o}from"../i18n.js";import{tabs as a,session as b,hooks as A}from"../store.js";import{makeFeed as q,showEmptyFeed as D,activeFeed as F,appendTo as x,feedHasContent as B,loadHistory as O,syncUrl as h,scrollToBottom as w}from"../feed.js";import{setIndicator as M}from"../dialog.js";import{sidebarSessionChanged as P,setSessionLoading as v}from"../sidebar.js";import{setSessOpen as H}from"../core/menus.js";import{closeCmdk as W}from"./cmdk.js";import{saveComposer as C,restoreComposer as L,renderAttachments as Y,renderSessBar as _,initComposer as N}from"./composer.js";import{renderSessionsDropdown as p,initSessionsMenu as U}from"./sessions-menu.js";export{reflectBusy}from"./composer.js";export{loadCommands}from"./cmdk.js";export{renderSessionsDropdown}from"./sessions-menu.js";const V={working:"●",waiting:"◉",queued:"○",failed:"✗",dead:"✗"};function T(e){return e==="working"?o("web.tab.working"):e==="waiting"?o("web.tab.waiting"):e==="queued"?o("web.tab.queued"):e==="failed"?o("web.tab.failed"):e==="dead"?o("web.tab.gone"):""}export function activeTab(){return a.tabs.find(e=>e.id===a.activeTabId)||null}export function setTabStatus(e,t){if(!e)return;const i=a.tabs.find(n=>n.id===e);!i||i.status===t||i.dead||(i.status=t,c())}export function markTabDead(e){const t=a.tabs.find(s=>s.id===e);if(!t||t.dead)return;t.dead=!0,t.status="dead",t.historyLoaded=!0,t.historyFailed=!1,t.planCard=null,v(!1),t.feed.replaceChildren();const i=u("div","warnline","✗ "+o("web.session.gone"));x(t.feed,i);const n=E(o("web.topbar.close"),"",()=>closeTab(e));x(t.feed,n),t.feed===F()&&w(),c()}function c(){l.textContent="",a.tabs.forEach(e=>{const t=e.id===a.activeTabId,i=e.name||e.id,n=e.kind==="session"?String(e.id):i,s=u("div","stab"+(t?" on":""));if(s.setAttribute("role","tab"),s.setAttribute("tabindex",t?"0":"-1"),s.setAttribute("aria-selected",t?"true":"false"),s.setAttribute("aria-label",i),s.title=n,e.status&&e.status!=="idle"){const d=u("span","dot st-"+e.status,V[e.status]||"●");d.title=T(e.status),d.setAttribute("aria-label",T(e.status)),s.appendChild(d)}const r=u("span","name",i);r.title=n,s.appendChild(r);const f=u("button","stab-x");f.type="button",f.title=o("web.topbar.close"),f.setAttribute("aria-label",o("web.topbar.close")+": "+i),f.appendChild(I("x")),f.addEventListener("click",d=>{d.stopPropagation(),closeTab(e.id)}),s.appendChild(f);const g=()=>openTab(e.id,e.name,e.kind,!0);s.addEventListener("click",g),s.addEventListener("keydown",d=>{(d.key==="Enter"||d.key===" ")&&(d.preventDefault(),g())}),l.appendChild(s)}),j(),_()}function j(){const e=l.querySelector(".stab.on");if(!e)return;const t=Math.max(0,e.offsetLeft-4);(t<l.scrollLeft||t+e.offsetWidth>l.scrollLeft+l.clientWidth)&&(l.scrollLeft=t)}l.addEventListener("wheel",e=>{e.deltaY!==0&&(e.preventDefault(),l.scrollLeft+=e.deltaY)},{passive:!1});export function updateTabName(e,t){if(!e||!t)return;const i=a.tabs.find(s=>s.id===e);i&&i.name!==t&&(i.name=t,c());const n=b.sessions.find(s=>s.id===e);n&&n.name!==t&&(n.name=t,p())}export function openTab(e,t,i,n){C();let s=a.tabs.find(r=>r.id===e);if(s?t&&(s.name=t):(s={id:e,name:t||e,kind:i||"session",feed:q(),historyLoaded:!1,historyLoading:!1,historyFailed:!1,dead:!1,planCard:null,draft:"",attachments:[],status:"idle"},a.tabs.push(s)),a.activeTabId=e,a.liveTabId=e,(i||"session")==="session"&&(b.activeSessionId=e,P(e),A.ensureTabState?.(e)),k.replaceChildren(s.feed),L(s),c(),p(),w(),s.kind==="session"&&!n&&(s.historyLoaded=!0),n&&s.kind==="session"){if(s.dead){h();return}(!B(s.feed)||s.historyFailed)&&(s.historyLoaded=!1),v(!0),m("/api/sessions/activate",{method:"POST",body:{id:e}}).then(r=>{if(r.status===404){markTabDead(e),loadSessions();return}loadSessions()}),O(s).then(r=>{r&&r.gone&&markTabDead(s.id)})}h()}export function closeTab(e){const t=a.tabs.findIndex(n=>n.id===e);if(t===-1)return;const i=a.activeTabId===e;if(i&&C(),a.tabs=a.tabs.filter(n=>n.id!==e),i){const n=a.tabs[Math.min(t,a.tabs.length-1)];n?(a.activeTabId=n.id,a.liveTabId=n.id,k.replaceChildren(n.feed),L(n),w()):(a.activeTabId=null,a.liveTabId=null,S&&(S.value=""),a.attachments=[],Y(),D())}c(),p(),h()}async function y(){const e=await m("/api/sessions",{method:"POST",body:{}});if(e.ok&&e.data&&e.data.session&&e.data.session.id){const t=e.data.session;openTab(t.id,t.name||String(t.id),"session",!1),await loadSessions(),v(!0);return}a.newSeq++,openTab("new"+a.newSeq,o("web.empty.title"),"new",!1),M(o("web.sessions.create_failed"),!0)}document.getElementById("newChat")?.addEventListener("click",()=>{y()});export function reconcileTabStatuses(){const e=b.runningSessionIds||[],t=b.queued||{};let i=!1;a.tabs.forEach(n=>{if(n.kind!=="session"||n.status==="waiting"||n.status==="failed"||n.status==="dead")return;const s=e.includes(n.id)?"working":t[n.id]>0?"queued":"idle";n.status!==s&&(n.status=s,i=!0)}),i&&c()}export async function loadSessions(){const e=await m("/api/sessions");!e.ok||!e.data||(b.sessions=Array.isArray(e.data.sessions)?e.data.sessions:[],p())}document.addEventListener("click",()=>{document.querySelectorAll("[data-sel]").forEach(e=>e.classList.remove("open")),H(!1),W()}),N({activeTab,setTabStatus,newChatTab:y,markTabDead,openTab,closeTab,statusTitle:T}),U({openTab,closeTab,loadSessions,newChatTab:y});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{el as o,icon as g}from"../dom.js";import{api as
|
|
1
|
+
import{el as o,icon as g}from"../dom.js";import{api as P}from"../api.js";import{t as r}from"../i18n.js";import{renderMarkdown as L}from"../../md.js";import{sb as t}from"./state.js";let m={insertPath:()=>{}};export function initFiles(e){m={...m,...e},t.files.treeEl=document.getElementById("filesTree"),t.files.detailEl=document.getElementById("filesDetail"),t.files.detailTitleEl=document.getElementById("filesTitle"),t.files.detailBodyEl=document.getElementById("filesBody"),t.files.detailAttachEl=document.getElementById("filesAttach"),document.getElementById("filesClose")?.addEventListener("click",closeFile),t.files.detailAttachEl?.addEventListener("click",()=>{t.files.selectedPath&&m.insertPath(t.files.selectedPath)}),document.addEventListener("keydown",n=>{n.key==="Escape"&&t.files.selectedPath&&closeFile()})}let w="",x=!0;const C=new Map,u=new Set,E=new Set;function c(){x=!0}export function sidebarFilesState(e){const n=e&&e.workspace||"";n!==w&&(w=n,t.files.listings.clear(),t.files.expanded.clear(),t.files.selectedPath=null,t.files.detailEl&&(t.files.detailEl.hidden=!0),c()),t.active==="files"&&renderFilesTree()}function h(e){if(t.files.listings.has(e))return Promise.resolve();const n=C.get(e);if(n)return n;const i=P("/api/files?path="+encodeURIComponent(e)).then(s=>{s.ok&&s.data?(t.files.listings.set(e,s.data.entries||[]),s.data.truncated&&E.add(e),u.delete(e)):u.add(e),c()}).finally(()=>C.delete(e));return C.set(e,i),i}export function refreshFilesTree(){c(),renderFilesTree()}export function renderFilesTree(){const e=t.files.treeEl;if(!(!e||!x)){if(x=!1,e.textContent="",!w){e.appendChild(o("div","fdim",r("web.files.no_workspace")));return}if(!t.files.listings.has("")){e.appendChild(o("div","fdim",u.has("")?r("web.files.error"):r("web.files.loading"))),h("").then(renderFilesTree);return}b(e,"",0)}}function b(e,n,i){const s=t.files.listings.get(n)||[];if(s.length===0&&i===0){e.appendChild(o("div","fdim",r("web.files.empty")));return}for(const d of s){const l=n?`${n}/${d.name}`:d.name;if(e.appendChild(B(d,l,i)),d.type==="dir"&&t.files.expanded.has(l))if(t.files.listings.has(l))b(e,l,i+1);else{const f=o("div","fdim",u.has(l)?r("web.files.error"):r("web.files.loading"));f.style.paddingLeft=`${8+(i+1)*14}px`,e.appendChild(f),h(l).then(renderFilesTree)}}if(E.has(n)){const d=o("div","fdim",r("web.files.truncated"));d.style.paddingLeft=`${8+i*14}px`,e.appendChild(d)}}function B(e,n,i){const s=e.type==="dir",d=!s&&t.files.selectedPath===n,l=o("div",`frow${s?" dir":""}${d?" sel":""}`);l.style.paddingLeft=`${8+i*14}px`;const f=o("span","ftw");s&&f.appendChild(g(t.files.expanded.has(n)?"chevron-down":"chevron-right")),l.appendChild(f);const a=o("span","fic");if(a.appendChild(g(s?"folder":"file")),l.appendChild(a),l.appendChild(o("span","fname",e.name)),!s){const p=o("button","fattach");p.type="button",p.title=r("web.files.attach"),p.setAttribute("aria-label",r("web.files.attach")),p.appendChild(g("paperclip")),p.addEventListener("click",k=>{k.stopPropagation(),m.insertPath(n)}),l.appendChild(p)}return l.addEventListener("click",()=>{s?I(n):openFile(n)}),l}function I(e){t.files.expanded.has(e)?t.files.expanded.delete(e):(t.files.expanded.add(e),t.files.listings.has(e)||h(e).then(renderFilesTree)),c(),renderFilesTree()}export async function openFile(e){t.files.selectedPath=e;const n=t.files.detailEl;t.files.detailTitleEl&&(t.files.detailTitleEl.textContent=e,t.files.detailTitleEl.title=e),n&&(n.hidden=!1);const i=t.files.detailBodyEl;i&&(i.textContent="",i.appendChild(o("div","fdim",r("web.files.loading")))),c(),renderFilesTree();let s;try{s=await fetch(v(e))}catch{y();return}if(!s.ok||!i){y();return}const d=s.headers.get("content-type")||"";i.textContent="",d.indexOf("text/plain")===0?O(i,e,await s.text()):T(i,e,d)}export function closeFile(){t.files.selectedPath=null,t.files.detailEl&&(t.files.detailEl.hidden=!0),c(),renderFilesTree()}export function sidebarFilesChanged(){const e=["",...t.files.expanded];e.forEach(i=>{t.files.listings.delete(i),u.delete(i),E.delete(i)}),c(),renderFilesTree();const n=t.files.selectedPath?openFile(t.files.selectedPath):Promise.resolve();Promise.all([...e.map(h),n]).then(renderFilesTree)}function y(){const e=t.files.detailBodyEl;e&&(e.textContent="",e.appendChild(o("div","fdim wn",r("web.files.open_failed"))))}function v(e){return"/api/file?path="+encodeURIComponent(e)}function F(e){const n=e.lastIndexOf(".");return n===-1?"":e.slice(n+1).toLowerCase()}function O(e,n,i){const s=F(n);if(s==="md"||s==="markdown"){const a=o("div","fmd");L(a,i),e.appendChild(a);return}const d=o("pre","fpre"),l=o("code","fcode");l.textContent=i;const f=window.hljs;if(f)try{const a=f.getLanguage(s)?f.highlight(i,{language:s,ignoreIllegals:!0}):f.highlightAuto(i);l.replaceChildren(...A(a.value))}catch{}d.appendChild(l),e.appendChild(d)}function T(e,n,i){const s=v(n);if(i.indexOf("image/")===0){const l=document.createElement("img");l.className="fimg",l.alt=n,l.src=s,e.appendChild(l);return}if(i.indexOf("application/pdf")===0){const l=o("embed","fembed");l.setAttribute("src",s),l.setAttribute("type","application/pdf"),e.appendChild(l);return}const d=i.indexOf("audio/")===0?"audio":i.indexOf("video/")===0?"video":null;if(d){const l=document.createElement(d);l.controls=!0,l.src=s,e.appendChild(l);return}y()}function A(e){const n=new DOMParser().parseFromString(e,"text/html");return Array.from(n.body.childNodes).map(i=>document.importNode(i,!0))}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{el as r}from"../dom.js";import{api as
|
|
2
|
-
`).map(s=>s.trim()).find(s=>s.length>0)||"").slice(0,160):A(e.args)}function w(e){return e.kind==="tool_fail"||e.kind==="error"||e.kind==="claim"||e.kind==="critic"&&e.status==="critical"||e.kind==="log"&&(e.level==="warn"||e.level==="error")}function _(e){const t=["trc",
|
|
3
|
-
… [truncated from `+i.textEntry.chars+" chars]"),P(i.textEntry);break}case"error":l(o({kind:"error",message:t.message||t.error||""}));break;case"meta":{if(t.kind!==void 0&&t.kind!=="status")break;const s=t.chunk||"";if(!s.trim())break;l(o({kind:"status",text:s}));break}case"log":{if(t.diagnostic&&t.level==="info")break;const s=t.text||"";if(!s.trim())break;l(o({kind:"log",text:s,level:t.level||"",source:t.source||""}));break}case"retract":l(o({kind:"retract",text:t.reason||""}));break;case"index":{const s=t.stats&&typeof t.stats=="object"?Object.entries(t.stats).map(([n,d])=>n+": "+d).join(", "):"";l(o({kind:"index",phase:t.phase||"",text:s}));break}default:break}}export async function sidebarPullLog(){const e=i.el&&i.el.dataset.sid;if(!(!e||i.logPulling)){i.logPulling=!0;try{let t="/api/sessions/"+encodeURIComponent(e)+"/log?limit=100";i.logCursor&&(t+="&since="+encodeURIComponent(i.logCursor));const s=await
|
|
4
|
-
… [truncated from `+e.length+" chars]"}export function renderDetail(e){const t=i.detailGlyph,s=i.detailTitle,n=i.detailBody,d=i.detailEl;if(!d||!t||!s||!n)return;d.hidden=!1;const m=w(e);t.textContent=m?"⚠":e.kind==="question"?"?":"◇",t.style.color=m?"var(--yellow)":"var(--accent)",s.textContent=C(e),n.textContent="";const c=r("div");c.appendChild(r("h5","",a("web.sidebar.detail_metadata")));const g=e.ts?new Date(e.ts):null;if((e.kind==="tool"||e.kind==="tool_fail")&&(c.appendChild(k(a("web.sidebar.detail_status"),e.success===!1?a("web.sidebar.detail_fail"):a("web.sidebar.detail_ok"))),e.durationMs&&c.appendChild(k(a("web.sidebar.detail_duration"),
|
|
5
|
-
`);p&&s.appendChild(b(a("web.sidebar.detail_provenance"),h(p)))}catch{}}export function collapseDetail(){i.selected=null,i.
|
|
1
|
+
import{el as r}from"../dom.js";import{api as E}from"../api.js";import{t as a}from"../i18n.js";import{labelOf as T,categoryOf as B,argText as A,formatMs as v}from"../format.js";import{sb as i,paneEl as S,TRACE_CAP as M,MAX_OUTPUT_CHARS as x}from"./state.js";function q(e){return e==="composing"?a("web.rail.composing"):e==="tool"?a("web.rail.working"):e==="thinking"?a("web.action.thinking"):String(e||"")}function L(e,t){return e==="tool"||e==="tool_fail"?B(t):e==="phase"?"phase":"meta"}function C(e){switch(e.kind){case"phase":return q(e.phase);case"plan":return a("web.sidebar.trace_plan");case"question":return a("web.sidebar.trace_question");case"text":return a("web.sidebar.trace_text",{count:e.chars||0});case"status":return a("web.sidebar.trace_status");case"log":return a("web.sidebar.trace_log",{level:e.level||""});case"retract":return a("web.sidebar.trace_retract");case"index":return a("web.sidebar.trace_index",{phase:e.phase||""});case"critic":return a("web.sidebar.trace_critic",{status:e.status||""});case"moe":return a("web.sidebar.trace_moe");case"compaction":return a("web.sidebar.trace_compaction");case"probe":return a("web.sidebar.trace_probe");case"usage":return a("web.sidebar.trace_usage");case"audit":return a("web.sidebar.trace_audit");case"claim":return a("web.sidebar.trace_claim",{kind:e.subkind||""});case"output":return a("web.sidebar.trace_output");default:return T(e.name)}}function R(e){if(e.kind==="text"||e.kind==="phase")return"";if(e.kind==="plan"){const t=typeof e.currentIndex=="number"?e.currentIndex:0,s=Array.isArray(e.steps)?e.steps.length:0;return s?a("web.rail.step_of",{cur:Math.min(t+1,s),total:s}):""}return e.kind==="question"?e.text||"":e.text&&typeof e.text=="string"&&e.kind!=="tool"&&e.kind!=="tool_fail"?(e.text.split(`
|
|
2
|
+
`).map(s=>s.trim()).find(s=>s.length>0)||"").slice(0,160):A(e.args)}function w(e){return e.kind==="tool_fail"||e.kind==="error"||e.kind==="claim"||e.kind==="critic"&&e.status==="critical"||e.kind==="log"&&(e.level==="warn"||e.level==="error")}function _(e){const t=["trc",L(e.kind,e.name)];w(e)&&t.push("warn"),i.selected===e.id&&t.push("sel");const s=r("div",t.join(" "));s.dataset.id=String(e.id),s.appendChild(r("span","g",w(e)?"⚠":e.kind==="question"?"?":"◇")),s.appendChild(r("span","lab",C(e)));const n=R(e);return n&&s.appendChild(r("span","args",n)),e.durationMs&&s.appendChild(r("span","t",v(e.durationMs))),s.addEventListener("click",()=>{if(i.selected===e.id){collapseDetail();return}i.listEl&&i.listEl.querySelectorAll(".trc.sel").forEach(d=>d.classList.remove("sel")),i.selected=e.id,s.classList.add("sel"),renderDetail(e)}),s}export function renderList(){const e=i.listEl;if(!e)return;if(e.textContent="",e.dataset.lastTurn="-1",i.nodeById.clear(),i.headerByTurn.clear(),i.selected&&!i.trace.some(s=>s.id===i.selected)&&(i.selected=null),i.trace.length===0){e.appendChild(r("div","trace-turn",a("web.sidebar.trace_empty")));return}let t=-1;for(const s of i.trace){if(s.turn!==t){t=s.turn;const d=r("div","trace-turn",a("web.sidebar.trace_turn",{n:s.turn}));i.headerByTurn.set(s.turn,d),e.appendChild(d)}const n=_(s);i.nodeById.set(s.id,n),e.appendChild(n)}e.dataset.lastTurn=String(t),e.scrollTop=e.scrollHeight}function o(e){for(e.id=++i.seq,e.turn=i.turn,e.ts=Date.now(),i.trace.push(e);i.trace.length>M;){const t=i.trace.shift();if(!t)break;const s=i.nodeById.get(t.id);if(s&&(s.remove(),i.nodeById.delete(t.id)),t.toolCallId!=null&&i.callIndex.delete(t.toolCallId),!i.trace.some(n=>n.turn===t.turn)){const n=i.headerByTurn.get(t.turn);n&&(n.remove(),i.headerByTurn.delete(t.turn))}}return e}function l(e){const t=i.listEl;if(!t)return;const s=t.dataset.lastTurn?Number(t.dataset.lastTurn):-1;if(e.turn!==s){const d=r("div","trace-turn",a("web.sidebar.trace_turn",{n:e.turn}));i.headerByTurn.set(e.turn,d),t.appendChild(d),t.dataset.lastTurn=String(e.turn)}const n=_(e);i.nodeById.set(e.id,n),t.appendChild(n),t.scrollTop=t.scrollHeight}function j(e){const t=i.nodeById.get(e.id),s=_(e);i.nodeById.set(e.id,s),t&&t.parentNode?t.replaceWith(s):i.listEl&&i.listEl.appendChild(s),i.listEl&&(i.listEl.scrollTop=i.listEl.scrollHeight)}function P(e){const t=i.nodeById.get(e.id);t&&(t.textContent="",t.appendChild(r("span","g","✦")),t.appendChild(r("span","lab",C(e))),i.listEl&&(i.listEl.scrollTop=i.listEl.scrollHeight))}export function sidebarSessionChanged(e){(i.el&&i.el.dataset.sid)!==(e||"")&&(i.el&&(i.el.dataset.sid=e||""),i.trace=[],i.callIndex.clear(),i.textEntry=null,i.turn=0,i.seq=0,i.logCursor=new Date().toISOString(),i.logPulling=!1,collapseDetail(),renderList())}export function sidebarSessionId(){return i.el&&i.el.dataset.sid||null}export function setSessionLoading(e){if(!i.el)return;i.el.classList.toggle("sb-loading",!!e);const t=S("session");t&&t.setAttribute("aria-busy",e?"true":"false")}export function sidebarTurnEnd(e){i.turn=typeof e=="number"&&e>i.turn?e:i.turn+1,i.textEntry=null}export function sidebarTraceEvent(e,t){if(t)switch(e){case"tool_start":{const s=o({kind:"tool",name:t.name,args:t.args||{},toolCallId:t.toolCallId});t.toolCallId!=null&&i.callIndex.set(t.toolCallId,s),l(s);break}case"tool_end":{const s=t.toolCallId!=null?i.callIndex.get(t.toolCallId):void 0;if(t.toolCallId!=null&&i.callIndex.delete(t.toolCallId),s)s.kind=t.success===!1?"tool_fail":"tool",s.success=t.success!==!1,s.durationMs=t.durationMs,s.output=t.output||"",j(s);else{const n=o({kind:t.success===!1?"tool_fail":"tool",name:t.name,args:t.args||{},toolCallId:t.toolCallId,success:t.success!==!1,durationMs:t.durationMs,output:t.output||""});l(n)}break}case"phase":t.phase!=="done"&&l(o({kind:"phase",phase:t.phase}));break;case"plan":l(o({kind:"plan",steps:Array.isArray(t.steps)?t.steps:[],currentIndex:typeof t.currentIndex=="number"?t.currentIndex:0}));break;case"question":l(o({kind:"question",text:t.question||t.text||""}));break;case"text":{i.textEntry||(i.textEntry=o({kind:"text",text:"",chars:0}),l(i.textEntry));const s=t.chunk||"";i.textEntry.chars+=s.length,i.textEntry.text+=s,i.textEntry.text.length>x&&(i.textEntry.text=i.textEntry.text.slice(0,x)+`
|
|
3
|
+
… [truncated from `+i.textEntry.chars+" chars]"),P(i.textEntry);break}case"error":l(o({kind:"error",message:t.message||t.error||""}));break;case"meta":{if(t.kind!==void 0&&t.kind!=="status")break;const s=t.chunk||"";if(!s.trim())break;l(o({kind:"status",text:s}));break}case"log":{if(t.diagnostic&&t.level==="info")break;const s=t.text||"";if(!s.trim())break;l(o({kind:"log",text:s,level:t.level||"",source:t.source||""}));break}case"retract":l(o({kind:"retract",text:t.reason||""}));break;case"index":{const s=t.stats&&typeof t.stats=="object"?Object.entries(t.stats).map(([n,d])=>n+": "+d).join(", "):"";l(o({kind:"index",phase:t.phase||"",text:s}));break}default:break}}export async function sidebarPullLog(){const e=i.el&&i.el.dataset.sid;if(!(!e||i.logPulling)){i.logPulling=!0;try{let t="/api/sessions/"+encodeURIComponent(e)+"/log?limit=100";i.logCursor&&(t+="&since="+encodeURIComponent(i.logCursor));const s=await E(t);if(!s.ok||!s.data||!Array.isArray(s.data.log))return;for(const n of s.data.log)typeof n.ts=="string"&&(i.logCursor===null||n.ts>i.logCursor)&&(i.logCursor=n.ts),O(n)}catch{}finally{i.logPulling=!1}}}function O(e){if(!(!e||typeof e.type!="string"))switch(e.type){case"critic_check":l(o({kind:"critic",status:"check",text:"",iteration:e.iteration}));break;case"critic_verdict":l(o({kind:"critic",status:e.status||"",text:e.content||"",iteration:e.iteration}));break;case"critic_escalation":l(o({kind:"critic",status:"escalation",text:e.content||"",iteration:e.iteration}));break;case"moe_plan":case"moe_subtask":case"moe_replan":case"moe_verify":{const t=[e.title,e.subtaskId,e.expertTag,e.status].filter(s=>typeof s=="string"&&s).join(" · ");l(o({kind:"moe",subtype:e.type,text:t,iteration:e.iteration}));break}case"compaction":l(o({kind:"compaction",text:e.content||"",iteration:e.iteration}));break;case"context_probe":l(o({kind:"probe",text:e.content||""}));break;case"llm_usage":{const t=typeof e.totalTokens=="number"?e.totalTokens:(e.promptTokens||0)+(e.completionTokens||0),s=[e.model||e.provider,t?t+" tok":""].filter(Boolean).join(" · ");l(o({kind:"usage",text:s,iteration:e.iteration}));break}case"audit":l(o({kind:"audit",text:e.content||"",iteration:e.iteration}));break;case"claim_retry":l(o({kind:"claim",subkind:e.kind||"",text:e.content||"",iteration:e.iteration}));break;case"output":l(o({kind:"output",text:e.content||"",iteration:e.iteration}));break;default:break}}function b(e,t){const s=r("div");return s.appendChild(r("h5","",e)),s.appendChild(t),s}function k(e,t){const s=r("div","kv");s.appendChild(r("span","dim",e));const n=r("b");return n.textContent=t,s.appendChild(n),s}function h(e){const t=r("div","code");return t.textContent=e,t}function D(e){return typeof e!="string"?"":e.length<=x?e:e.slice(0,x)+`
|
|
4
|
+
… [truncated from `+e.length+" chars]"}export function renderDetail(e){const t=i.detailGlyph,s=i.detailTitle,n=i.detailBody,d=i.detailEl;if(!d||!t||!s||!n)return;d.hidden=!1;const m=w(e);t.textContent=m?"⚠":e.kind==="question"?"?":"◇",t.style.color=m?"var(--yellow)":"var(--accent)",s.textContent=C(e),n.textContent="";const c=r("div");c.appendChild(r("h5","",a("web.sidebar.detail_metadata")));const g=e.ts?new Date(e.ts):null;if((e.kind==="tool"||e.kind==="tool_fail")&&(c.appendChild(k(a("web.sidebar.detail_status"),e.success===!1?a("web.sidebar.detail_fail"):a("web.sidebar.detail_ok"))),e.durationMs&&c.appendChild(k(a("web.sidebar.detail_duration"),v(e.durationMs)))),g&&c.appendChild(k(a("web.sidebar.detail_time"),g.toLocaleTimeString())),e.toolCallId&&c.appendChild(k(a("web.sidebar.detail_tool_call"),String(e.toolCallId))),i.el&&i.el.dataset.sid&&c.appendChild(k(a("web.sidebar.detail_session"),i.el.dataset.sid)),c.appendChild(k(a("web.sidebar.detail_turn"),String(e.turn))),typeof e.iteration=="number"&&c.appendChild(k(a("web.sidebar.detail_iteration"),String(e.iteration))),n.appendChild(c),e.kind==="tool"||e.kind==="tool_fail")n.appendChild(b(a("web.sidebar.detail_arguments"),h(JSON.stringify(e.args||{},null,2)))),n.appendChild(b(a("web.sidebar.detail_output"),h(D(e.output))));else if(e.kind==="text")n.appendChild(b(a("web.sidebar.detail_text"),h(e.text||""))),H(e);else if(e.kind==="plan"){const u=r("div");(e.steps||[]).forEach(p=>{const f=p.status==="done"?"✓":p.status==="failed"?"✗":p.status==="in_progress"?"▸":"○",I=p.status==="failed"?"fail":p.status==="in_progress"?"cur":p.status==="done"?"done":"";u.appendChild(r("div",("plan-step "+I).trim(),f+" "+p.text))}),n.appendChild(b(a("web.sidebar.detail_plan"),u))}else if(e.kind==="question")n.appendChild(b(a("web.sidebar.trace_question"),h(e.text||"")));else if(e.kind==="error")n.appendChild(b(a("web.sidebar.detail_error"),h(e.message||"")));else if(e.kind==="status"||e.kind==="log"||e.kind==="retract"||e.kind==="index"||e.kind==="critic"||e.kind==="moe"||e.kind==="compaction"||e.kind==="probe"||e.kind==="usage"||e.kind==="audit"||e.kind==="claim"||e.kind==="output"){const u=e.kind==="moe"&&e.subtype?e.subtype:e.kind==="log"&&e.level?"log · "+e.level:e.kind==="index"&&e.phase?"index · "+e.phase:e.kind==="critic"&&e.status?"critic · "+e.status:e.kind==="claim"&&e.subkind?"claim_retry · "+e.subkind:C(e);n.appendChild(b(u,h(e.text||"")))}}async function H(e){const t=i.el&&i.el.dataset.sid,s=i.detailBody;if(!(!t||!s||i.selected!==e.id))try{const n=await E("/api/sessions/"+encodeURIComponent(t)+"/log?types=assistant,llm_usage&limit=20");if(!n.ok||!n.data||!Array.isArray(n.data.log)||i.selected!==e.id)return;const d=n.data.log,m=d.filter(f=>f.type==="assistant"),c=d.filter(f=>f.type==="llm_usage"),g=m.map(f=>f.iteration).filter(f=>typeof f=="number"),u=c.length>0?c[c.length-1]:null,p=[a("web.sidebar.detail_provenance_count",{n:m.length})+(g.length>0?" · iter "+Math.min(...g)+"–"+Math.max(...g):""),u?[u.model||u.provider,u.totalTokens??(u.promptTokens||0)+(u.completionTokens||0)].filter(Boolean).join(" · "):""].filter(Boolean).join(`
|
|
5
|
+
`);p&&s.appendChild(b(a("web.sidebar.detail_provenance"),h(p)))}catch{}}export function collapseDetail(){i.selected=null,i.detailEl&&(i.detailEl.hidden=!0),i.listEl&&i.listEl.querySelectorAll(".trc.sel").forEach(e=>e.classList.remove("sel"))}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{tabs as o,session as i}from"./store.js";export function applyCounters(s){i.busy=!!s.busy,i.runningSessionId=s.runningSessionId||null,i.runningSessionIds=s.runningSessionIds||(i.runningSessionId?[i.runningSessionId]:[]),i.queued=s.queued||{}}export function routeState(s){applyCounters(s);const t=o.activeTabId;if(s.state){const n=typeof s.sessionId=="string"?s.sessionId:t,e=n?o.tabs.find(a=>a.id===n):null;e&&(e.state=s.state)}return!s.sessionId||s.sessionId===t}export function storeSnapshot(s){const t=s&&s.sessionId;if(typeof t!="string")return null;const n=o.tabs.find(e=>e.id===t);return n&&(n.state=s),t}export function mergeUsage(s,t){const n=s?o.tabs.find(a=>a.id===s):null;n&&(n.state=Object.assign({},n.state,t));const e=!s||s===o.activeTabId;return e&&(i.host=Object.assign({},i.host,t)),e}
|