micro-models-agent 2.22.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 +70 -0
- package/dist/assets/app.js +1 -1
- package/dist/assets/index.html +17 -0
- package/dist/assets/js/core/store/index.js +1 -1
- package/dist/assets/js/dom.js +1 -1
- package/dist/assets/js/session/composer.js +1 -1
- package/dist/assets/js/session/tabs.js +1 -1
- package/dist/assets/js/sidebar/core.js +1 -1
- package/dist/assets/js/sidebar/files.js +1 -0
- package/dist/assets/js/sidebar/state.js +1 -1
- package/dist/assets/js/sidebar/trace.js +5 -5
- package/dist/assets/js/sidebar.js +1 -1
- 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 +392 -392
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,76 @@ 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
|
+
|
|
61
|
+
## [2.23.0] - 2026-10-07
|
|
62
|
+
|
|
63
|
+
A new **Files** sidebar tab in `mma web`: browse the workspace as a lazy tree,
|
|
64
|
+
read files in-app (read-only) and attach a file to the message by inserting its
|
|
65
|
+
path. Live-refreshes on workspace changes.
|
|
66
|
+
|
|
67
|
+
### Added
|
|
68
|
+
|
|
69
|
+
- **Files sidebar tab** (`src/modules/webui/assets/js/sidebar/files.ts`, `index.html`, `styles.css`): a fifth sidebar tab (`Alt+5`) renders a lazy file tree (fetch a directory only when it is expanded), master-detail read-only viewer (text with highlight.js, markdown, images/PDF/media) and an "attach path" action on file rows and in the viewer header. Attaching inserts the workspace-relative path (backticked) into the active composer draft — no new attachment channel; the agent reads it via `read_file`.
|
|
70
|
+
- **`GET /api/files?path=`** (`src/modules/webui/file/files-api.ts`): JSON listing of one directory (dirs first, then files; `MAX_DIR_ENTRIES` cap with `truncated`), jailed to the workspace and filtered with the indexer's ignore primitives (`IGNORE_DIRS`, `.gitignore`/`.mmaignore`) and protected paths.
|
|
71
|
+
- **Live tree updates** (`src/modules/indexer/module.ts`, `src/modules/webui/index-watcher.ts`, `module.ts`, `assets/app.ts`): the workspace watcher now invokes an `onSettled` callback after its debounced rebuild, which bumps `HostStateSnapshot.filesRevision` and broadcasts a `files` SSE event; the Files tab re-reads expanded directories.
|
|
72
|
+
|
|
73
|
+
### Changed
|
|
74
|
+
|
|
75
|
+
- **Shared workspace path resolver** (`src/modules/webui/file/paths.ts`): `resolveWorkspacePath` centralizes the lexical + `realpath` + protected-path jail; `file-api.ts` and the new `files-api.ts` both use it.
|
|
76
|
+
|
|
7
77
|
## [2.22.0] - 2026-10-06
|
|
8
78
|
|
|
9
79
|
Web sidebar metrics are no longer frozen until a turn ends, and the cache cell no
|
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();
|
package/dist/assets/index.html
CHANGED
|
@@ -116,6 +116,10 @@
|
|
|
116
116
|
<span class="sb-ico" data-icon="lsp" aria-hidden="true"></span>
|
|
117
117
|
<span class="sb-dot" aria-hidden="true"></span>
|
|
118
118
|
</button>
|
|
119
|
+
<button class="sb-tab" type="button" role="tab" data-tab="files" aria-selected="false" aria-controls="pane-files" title="Files">
|
|
120
|
+
<span class="sb-ico" data-icon="files" aria-hidden="true"></span>
|
|
121
|
+
<span class="sb-dot" aria-hidden="true"></span>
|
|
122
|
+
</button>
|
|
119
123
|
</div>
|
|
120
124
|
<div class="sb-name" id="sbName"><span class="sb-ico" data-icon="session" aria-hidden="true"></span><span id="sbNameText">Session</span></div>
|
|
121
125
|
|
|
@@ -153,6 +157,19 @@
|
|
|
153
157
|
<div class="sec-body" id="lspBody"></div>
|
|
154
158
|
</div>
|
|
155
159
|
</div>
|
|
160
|
+
|
|
161
|
+
<div class="sb-pane" id="pane-files" role="tabpanel" data-pane="files" hidden>
|
|
162
|
+
<div class="files-tree" id="filesTree"></div>
|
|
163
|
+
<div class="files-detail" id="filesDetail" hidden>
|
|
164
|
+
<div class="detail-h">
|
|
165
|
+
<span class="g" id="filesGlyph" aria-hidden="true">◆</span>
|
|
166
|
+
<span id="filesTitle"></span>
|
|
167
|
+
<button class="x linkbtn" type="button" id="filesAttach" title="attach path">◧</button>
|
|
168
|
+
<button class="x linkbtn" type="button" id="filesClose" title="close">✕</button>
|
|
169
|
+
</div>
|
|
170
|
+
<div class="detail-b" id="filesBody"></div>
|
|
171
|
+
</div>
|
|
172
|
+
</div>
|
|
156
173
|
</div>
|
|
157
174
|
</div>
|
|
158
175
|
|
|
@@ -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}
|
package/dist/assets/js/dom.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const msgs=document.getElementById("msgs"),inp=document.getElementById("inp"),tabstripEl=document.getElementById("tabstrip"),planEl=document.getElementById("plan"),planCountEl=document.getElementById("planCount"),usageEl=document.getElementById("usage"),envEl=document.getElementById("env"),wsLine=document.getElementById("wsLine"),saveIndicator=document.getElementById("saveIndicator"),attachStrip=document.getElementById("attachStrip"),attachErr=document.getElementById("attachErr"),imgPicker=document.getElementById("imgPicker"),connStatus=document.getElementById("connStatus"),staleBar=document.getElementById("staleBar"),liveEl=document.getElementById("live"),sendBtn=document.getElementById("sendBtn");export function announce(e){!liveEl||!e||(liveEl.textContent="",setTimeout(()=>{liveEl.textContent=e},30))}export function el(e,a,t){const n=document.createElement(e);return a&&(n.className=a),t!=null&&(n.textContent=String(t)),n}let i=null,s=!1;function p(){return i||(i=el("div","ctip"),i.setAttribute("role","tooltip"),document.body.appendChild(i)),i}function
|
|
1
|
+
export const msgs=document.getElementById("msgs"),inp=document.getElementById("inp"),tabstripEl=document.getElementById("tabstrip"),planEl=document.getElementById("plan"),planCountEl=document.getElementById("planCount"),usageEl=document.getElementById("usage"),envEl=document.getElementById("env"),wsLine=document.getElementById("wsLine"),saveIndicator=document.getElementById("saveIndicator"),attachStrip=document.getElementById("attachStrip"),attachErr=document.getElementById("attachErr"),imgPicker=document.getElementById("imgPicker"),connStatus=document.getElementById("connStatus"),staleBar=document.getElementById("staleBar"),liveEl=document.getElementById("live"),sendBtn=document.getElementById("sendBtn");export function announce(e){!liveEl||!e||(liveEl.textContent="",setTimeout(()=>{liveEl.textContent=e},30))}export function el(e,a,t){const n=document.createElement(e);return a&&(n.className=a),t!=null&&(n.textContent=String(t)),n}let i=null,s=!1;function p(){return i||(i=el("div","ctip"),i.setAttribute("role","tooltip"),document.body.appendChild(i)),i}function c(){i&&i.classList.remove("show")}function h(){s||(s=!0,window.addEventListener("scroll",c,!0),window.addEventListener("resize",c))}export function attachTooltip(e,a){const t=()=>{const n=p();n.replaceChildren(a()),n.classList.add("show");const o=e.getBoundingClientRect(),r=n.getBoundingClientRect();let d=o.left+o.width/2-r.width/2;d=Math.max(6,Math.min(d,window.innerWidth-r.width-6));let l=o.top-r.height-7;l<6&&(l=o.bottom+7),n.style.left=d+"px",n.style.top=l+"px"};e.addEventListener("mouseenter",t),e.addEventListener("mouseleave",c),e.addEventListener("focus",t),e.addEventListener("blur",c),h()}export const SVG_NS="http://www.w3.org/2000/svg",ICONS={plus:[["path",{d:"M5 12h14"}],["path",{d:"M12 5v14"}]],menu:[["line",{x1:4,y1:6,x2:20,y2:6}],["line",{x1:4,y1:12,x2:20,y2:12}],["line",{x1:4,y1:18,x2:20,y2:18}]],settings:[["path",{d:"M12.22 2h-.44a2 2 0 0 0-2 2v.18a2 2 0 0 1-1 1.73l-.43.25a2 2 0 0 1-2 0l-.15-.08a2 2 0 0 0-2.73.73l-.22.38a2 2 0 0 0 .73 2.73l.15.1a2 2 0 0 1 1 1.72v.51a2 2 0 0 1-1 1.74l-.15.09a2 2 0 0 0-.73 2.73l.22.38a2 2 0 0 0 2.73.73l.15-.08a2 2 0 0 1 2 0l.43.25a2 2 0 0 1 1 1.73V20a2 2 0 0 0 2 2h.44a2 2 0 0 0 2-2v-.18a2 2 0 0 1 1-1.73l.43-.25a2 2 0 0 1 2 0l.15.08a2 2 0 0 0 2.73-.73l.22-.39a2 2 0 0 0-.73-2.73l-.15-.08a2 2 0 0 1-1-1.74v-.5a2 2 0 0 1 1-1.74l.15-.09a2 2 0 0 0 .73-2.73l-.22-.38a2 2 0 0 0-2.73-.73l-.15.08a2 2 0 0 1-2 0l-.43-.25a2 2 0 0 1-1-1.73V4a2 2 0 0 0-2-2z"}],["circle",{cx:12,cy:12,r:3}]],image:[["rect",{width:18,height:18,x:3,y:3,rx:2,ry:2}],["circle",{cx:9,cy:9,r:2}],["path",{d:"m21 15-3.086-3.086a2 2 0 0 0-2.828 0L6 21"}]],x:[["path",{d:"M18 6 6 18"}],["path",{d:"m6 6 12 12"}]],trash:[["path",{d:"M3 6h18"}],["path",{d:"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6"}],["path",{d:"M8 6V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"}],["line",{x1:10,y1:11,x2:10,y2:17}],["line",{x1:14,y1:11,x2:14,y2:17}]],refresh:[["path",{d:"M3 12a9 9 0 0 1 9-9 9.75 9.75 0 0 1 6.74 2.74L21 8"}],["path",{d:"M21 3v5h-5"}],["path",{d:"M21 12a9 9 0 0 1-9 9 9.75 9.75 0 0 1-6.74-2.74L3 16"}],["path",{d:"M8 21H3v-5"}]],"chevron-down":[["path",{d:"m6 9 6 6 6-6"}]],"chevron-left":[["path",{d:"m15 18-6-6 6-6"}]],"chevron-right":[["path",{d:"m9 18 6-6-6-6"}]],search:[["circle",{cx:11,cy:11,r:8}],["path",{d:"m21 21-4.3-4.3"}]],"list-checks":[["path",{d:"m3 17 2 2 4-4"}],["path",{d:"m3 7 2 2 4-4"}],["path",{d:"M13 6h8"}],["path",{d:"M13 12h8"}],["path",{d:"M13 18h8"}]],map:[["path",{d:"M14.106 5.553a2 2 0 0 0 1.788 0l3.659-1.83A1 1 0 0 1 21 4.619v12.764a1 1 0 0 1-.553.894l-4.553 2.277a2 2 0 0 1-1.788 0l-4.212-2.106a2 2 0 0 0-1.788 0l-3.659 1.83A1 1 0 0 1 3 19.381V6.618a1 1 0 0 1 .553-.894l4.553-2.277a2 2 0 0 1 1.788 0z"}],["path",{d:"M15 5.764v15"}],["path",{d:"M9 3.236v15"}]],activity:[["path",{d:"M22 12h-2.48a2 2 0 0 0-1.93 1.46l-2.35 8.36a.25.25 0 0 1-.48 0L9.24 2.18a.25.25 0 0 0-.48 0l-2.35 8.36A2 2 0 0 1 4.49 12H2"}]],"arrow-up":[["path",{d:"M12 19V5"}],["path",{d:"m5 12 7-7 7 7"}]],panel:[["rect",{width:18,height:18,x:3,y:3,rx:2,ry:2}],["line",{x1:15,y1:3,x2:15,y2:21}]],square:[["rect",{width:14,height:14,x:5,y:5,rx:2}]],copy:[["rect",{width:14,height:14,x:8,y:8,rx:2,ry:2}],["path",{d:"M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"}]],check:[["path",{d:"M20 6 9 17l-5-5"}]],info:[["circle",{cx:12,cy:12,r:10}],["path",{d:"M12 16v-4"}],["path",{d:"M12 8h.01"}]],stethoscope:[["path",{d:"M11 2v2"}],["path",{d:"M5 2v2"}],["path",{d:"M5 3H4a2 2 0 0 0-2 2v4a6 6 0 0 0 12 0V5a2 2 0 0 0-2-2h-1"}],["path",{d:"M8 15a6 6 0 0 0 12 0v-3"}],["circle",{cx:20,cy:10,r:2}]],"folder-tree":[["path",{d:"M20 10a1 1 0 0 0 1-1V6a1 1 0 0 0-1-1h-2.5a1 1 0 0 1-.8-.4l-.9-1.2A1 1 0 0 0 15 3h-2a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z"}],["path",{d:"M20 21a1 1 0 0 0 1-1v-3a1 1 0 0 0-1-1h-2.9a1 1 0 0 1-.88-.55l-.42-.85a1 1 0 0 0-.9-.6H13a1 1 0 0 0-1 1v5a1 1 0 0 0 1 1Z"}],["path",{d:"M3 5a2 2 0 0 1 2-2h3"}],["path",{d:"M3 3v13a3 3 0 0 0 3 3h4"}]],folder:[["path",{d:"M20 20a2 2 0 0 0 2-2V8a2 2 0 0 0-2-2h-7.9a2 2 0 0 1-1.69-.9L9.6 3.9A2 2 0 0 0 7.93 3H4a2 2 0 0 0-2 2v13a2 2 0 0 0 2 2Z"}]],file:[["path",{d:"M15 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7Z"}],["path",{d:"M14 2v4a2 2 0 0 0 2 2h4"}]],paperclip:[["path",{d:"m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48"}]]};export function icon(e,a){const t=document.createElementNS(SVG_NS,"svg");return t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","none"),t.setAttribute("stroke","currentColor"),t.setAttribute("stroke-width","2"),t.setAttribute("stroke-linecap","round"),t.setAttribute("stroke-linejoin","round"),t.setAttribute("aria-hidden","true"),t.setAttribute("focusable","false"),t.setAttribute("class","svg-icon"+(a?" "+a:"")),(ICONS[e]||[]).forEach(([n,o])=>{const r=document.createElementNS(SVG_NS,n);Object.keys(o).forEach(d=>r.setAttribute(d,String(o[d]))),t.appendChild(r)}),t}export function setIcon(e,a,t){return e?(e.textContent="",e.appendChild(icon(a)),t!=null&&e.appendChild(el("span","",t)),e):null}export function makeToggle(e,a){const t=el("button","toggle"+(e?" on":""));return t.type="button",t.setAttribute("role","switch"),t.setAttribute("aria-checked",e?"true":"false"),t.addEventListener("click",()=>{const n=!t.classList.contains("on");a(n)&&(t.classList.toggle("on",n),t.setAttribute("aria-checked",n?"true":"false"))}),t}export function link(e,a,t){const n=el("button","linkbtn"+(a?" "+a:""),e);return n.type="button",n.addEventListener("click",t),n}export function inlineTextNodes(e){const a=document.createDocumentFragment();return String(e??"").replace(/^-\s*/,"").split("**").forEach((n,o)=>{if(n!=="")if(o%2===1){const r=document.createElement("b");r.textContent=n,a.appendChild(r)}else a.appendChild(document.createTextNode(n))}),a}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{inp as
|
|
1
|
+
import{inp as i,imgPicker as g,attachStrip as B,attachErr as k,sendBtn as p,el as f,icon as _}from"../dom.js";import{api as S}from"../api.js";import{t as c}from"../i18n.js";import{tabs as o,session as m,settings as y,MAX_IMAGES as C,MAX_IMAGE_BYTES as z}from"../store.js";import{contextLabel as W}from"../format.js";import{clearEmpty as N,activeFeed as Y,liveFeed as j,appendTo as v,scrollToBottom as P,clearFeed as J,finishMd as Q,resetTurnText as V,finishThink as Z,showBusy as $}from"../feed.js";import{setBusy as ee}from"../rail.js";import"../core/menus.js";import{openSessionsMenu as te}from"./sessions-menu.js";import{closeCmdk as F,updateCmdk as ne,cmdkKeydown as se,initCmdk as ae}from"./cmdk.js";let r={activeTab:()=>null,setTabStatus:()=>{},newChatTab:async()=>{},markTabDead:()=>{},openTab:()=>{},closeTab:()=>{},statusTitle:()=>""};export function initComposer(e){r={...r,...e}}ae({autogrow:T});const ie=200;function T(){i&&(i.style.height="auto",i.style.height=Math.min(i.scrollHeight,ie)+"px")}function oe(e){k&&(k.textContent=e,k.hidden=!1,clearTimeout(o.attachErrTimer),o.attachErrTimer=setTimeout(()=>{k.hidden=!0},4e3))}export function renderAttachments(){if(!B)return;B.textContent="",B.hidden=o.attachments.length===0,o.attachments.forEach((t,n)=>{const s=f("div","thumb"),a=document.createElement("img");a.alt="",a.src=t,s.appendChild(a);const d=f("button","rm");d.type="button",d.title=c("web.attach.remove"),d.setAttribute("aria-label",c("web.attach.remove")),d.appendChild(_("x")),d.addEventListener("click",()=>{o.attachments.splice(n,1),renderAttachments()}),s.appendChild(d),B.appendChild(s)});const e=r.activeTab();e&&(e.attachments=o.attachments.slice())}function re(e){return new Promise((t,n)=>{const s=new FileReader;s.onload=()=>t(String(s.result)),s.onerror=()=>n(s.error||new Error("read failed")),s.readAsDataURL(e)})}async function x(e){let t="";for(const n of e){if(!n||typeof n.type!="string"||n.type.indexOf("image/")!==0){t=c("web.attach.only_images");continue}if(o.attachments.length>=C){t=c("web.attach.too_many",{max:C});break}if(n.size>z){t=c("web.attach.too_large");continue}try{const s=await re(n);if(s.indexOf("data:image/")!==0){t=c("web.attach.invalid");continue}if(o.attachments.length>=C){t=c("web.attach.too_many",{max:C});break}o.attachments.push(s)}catch{t=c("web.attach.read_failed")}}renderAttachments(),t&&oe(t)}function ce(e,t){const n=f("div","u",e);return(t||[]).forEach(s=>{const a=document.createElement("img");a.className="uimg",a.alt="",a.src=s,n.appendChild(a)}),n}export function saveComposer(){const e=r.activeTab();!e||!i||(e.draft=i.value,e.attachments=o.attachments.slice())}export function restoreComposer(e){!e||!i||(i.value=e.draft||"",o.attachments=(e.attachments||[]).slice(),renderAttachments(),T(),F())}const de=document.getElementById("sessBar"),I=document.getElementById("sessNameBtn"),le=document.getElementById("sessName"),L=document.getElementById("sessPrev"),A=document.getElementById("sessNext"),D=document.getElementById("sessClose"),O=document.getElementById("sessTools"),q=document.getElementById("sessDD"),w=document.querySelector(".bar-top"),E=document.getElementById("newChat"),M=document.createComment("top-tools");w&&E&&w.insertBefore(M,E);function X(e){if(o.tabs.length<2)return;const t=o.tabs.findIndex(a=>a.id===o.activeTabId),n=t===-1?0:(t+e+o.tabs.length)%o.tabs.length,s=o.tabs[n];s&&r.openTab(s.id,s.name,s.kind,!0)}export function renderSessBar(){if(!de)return;const e=o.tabs.find(s=>s.id===o.activeTabId),t=e?e.name||String(e.id):"—";le.textContent=t,I.title=t+(e&&e.status&&e.status!=="idle"?" · "+r.statusTitle(e.status):"");const n=o.tabs.length>0;L.disabled=o.tabs.length<2,A.disabled=o.tabs.length<2,D.disabled=!n,I.disabled=!n}function U(){!w||!O||!E||!q||(window.matchMedia("(max-width: 760px)").matches?O.append(E,q):(w.insertBefore(E,M),w.insertBefore(q,M)))}if(L&&L.addEventListener("click",()=>X(-1)),A&&A.addEventListener("click",()=>X(1)),D&&D.addEventListener("click",()=>{o.activeTabId&&r.closeTab(o.activeTabId)}),I&&I.addEventListener("click",e=>{e.stopPropagation(),te()}),typeof window.matchMedia=="function"){const e=window.matchMedia("(max-width: 760px)");typeof e.addEventListener=="function"&&e.addEventListener("change",U),U()}g&&g.addEventListener("change",()=>{x(Array.from(g.files||[])),g.value=""});const G=document.getElementById("attachBtn");G&&g&&G.addEventListener("click",()=>g.click()),i.addEventListener("paste",e=>{const t=e.clipboardData&&e.clipboardData.items;if(!t)return;const n=[];for(const s of t)if(s.kind==="file"&&s.type&&s.type.indexOf("image/")===0){const a=s.getAsFile();a&&n.push(a)}n.length&&(e.preventDefault(),x(n))});const h=document.querySelector(".input-area");h&&(["dragenter","dragover"].forEach(e=>{h.addEventListener(e,t=>{t.preventDefault(),h.classList.add("dragover")})}),h.addEventListener("dragleave",e=>{const t=e;t.relatedTarget&&h.contains(t.relatedTarget)||h.classList.remove("dragover")}),h.addEventListener("drop",e=>{e.preventDefault(),h.classList.remove("dragover");const t=e.dataTransfer;t&&t.files&&t.files.length&&x(Array.from(t.files))}));function H(){i.value="",T(),F()}export function insertIntoDraft(e){if(!i||!e)return;const t=i.selectionStart??i.value.length,n=i.selectionEnd??t;i.value=i.value.slice(0,t)+e+i.value.slice(n);const s=t+e.length;i.selectionStart=i.selectionEnd=s;const a=r.activeTab();a&&(a.draft=i.value),T(),i.focus()}i&&i.addEventListener("input",()=>{const e=r.activeTab();e&&(e.draft=i.value),T(),ne()});async function K(){const e=i.value.trim(),t=o.attachments.slice();if(!e&&!t.length)return;const n=r.activeTab(),s=n&&n.kind==="session"?n.id:null,a=j()||Y();if(n&&n.dead){N(a),r.markTabDead(n.id);return}if(N(a),Q(),V(),Z(),e.startsWith("/")){v(a,f("div","u",e)),P(),n&&(n.draft="",n.attachments=[]),o.attachments=[],renderAttachments(),H();const u=e.slice(1).split(/\s+/)[0].toLowerCase();if(u==="clear"){J(a);return}if(u==="new"){r.newChatTab();return}const b={line:e};s&&(b.sessionId=s),(await S("/api/command",{method:"POST",body:b})).ok||v(a,f("div","detail","↳ "+c("web.misc.command_unavailable")));return}if(a&&a.querySelector(".startbanner")===null&&a.querySelector(".u")===null){const u=f("div","startbanner");u.appendChild(document.createTextNode(c("web.start.label")+" ")),u.appendChild(f("b","",y.config&&y.config.model||m.host.model||"—"));const b=m.host.sessionId?" · "+c("web.start.session")+" "+String(m.host.sessionId):"";u.appendChild(document.createTextNode(" · "+(m.host.provider||y.config&&y.config.provider&&y.config.provider.active||"—")+" · "+W()+b)),a.insertBefore(u,a.firstChild)}v(a,ce(e,t)),P(),n&&(n.draft="",n.attachments=[]),o.attachments=[],renderAttachments(),H(),s&&r.setTabStatus(s,"working");const d={text:e};t.length&&(d.images=t),s&&(d.sessionId=s);const l=await S("/api/message",{method:"POST",body:d});if(l.ok)if(l.data&&l.data.noop)l.data.notice&&v(a,f("div","detail",String(l.data.notice)));else if(l.data&&l.data.queued){const u=l.data.queuedForSession||l.data.queued;v(a,f("div","detail","↳ "+c("web.input.queued",{n:u}))),s&&r.setTabStatus(s,"queued")}else window.setTimeout(()=>$(a),180);else{const u=l.data&&l.data.error||l.status,b=u==="queue_full"?c("web.input.queue_full"):u;v(a,f("div","warnline","⚠ "+b)),s&&r.setTabStatus(s,"failed")}}async function R(){const e=r.activeTab(),t=e&&e.kind==="session"?e.id:null,n=m.runningSessionIds||[];t&&!n.includes(t)||!t&&!m.busy||await S("/api/interrupt",{method:"POST",body:t?{sessionId:t}:{}})}i.addEventListener("keydown",e=>{e.isComposing||e.keyCode===229||se(e)||(e.key==="Enter"&&!e.shiftKey?(e.preventDefault(),K()):e.key==="Escape"&&(e.preventDefault(),R()))}),p&&p.addEventListener("click",()=>{const e=r.activeTab();e&&e.kind==="session"&&m.runningSessionIds.includes(e.id)?R():K()});export function reflectBusy(){const e=r.activeTab(),t=m.runningSessionIds||[],n=!!(e&&e.kind==="session"&&t.includes(e.id));i&&i.setAttribute("aria-busy",n?"true":"false");const s=document.querySelector(".input-area");if(s&&s.classList.toggle("busy",n),p){const d=n?c("web.input.stop"):c("web.input.send");p.textContent="",p.appendChild(_(n?"square":"arrow-up")),p.classList.toggle("busy",n),p.title=d,p.setAttribute("aria-label",d)}const a=document.getElementById("hintEsc");a&&(a.hidden=!n),ee(m.busy)}
|
|
@@ -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{icon as m}from"../dom.js";import{session as g}from"../store.js";import{t as
|
|
1
|
+
import{icon as m}from"../dom.js";import{session as g}from"../store.js";import{t as f}from"../i18n.js";import{sb as e,TABS as a,ICON_NAME as b,paneEl as B,mqMobile as S,readStored as h,storeTab as v}from"./state.js";import{collapseDetail as d,renderList as u,renderDetail as x}from"./trace.js";import{sidebarMapState as y,sidebarMapIndicator as I}from"./map.js";import{renderLsp as E,sidebarLspState as p}from"./lsp.js";import{renderFilesTree as T,refreshFilesTree as k}from"./files.js";export function setSidebarTab(n,i=!0){a.includes(n)||(n="session"),i&&v(n);const t=n==="trace"&&S()?"session":n;t!==e.active&&d(),e.active=t,a.forEach(r=>{const s=B(r);s&&(s.hidden=r!==t);const l=e.el&&e.el.querySelector('.sb-tab[data-tab="'+r+'"]');if(l){const c=r===t;l.classList.toggle("on",c),l.setAttribute("aria-selected",c?"true":"false")}}),e.nameTextEl&&(e.nameTextEl.textContent=f("web.sidebar.tab_"+t));const o=e.nameEl&&e.nameEl.querySelector(".sb-ico");o&&(o.textContent="",o.appendChild(m(b[t]))),t==="lsp"&&p(),t==="files"&&T()}export function sidebarBusy(n){const i=e.el&&e.el.querySelector('.sb-tab[data-tab="trace"]');i&&(i.dataset.indicator=n?"live":"")}export function applySidebarI18n(){if(e.el){if(a.forEach(n=>{const i=e.el?.querySelector('.sb-tab[data-tab="'+n+'"]');if(i){const t=f("web.sidebar.tab_"+n);i.title=t,i.setAttribute("aria-label",t)}}),setSidebarTab(e.active,!1),u(),e.selected){const n=e.trace.find(i=>i.id===e.selected);n&&x(n)}y(g.host),E(),k()}}export function initSidebar(){if(e.el||(e.el=document.querySelector(".sb"),!e.el))return;const n=e.el;e.nameEl=document.getElementById("sbName"),e.nameTextEl=document.getElementById("sbNameText"),e.mapEl=document.getElementById("mapBody"),e.lspEl=document.getElementById("lspBody"),e.listEl=document.getElementById("traceList"),e.detailEl=document.getElementById("traceDetail"),e.detailGlyph=document.getElementById("detailGlyph"),e.detailTitle=document.getElementById("detailTitle"),e.detailBody=document.getElementById("detailBody"),e.detailClose=document.getElementById("detailClose"),e.detailClose&&e.detailClose.addEventListener("click",d),n.querySelectorAll(".sb-tab .sb-ico").forEach(t=>{const o=t.closest(".sb-tab")?.dataset.tab||"session";t.textContent="",t.appendChild(m(b[o]))}),n.querySelectorAll(".sb-tab").forEach(t=>{t.addEventListener("click",()=>setSidebarTab(t.dataset.tab||"session")),t.addEventListener("keydown",o=>{if(o.key!=="ArrowLeft"&&o.key!=="ArrowRight")return;o.preventDefault();const r=a.indexOf(t.dataset.tab||"session"),s=a[(r+(o.key==="ArrowRight"?1:a.length-1))%a.length];setSidebarTab(s);const l=n.querySelector('.sb-tab[data-tab="'+s+'"]');l&&l.focus()})}),document.addEventListener("keydown",t=>{if(!t.altKey||!["1","2","3","4","5"].includes(t.key))return;const o=document.activeElement?String(document.activeElement.tagName):"";o==="INPUT"||o==="TEXTAREA"||(t.preventDefault(),setSidebarTab(a[Number(t.key)-1]))}),document.addEventListener("keydown",t=>{t.key==="Escape"&&e.selected&&d()});const i=h();setSidebarTab(i&&a.includes(i)?i:"session"),u()}export{y as sidebarMapState,I as sidebarMapIndicator,E as renderLsp,p as sidebarLspState};
|
|
@@ -0,0 +1 @@
|
|
|
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 +1 @@
|
|
|
1
|
-
export const TAB_KEY="mma-sidebar-tab",TABS=["session","map","trace","lsp"],ICON_NAME={session:"list-checks",map:"map",trace:"activity",lsp:"stethoscope"},TRACE_CAP=500,MAX_OUTPUT_CHARS=2e4,sb={el:null,nameEl:null,nameTextEl:null,mapEl:null,listEl:null,detailEl:null,detailGlyph:null,detailTitle:null,detailBody:null,detailClose:null,lspEl:null,active:"session",trace:[],selected:null,turn:0,seq:0,logCursor:null,logPulling:!1,nodeById:new Map,callIndex:new Map,headerByTurn:new Map,textEntry:null,lspDiag:null,lspFlags:null,lspProbing:!1,lspLoaded:!1,lspUnavailable:!1,reindexing:!1,postResolved:!1,reindexError:!1};export function paneEl(
|
|
1
|
+
export const TAB_KEY="mma-sidebar-tab",TABS=["session","map","trace","lsp","files"],ICON_NAME={session:"list-checks",map:"map",trace:"activity",lsp:"stethoscope",files:"folder-tree"},TRACE_CAP=500,MAX_OUTPUT_CHARS=2e4,sb={el:null,nameEl:null,nameTextEl:null,mapEl:null,listEl:null,detailEl:null,detailGlyph:null,detailTitle:null,detailBody:null,detailClose:null,lspEl:null,active:"session",trace:[],selected:null,turn:0,seq:0,logCursor:null,logPulling:!1,nodeById:new Map,callIndex:new Map,headerByTurn:new Map,textEntry:null,lspDiag:null,lspFlags:null,lspProbing:!1,lspLoaded:!1,lspUnavailable:!1,reindexing:!1,postResolved:!1,reindexError:!1,files:{treeEl:null,detailEl:null,detailTitleEl:null,detailBodyEl:null,detailAttachEl:null,expanded:new Set,listings:new Map,selectedPath:null}};export function paneEl(l){return document.getElementById("pane-"+l)}export function mqMobile(){return typeof window<"u"&&window.matchMedia?window.matchMedia("(max-width: 760px)").matches:!1}export function readStored(){try{return localStorage.getItem(TAB_KEY)}catch{return null}}export function storeTab(l){try{localStorage.setItem(TAB_KEY,l)}catch{}}
|
|
@@ -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"))}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export*from"./sidebar/core.js";export*from"./sidebar/trace.js";export*from"./sidebar/map.js";export*from"./sidebar/lsp.js";
|
|
1
|
+
export*from"./sidebar/core.js";export*from"./sidebar/trace.js";export*from"./sidebar/map.js";export*from"./sidebar/lsp.js";export*from"./sidebar/files.js";
|
|
@@ -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}
|