herm-tui 1.0.0-dev.2 → 1.0.0-dev.3

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.
Files changed (3) hide show
  1. package/db.worker.js +81 -0
  2. package/index.js +115 -116
  3. package/package.json +1 -1
package/db.worker.js ADDED
@@ -0,0 +1,81 @@
1
+ // @bun
2
+ var __create=Object.create;var{getPrototypeOf:__getProtoOf,defineProperty:__defProp,getOwnPropertyNames:__getOwnPropNames}=Object;var __hasOwnProp=Object.prototype.hasOwnProperty;function __accessProp(key){return this[key]}var __toESMCache_node,__toESMCache_esm,__toESM=(mod,isNodeMode,target)=>{var canCache=mod!=null&&typeof mod==="object";if(canCache){var cache=isNodeMode?__toESMCache_node??=new WeakMap:__toESMCache_esm??=new WeakMap,cached=cache.get(mod);if(cached)return cached}target=mod!=null?__create(__getProtoOf(mod)):{};let to=isNodeMode||!mod||!mod.__esModule?__defProp(target,"default",{value:mod,enumerable:!0}):target;for(let key of __getOwnPropNames(mod))if(!__hasOwnProp.call(to,key))__defProp(to,key,{get:__accessProp.bind(mod,key),enumerable:!0});if(canCache)cache.set(mod,to);return to};var __commonJS=(cb,mod)=>()=>(mod||cb((mod={exports:{}}).exports,mod),mod.exports);var __returnValue=(v)=>v;function __exportSetter(name,newValue){this[name]=__returnValue.bind(null,newValue)}var __export=(target,all)=>{for(var name in all)__defProp(target,name,{get:all[name],enumerable:!0,configurable:!0,set:__exportSetter.bind(all,name)})};var __esm=(fn,res)=>()=>(fn&&(res=fn(fn=0)),res);var __require=import.meta.require;var level,enabled,verbose,timings,noop=()=>0,mark,stages,boot=(label,ms)=>{if(stages.push([label,ms]),enabled)log(`\uD83D\uDE80 boot:${label} ${ms.toFixed(1)}ms`)},counters,count,snapshots,mb=(n)=>(n/1024/1024).toFixed(1),mem,monitor,renders,onRender,report=()=>{if(!enabled)return;let lines=[`
3
+ \x1B[1m\u2550\u2550\u2550 PERF REPORT \u2550\u2550\u2550\x1B[0m
4
+ `];if(snapshots.length>0){lines.push("\x1B[1mMemory Snapshots:\x1B[0m");for(let s of snapshots)lines.push(` ${s.label}: RSS=${mb(s.rss)}MB heap=${mb(s.heap)}MB ext=${mb(s.external)}MB`);let first=snapshots[0],last=snapshots[snapshots.length-1],drift=last.rss-first.rss;lines.push(` \u0394 RSS: ${drift>0?"+":""}${mb(drift)}MB (${first.label} \u2192 ${last.label})`),lines.push("")}if(timings.size>0){lines.push("\x1B[1mTimings:\x1B[0m");let sorted=[...timings.entries()].sort((a,b)=>b[1].total-a[1].total);for(let[label,t]of sorted){let avg=t.total/t.count;lines.push(` ${label}: ${t.count}\xD7 avg=${avg.toFixed(2)}ms min=${t.min.toFixed(2)}ms max=${t.max.toFixed(2)}ms total=${t.total.toFixed(0)}ms`)}lines.push("")}if(renders.size>0){lines.push("\x1B[1mReact Renders:\x1B[0m");let sorted=[...renders.entries()].sort((a,b)=>b[1].count-a[1].count);for(let[id,r]of sorted){let avg=r.total/r.count;lines.push(` <${id}>: ${r.count}\xD7 avg=${avg.toFixed(2)}ms max=${r.max.toFixed(2)}ms total=${r.total.toFixed(0)}ms`)}lines.push("")}if(counters.size>0){lines.push("\x1B[1mCounters:\x1B[0m");let sorted=[...counters.entries()].sort((a,b)=>b[1]-a[1]);for(let[label,n]of sorted)lines.push(` ${label}: ${n}`);lines.push("")}log(lines.join(`
5
+ `))},data=()=>{if(!enabled)return null;let m=process.memoryUsage();return{boot:Object.fromEntries(stages.map(([l,ms])=>[l,+ms.toFixed(1)])),memory:{rss:Math.round(m.rss/1024/1024),heap:Math.round(m.heapUsed/1024/1024),heapTotal:Math.round(m.heapTotal/1024/1024),external:Math.round(m.external/1024/1024)},snapshots:snapshots.map((s)=>({label:s.label,rss:Math.round(s.rss/1024/1024),heap:Math.round(s.heap/1024/1024),external:Math.round(s.external/1024/1024)})),timings:Object.fromEntries([...timings.entries()].sort((a,b)=>b[1].total-a[1].total).map(([k,v])=>[k,{count:v.count,avg:+(v.total/v.count).toFixed(2),min:+v.min.toFixed(2),max:+v.max.toFixed(2),total:Math.round(v.total)}])),renders:Object.fromEntries([...renders.entries()].sort((a,b)=>b[1].count-a[1].count).map(([k,v])=>[k,{count:v.count,avg:+(v.total/v.count).toFixed(2),max:+v.max.toFixed(2),total:Math.round(v.total)}])),counters:Object.fromEntries([...counters.entries()].sort((a,b)=>b[1]-a[1]))}},log=(msg)=>process.stderr.write(msg+`
6
+ `);var init_perf=__esm(()=>{level=process.env.PERF??"",enabled=level==="1"||level==="verbose",verbose=level==="verbose",timings=new Map,mark=enabled?(label)=>{let start=Bun.nanoseconds();return()=>{let ms=(Bun.nanoseconds()-start)/1e6,t=timings.get(label);if(t){if(t.count++,t.total+=ms,ms<t.min)t.min=ms;if(ms>t.max)t.max=ms;t.last=ms}else timings.set(label,{count:1,total:ms,min:ms,max:ms,last:ms});if(verbose)log(`\u23F1 ${label}: ${ms.toFixed(2)}ms`);return ms}}:(_)=>noop,stages=[],counters=new Map,count=enabled?(label,n=1)=>{counters.set(label,(counters.get(label)??0)+n)}:(_label,_n)=>{},snapshots=[],mem=enabled?(label)=>{let m=process.memoryUsage();snapshots.push({label,rss:m.rss,heap:m.heapUsed,external:m.external,ts:Date.now()}),log(`\uD83D\uDCCA [${label}] RSS=${mb(m.rss)}MB heap=${mb(m.heapUsed)}MB ext=${mb(m.external)}MB`)}:(_)=>{},monitor=enabled?(ms=1e4)=>{let id=setInterval(()=>{let m=process.memoryUsage(),gc=Bun.gc(!1);log(`\x1B[90m[mem] RSS=${mb(m.rss)}MB heap=${mb(m.heapUsed)}/${mb(m.heapTotal)}MB ext=${mb(m.external)}MB gcRuns=${gc?.eden_collections??"?"}/${gc?.full_collections??"?"}\x1B[0m`)},ms);return()=>clearInterval(id)}:(_ms)=>noop,renders=new Map,onRender=enabled?(id,phase,actual)=>{let r=renders.get(id);if(r){if(r.count++,r.total+=actual,actual>r.max)r.max=actual;r.last=actual}else renders.set(id,{count:1,total:actual,max:actual,last:actual});if(verbose&&actual>1)log(`\uD83D\uDD04 [${id}] ${phase}: ${actual.toFixed(2)}ms`)}:(_id,_phase,_actual)=>{};if(enabled)process.on("exit",report),process.on("SIGINT",()=>{report(),process.exit(0)})});import{Database}from"bun:sqlite";import{homedir}from"os";function roots(limit=30){let end=mark("io:sessions.roots");try{return(q(`SELECT ${COLS} FROM sessions s
7
+ WHERE s.parent_session_id IS NULL
8
+ OR EXISTS (SELECT 1 FROM sessions p
9
+ WHERE p.id = s.parent_session_id
10
+ AND ${BR("s")})
11
+ ORDER BY s.started_at DESC
12
+ LIMIT ?`)?.all(limit)??[]).map((r)=>{if(r.end_reason!=="compression")return toRow(r);let tid=tip(r.id);if(tid===r.id)return toRow(r);let t=one(tid);return t?{...toRow(t,r.id),started_at:r.started_at}:toRow(r)})}finally{end()}}function children(pid){let end=mark("io:sessions.children");try{return(q(`SELECT ${COLS} FROM sessions s
13
+ JOIN sessions p ON p.id = s.parent_session_id
14
+ WHERE s.parent_session_id = ? AND ${SUB("s")}
15
+ ORDER BY s.started_at ASC`)?.all(pid)??[]).map((r)=>toRow(r))}finally{end()}}function lineage(sid){let end=mark("io:sessions.lineage");try{let pred=q(`SELECT p.id, p.title FROM sessions c
16
+ JOIN sessions p ON p.id = c.parent_session_id
17
+ WHERE c.id = ? AND ${CONT("c")}`)?.get(sid),succ=q(`SELECT c.id, c.title FROM sessions c
18
+ JOIN sessions p ON p.id = c.parent_session_id
19
+ WHERE p.id = ? AND ${CONT("c")}
20
+ ORDER BY c.started_at DESC LIMIT 1`)?.get(sid);return{...pred&&{continuesFrom:pred},...succ&&{compressedTo:succ}}}finally{end()}}function tip(sid){let step=q(`SELECT c.id FROM sessions c
21
+ JOIN sessions p ON p.id = c.parent_session_id
22
+ WHERE p.id = ? AND ${CONT("c")}
23
+ ORDER BY c.started_at DESC LIMIT 1`),cur=sid;for(let i=0;i<100;i++){let next=step?.get(cur);if(!next)return cur;cur=next.id}return cur}function peek(sid,n=60){let end=mark("io:sessions.peek");try{return q(`SELECT role, SUBSTR(content,1,400) AS content, tool_name,
24
+ SUBSTR(tool_calls,1,400) AS tool_calls, timestamp AS at
25
+ FROM (SELECT * FROM messages WHERE session_id = ?
26
+ ORDER BY id DESC LIMIT ?)
27
+ ORDER BY id ASC`)?.all(sid,n)??[]}finally{end()}}function goalState(sid){let row=q("SELECT value FROM state_meta WHERE key = ?")?.get(`goal:${sid}`);if(!row)return null;try{let j=JSON.parse(row.value);return{goal:String(j.goal??""),status:j.status??"active",turn_count:typeof j.turn_count==="number"?j.turn_count:void 0,max_turns:j.max_turns??null}}catch{return null}}function search(query,limit=30){let m=fts(query);if(!m)return[];let end=mark("io:sessions.search");try{let raw=q(`SELECT m.session_id, m.role,
28
+ snippet(messages_fts, 0, '>>>', '<<<', '...', 40) AS snippet,
29
+ s.source, s.model, s.started_at,
30
+ COALESCE(s.title, SUBSTR(m.content, 1, 120)) AS title
31
+ FROM messages_fts
32
+ JOIN messages m ON m.id = messages_fts.rowid
33
+ JOIN sessions s ON s.id = m.session_id
34
+ WHERE messages_fts MATCH ?
35
+ ORDER BY rank LIMIT ?`)?.all(m,limit*4)??[],seen=new Set;return raw.filter((r)=>!seen.has(r.session_id)&&(seen.add(r.session_id),!0)).slice(0,limit)}finally{end()}}function rename(sid,title){let db=new Database(conn.path);try{return db.run("UPDATE sessions SET title = ? WHERE id = ?",[title,sid]),db.query("SELECT changes() AS c").get().c>0}finally{db.close()}}function remove(sid){let db=new Database(conn.path);try{if(!db.query("SELECT 1 FROM sessions WHERE id = ?").get(sid))return!1;return db.run("UPDATE sessions SET parent_session_id = NULL WHERE parent_session_id = ?",[sid]),db.run("DELETE FROM messages WHERE session_id = ?",[sid]),db.run("DELETE FROM sessions WHERE id = ?",[sid]),!0}finally{db.close()}}var HERMES,SRC,conn,setHome=(h)=>{let next=`${h}/state.db`;if(conn.path===next)return;conn.path=SRC.file=next,resetDb()},stateDb=()=>{if(conn.ro)return conn.ro;try{return conn.ro=new Database(conn.path,{readonly:!0})}catch{return null}},resetDb=()=>{for(let s of stmts.values())s.finalize();stmts.clear(),conn.ro?.close(),conn.ro=null},stmts,q=(sql)=>{let db=stateDb();if(!db)return null;let s=stmts.get(sql);if(!s)stmts.set(sql,s=db.query(sql));return s},SUB=(c)=>`(p.ended_at IS NULL OR ${c}.started_at < p.ended_at)`,CONT=(c)=>`(p.end_reason = 'compression' AND ${c}.started_at >= p.ended_at)`,BR=(c)=>`(p.end_reason = 'branched' AND ${c}.started_at >= p.ended_at)`,COLS=`
36
+ s.id, s.source, s.model, s.started_at, s.ended_at, s.end_reason,
37
+ s.message_count, s.tool_call_count,
38
+ s.input_tokens, s.output_tokens,
39
+ s.cache_read_tokens, s.cache_write_tokens, s.reasoning_tokens,
40
+ s.estimated_cost_usd, s.parent_session_id,
41
+ COALESCE(s.title,
42
+ (SELECT SUBSTR(content,1,120) FROM messages
43
+ WHERE session_id = s.id AND role = 'user' ORDER BY id LIMIT 1)) AS title,
44
+ (SELECT SUBSTR(content,1,120) FROM messages
45
+ WHERE session_id = s.id AND role = 'user' ORDER BY id DESC LIMIT 1) AS lastMessage,
46
+ (SELECT MAX(timestamp) FROM messages WHERE session_id = s.id) AS last_active,
47
+ (SELECT COUNT(*) FROM sessions c
48
+ WHERE c.parent_session_id = s.id
49
+ AND (s.ended_at IS NULL OR c.started_at < s.ended_at)) AS subagent_count`,toRow=(r,lineage=null)=>({source:SRC,id:r.id,sessionSource:r.source,model:r.model,started_at:r.started_at,ended_at:r.ended_at,end_reason:r.end_reason,message_count:r.message_count,tool_call_count:r.tool_call_count,input_tokens:r.input_tokens,output_tokens:r.output_tokens,cache_read_tokens:r.cache_read_tokens,cache_write_tokens:r.cache_write_tokens,reasoning_tokens:r.reasoning_tokens,estimated_cost_usd:r.estimated_cost_usd,title:r.title,lastMessage:r.lastMessage,last_active:r.last_active,parent_session_id:r.parent_session_id,subagent_count:r.subagent_count,lineage_root_id:lineage}),one=(id)=>q(`SELECT ${COLS} FROM sessions s WHERE s.id = ?`)?.get(id)??null,byId=(id)=>{let r=one(id);return r?toRow(r):null},lastReal=()=>roots().find((r)=>r.message_count>0&&r.sessionSource==="tui"),systemPrompt=()=>q(`SELECT id, system_prompt AS text FROM sessions
50
+ WHERE system_prompt IS NOT NULL AND length(system_prompt) > 1000
51
+ ORDER BY started_at DESC LIMIT 1`)?.get()??null,fts=(s)=>s.trim().split(/\s+/).filter(Boolean).map((w)=>/^\w+$/.test(w)?`${w}*`:`"${w.replace(/"/g,'""')}"`).join(" ");var init_sessions_db=__esm(()=>{init_perf();HERMES=process.env.HERMES_HOME||`${process.env.HOME||homedir()}/.hermes`,SRC={file:`${HERMES}/state.db`,relative:"state.db",label:"state.db"},conn={path:SRC.file,ro:null},stmts=new Map});function analytics(days,opts){let since=Math.floor(Date.now()/1000)-days*86400,db=stateDb();if(!db)return ZERO;let q2=db.query.bind(db),tot=q2(`SELECT COUNT(*) n,
52
+ COALESCE(SUM(message_count),0) msgs,
53
+ COALESCE(SUM(input_tokens),0) i,
54
+ COALESCE(SUM(output_tokens),0) o,
55
+ COALESCE(SUM(${CACHE}),0) c,
56
+ COALESCE(SUM(tool_call_count),0) calls,
57
+ COALESCE(SUM(${COST}),0) cost
58
+ FROM sessions WHERE started_at > ?`).get(since),models=q2(`SELECT COALESCE(model,'(unknown)') model,
59
+ COUNT(*) n,
60
+ COALESCE(SUM(input_tokens),0) i,
61
+ COALESCE(SUM(output_tokens),0) o,
62
+ COALESCE(SUM(${CACHE}),0) c,
63
+ COALESCE(SUM(${COST}),0) cost
64
+ FROM sessions WHERE started_at > ?
65
+ GROUP BY model ORDER BY i+o DESC`).all(since),daily=q2(`SELECT date(started_at,'unixepoch','localtime') day,
66
+ COUNT(*) n,
67
+ COALESCE(SUM(${COST}),0) cost
68
+ FROM sessions WHERE started_at > ?
69
+ GROUP BY day`).all(since),byDate=new Map(daily.map((r)=>[String(r.day),{date:String(r.day),sessions:num(r.n),cost:num(r.cost)}])),sources=q2(`SELECT COALESCE(source,'(unknown)') name, COUNT(*) n
70
+ FROM sessions WHERE started_at > ?
71
+ GROUP BY name ORDER BY n DESC`).all(since),tools=(()=>{if(opts?.tools===!1)return[];try{return q2(`SELECT json_extract(j.value,'$.function.name') name, COUNT(*) n
72
+ FROM messages m
73
+ JOIN sessions s ON s.id = m.session_id
74
+ , json_each(m.tool_calls) j
75
+ WHERE s.started_at > ? AND m.role='assistant'
76
+ AND m.tool_calls IS NOT NULL
77
+ GROUP BY name ORDER BY n DESC LIMIT 30`).all(since)}catch{return[]}})(),start=Date.now()-(days-1)*86400000;return{total:{sessions:num(tot.n),messages:num(tot.msgs),input:num(tot.i),output:num(tot.o),cache:num(tot.c),cost:num(tot.cost),calls:num(tot.calls)},byModel:models.map((r)=>({model:String(r.model),sessions:num(r.n),input:num(r.i),output:num(r.o),cache:num(r.c),cost:num(r.cost)})),byDay:Array.from({length:Math.max(1,Math.ceil(days))},(_,k)=>{let key=iso(start+k*86400000);return byDate.get(key)??{date:key,sessions:0,cost:0}}),byTool:tools.map((r)=>({name:String(r.name),n:num(r.n)})),bySource:sources.map((r)=>({name:String(r.name),n:num(r.n)}))}}var ZERO,num=(v)=>Number(v)||0,iso=(t)=>{let d=new Date(t),p=(n)=>String(n).padStart(2,"0");return`${d.getFullYear()}-${p(d.getMonth()+1)}-${p(d.getDate())}`},COST="COALESCE(actual_cost_usd, estimated_cost_usd, 0)",CACHE="COALESCE(cache_read_tokens,0)+COALESCE(cache_write_tokens,0)",cache;var init_hermes_analytics=__esm(()=>{init_sessions_db();ZERO={total:{sessions:0,messages:0,input:0,output:0,cache:0,cost:0,calls:0},byModel:[],byDay:[],byTool:[],bySource:[]},cache=new Map});function readMemoryActivity(limit=100,scan=2000){let db=stateDb();if(!db)return[];let rows=db.query(`SELECT m.timestamp ts, m.tool_calls, m.session_id,
78
+ s.title
79
+ FROM messages m LEFT JOIN sessions s ON m.session_id = s.id
80
+ WHERE m.role = 'assistant' AND m.tool_calls IS NOT NULL
81
+ ORDER BY m.id DESC LIMIT ?`).all(scan),out=[];for(let r of rows)for(let a of extract(r))if(out.push(a),out.length>=limit)return out;return out}var WRITE,READ,MEMORY_TOOLS,trunc=(s,n=80)=>{let t=String(s??"").replace(/\s+/g," ").trim();return t.length>n?t.slice(0,n-1)+"\u2026":t},stripPrefix=(name)=>name.replace(/^(mem0|honcho|hindsight|viking|retaindb|supermemory|brv|fact)_/,""),describe=(name,args)=>{if(name==="memory"){let action=String(args.action??""),target=String(args.target??""),body=action==="remove"?args.old_text:args.content??args.old_text;return{verb:action,summary:`${target}: ${trunc(body)}`}}let verb=stripPrefix(name);for(let k of["conclusion","content","query","text","fact","question","note","path"])if(k in args)return{verb,summary:trunc(args[k])};let first=Object.values(args).find((v)=>typeof v==="string");return{verb,summary:trunc(first??"")}},extract=(r)=>{let calls;try{calls=JSON.parse(r.tool_calls)}catch{return[]}if(!Array.isArray(calls))return[];let out=[];for(let c of calls){let name=c.function?.name;if(!name||!(name in MEMORY_TOOLS))continue;let args={};try{args=JSON.parse(c.function?.arguments??"{}")}catch{}let{verb,summary}=describe(name,args);out.push({ts:r.ts,provider:MEMORY_TOOLS[name],tool:name,op:name in WRITE?"write":"read",verb,summary,sessionId:r.session_id,sessionTitle:r.title??r.session_id})}return out};var init_memory_activity=__esm(()=>{init_sessions_db();WRITE={memory:"builtin",mem0_conclude:"mem0",honcho_conclude:"honcho",hindsight_retain:"hindsight",hindsight_reflect:"hindsight",fact_store:"holographic",fact_feedback:"holographic",viking_remember:"openviking",viking_add_resource:"openviking",retaindb_remember:"retaindb",retaindb_forget:"retaindb",supermemory_store:"supermemory",supermemory_forget:"supermemory",brv_curate:"byterover"},READ={mem0_search:"mem0",mem0_profile:"mem0",honcho_search:"honcho",honcho_profile:"honcho",honcho_reasoning:"honcho",honcho_context:"honcho",hindsight_recall:"hindsight",viking_search:"openviking",viking_read:"openviking",viking_browse:"openviking",retaindb_search:"retaindb",retaindb_profile:"retaindb",retaindb_context:"retaindb",supermemory_search:"supermemory",supermemory_profile:"supermemory",brv_query:"byterover",brv_status:"byterover"},MEMORY_TOOLS={...WRITE,...READ}});var exports_fns={};__export(exports_fns,{FNS:()=>FNS});var FNS;var init_fns=__esm(()=>{init_sessions_db();init_hermes_analytics();init_memory_activity();FNS={roots,children,lineage,peek,search,systemPrompt,goalState,analytics,memoryActivity:readMemoryActivity}});init_sessions_db();init_fns();var bound={home:""};self.onmessage=(e)=>{let{id,home,fn,args}=e.data;if(bound.home!==home)setHome(home),bound.home=home;let f=FNS[fn];if(!f)return self.postMessage({id,ok:!1,err:`io: unknown fn '${fn}'`});try{self.postMessage({id,ok:!0,v:f(...args)})}catch(e2){self.postMessage({id,ok:!1,err:e2.message})}};