herm-tui 1.2.2-dev.1 → 1.3.0-dev.1
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/index.js +1 -1
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -4139,7 +4139,7 @@ Usage:
|
|
|
4139
4139
|
`).length)),lift=rows3+3;return $jsxs("box",{flexDirection:"column",position:"relative",children:[props.focused&&pop2.open?$jsx("box",{position:"absolute",bottom:lift,left:0,right:0,children:$jsx(SlashPopover,{commands:pop2.popover,cursor:pop2.cursor,onCursor:pop2.setCursor,onSelect:select})}):props.focused&&at.open?$jsx("box",{position:"absolute",bottom:lift,left:0,right:0,children:$jsx(AtRefPopover,{items:at.items,cursor:at.cursor,onCursor:at.setCursor,onSelect:atAccept})}):null,(props.queue?.length??0)>0?$jsx("box",{flexDirection:"column",paddingX:1,paddingBottom:1,children:props.queue.map((q4,i)=>$jsx("box",{height:1,onMouseDown:()=>props.onDequeue?.(i),children:$jsxs("text",{children:[$jsxs("span",{fg:theme.borderSubtle,children:[i===0?"\u256D":"\u2502"," "]}),$jsxs("span",{fg:theme.textMuted,children:["\u23F8 ",i+1,". ",trunc4(q4,60)]})]})},i))}):null,(props.attachments?.length??0)>0?$jsx("box",{flexDirection:"column",paddingX:1,paddingBottom:1,gap:1,children:props.attachments.map((a)=>a.path?$jsx(ChafaImage,{path:a.path,width:60},`p-${a.path}`):null)}):null,(props.attachments?.length??0)>0?$jsx("box",{flexDirection:"row",flexWrap:"wrap",gap:1,paddingX:1,paddingBottom:1,children:props.attachments.map((a,i)=>$jsxs("text",{children:[$jsx("span",{bg:theme.accent,fg:theme.background,children:" img "}),$jsxs("span",{bg:theme.backgroundElement,fg:theme.textMuted,children:[" ",a.name??`image ${i+1}`," "]}),a.width&&a.height?$jsxs("span",{bg:theme.backgroundElement,fg:theme.textMuted,children:[a.width,"\xD7",a.height," "]}):null,a.token_estimate?$jsxs("span",{bg:theme.backgroundElement,fg:theme.textMuted,children:["~",fmt3(a.token_estimate),"t "]}):null,$jsx("span",{fg:theme.textMuted,children:" "}),$jsx("span",{fg:theme.textMuted,children:"\u232B to detach"})]},a.path??i))}):null,$jsxs("box",{border:!0,borderStyle:"single",borderColor:props.focused?theme.borderActive:theme.border,flexDirection:"row",position:"relative",children:[$jsx("box",{width:1,children:$jsx("text",{fg:theme.primary,children:">"})}),$jsx("box",{width:1}),$jsx("textarea",{ref:ta,onContentChange:()=>setInput(ta.current?.plainText??""),onSubmit:submit,onPaste:paste,keyBindings:bindings,wrapMode:"word",minHeight:1,maxHeight:MAX_ROWS,placeholder:props.streaming?"Type to queue... (Enter queues, click chip to edit)":"Message Hermes... (/ for commands, Shift+Enter for newline)",focused:props.focused,textColor:theme.text,focusedTextColor:theme.text,placeholderColor:theme.textMuted,cursorColor:theme.text,backgroundColor:"transparent",focusedBackgroundColor:"transparent",flexGrow:1}),pop2.ghost&&props.focused&&rows3===1?$jsx("box",{position:"absolute",top:0,left:2+input.length,height:1,children:$jsx("text",{fg:theme.textMuted,children:pop2.ghost})}):null]}),$jsxs("box",{height:1,flexDirection:"row",paddingX:1,children:[$jsxs("text",{children:[$jsx("span",{fg:dot,children:"\u25CF "}),$jsx("span",{fg:theme.textMuted,children:label})]}),$jsx("box",{flexGrow:1}),props.streaming&&(props.queue?.length??0)>0?$jsxs("text",{fg:theme.textMuted,children:[keys.print("queue.flush")," to send queued now"]}):null]})]})}));var initialTurn={messages:[],streaming:!1,hasContent:!1,toolActive:!1};function turnReducer(state2,a){switch(a.kind){case"reset":return initialTurn;case"load":return{...initialTurn,messages:a.messages};case"push":return{...state2,messages:[...state2.messages,a.message]};case"user":return{...state2,messages:[...state2.messages,userMessage(a.text)]};case"system":return{...state2,messages:[...state2.messages,systemMessage(a.text)]};case"message.start":return{...state2,streaming:!0,hasContent:!1,toolActive:!1};case"message.delta":return{...state2,hasContent:!0,toolActive:!1,messages:appendText(state2.messages,a.chunk)};case"message.complete":return{...state2,streaming:!1,hasContent:!1,toolActive:!1,messages:finalize(state2.messages,a.text,a.usage)};case"tool.start":{let json2=a.preview&&/^\s*\{/.test(a.preview),part={type:"tool",id:a.id,name:a.name,args:json2?a.preview:"",status:"running",startedAt:Date.now(),preview:a.preview};return{...state2,toolActive:!0,hasContent:!1,messages:appendPart(state2.messages,part,!0)}}case"tool.progress":return{...state2,messages:updateRunningTool(state2.messages,a.name,(p)=>({...p,preview:a.preview||p.preview}))};case"tool.generating":return{...state2,messages:updateRunningTool(state2.messages,a.name,(p)=>({...p,preview:p.preview??"generating\u2026"}))};case"tool.complete":return{...state2,toolActive:!1,messages:updateToolById(state2.messages,a.id,(p)=>({...p,status:a.error?"error":"done",duration:p.startedAt?Date.now()-p.startedAt:void 0,preview:a.summary||a.inline_diff||p.preview,result:a.error||a.summary,diff:a.inline_diff}))};case"thinking":return{...state2,messages:upsertThinking(state2.messages,a.text,a.final)};case"subagent":return{...state2,messages:renderSubagent(state2.messages,a.event,a.payload)};case"prompt":{let part={type:"prompt",id:a.id,variant:a.req.variant,req:a.req};return{...state2,messages:appendPart(state2.messages,part,!0)}}case"prompt.answered":return{...state2,messages:updatePrompt(state2.messages,a.id,(p)=>({...p,answered:{label:a.label,ok:a.ok,at:Date.now()}}))};case"error":return{...state2,streaming:!1,hasContent:!1,toolActive:!1,messages:[...state2.messages,systemMessage(`Error: ${a.text}`)]};case"interrupt.notice":{let last3=state2.messages[state2.messages.length-1];if(last3?.role==="system"&&last3.parts[0]?.type==="text"&&last3.parts[0].content.includes(a.text))return state2;return{...state2,messages:[...state2.messages,systemMessage(a.text)]}}}}function userMessage(text2){return{id:mid(),role:"user",parts:[{type:"text",content:text2,streaming:!1}],timestamp:Date.now()/1000}}function systemMessage(text2){return{id:mid(),role:"system",parts:[{type:"text",content:text2,streaming:!1}],timestamp:Date.now()/1000}}function flatten3(text2){if(typeof text2==="string")return text2;if(!Array.isArray(text2))return"";let out=[];for(let p of text2)if(p&&typeof p==="object"&&"type"in p&&p.type==="text"&&"text"in p&&typeof p.text==="string")out.push(p.text);return out.join(`
|
|
4140
4140
|
`)}function transcriptToMessages(rows3){return rows3.filter((r)=>r.role==="user"||r.role==="assistant").map((r)=>({role:r.role,content:flatten3(r.text)})).filter((r)=>r.content).map((r)=>({id:mid(),role:r.role,parts:[{type:"text",content:r.content,streaming:!1}],timestamp:Date.now()/1000}))}function assistant(parts2){return{id:mid(),role:"assistant",parts:parts2,timestamp:Date.now()/1000}}function withLastAssistant(messages,fn,otherwise){let last3=messages[messages.length-1];if(last3?.role==="assistant")return[...messages.slice(0,-1),fn(last3)];return[...messages,otherwise()]}function seal(parts2){let last3=parts2[parts2.length-1];if(last3?.type==="text"&&last3.streaming)return[...parts2.slice(0,-1),{...last3,streaming:!1}];return parts2}function appendText(messages,chunk){return withLastAssistant(messages,(m2)=>{let last3=m2.parts[m2.parts.length-1];if(last3?.type==="text"&&last3.streaming){let part={...last3,content:last3.content+chunk};return{...m2,parts:[...m2.parts.slice(0,-1),part]}}return{...m2,parts:[...m2.parts,{type:"text",key:pid(),content:chunk,streaming:!0}]}},()=>assistant([{type:"text",key:pid(),content:chunk,streaming:!0}]))}function appendPart(messages,part,close){return withLastAssistant(messages,(m2)=>({...m2,parts:[...close?seal(m2.parts):m2.parts,part]}),()=>assistant([part]))}function finalize(messages,final,usage){let last3=messages[messages.length-1];if(last3?.role==="assistant"){let tail=last3.parts[last3.parts.length-1],parts2=tail?.type==="text"&&tail.streaming?[...last3.parts.slice(0,-1),{...tail,content:final||tail.content,streaming:!1}]:final&&final!==joinText(last3.parts)?[...last3.parts,{type:"text",content:final,streaming:!1}]:seal(last3.parts);return[...messages.slice(0,-1),{...last3,parts:parts2,usage}]}if(!final)return messages;return[...messages,{...assistant([{type:"text",content:final,streaming:!1}]),usage}]}function joinText(parts2){return parts2.filter((p)=>p.type==="text").map((p)=>p.content).join("")}function updateRunningTool(messages,name,fn){let last3=messages[messages.length-1];if(!last3||last3.role!=="assistant")return messages;for(let i=last3.parts.length-1;i>=0;i--){let p=last3.parts[i];if(p.type!=="tool"||p.status!=="running")continue;if(name&&p.name!==name)continue;let parts2=[...last3.parts];return parts2[i]=fn(p),[...messages.slice(0,-1),{...last3,parts:parts2}]}return messages}function updateToolById(messages,id,fn){let last3=messages[messages.length-1];if(!last3||last3.role!=="assistant")return messages;let parts2=last3.parts.map((p)=>p.type==="tool"&&p.id===id?fn(p):p);return[...messages.slice(0,-1),{...last3,parts:parts2}]}function updatePrompt(messages,id,fn){return messages.map((m2)=>{if(m2.role!=="assistant")return m2;if(!m2.parts.some((p)=>p.type==="prompt"&&p.id===id))return m2;return{...m2,parts:m2.parts.map((p)=>p.type==="prompt"&&p.id===id?fn(p):p)}})}function upsertThinking(messages,text2,final){return withLastAssistant(messages,(m2)=>{let idx3=m2.parts.findIndex((p)=>p.type==="thinking");if(idx3>=0){let prev=m2.parts[idx3],content=final?prev.content.trim()||text2:prev.content+text2,parts2=[...m2.parts];return parts2[idx3]={...prev,content,streaming:!final},{...m2,parts:parts2}}return{...m2,parts:[{type:"thinking",key:pid(),content:text2,streaming:!final},...m2.parts]}},()=>assistant([{type:"thinking",key:pid(),content:text2,streaming:!final}]))}function renderSubagent(messages,event,p){let id=p.subagent_id?`sub-${p.subagent_id}`:`sub-${p.task_index}`;if(event==="start"){let part={type:"tool",id,name:"delegate_task",args:"",status:"running",startedAt:Date.now(),preview:p.goal,goal:p.goal,depth:p.depth??0,trail:[]};return appendPart(messages,part,!0)}if(event==="tool"&&p.tool_name)return updateToolById(messages,id,(t2)=>({...t2,trail:[...t2.trail??[],{name:p.tool_name,preview:p.tool_preview}],preview:p.tool_preview?`${p.tool_name}: ${p.tool_preview}`:p.tool_name}));if(event==="complete"){let tokens3=(p.input_tokens??0)+(p.output_tokens??0),extra=tokens3?` \xB7 ${(tokens3/1000).toFixed(1)}k tok`:"";return updateToolById(messages,id,(t2)=>({...t2,status:p.status==="failed"?"error":"done",duration:p.duration_seconds?p.duration_seconds*1000:t2.startedAt?Date.now()-t2.startedAt:void 0,result:p.summary?p.summary+extra:void 0,preview:t2.goal??t2.preview}))}return updateToolById(messages,id,(t2)=>({...t2,preview:p.text??t2.preview}))}init_perf();function count3(o){return o?Object.values(o).reduce((n,v2)=>n+v2.length,0):0}function mapEvent(ev,side){switch(ev.type){case"gateway.ready":if(side.onReady?.(),ev.payload?.skin)side.onSkin?.(ev.payload.skin);return null;case"session.info":{let si=ev.payload;side.onSessionInfo?.(si);let label=si.model?`Connected \u2014 ${si.model} \xB7 ${count3(si.tools)} tools \xB7 ${count3(si.skills)} skills`:"Connected to Hermes";if(si.credential_warning)side.onStatus?.(si.credential_warning);return{kind:"system",text:label}}case"message.start":return count("stream:start"),mem("stream-start"),{kind:"message.start"};case"message.delta":{let chunk=ev.payload?.text??"";if(!chunk)return null;return count("stream:chunk"),{kind:"message.delta",chunk}}case"message.complete":{count("stream:done"),mem("stream-done");let p=ev.payload;if(p?.usage)side.onUsage?.(p.usage);if(side.onTurnComplete?.(),p?.status==="error")return{kind:"error",text:p.text||"request failed \u2014 see messages above"};if(p?.status==="interrupted")return{kind:"message.complete",text:(p.text||"")+`
|
|
4141
4141
|
|
|
4142
|
-
*[interrupted]*`,usage:p?.usage};return{kind:"message.complete",text:p?.text??void 0,usage:p?.usage}}case"tool.start":return{kind:"tool.start",id:ev.payload.tool_id,name:ev.payload.name??"unknown",preview:ev.payload.context};case"tool.progress":return{kind:"tool.progress",name:ev.payload.name,preview:ev.payload.preview};case"tool.generating":return{kind:"tool.generating",name:ev.payload.name};case"tool.complete":return{kind:"tool.complete",id:ev.payload.tool_id,summary:ev.payload.summary,error:ev.payload.error,inline_diff:ev.payload.inline_diff};case"thinking.delta":return side.onStatus?.(ev.payload?.text??""),null;case"reasoning.delta":case"reasoning.available":{let text2=ev.payload?.text;if(!text2)return null;return{kind:"thinking",text:text2,final:ev.type==="reasoning.available"}}case"subagent.start":case"subagent.thinking":case"subagent.tool":case"subagent.progress":case"subagent.complete":{let sub2=ev.type.slice(9);return record(sub2,ev.payload),{kind:"subagent",event:sub2,payload:ev.payload}}case"error":return{kind:"error",text:ev.payload?.message??"Unknown error"};case"clarify.request":return{kind:"prompt",id:ev.payload.request_id,req:{variant:"clarify",...ev.payload}};case"approval.request":return{kind:"prompt",id:`approval-${pid()}`,req:{variant:"approval",...ev.payload}};case"sudo.request":return{kind:"prompt",id:ev.payload.request_id,req:{variant:"sudo",...ev.payload}};case"secret.request":return{kind:"prompt",id:ev.payload.request_id,req:{variant:"secret",...ev.payload}};case"background.complete":return side.onBackground?.(ev.payload.task_id,ev.payload.text),null;case"review.summary":{let text2=String(ev.payload?.text??"").trim();if(!text2)return null;return{kind:"system",text:text2}}case"btw.complete":return side.onBtw?.(ev.payload.text),null;case"gateway.stderr":{let line3=ev.payload.line;if(/error|fail|traceback|exception|\b[45]\d\d\b|refused|denied|unauthori/i.test(line3))return{kind:"system",text:line3.slice(0,200)};return null}case"skin.changed":return side.onSkin?.(ev.payload),null;case"gateway.start_timeout":return{kind:"error",text:`gateway startup timed out (${ev.payload?.python??"python"} @ ${ev.payload?.cwd??"?"})`};case"gateway.protocol_error":return{kind:"system",text:`protocol error: ${ev.payload?.preview??"?"}`};case"browser.progress":{let text2=ev.payload?.message??"";if(!text2)return null;return ev.payload?.level==="error"?{kind:"error",text:text2}:{kind:"system",text:`\xB7 ${text2}`}}case"status.update":{let kind=ev.payload?.kind,text2=ev.payload?.text??"";if(side.onStatus?.(text2),!kind||kind==="status")return null;return{kind:"system",text:text2}}}return null}var import_react104=__toESM(require_react_production(),1);init_sessions_db();function useSession(){let gw=useGateway(),resume=import_react104.useCallback(async(sid)=>{let res=await gw.request("session.resume",{session_id:sid}),id=res.session_id;gw.setSession(id),set("lastSessionId",res.resumed??sid);let messages=res.messages?.length?transcriptToMessages(res.messages):[];return{id,messages}},[gw]),create=import_react104.useCallback(async()=>{let res=await gw.request("session.create",{});return gw.setSession(res.session_id),res.session_id},[gw]),boot2=import_react104.useCallback(async(launch)=>{let fresh=async(note)=>({id:await create(),messages:[],note});if(launch.mode==="resume"){let target=launch.sid??lastReal()?.id;if(!target)return fresh("no prior session to resume \u2014 starting fresh");try{return await resume(target)}catch{return fresh(`resume ${target} failed \u2014 starting fresh`)}}let last3=get("lastSessionId");if(last3&&byId(last3)?.message_count===0)try{return await resume(last3)}catch{}return fresh()},[create,resume]),interrupt=import_react104.useCallback(async()=>{try{await gw.request("session.interrupt")}catch{}},[gw]),branch2=import_react104.useCallback(async(name)=>{try{return(await gw.request("session.branch",name?{name}:{})).session_id??null}catch{return null}},[gw]),compress=import_react104.useCallback(async()=>{try{return await gw.request("session.compress")}catch{return null}},[gw]),undo=import_react104.useCallback(async()=>{try{await gw.request("session.undo")}catch{}},[gw]);return import_react104.useMemo(()=>({boot:boot2,create,resume,interrupt,branch:branch2,compress,undo}),[boot2,create,resume,interrupt,branch2,compress,undo])}var import_react106=__toESM(require_react_production(),1);import{tmpdir}from"os";import{join as join15}from"path";import{rm}from"fs/promises";async function editInEditor(renderer,seed){let cmd=process.env.VISUAL||process.env.EDITOR;if(!cmd)return;let path7=join15(tmpdir(),`herm-${Date.now()}.md`);await Bun.write(path7,seed),renderer.suspend(),renderer.currentRenderBuffer.clear();let parts2=cmd.split(" ");await Bun.spawn([...parts2,path7],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited;let text2=await Bun.file(path7).text().catch(()=>"");if(rm(path7,{force:!0}).catch(()=>{}),renderer.isDestroyed)return text2.trim()||void 0;return renderer.currentRenderBuffer.clear(),renderer.resume(),renderer.requestRender(),text2.trim()||void 0}function redraw(renderer){resolveRenderLib().clearTerminal(renderer.rendererPtr),renderer.currentRenderBuffer.clear(RGBA.fromValues(0,0,0,0)),renderer.requestRender()}var INTERRUPT_MS=5000,DOUBLE_TAB_MS=400;function useAppKeys(o){let renderer=useRenderer(),keys=useKeys(),lastEsc=import_react106.useRef(0),lastTab=import_react106.useRef(0),regionFor=(t2)=>t2===o.chatTab?"input":"content";import_react106.useEffect(()=>{let found=conflicts(keys.table).filter((c)=>!(c.a==="session.interrupt"&&c.b==="dialog.cancel")).filter((c)=>!(c.a==="app.exit"&&c.b==="input.clear"));if(found.length===0)return;let first=found[0];o.onNotice(`Keybinding conflict: ${print([first.chord])} \u2192 ${first.a} and ${first.b}`+(found.length>1?` (+${found.length-1} more)`:""))},[keys.table]),useKeyboard((key2)=>{let c=o.composer.current;if(keys.match("input.clear",key2)&&c&&!c.isEmpty()){c.set(""),key2.stopPropagation();return}if(keys.match("app.exit",key2))return o.onQuit();if(keys.match("app.suspend",key2)){renderer.suspend(),process.kill(process.pid,"SIGTSTP"),process.once("SIGCONT",()=>renderer.resume());return}if(keys.match("app.redraw",key2)){redraw(renderer),key2.stopPropagation();return}if(keys.match("app.sidebar",key2)){o.onToggleSidebar();return}if(o.dialogOpen())return;if(keys.match("queue.flush",key2)&&o.streaming&&o.queued>0){o.onFlushQueue(),key2.stopPropagation();return}if(o.onPromptKey&&!keys.leader&&!key2.ctrl&&!key2.meta&&key2.eventType!=="release"){if(o.onPromptKey(key2)){key2.stopPropagation();return}}if(keys.match("editor.open",key2)&&!o.streaming){let seed=c?.value()??"";editInEditor(renderer,seed).then((out)=>{if(out===void 0){if(!process.env.VISUAL&&!process.env.EDITOR)o.onNotice("Set $EDITOR or $VISUAL to use the external editor");return}c?.set(out),o.setFocusRegion("input")});return}if(keys.match("tab.prev",key2)){o.setTab((t2)=>{let n=Math.max(0,t2-1);return o.setFocusRegion(regionFor(n)),n});return}if(keys.match("tab.next",key2)){o.setTab((t2)=>{let n=Math.min(o.tabMax,t2+1);return o.setFocusRegion(regionFor(n)),n});return}if(keys.leader&&!key2.ctrl&&!key2.meta&&!key2.shift&&key2.eventType!=="release"){let n={"1":0,"2":1,"3":2,"4":3,"5":4,"6":5,"7":6,"8":7,"9":8,"0":9,"-":10}[key2.name];if(n!==void 0&&n<=o.tabMax){o.setTab(()=>{return o.setFocusRegion(regionFor(n)),n}),key2.stopPropagation();return}}if(c?.popOpen()){if(key2.name==="escape")return c.popCancel();if(key2.name==="up"){c.popNav(-1),key2.stopPropagation();return}if(key2.name==="down"){c.popNav(1),key2.stopPropagation();return}if(key2.name==="tab")return c.popAccept();return}if(keys.match("focus.cycle",key2)&&!o.streaming){if(o.tab===o.chatTab){o.setFocusRegion((r)=>r==="input"?"content":"input");return}if(o.focusRegion==="input"){o.setFocusRegion("content");return}let now=Date.now();if(now-lastTab.current<DOUBLE_TAB_MS)o.setFocusRegion("input"),lastTab.current=0,key2.stopPropagation();else lastTab.current=now;return}if(keys.match("session.interrupt",key2)){if(!o.streaming&&o.onEscape?.())return;if(o.streaming){let now=Date.now();if(now-lastEsc.current<INTERRUPT_MS){o.onInterrupt(),lastEsc.current=0;return}lastEsc.current=now,o.onInterruptNotice();return}if(o.tab===o.chatTab&&o.focusRegion==="content")o.setFocusRegion("input");return}if(keys.match("reply.copy",key2))return o.onCopyLast();if(keys.match("clipboard.attach",key2)){o.onAttachClipboard(),key2.stopPropagation();return}if(o.focusRegion==="input"&&!o.streaming){if(key2.name==="up")return void c?.historyUp();if(key2.name==="down")return void c?.historyDown();if(key2.name==="backspace"&&!key2.ctrl&&!key2.meta&&c?.isEmpty()&&o.onDetachLast()){key2.stopPropagation();return}}if(o.tab===o.chatTab&&o.focusRegion==="content"&&!o.streaming&&!key2.ctrl&&!key2.meta&&key2.eventType!=="release"){if(key2.name.length===1&&key2.name!==" "){let ch=key2.shift&&/[a-z]/.test(key2.name)?key2.name.toUpperCase():key2.name;o.setFocusRegion("input"),c?.insert(ch),key2.stopPropagation()}}})}import{writeSync}from"fs";var done=!1;function quit(renderer,sid,title){if(done)process.exit(0);if(done=!0,renderer.destroy(),process.stdout.isTTY&&sid){let t2=title?` \u2014 ${title.slice(0,60)}`:"";writeSync(1,`
|
|
4142
|
+
*[interrupted]*`,usage:p?.usage};return{kind:"message.complete",text:p?.text??void 0,usage:p?.usage}}case"tool.start":return{kind:"tool.start",id:ev.payload.tool_id,name:ev.payload.name??"unknown",preview:ev.payload.context};case"tool.progress":return{kind:"tool.progress",name:ev.payload.name,preview:ev.payload.preview};case"tool.generating":return{kind:"tool.generating",name:ev.payload.name};case"tool.complete":return{kind:"tool.complete",id:ev.payload.tool_id,summary:ev.payload.summary,error:ev.payload.error,inline_diff:ev.payload.inline_diff};case"thinking.delta":return side.onStatus?.(ev.payload?.text??""),null;case"reasoning.delta":case"reasoning.available":{let text2=ev.payload?.text;if(!text2)return null;return{kind:"thinking",text:text2,final:ev.type==="reasoning.available"}}case"subagent.start":case"subagent.thinking":case"subagent.tool":case"subagent.progress":case"subagent.complete":{let sub2=ev.type.slice(9);return record(sub2,ev.payload),{kind:"subagent",event:sub2,payload:ev.payload}}case"error":return{kind:"error",text:ev.payload?.message??"Unknown error"};case"clarify.request":return{kind:"prompt",id:ev.payload.request_id,req:{variant:"clarify",...ev.payload}};case"approval.request":return{kind:"prompt",id:`approval-${pid()}`,req:{variant:"approval",...ev.payload}};case"sudo.request":return{kind:"prompt",id:ev.payload.request_id,req:{variant:"sudo",...ev.payload}};case"secret.request":return{kind:"prompt",id:ev.payload.request_id,req:{variant:"secret",...ev.payload}};case"background.complete":return side.onBackground?.(ev.payload.task_id,ev.payload.text),null;case"review.summary":{let text2=String(ev.payload?.text??"").trim();if(!text2)return null;return{kind:"system",text:text2}}case"btw.complete":return side.onBtw?.(ev.payload.text),null;case"gateway.stderr":{let line3=ev.payload.line;if(/error|fail|traceback|exception|\b[45]\d\d\b|refused|denied|unauthori/i.test(line3))return{kind:"system",text:line3.slice(0,200)};return null}case"skin.changed":return side.onSkin?.(ev.payload),null;case"gateway.start_timeout":return{kind:"error",text:`gateway startup timed out (${ev.payload?.python??"python"} @ ${ev.payload?.cwd??"?"})`};case"gateway.protocol_error":return{kind:"system",text:`protocol error: ${ev.payload?.preview??"?"}`};case"browser.progress":{let text2=ev.payload?.message??"";if(!text2)return null;return ev.payload?.level==="error"?{kind:"error",text:text2}:{kind:"system",text:`\xB7 ${text2}`}}case"status.update":{let kind=ev.payload?.kind,text2=ev.payload?.text??"";if(side.onStatus?.(text2),!kind||kind==="status")return null;return{kind:"system",text:text2}}}return null}var import_react104=__toESM(require_react_production(),1);init_sessions_db();function useSession(){let gw=useGateway(),resume=import_react104.useCallback(async(sid)=>{let res=await gw.request("session.resume",{session_id:sid}),id=res.session_id;gw.setSession(id),set("lastSessionId",res.resumed??sid);let messages=res.messages?.length?transcriptToMessages(res.messages):[];return{id,messages}},[gw]),create=import_react104.useCallback(async()=>{let res=await gw.request("session.create",{});return gw.setSession(res.session_id),res.session_id},[gw]),boot2=import_react104.useCallback(async(launch)=>{let fresh=async(note)=>({id:await create(),messages:[],note});if(launch.mode==="resume"){let target=launch.sid??lastReal()?.id;if(!target)return fresh("no prior session to resume \u2014 starting fresh");try{return await resume(target)}catch{return fresh(`resume ${target} failed \u2014 starting fresh`)}}let last3=get("lastSessionId");if(last3&&byId(last3)?.message_count===0)try{return await resume(last3)}catch{}return fresh()},[create,resume]),interrupt=import_react104.useCallback(async()=>{try{await gw.request("session.interrupt")}catch{}},[gw]),branch2=import_react104.useCallback(async(name)=>{try{return(await gw.request("session.branch",name?{name}:{})).session_id??null}catch{return null}},[gw]),compress=import_react104.useCallback(async()=>{try{return await gw.request("session.compress")}catch{return null}},[gw]),undo=import_react104.useCallback(async()=>{try{await gw.request("session.undo")}catch{}},[gw]);return import_react104.useMemo(()=>({boot:boot2,create,resume,interrupt,branch:branch2,compress,undo}),[boot2,create,resume,interrupt,branch2,compress,undo])}var import_react106=__toESM(require_react_production(),1);import{tmpdir}from"os";import{join as join15}from"path";import{rm}from"fs/promises";async function editInEditor(renderer,seed){let cmd=process.env.VISUAL||process.env.EDITOR;if(!cmd)return;let path7=join15(tmpdir(),`herm-${Date.now()}.md`);await Bun.write(path7,seed),renderer.suspend(),renderer.currentRenderBuffer.clear();let parts2=cmd.split(" ");await Bun.spawn([...parts2,path7],{stdin:"inherit",stdout:"inherit",stderr:"inherit"}).exited;let text2=await Bun.file(path7).text().catch(()=>"");if(rm(path7,{force:!0}).catch(()=>{}),renderer.isDestroyed)return text2.trim()||void 0;return renderer.currentRenderBuffer.clear(),renderer.resume(),renderer.requestRender(),text2.trim()||void 0}function redraw(renderer){resolveRenderLib().clearTerminal(renderer.rendererPtr),renderer.currentRenderBuffer.clear(RGBA.fromValues(0,0,0,0)),renderer.requestRender()}var INTERRUPT_MS=5000,DOUBLE_TAB_MS=400;function useAppKeys(o){let renderer=useRenderer(),keys=useKeys(),lastEsc=import_react106.useRef(0),lastTab=import_react106.useRef(0),regionFor=(t2)=>t2===o.chatTab?"input":"content";import_react106.useEffect(()=>{let found=conflicts(keys.table).filter((c)=>!(c.a==="session.interrupt"&&c.b==="dialog.cancel")).filter((c)=>!(c.a==="app.exit"&&c.b==="input.clear"));if(found.length===0)return;let first=found[0];o.onNotice(`Keybinding conflict: ${print([first.chord])} \u2192 ${first.a} and ${first.b}`+(found.length>1?` (+${found.length-1} more)`:""))},[keys.table]),useKeyboard((key2)=>{let c=o.composer.current;if(keys.match("input.clear",key2)&&c&&!c.isEmpty()){c.set(""),key2.stopPropagation();return}if(keys.match("app.exit",key2))return o.onQuit();if(keys.match("app.suspend",key2)){renderer.suspend(),process.kill(process.pid,"SIGTSTP"),process.once("SIGCONT",()=>renderer.resume());return}if(keys.match("app.redraw",key2)){redraw(renderer),key2.stopPropagation();return}if(keys.match("app.sidebar",key2)){o.onToggleSidebar();return}if(o.dialogOpen())return;if(keys.match("queue.flush",key2)&&o.streaming&&o.queued>0){o.onFlushQueue(),key2.stopPropagation();return}if(o.onPromptKey&&!keys.leader&&!key2.ctrl&&!key2.meta&&key2.eventType!=="release"){if(o.onPromptKey(key2)){key2.stopPropagation();return}}if(keys.match("editor.open",key2)&&!o.streaming){let seed=c?.value()??"";editInEditor(renderer,seed).then((out)=>{if(out===void 0){if(!process.env.VISUAL&&!process.env.EDITOR)o.onNotice("Set $EDITOR or $VISUAL to use the external editor");return}c?.set(out),o.setFocusRegion("input")});return}if(keys.match("tab.prev",key2)){o.setTab((t2)=>{let n=Math.max(0,t2-1);return o.setFocusRegion(regionFor(n)),n});return}if(keys.match("tab.next",key2)){o.setTab((t2)=>{let n=Math.min(o.tabMax,t2+1);return o.setFocusRegion(regionFor(n)),n});return}if(keys.leader&&!key2.ctrl&&!key2.meta&&!key2.shift&&key2.eventType!=="release"){let n={"1":0,"2":1,"3":2,"4":3,"5":4,"6":5,"7":6,"8":7,"9":8,"0":9,"-":10}[key2.name];if(n!==void 0&&n<=o.tabMax){o.setTab(()=>{return o.setFocusRegion(regionFor(n)),n}),key2.stopPropagation();return}}if(key2.meta&&!key2.ctrl&&!key2.shift&&key2.eventType!=="release"){let n={"1":0,"2":1,"3":2,"4":3,"5":4,"6":5,"7":6,"8":7,"9":8,"0":9,"-":10}[key2.name];if(n!==void 0&&n<=o.tabMax){o.setTab(()=>{return o.setFocusRegion(regionFor(n)),n}),key2.stopPropagation();return}}if(c?.popOpen()){if(key2.name==="escape")return c.popCancel();if(key2.name==="up"){c.popNav(-1),key2.stopPropagation();return}if(key2.name==="down"){c.popNav(1),key2.stopPropagation();return}if(key2.name==="tab")return c.popAccept();return}if(keys.match("focus.cycle",key2)&&!o.streaming){if(o.tab===o.chatTab){o.setFocusRegion((r)=>r==="input"?"content":"input");return}if(o.focusRegion==="input"){o.setFocusRegion("content");return}let now=Date.now();if(now-lastTab.current<DOUBLE_TAB_MS)o.setFocusRegion("input"),lastTab.current=0,key2.stopPropagation();else lastTab.current=now;return}if(keys.match("session.interrupt",key2)){if(!o.streaming&&o.onEscape?.())return;if(o.streaming){let now=Date.now();if(now-lastEsc.current<INTERRUPT_MS){o.onInterrupt(),lastEsc.current=0;return}lastEsc.current=now,o.onInterruptNotice();return}if(o.tab===o.chatTab&&o.focusRegion==="content")o.setFocusRegion("input");return}if(keys.match("reply.copy",key2))return o.onCopyLast();if(keys.match("clipboard.attach",key2)){o.onAttachClipboard(),key2.stopPropagation();return}if(o.focusRegion==="input"&&!o.streaming){if(key2.name==="up")return void c?.historyUp();if(key2.name==="down")return void c?.historyDown();if(key2.name==="backspace"&&!key2.ctrl&&!key2.meta&&c?.isEmpty()&&o.onDetachLast()){key2.stopPropagation();return}}if(o.tab===o.chatTab&&o.focusRegion==="content"&&!o.streaming&&!key2.ctrl&&!key2.meta&&key2.eventType!=="release"){if(key2.name.length===1&&key2.name!==" "){let ch=key2.shift&&/[a-z]/.test(key2.name)?key2.name.toUpperCase():key2.name;o.setFocusRegion("input"),c?.insert(ch),key2.stopPropagation()}}})}import{writeSync}from"fs";var done=!1;function quit(renderer,sid,title){if(done)process.exit(0);if(done=!0,renderer.destroy(),process.stdout.isTTY&&sid){let t2=title?` \u2014 ${title.slice(0,60)}`:"";writeSync(1,`
|
|
4143
4143
|
continue herm --resume ${sid}${t2}
|
|
4144
4144
|
|
|
4145
4145
|
`)}process.exit(0)}init_sessions_db();init_hermes_analytics();function rehome(newHome){process.env.HERMES_HOME=newHome,setHome2(newHome),setHome(newHome),cache2.clear(),resetKanban(),reload(),home2.reset()}var import_react107=__toESM(require_react_production(),1);var Countdown=(p)=>{let theme=useTheme().theme,[n,setN]=import_react107.useState(p.seconds);import_react107.useEffect(()=>{if(n<=0){p.onFire();return}let t2=setTimeout(()=>setN((v2)=>v2-1),1000);return()=>clearTimeout(t2)},[n,p.onFire]),useKeyboard(()=>p.onCancel());let bar3="\u2588".repeat(n)+"\u2591".repeat(Math.max(0,p.seconds-n));return $jsxs("box",{flexDirection:"column",width:58,children:[$jsx("box",{height:1,children:$jsx("text",{fg:theme.warning,children:$jsx("strong",{children:p.title})})}),$jsx("box",{height:1}),$jsx("box",{minHeight:1,children:$jsx("text",{wrapMode:"word",children:p.body})}),$jsx("box",{height:1}),$jsx("box",{height:1,children:$jsxs("text",{fg:theme.warning,children:[bar3," ",n,"s"]})}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:p.action})}),$jsx("box",{height:1}),$jsx("box",{height:1,children:$jsx("text",{fg:theme.textMuted,children:"press any key to cancel"})})]})};function openCountdown(dialog,opts){return new Promise((resolve4)=>{dialog.replace($jsx(Countdown,{...opts,onFire:()=>{dialog.clear(),resolve4(!0)},onCancel:()=>{dialog.clear(),resolve4(!1)}}),()=>resolve4(!1))})}var SECONDS=10,SUSPEND=process.platform==="darwin"?"pmset sleepnow":"systemctl suspend",run=(cmd)=>Bun.spawn(["sh","-c",cmd],{stdout:"ignore",stderr:"ignore"}),fired=new Map;function makeGoalHook(dialog,toast){let act=(goal)=>{let pref=(get("onGoalDone")??"toast").trim(),head=goal.length>60?goal.slice(0,57)+"\u2026":goal;if(toast.show({variant:"success",title:"Goal complete",message:head,duration:8000}),pref==="toast")return;let cmd=pref==="suspend"?SUSPEND:pref;openCountdown(dialog,{title:"Goal complete \u2014 "+(pref==="suspend"?"suspending":"running hook"),body:head,action:`\u2192 ${cmd}`,seconds:SECONDS}).then((ok)=>{if(ok)run(cmd)})};return{check:(sid)=>{if(!sid)return;io.goalState(sid).then((s)=>{if(!s||s.status!=="done")return;if(fired.get(sid)===s.goal)return;fired.set(sid,s.goal),act(s.goal)}).catch(()=>{})}}}var App=(props)=>$jsx(ThemeProvider,{initial:props.initialTheme,children:$jsx(GatewayProvider,{client:props.gateway,children:$jsx(ToastProvider,{children:$jsx(KeysProvider,{children:$jsx(DialogProvider,{children:$jsx(CommandProvider,{children:$jsx(AppInner,{launch:props.launch??{mode:"new"}})})})})})})}),AppInner=({launch:launch0})=>{let gw=useGateway(),gwRestart=useGatewayRestart(),dialog=useDialog(),themeCtx=useTheme(),cmd=useCommand(),toast=useToast(),renderer=useRenderer(),session=useSession(),dims=useTerminalDimensions(),goalHook=import_react110.useMemo(()=>makeGoalHook(dialog,toast),[dialog,toast]),[turn,dispatch]=import_react110.useReducer(turnReducer,initialTurn),[ready,setReady]=import_react110.useState(!1),[sid,setSid]=import_react110.useState(""),sidRef=import_react110.useRef(sid);sidRef.current=sid;let[tab,setTab]=import_react110.useState(CHAT_TAB),[hideSidebar,setHideSidebar]=import_react110.useState(!1),[usage,setUsage]=import_react110.useState(void 0),[info2,setInfo]=import_react110.useState(null),[title,setTitle]=import_react110.useState(""),[focusRegion,setFocusRegion]=import_react110.useState("input"),goToTab=import_react110.useCallback((t2)=>{setTab(t2),setFocusRegion(t2===CHAT_TAB?"input":"content")},[]),[status,setStatus]=import_react110.useState(""),[eikon,setEikon]=import_react110.useState(void 0),[queue,setQueue]=import_react110.useState([]),launchRef=import_react110.useRef(launch0),launch=launchRef.current,[splash,setSplash]=import_react110.useState(launch.splash!==!1),[switching,setSwitching]=import_react110.useState(!1),summoned=import_react110.useRef(!1),[composing,setComposing]=import_react110.useState(!1),splashLast=import_react110.useMemo(()=>launch.mode==="new"?lastReal():void 0,[launch.mode]),news=import_react110.useMemo(()=>readChangelog()?.headline,[]),[attachments,setAttachments]=import_react110.useState([]),[cloudH,setCloudH]=import_react110.useState(CLOUD_MIN),[pick,setPick]=import_react110.useState(void 0),[skin,setSkin]=import_react110.useState(()=>deriveSkin(void 0)),inflight=import_react110.useRef(!1),interrupted=import_react110.useRef(!1),sessionStart=import_react110.useRef(Date.now()),composer2=import_react110.useRef(null),promptRef=import_react110.useRef(null),{cmds}=useSlashCommands(),cmdsRef=import_react110.useRef(cmds);cmdsRef.current=cmds;let[errorPulse,setErrorPulse]=import_react110.useState(!1),agentState=errorPulse?"error":turn.toolActive?"working":turn.streaming&&turn.hasContent?"speaking":turn.streaming?"thinking":composing?"listening":"idle",onAvatarHold=import_react110.useCallback((s)=>{if(s==="error")setErrorPulse(!1)},[]),prompt=pending(turn.messages),cloudAuto=turn.streaming&&!turn.hasContent&&!prompt,[force,setForce]=import_react110.useState(void 0),cloud=!prompt&&(force??cloudAuto),prevStream=import_react110.useRef(turn.streaming);import_react110.useEffect(()=>{if(!prevStream.current&&turn.streaming)setForce(void 0),setPick(void 0);prevStream.current=turn.streaming},[turn.streaming]);let onPick=import_react110.useCallback((m2)=>{setPick((p)=>{if(m2&&p&&m2.id===p.id){setForce(!1);return}return setForce(!!m2),m2})},[]),onAvatar=import_react110.useCallback(()=>{let next2=!cloud;if(!next2)setPick(void 0);setForce(next2)},[cloud]),closeCloud=import_react110.useCallback(()=>{setForce(!1),setPick(void 0)},[]),onEnqueue=import_react110.useCallback((t2)=>setQueue((q4)=>[...q4,t2]),[]),onAttach=import_react110.useCallback((r)=>setAttachments((a)=>[...a,r]),[]),reset=import_react110.useCallback(()=>{interrupted.current=!1,dispatch({kind:"reset"}),setUsage(void 0),setReady(!1),setStatus(""),setTitle(""),setAttachments([])},[]),newSession=import_react110.useCallback(async()=>{reset(),summoned.current=!0,setSplash(!0);try{setSid(await session.create()),sessionStart.current=Date.now()}catch{}},[reset,session]),switchSession=import_react110.useCallback(async(target)=>{reset(),summoned.current=!0,setSplash(!0),setSwitching(!0),goToTab(CHAT_TAB);try{let res=await session.resume(target);if(setSid(res.id),sessionStart.current=Date.now(),res.messages.length)dispatch({kind:"load",messages:res.messages});setSplash(!1),summoned.current=!1}catch(err){dispatch({kind:"system",text:`Failed to resume: ${err instanceof Error?err.message:String(err)}`}),setSplash(!1),summoned.current=!1}finally{setSwitching(!1)}},[reset,session,goToTab]),switchProfile=import_react110.useCallback((newHome,name)=>{rehome(newHome),reset(),gw.setSession(""),setSid(""),setInfo(null),setSkin(deriveSkin(void 0)),summoned.current=!0,setSplash(!0),launchRef.current={mode:"new",splash:!0},toast.show({variant:"info",message:`Switching to '${name}'\u2026`}),goToTab(CHAT_TAB),gwRestart()},[reset,goToTab,gwRestart,toast,gw]),runCompress=import_react110.useCallback(async()=>{toast.show({variant:"info",message:"Compressing session\u2026"});let r=await session.compress();if(!r||!r.summary)return;let s=r.summary;if(s.noop){toast.show({variant:"info",message:s.headline??`No changes \xB7 ~${r.before_tokens??0} tokens`});return}let lines2=[s.headline,s.token_line,s.note].filter(Boolean).join(`
|