@clauderecallhq/cli 0.65.9 → 0.66.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.
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /* Claude Recall (proprietary). See LICENSE for terms. */
3
- var Bu=Object.defineProperty;var be=(e,t)=>()=>(e&&(t=e(e=0)),t);var vo=(e,t)=>{for(var s in t)Bu(e,s,{get:t[s],enumerable:!0})};import{homedir as jo}from"node:os";import{join as Tn,basename as OT}from"node:path";import{existsSync as Hu,mkdirSync as Wu,chmodSync as qu,readdirSync as CT,statSync as IT}from"node:fs";function J(){Hu($)||Wu($,{recursive:!0,mode:448}),process.platform!=="win32"&&qu($,448)}var Mo,$,yn,Z=be(()=>{"use strict";Mo=Tn(jo(),".claude","projects"),$=process.env.RECALL_HOME?process.env.RECALL_HOME:Tn(jo(),".recall"),yn=Tn($,"db.sqlite")});import{DatabaseSync as gp}from"node:sqlite";var _p,kn,An,Yo,Ko=be(()=>{"use strict";{let e=process.emit.bind(process);process.emit=function(t,...s){let n=s[0];return t==="warning"&&n instanceof Error&&n.name==="ExperimentalWarning"&&/SQLite/i.test(n.message)?!1:e(t,...s)}}_p={DatabaseSync:gp},kn=class{inner;constructor(t){this.inner=t}get(...t){return t.length===0?this.inner.get():this.inner.get(...t)}all(...t){return t.length===0?this.inner.all():this.inner.all(...t)}run(...t){let s=t.length===0?this.inner.run():this.inner.run(...t);return{changes:s.changes,lastInsertRowid:s.lastInsertRowid}}iterate(...t){return t.length===0?this.inner.iterate():this.inner.iterate(...t)}},An=class{inner;extensionLoadingEnabled=!1;txDepth=0;constructor(t,s={}){this.inner=new _p.DatabaseSync(t,{readOnly:s.readonly??!1,allowExtension:!0})}prepare(t){return new kn(this.inner.prepare(t))}exec(t){this.inner.exec(t)}close(){this.inner.close()}pragma(t,s={}){if(t.includes("=")){this.inner.exec(`PRAGMA ${t}`);return}if(s.simple){let n=this.inner.prepare(`PRAGMA ${t}`).get();return n&&typeof n=="object"?Object.values(n)[0]:void 0}return this.inner.prepare(`PRAGMA ${t}`).all()}transaction(t){return((...n)=>{this.txDepth===0?this.inner.exec("BEGIN"):this.inner.exec(`SAVEPOINT sp_${this.txDepth}`),this.txDepth+=1;try{let r=t(...n);return this.txDepth-=1,this.txDepth===0?this.inner.exec("COMMIT"):this.inner.exec(`RELEASE sp_${this.txDepth}`),r}catch(r){this.txDepth-=1;try{this.txDepth===0?this.inner.exec("ROLLBACK"):(this.inner.exec(`ROLLBACK TO sp_${this.txDepth}`),this.inner.exec(`RELEASE sp_${this.txDepth}`))}catch{}throw r}})}loadExtension(t,s){this.extensionLoadingEnabled||(this.inner.enableLoadExtension(!0),this.extensionLoadingEnabled=!0),s===void 0?this.inner.loadExtension(t):this.inner.loadExtension(t,s)}},Yo=An});function Vo(e){let t=e.prepare("PRAGMA table_info(sessions)").all(),s=new Set(t.map(S=>S.name)),n=[["total_input_tokens","INTEGER"],["total_output_tokens","INTEGER"],["total_cache_create_tokens","INTEGER"],["total_cache_read_tokens","INTEGER"],["primary_model","TEXT"],["auto_title","TEXT"],["auto_title_source","TEXT"],["auto_title_generated_at","INTEGER"],["auto_title_history","TEXT"],["verification_status","TEXT"],["verification_computed_at","INTEGER"],["title_quality","TEXT"],["title_quality_computed_at","INTEGER"]];for(let[S,y]of n)s.has(S)||e.exec(`ALTER TABLE sessions ADD COLUMN ${S} ${y}`);let r=e.prepare("PRAGMA table_info(collection_sessions)").all(),o=new Set(r.map(S=>S.name)),a=[["source","TEXT NOT NULL DEFAULT 'manual'"],["rule_id","TEXT"]];for(let[S,y]of a)o.has(S)||e.exec(`ALTER TABLE collection_sessions ADD COLUMN ${S} ${y}`);let c=e.prepare("PRAGMA table_info(session_notes)").all(),d=new Set(c.map(S=>S.name)),u=[["auto_synopsis","TEXT"],["auto_synopsis_generated_at","INTEGER"],["auto_synopsis_history","TEXT"]];for(let[S,y]of u)d.has(S)||e.exec(`ALTER TABLE session_notes ADD COLUMN ${S} ${y}`);let g=e.prepare("PRAGMA table_info(threads)").all();new Set(g.map(S=>S.name)).has("folder_id")||(e.exec("ALTER TABLE threads ADD COLUMN folder_id TEXT REFERENCES thread_folders(id) ON DELETE SET NULL"),e.exec("CREATE INDEX IF NOT EXISTS idx_threads_folder ON threads(folder_id)"));let h=e.prepare("PRAGMA table_info(thread_folders)").all(),b=new Set(h.map(S=>S.name));b.has("project_scope")||(e.exec("ALTER TABLE thread_folders ADD COLUMN project_scope TEXT"),e.exec("CREATE INDEX IF NOT EXISTS idx_thread_folders_project ON thread_folders(project_scope)")),b.has("sort_order")||e.exec("ALTER TABLE thread_folders ADD COLUMN sort_order INTEGER NOT NULL DEFAULT 0"),e.exec(`
3
+ var Bu=Object.defineProperty;var be=(e,t)=>()=>(e&&(t=e(e=0)),t);var vo=(e,t)=>{for(var s in t)Bu(e,s,{get:t[s],enumerable:!0})};import{homedir as jo}from"node:os";import{join as Tn,basename as CT}from"node:path";import{existsSync as Hu,mkdirSync as Wu,chmodSync as qu,readdirSync as vT,statSync as jT}from"node:fs";function J(){Hu($)||Wu($,{recursive:!0,mode:448}),process.platform!=="win32"&&qu($,448)}var Mo,$,yn,Z=be(()=>{"use strict";Mo=Tn(jo(),".claude","projects"),$=process.env.RECALL_HOME?process.env.RECALL_HOME:Tn(jo(),".recall"),yn=Tn($,"db.sqlite")});import{createRequire as gp}from"node:module";var _p,fp,hp,kn,An,Yo,Ko=be(()=>{"use strict";{let e=process.emit.bind(process);process.emit=function(t,...s){let n=s[0];return t==="warning"&&n instanceof Error&&n.name==="ExperimentalWarning"&&/SQLite/i.test(n.message)?!1:e(t,...s)}}_p=gp(import.meta.url),fp=["node","sqlite"].join(":"),hp=_p(fp),kn=class{inner;constructor(t){this.inner=t}get(...t){return t.length===0?this.inner.get():this.inner.get(...t)}all(...t){return t.length===0?this.inner.all():this.inner.all(...t)}run(...t){let s=t.length===0?this.inner.run():this.inner.run(...t);return{changes:s.changes,lastInsertRowid:s.lastInsertRowid}}iterate(...t){return t.length===0?this.inner.iterate():this.inner.iterate(...t)}},An=class{inner;extensionLoadingEnabled=!1;txDepth=0;constructor(t,s={}){this.inner=new hp.DatabaseSync(t,{readOnly:s.readonly??!1,allowExtension:!0})}prepare(t){return new kn(this.inner.prepare(t))}exec(t){this.inner.exec(t)}close(){this.inner.close()}pragma(t,s={}){if(t.includes("=")){this.inner.exec(`PRAGMA ${t}`);return}if(s.simple){let n=this.inner.prepare(`PRAGMA ${t}`).get();return n&&typeof n=="object"?Object.values(n)[0]:void 0}return this.inner.prepare(`PRAGMA ${t}`).all()}transaction(t){return((...n)=>{this.txDepth===0?this.inner.exec("BEGIN"):this.inner.exec(`SAVEPOINT sp_${this.txDepth}`),this.txDepth+=1;try{let r=t(...n);return this.txDepth-=1,this.txDepth===0?this.inner.exec("COMMIT"):this.inner.exec(`RELEASE sp_${this.txDepth}`),r}catch(r){this.txDepth-=1;try{this.txDepth===0?this.inner.exec("ROLLBACK"):(this.inner.exec(`ROLLBACK TO sp_${this.txDepth}`),this.inner.exec(`RELEASE sp_${this.txDepth}`))}catch{}throw r}})}loadExtension(t,s){this.extensionLoadingEnabled||(this.inner.enableLoadExtension(!0),this.extensionLoadingEnabled=!0),s===void 0?this.inner.loadExtension(t):this.inner.loadExtension(t,s)}},Yo=An});function Vo(e){let t=e.prepare("PRAGMA table_info(sessions)").all(),s=new Set(t.map(S=>S.name)),n=[["total_input_tokens","INTEGER"],["total_output_tokens","INTEGER"],["total_cache_create_tokens","INTEGER"],["total_cache_read_tokens","INTEGER"],["primary_model","TEXT"],["auto_title","TEXT"],["auto_title_source","TEXT"],["auto_title_generated_at","INTEGER"],["auto_title_history","TEXT"],["verification_status","TEXT"],["verification_computed_at","INTEGER"],["title_quality","TEXT"],["title_quality_computed_at","INTEGER"]];for(let[S,y]of n)s.has(S)||e.exec(`ALTER TABLE sessions ADD COLUMN ${S} ${y}`);let r=e.prepare("PRAGMA table_info(collection_sessions)").all(),o=new Set(r.map(S=>S.name)),a=[["source","TEXT NOT NULL DEFAULT 'manual'"],["rule_id","TEXT"]];for(let[S,y]of a)o.has(S)||e.exec(`ALTER TABLE collection_sessions ADD COLUMN ${S} ${y}`);let c=e.prepare("PRAGMA table_info(session_notes)").all(),d=new Set(c.map(S=>S.name)),u=[["auto_synopsis","TEXT"],["auto_synopsis_generated_at","INTEGER"],["auto_synopsis_history","TEXT"]];for(let[S,y]of u)d.has(S)||e.exec(`ALTER TABLE session_notes ADD COLUMN ${S} ${y}`);let g=e.prepare("PRAGMA table_info(threads)").all();new Set(g.map(S=>S.name)).has("folder_id")||(e.exec("ALTER TABLE threads ADD COLUMN folder_id TEXT REFERENCES thread_folders(id) ON DELETE SET NULL"),e.exec("CREATE INDEX IF NOT EXISTS idx_threads_folder ON threads(folder_id)"));let h=e.prepare("PRAGMA table_info(thread_folders)").all(),b=new Set(h.map(S=>S.name));b.has("project_scope")||(e.exec("ALTER TABLE thread_folders ADD COLUMN project_scope TEXT"),e.exec("CREATE INDEX IF NOT EXISTS idx_thread_folders_project ON thread_folders(project_scope)")),b.has("sort_order")||e.exec("ALTER TABLE thread_folders ADD COLUMN sort_order INTEGER NOT NULL DEFAULT 0"),e.exec(`
4
4
  CREATE TABLE IF NOT EXISTS message_embeddings (
5
5
  message_uuid TEXT PRIMARY KEY REFERENCES messages(uuid) ON DELETE CASCADE,
6
6
  session_id TEXT NOT NULL REFERENCES sessions(id) ON DELETE CASCADE,
@@ -618,8 +618,8 @@ CREATE INDEX IF NOT EXISTS idx_synth_results_target
618
618
  ON bug_synthesis_results(scope, target_id, created_at DESC);
619
619
  CREATE INDEX IF NOT EXISTS idx_synth_results_created
620
620
  ON bug_synthesis_results(created_at DESC);
621
- `});import*as Qo from"sqlite-vec";function f(){if(ie)return ie;J(),ie=new Yo(yn),Qo.load(ie),ie.pragma("cache_size = -64000"),ie.pragma("mmap_size = 268435456"),ie.pragma("temp_store = MEMORY"),ie.pragma("busy_timeout = 5000"),ie.pragma("journal_size_limit = 67108864"),ie.pragma("wal_autocheckpoint = 1000"),ie.exec(zo),Vo(ie);try{ie.exec("PRAGMA optimize")}catch{}return ie}var ie,H=be(()=>{"use strict";Ko();Z();Zo();ie=null});import{writeFileSync as Np}from"node:fs";import{join as Op}from"node:path";function De(e){return e.trim().toLowerCase().replace(/^#+/,"").replace(/[\s/\\]+/g,"-").replace(/[^a-z0-9\-._]/g,"").slice(0,40)}function Je(e,t){let s=De(t);if(!s)throw new Error("tag must contain at least one alphanumeric character");let n=f(),r=new Date().toISOString();return n.prepare("SELECT 1 FROM session_tags WHERE session_id = ? AND tag = ?").get(e,s)?{tag:s,added:!1}:(n.transaction(()=>{n.prepare("INSERT INTO session_tags (session_id, tag, created_at) VALUES (?, ?, ?)").run(e,s,r),n.prepare("INSERT INTO tag_events (session_id, tag, action, at) VALUES (?, ?, 'add', ?)").run(e,s,r)})(),oi(),{tag:s,added:!0})}function ri(e,t){let s=De(t);if(!s)return{tag:"",removed:!1};let n=f(),r=new Date().toISOString();return n.prepare("SELECT 1 FROM session_tags WHERE session_id = ? AND tag = ?").get(e,s)?(n.transaction(()=>{n.prepare("DELETE FROM session_tags WHERE session_id = ? AND tag = ?").run(e,s),n.prepare("INSERT INTO tag_events (session_id, tag, action, at) VALUES (?, ?, 'remove', ?)").run(e,s,r)})(),oi(),{tag:s,removed:!0}):{tag:s,removed:!1}}function wt(e){return f().prepare("SELECT tag FROM session_tags WHERE session_id = ? ORDER BY tag").all(e).map(t=>t.tag)}function Xe(){return f().prepare(`SELECT tag, COUNT(*) AS count FROM session_tags
622
- GROUP BY tag ORDER BY count DESC, tag ASC`).all()}function oi(){try{J();let e=f(),t=e.prepare("SELECT session_id, tag, created_at FROM session_tags ORDER BY session_id, tag").all(),s=e.prepare("SELECT id, session_id, tag, action, at FROM tag_events ORDER BY at ASC, id ASC").all(),n={schema:"claude-recall.tags.v1",backed_up_at:new Date().toISOString(),current:t,events:s};Np(Lp,JSON.stringify(n,null,2))}catch(e){console.error("[tags] backup failed:",e)}}var Lp,Ge=be(()=>{"use strict";H();Z();Lp=Op($,"tags.json")});function Cp(e,t){let s=e.filter(o=>o.content_text&&o.content_text.trim().length>0);if(s.length<=t)return s;let n=new Set;n.add(0),n.add(s.length-1);let r=(s.length-2)/Math.max(1,t-2);for(let o=1;o<t-1;o++)n.add(Math.floor(o*r));return Array.from(n).sort((o,a)=>o-a).slice(0,t).map(o=>s[o])}function Ye(e){let t=f(),s={limit:e.limit??500},n=e.sessionIds&&e.sessionIds.length>0,r=n?"1=1":"s.message_count > 2";if(n){let a=e.sessionIds.map((c,d)=>`@sid_${d}`).join(", ");r+=` AND s.id IN (${a})`,e.sessionIds.forEach((c,d)=>{s[`sid_${d}`]=c})}return e.untaggedOnly&&(r+=" AND NOT EXISTS (SELECT 1 FROM session_tags st WHERE st.session_id = s.id)"),e.project&&(r+=" AND p.name = @project",s.project=e.project),e.collectionId&&(r+=" AND s.id IN (SELECT session_id FROM collection_sessions WHERE collection_id = @col)",s.col=e.collectionId),t.prepare(`SELECT s.id, p.name AS project, s.git_branch,
621
+ `});import*as Qo from"sqlite-vec";function f(){if(ie)return ie;J(),ie=new Yo(yn),Qo.load(ie),ie.pragma("cache_size = -64000"),ie.pragma("mmap_size = 268435456"),ie.pragma("temp_store = MEMORY"),ie.pragma("busy_timeout = 5000"),ie.pragma("journal_size_limit = 67108864"),ie.pragma("wal_autocheckpoint = 1000"),ie.exec(zo),Vo(ie);try{ie.exec("PRAGMA optimize")}catch{}return ie}var ie,H=be(()=>{"use strict";Ko();Z();Zo();ie=null});import{writeFileSync as Lp}from"node:fs";import{join as Cp}from"node:path";function De(e){return e.trim().toLowerCase().replace(/^#+/,"").replace(/[\s/\\]+/g,"-").replace(/[^a-z0-9\-._]/g,"").slice(0,40)}function Je(e,t){let s=De(t);if(!s)throw new Error("tag must contain at least one alphanumeric character");let n=f(),r=new Date().toISOString();return n.prepare("SELECT 1 FROM session_tags WHERE session_id = ? AND tag = ?").get(e,s)?{tag:s,added:!1}:(n.transaction(()=>{n.prepare("INSERT INTO session_tags (session_id, tag, created_at) VALUES (?, ?, ?)").run(e,s,r),n.prepare("INSERT INTO tag_events (session_id, tag, action, at) VALUES (?, ?, 'add', ?)").run(e,s,r)})(),oi(),{tag:s,added:!0})}function ri(e,t){let s=De(t);if(!s)return{tag:"",removed:!1};let n=f(),r=new Date().toISOString();return n.prepare("SELECT 1 FROM session_tags WHERE session_id = ? AND tag = ?").get(e,s)?(n.transaction(()=>{n.prepare("DELETE FROM session_tags WHERE session_id = ? AND tag = ?").run(e,s),n.prepare("INSERT INTO tag_events (session_id, tag, action, at) VALUES (?, ?, 'remove', ?)").run(e,s,r)})(),oi(),{tag:s,removed:!0}):{tag:s,removed:!1}}function wt(e){return f().prepare("SELECT tag FROM session_tags WHERE session_id = ? ORDER BY tag").all(e).map(t=>t.tag)}function Xe(){return f().prepare(`SELECT tag, COUNT(*) AS count FROM session_tags
622
+ GROUP BY tag ORDER BY count DESC, tag ASC`).all()}function oi(){try{J();let e=f(),t=e.prepare("SELECT session_id, tag, created_at FROM session_tags ORDER BY session_id, tag").all(),s=e.prepare("SELECT id, session_id, tag, action, at FROM tag_events ORDER BY at ASC, id ASC").all(),n={schema:"claude-recall.tags.v1",backed_up_at:new Date().toISOString(),current:t,events:s};Lp(Ip,JSON.stringify(n,null,2))}catch(e){console.error("[tags] backup failed:",e)}}var Ip,Ge=be(()=>{"use strict";H();Z();Ip=Cp($,"tags.json")});function vp(e,t){let s=e.filter(o=>o.content_text&&o.content_text.trim().length>0);if(s.length<=t)return s;let n=new Set;n.add(0),n.add(s.length-1);let r=(s.length-2)/Math.max(1,t-2);for(let o=1;o<t-1;o++)n.add(Math.floor(o*r));return Array.from(n).sort((o,a)=>o-a).slice(0,t).map(o=>s[o])}function Ye(e){let t=f(),s={limit:e.limit??500},n=e.sessionIds&&e.sessionIds.length>0,r=n?"1=1":"s.message_count > 2";if(n){let a=e.sessionIds.map((c,d)=>`@sid_${d}`).join(", ");r+=` AND s.id IN (${a})`,e.sessionIds.forEach((c,d)=>{s[`sid_${d}`]=c})}return e.untaggedOnly&&(r+=" AND NOT EXISTS (SELECT 1 FROM session_tags st WHERE st.session_id = s.id)"),e.project&&(r+=" AND p.name = @project",s.project=e.project),e.collectionId&&(r+=" AND s.id IN (SELECT session_id FROM collection_sessions WHERE collection_id = @col)",s.col=e.collectionId),t.prepare(`SELECT s.id, p.name AS project, s.git_branch,
623
623
  NULLIF(sa.alias, '') AS alias,
624
624
  COALESCE(s.first_user_message, '') AS first_user_message
625
625
  FROM sessions s
@@ -629,21 +629,21 @@ CREATE INDEX IF NOT EXISTS idx_synth_results_created
629
629
  ORDER BY COALESCE(s.started_at, '') DESC
630
630
  LIMIT @limit`).all(s).map(a=>{let c=t.prepare(`SELECT role, COALESCE(content_text, '') AS content_text
631
631
  FROM messages WHERE session_id = ?
632
- ORDER BY COALESCE(timestamp, ''), rowid`).all(a.id),u=Cp(c,5).map(g=>`${g.role}: ${g.content_text.slice(0,400)}`).join(`
632
+ ORDER BY COALESCE(timestamp, ''), rowid`).all(a.id),u=vp(c,5).map(g=>`${g.role}: ${g.content_text.slice(0,400)}`).join(`
633
633
  ---
634
634
  `);return{id:a.id,project:a.project,git_branch:a.git_branch,alias:a.alias,first_user_message:a.first_user_message,message_sample:u,current_tags:wt(a.id)}})}var rs=be(()=>{"use strict";H();Ge()});import{z as ue}from"zod";function On(e){let t=e.minTags??2,s=e.maxTags??4,n=e.untaggedOnly??!e.sessionId,r=["Auto-tag my Claude Recall sessions using the MCP tools available to you.","","1. Call `list_tags` first to see which tags I already use (prefer those for consistency over inventing new ones).","2. Call `list_sessions_to_tag` with these filters:"],o=[];return e.sessionId?(o.push("limit: 1"),r.push(` ${o.join(", ")}`),r.push(` Then match the session id ${e.sessionId} from the returned list.`)):(n&&o.push("untaggedOnly: true"),e.project&&o.push(`project: "${e.project}"`),e.collectionId&&o.push(`collectionId: "${e.collectionId}"`),o.push(`limit: ${e.limit??100}`),r.push(` ${o.join(", ")}`)),r.push(""),r.push(`3. For each session returned, look at the alias, first user message, git branch, and sampled messages. Pick ${t}-${s} concise, lowercase, hyphen-separated tags describing:`),r.push(" - domain/subsystem (auth, db, frontend, billing, etc.)"),r.push(" - kind of work (bugfix, feature, refactor, research)"),r.push(" - prominent tools or libraries if relevant"),r.push(""),r.push("4. Call `apply_tags` once per session to write the tags."),r.push(""),r.push("Work through EVERY session returned \u2014 do not stop partway. When done, reply with a short summary of how many sessions were tagged. Do not ask clarifying questions; just do the work."),r.join(`
635
- `)}function jp(e){let t=e.mode==="detailed";return[`Summarize Claude Recall session ${e.sessionId} using the MCP tools available to you.`,"",`1. Call \`context_for_session\` with id "${e.sessionId}" and mode "condensed" to get the transcript as markdown.`,t?"2. Write a 1-paragraph overview (\u22643 sentences) of what this session was for, then 5-8 bullet points covering:":"2. Write 3-5 bullet points covering:"," - What was accomplished (shipped, decided, learned)"," - What was tried and abandoned"," - Any explicit open questions or follow-ups","","Rules:",'- Be concrete. Name files, functions, and decisions. Avoid vague "discussed X".',"- If nothing was actually shipped or decided, say so plainly.",'- Reply with just the summary \u2014 no preamble, no "Here is the summary:".'].join(`
636
- `)}function Dp(e){return[`Extract every architectural or product decision made in Claude Recall session ${e.sessionId}.`,"",`1. Call \`context_for_session\` with id "${e.sessionId}" and mode "full" (so tool I/O is included \u2014 sometimes the decision lives in a commit message or diff).`,"2. For each distinct decision, emit one block:",""," - **Decision:** one sentence."," - **Why:** the stated rationale (quote if possible).",' - **Alternatives considered:** bullet list, or "none mentioned".',' - **Where it landed:** file path / function name / commit SHA if identifiable, otherwise "TBD".',"","Rules:","- Include only decisions that were actually made, not ideas merely discussed.","- If an alternative was rejected, list it with a one-line reason.","- Group related decisions under a short heading when useful.",'- If the session made zero real decisions, reply exactly with: "No decisions made in this session."',"- No preamble, no closing, just the decision blocks."].join(`
637
- `)}function Pp(e){let t=e.limit??5;return[`Find ${t} Recall sessions most similar to session ${e.sessionId}.`,"",`1. Call \`get_session\` with id "${e.sessionId}" \u2014 note its alias, first user message, tags, and git branch.`,'2. Derive 2-3 short search queries from that content (topic words, library names, error strings \u2014 NOT generic words like "fix" or "add").',`3. Call \`search\` once per query (limit: ${Math.max(5,t*2)}). Dedupe hits by session_id.`,"4. Also call `list_sessions` with the same tag(s) if the target session has any (pick the most specific tag).","5. Union the results. Exclude the target session itself. Rank by a mix of:"," - Shared tags (strongest signal)"," - Matching search hits across multiple queries"," - Recency as a tiebreaker","",`6. Return the top ${t} as a numbered list. For each:`," - **<short_id> \xB7 <project>** \u2014 <alias or first_user_message truncated>",' - One sentence on WHY it is similar (not a generic "same topic" \u2014 be specific).',"","If fewer than 2 genuinely-similar sessions exist, say so rather than padding with weak matches.","No preamble. Just the ranked list."].join(`
638
- `)}function ii(e){return Ln.find(t=>t.name===e)}var Ip,vp,Mp,Fp,Up,$p,Bp,Hp,Ln,Cn=be(()=>{"use strict";Ip={project:ue.string().optional().describe("Exact project name match (optional)."),collectionId:ue.string().optional().describe("Restrict to sessions in this collection (optional)."),sessionId:ue.string().optional().describe("Full session UUID to tag just one session (optional)."),untaggedOnly:ue.boolean().optional().describe("Skip sessions that already have any tag (default: true)."),limit:ue.number().int().min(1).max(500).optional().describe("Max sessions to process (default: 100)."),minTags:ue.number().int().min(1).max(10).optional().describe("Minimum tags per session (default: 2)."),maxTags:ue.number().int().min(1).max(10).optional().describe("Maximum tags per session (default: 4).")};vp={sessionId:ue.string().describe("Session UUID (or 8+-char prefix) to summarize."),mode:ue.enum(["brief","detailed"]).optional().describe("brief = 3-5 bullets; detailed = paragraph + bullets. Default: brief.")};Mp={sessionId:ue.string().describe("Session UUID (or 8+-char prefix) to extract decisions from.")};Fp={sessionId:ue.string().describe("Session UUID (or 8+-char prefix) to find similar sessions to."),limit:ue.number().int().min(1).max(20).optional().describe("How many similar sessions to surface (default: 5).")};Up={name:"auto_tag_sessions",title:"Auto-tag Recall sessions",description:"Have the agent auto-tag Recall sessions using the Recall MCP tools. Scope can be restricted to a project, collection, or single session.",argsSchema:Ip,build:On,allowedTools:["mcp__recall__list_tags","mcp__recall__list_sessions_to_tag","mcp__recall__apply_tags"]},$p={name:"summarize_session",title:"Summarize a session",description:"Produce a concise, concrete summary of one session \u2014 what shipped, what was tried, what's still open.",argsSchema:vp,build:jp,allowedTools:["mcp__recall__get_session","mcp__recall__context_for_session"]},Bp={name:"extract_decisions",title:"Extract architectural decisions",description:"Scan a session and emit one structured block per architectural / product decision: what, why, alternatives, where it landed.",argsSchema:Mp,build:Dp,allowedTools:["mcp__recall__get_session","mcp__recall__context_for_session"]},Hp={name:"find_similar_sessions",title:"Find similar sessions",description:"Given a session, find other sessions that touched the same topic / library / error \u2014 ranked with reasons.",argsSchema:Fp,build:Pp,allowedTools:["mcp__recall__get_session","mcp__recall__search","mcp__recall__list_sessions","mcp__recall__list_tags"]},Ln=[Up,$p,Bp,Hp]});function os(e,t){let s=Rt.get(e);if(!(!s||s.size===0))for(let n of s)try{n(t)}catch{}}function ai(e,t){let s=Rt.get(e);return s||(s=new Set,Rt.set(e,s)),s.add(t),()=>{let n=Rt.get(e);n&&(n.delete(t),n.size===0&&Rt.delete(e))}}var Rt,In=be(()=>{"use strict";Rt=new Map});var Pe={};vo(Pe,{buildScanPrompt:()=>ci,isClaudeCliAvailable:()=>oe,runClaudeCliScan:()=>vn,spawnClaudePrompt:()=>Fe});import{execFileSync as Wp,execSync as qp,spawn as Jp}from"node:child_process";function Gp(){if(kt)return kt;try{kt=qp("which claude",{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{kt="claude"}return kt}function oe(){try{return Wp("command",["-v","claude"],{stdio:"ignore"}),!0}catch{return!1}}function ci(e){return On({project:e.project,collectionId:e.collectionId,sessionId:e.sessionIds&&e.sessionIds.length===1?e.sessionIds[0]:void 0,untaggedOnly:e.untaggedOnly,limit:e.limit})}function Yp(e,t){let s=t.get(e);return s||e.slice(0,8)}function Kp(e){try{return Ye(e).map(s=>({id:s.id,label:s.alias&&s.alias.trim().length>0?s.alias:s.first_user_message&&s.first_user_message.trim().length>0?s.first_user_message.slice(0,60):s.id.slice(0,8)}))}catch{return[]}}function zp(e){let{scanId:t,total:s,labelTable:n}=e,r=new Set;return o=>{let a=o.trim();if(!a.startsWith("{"))return;let c;try{c=JSON.parse(a)}catch{return}if(!c||typeof c!="object")return;let d=c;if(!(d.type!=="assistant"||!d.message?.content))for(let u of d.message.content){if(u?.type!=="tool_use"||u.name!=="mcp__recall__apply_tags")continue;let g=u.input,h=typeof g?.sessionId=="string"?g.sessionId:null;!h||r.has(h)||(r.add(h),os(t,{type:"progress",current:r.size,total:s,sessionId:h,sessionLabel:Yp(h,n)}))}}}function Vp(e){let t="";return s=>{t+=s.toString("utf8");let n=t.indexOf(`
635
+ `)}function Dp(e){let t=e.mode==="detailed";return[`Summarize Claude Recall session ${e.sessionId} using the MCP tools available to you.`,"",`1. Call \`context_for_session\` with id "${e.sessionId}" and mode "condensed" to get the transcript as markdown.`,t?"2. Write a 1-paragraph overview (\u22643 sentences) of what this session was for, then 5-8 bullet points covering:":"2. Write 3-5 bullet points covering:"," - What was accomplished (shipped, decided, learned)"," - What was tried and abandoned"," - Any explicit open questions or follow-ups","","Rules:",'- Be concrete. Name files, functions, and decisions. Avoid vague "discussed X".',"- If nothing was actually shipped or decided, say so plainly.",'- Reply with just the summary \u2014 no preamble, no "Here is the summary:".'].join(`
636
+ `)}function Pp(e){return[`Extract every architectural or product decision made in Claude Recall session ${e.sessionId}.`,"",`1. Call \`context_for_session\` with id "${e.sessionId}" and mode "full" (so tool I/O is included \u2014 sometimes the decision lives in a commit message or diff).`,"2. For each distinct decision, emit one block:",""," - **Decision:** one sentence."," - **Why:** the stated rationale (quote if possible).",' - **Alternatives considered:** bullet list, or "none mentioned".',' - **Where it landed:** file path / function name / commit SHA if identifiable, otherwise "TBD".',"","Rules:","- Include only decisions that were actually made, not ideas merely discussed.","- If an alternative was rejected, list it with a one-line reason.","- Group related decisions under a short heading when useful.",'- If the session made zero real decisions, reply exactly with: "No decisions made in this session."',"- No preamble, no closing, just the decision blocks."].join(`
637
+ `)}function $p(e){let t=e.limit??5;return[`Find ${t} Recall sessions most similar to session ${e.sessionId}.`,"",`1. Call \`get_session\` with id "${e.sessionId}" \u2014 note its alias, first user message, tags, and git branch.`,'2. Derive 2-3 short search queries from that content (topic words, library names, error strings \u2014 NOT generic words like "fix" or "add").',`3. Call \`search\` once per query (limit: ${Math.max(5,t*2)}). Dedupe hits by session_id.`,"4. Also call `list_sessions` with the same tag(s) if the target session has any (pick the most specific tag).","5. Union the results. Exclude the target session itself. Rank by a mix of:"," - Shared tags (strongest signal)"," - Matching search hits across multiple queries"," - Recency as a tiebreaker","",`6. Return the top ${t} as a numbered list. For each:`," - **<short_id> \xB7 <project>** \u2014 <alias or first_user_message truncated>",' - One sentence on WHY it is similar (not a generic "same topic" \u2014 be specific).',"","If fewer than 2 genuinely-similar sessions exist, say so rather than padding with weak matches.","No preamble. Just the ranked list."].join(`
638
+ `)}function ii(e){return Ln.find(t=>t.name===e)}var jp,Mp,Fp,Up,Bp,Hp,Wp,qp,Ln,Cn=be(()=>{"use strict";jp={project:ue.string().optional().describe("Exact project name match (optional)."),collectionId:ue.string().optional().describe("Restrict to sessions in this collection (optional)."),sessionId:ue.string().optional().describe("Full session UUID to tag just one session (optional)."),untaggedOnly:ue.boolean().optional().describe("Skip sessions that already have any tag (default: true)."),limit:ue.number().int().min(1).max(500).optional().describe("Max sessions to process (default: 100)."),minTags:ue.number().int().min(1).max(10).optional().describe("Minimum tags per session (default: 2)."),maxTags:ue.number().int().min(1).max(10).optional().describe("Maximum tags per session (default: 4).")};Mp={sessionId:ue.string().describe("Session UUID (or 8+-char prefix) to summarize."),mode:ue.enum(["brief","detailed"]).optional().describe("brief = 3-5 bullets; detailed = paragraph + bullets. Default: brief.")};Fp={sessionId:ue.string().describe("Session UUID (or 8+-char prefix) to extract decisions from.")};Up={sessionId:ue.string().describe("Session UUID (or 8+-char prefix) to find similar sessions to."),limit:ue.number().int().min(1).max(20).optional().describe("How many similar sessions to surface (default: 5).")};Bp={name:"auto_tag_sessions",title:"Auto-tag Recall sessions",description:"Have the agent auto-tag Recall sessions using the Recall MCP tools. Scope can be restricted to a project, collection, or single session.",argsSchema:jp,build:On,allowedTools:["mcp__recall__list_tags","mcp__recall__list_sessions_to_tag","mcp__recall__apply_tags"]},Hp={name:"summarize_session",title:"Summarize a session",description:"Produce a concise, concrete summary of one session \u2014 what shipped, what was tried, what's still open.",argsSchema:Mp,build:Dp,allowedTools:["mcp__recall__get_session","mcp__recall__context_for_session"]},Wp={name:"extract_decisions",title:"Extract architectural decisions",description:"Scan a session and emit one structured block per architectural / product decision: what, why, alternatives, where it landed.",argsSchema:Fp,build:Pp,allowedTools:["mcp__recall__get_session","mcp__recall__context_for_session"]},qp={name:"find_similar_sessions",title:"Find similar sessions",description:"Given a session, find other sessions that touched the same topic / library / error \u2014 ranked with reasons.",argsSchema:Up,build:$p,allowedTools:["mcp__recall__get_session","mcp__recall__search","mcp__recall__list_sessions","mcp__recall__list_tags"]},Ln=[Bp,Hp,Wp,qp]});function os(e,t){let s=Rt.get(e);if(!(!s||s.size===0))for(let n of s)try{n(t)}catch{}}function ai(e,t){let s=Rt.get(e);return s||(s=new Set,Rt.set(e,s)),s.add(t),()=>{let n=Rt.get(e);n&&(n.delete(t),n.size===0&&Rt.delete(e))}}var Rt,In=be(()=>{"use strict";Rt=new Map});var Pe={};vo(Pe,{buildScanPrompt:()=>ci,isClaudeCliAvailable:()=>oe,runClaudeCliScan:()=>vn,spawnClaudePrompt:()=>Fe});import{execFileSync as Jp,execSync as Xp,spawn as Gp}from"node:child_process";function Kp(){if(kt)return kt;try{kt=Xp("which claude",{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{kt="claude"}return kt}function oe(){try{return Jp("command",["-v","claude"],{stdio:"ignore"}),!0}catch{return!1}}function ci(e){return On({project:e.project,collectionId:e.collectionId,sessionId:e.sessionIds&&e.sessionIds.length===1?e.sessionIds[0]:void 0,untaggedOnly:e.untaggedOnly,limit:e.limit})}function zp(e,t){let s=t.get(e);return s||e.slice(0,8)}function Vp(e){try{return Ye(e).map(s=>({id:s.id,label:s.alias&&s.alias.trim().length>0?s.alias:s.first_user_message&&s.first_user_message.trim().length>0?s.first_user_message.slice(0,60):s.id.slice(0,8)}))}catch{return[]}}function Zp(e){let{scanId:t,total:s,labelTable:n}=e,r=new Set;return o=>{let a=o.trim();if(!a.startsWith("{"))return;let c;try{c=JSON.parse(a)}catch{return}if(!c||typeof c!="object")return;let d=c;if(!(d.type!=="assistant"||!d.message?.content))for(let u of d.message.content){if(u?.type!=="tool_use"||u.name!=="mcp__recall__apply_tags")continue;let g=u.input,h=typeof g?.sessionId=="string"?g.sessionId:null;!h||r.has(h)||(r.add(h),os(t,{type:"progress",current:r.size,total:s,sessionId:h,sessionLabel:zp(h,n)}))}}}function Qp(e){let t="";return s=>{t+=s.toString("utf8");let n=t.indexOf(`
639
639
  `);for(;n!==-1;){let r=t.slice(0,n);t=t.slice(n+1),r.length>0&&e(r),n=t.indexOf(`
640
- `)}}}async function vn(e,t={},s){let n=!!t.scanId,r=n?Kp(e):[],o=new Map(r.map(d=>[d.id,d.label])),a=r.length,c;return n&&t.scanId&&(c=zp({scanId:t.scanId,total:a,labelTable:o})),li({prompt:ci(e),allowedTools:Xp.split(","),opts:t,onProgress:s,onStdoutLine:c,outputFormat:n?"stream-json":"json"})}async function Fe(e,t,s={},n){return li({prompt:e,allowedTools:t,opts:s,onProgress:n,outputFormat:"json"})}function li(e){let{prompt:t,allowedTools:s,opts:n,onProgress:r,onStdoutLine:o,outputFormat:a}=e,c=["-p",t,"--output-format",a,"--allowedTools",s.join(","),"--permission-mode","bypassPermissions"];return a==="stream-json"&&c.push("--verbose"),n.model&&c.push("--model",n.model),new Promise(d=>{let u=Jp(Gp(),c,{stdio:["ignore","pipe","pipe"]}),g=[],h=[],b=o?Vp(o):void 0;u.stdout.on("data",y=>{g.push(y),b&&b(y)}),u.stderr.on("data",y=>{if(h.push(y),r){let k=y.toString("utf8").trim();k&&r(k)}});let S=setTimeout(()=>{u.kill("SIGKILL")},1800*1e3);u.on("close",y=>{clearTimeout(S),d({success:y===0,stdout:Buffer.concat(g).toString("utf8"),stderr:Buffer.concat(h).toString("utf8"),exitCode:y})}),u.on("error",y=>{clearTimeout(S),d({success:!1,stdout:"",stderr:String(y),exitCode:null})})})}var Xp,kt,ge=be(()=>{"use strict";rs();Cn();In();Xp=["mcp__recall__list_tags","mcp__recall__list_sessions_to_tag","mcp__recall__apply_tags"].join(",")});var Xc={};vo(Xc,{EmbedderUnavailableError:()=>Ut,embed:()=>$t,embedQuery:()=>Tr,getEmbedderStatus:()=>ke,loadEmbedder:()=>Ws,unloadEmbedder:()=>Qf});import{join as qc}from"node:path";function Zf(){return qc($,"models","bge-base-en-v1.5")}async function Ws(){if(Hs&&Pt)return;let e;try{e=await import("@huggingface/transformers")}catch(n){throw new Ut(n)}let{pipeline:t,env:s}=e;s.localModelPath=qc($,"models"),s.allowRemoteModels=!1;try{Pt=await t("feature-extraction",Jc,{local_files_only:!0,cache_dir:Zf()}),Hs=!0}catch(n){throw n instanceof Error&&/Cannot find module|onnxruntime_binding/.test(n.message)?new Ut(n):n}}function ke(){return{loaded:Hs,modelId:Jc,dim:zf}}async function $t(e){if(!Pt)throw new Error("[embedder] Model not loaded. Call loadEmbedder() before embedding.");let t=[];for(let s=0;s<e.length;s+=Wc){let n=e.slice(s,s+Wc),o=(await Pt(n,{pooling:"cls",normalize:!0})).tolist();for(let a=0;a<n.length;a++){let c=o[a],d=Array.isArray(c[0])?c[0]:c;t.push(new Float32Array(d))}}return t}async function Tr(e){let t=Vf+e,[s]=await $t([t]);return s}function Qf(){Pt=null,Hs=!1}var Jc,zf,Wc,Vf,Pt,Hs,Ut,ot=be(()=>{"use strict";Z();Jc="BAAI/bge-base-en-v1.5",zf=768,Wc=16,Vf="Represent this sentence for searching relevant passages: ",Pt=null,Hs=!1;Ut=class extends Error{cause;constructor(t){let s=t instanceof Error?t.message:String(t);super(["Semantic search is unavailable on this platform.","",`Reason: ${s}`,"",`Platform: ${process.platform}/${process.arch}, Node ${process.version}`,"","Claude Recall supports macOS (arm64/x64), Linux (x64/arm64), and Windows (x64).","Core CLI features (search, list, context, daemon) work everywhere.","Only `recall semantic *` requires the on-device embedder.","","See: https://clauderecall.com/docs (Supported platforms) \u2014 or file an issue at","https://gitlab.com/clauderecallhq/clauderecallhq/-/issues with the platform line above."].join(`
641
- `)),this.name="EmbedderUnavailableError",this.cause=t}}});import{Hono as Xb}from"hono";import{serve as Gb}from"@hono/node-server";Z();import{existsSync as Ju,readFileSync as Xu,writeFileSync as MT,unlinkSync as DT}from"node:fs";import{join as Gu}from"node:path";var Do=Gu($,"license.json");function St(){if(!Ju(Do))return null;try{let e=Xu(Do,"utf8"),t=JSON.parse(e);return typeof t.license_jwt!="string"||t.license_jwt.length===0?null:t}catch{return null}}import{jwtVerify as Yu,importSPKI as Ku}from"jose";var Fo=`-----BEGIN PUBLIC KEY-----
640
+ `)}}}async function vn(e,t={},s){let n=!!t.scanId,r=n?Vp(e):[],o=new Map(r.map(d=>[d.id,d.label])),a=r.length,c;return n&&t.scanId&&(c=Zp({scanId:t.scanId,total:a,labelTable:o})),li({prompt:ci(e),allowedTools:Yp.split(","),opts:t,onProgress:s,onStdoutLine:c,outputFormat:n?"stream-json":"json"})}async function Fe(e,t,s={},n){return li({prompt:e,allowedTools:t,opts:s,onProgress:n,outputFormat:"json"})}function li(e){let{prompt:t,allowedTools:s,opts:n,onProgress:r,onStdoutLine:o,outputFormat:a}=e,c=["-p",t,"--output-format",a,"--allowedTools",s.join(","),"--permission-mode","bypassPermissions"];return a==="stream-json"&&c.push("--verbose"),n.model&&c.push("--model",n.model),new Promise(d=>{let u=Gp(Kp(),c,{stdio:["ignore","pipe","pipe"]}),g=[],h=[],b=o?Qp(o):void 0;u.stdout.on("data",y=>{g.push(y),b&&b(y)}),u.stderr.on("data",y=>{if(h.push(y),r){let k=y.toString("utf8").trim();k&&r(k)}});let S=setTimeout(()=>{u.kill("SIGKILL")},1800*1e3);u.on("close",y=>{clearTimeout(S),d({success:y===0,stdout:Buffer.concat(g).toString("utf8"),stderr:Buffer.concat(h).toString("utf8"),exitCode:y})}),u.on("error",y=>{clearTimeout(S),d({success:!1,stdout:"",stderr:String(y),exitCode:null})})})}var Yp,kt,ge=be(()=>{"use strict";rs();Cn();In();Yp=["mcp__recall__list_tags","mcp__recall__list_sessions_to_tag","mcp__recall__apply_tags"].join(",")});var Xc={};vo(Xc,{EmbedderUnavailableError:()=>Ut,embed:()=>$t,embedQuery:()=>Tr,getEmbedderStatus:()=>ke,loadEmbedder:()=>Ws,unloadEmbedder:()=>th});import{join as qc}from"node:path";function eh(){return qc($,"models","bge-base-en-v1.5")}async function Ws(){if(Hs&&Pt)return;let e;try{e=await import("@huggingface/transformers")}catch(n){throw new Ut(n)}let{pipeline:t,env:s}=e;s.localModelPath=qc($,"models"),s.allowRemoteModels=!1;try{Pt=await t("feature-extraction",Jc,{local_files_only:!0,cache_dir:eh()}),Hs=!0}catch(n){throw n instanceof Error&&/Cannot find module|onnxruntime_binding/.test(n.message)?new Ut(n):n}}function ke(){return{loaded:Hs,modelId:Jc,dim:Zf}}async function $t(e){if(!Pt)throw new Error("[embedder] Model not loaded. Call loadEmbedder() before embedding.");let t=[];for(let s=0;s<e.length;s+=Wc){let n=e.slice(s,s+Wc),o=(await Pt(n,{pooling:"cls",normalize:!0})).tolist();for(let a=0;a<n.length;a++){let c=o[a],d=Array.isArray(c[0])?c[0]:c;t.push(new Float32Array(d))}}return t}async function Tr(e){let t=Qf+e,[s]=await $t([t]);return s}function th(){Pt=null,Hs=!1}var Jc,Zf,Wc,Qf,Pt,Hs,Ut,ot=be(()=>{"use strict";Z();Jc="BAAI/bge-base-en-v1.5",Zf=768,Wc=16,Qf="Represent this sentence for searching relevant passages: ",Pt=null,Hs=!1;Ut=class extends Error{cause;constructor(t){let s=t instanceof Error?t.message:String(t);super(["Semantic search is unavailable on this platform.","",`Reason: ${s}`,"",`Platform: ${process.platform}/${process.arch}, Node ${process.version}`,"","Claude Recall supports macOS (arm64/x64), Linux (x64/arm64), and Windows (x64).","Core CLI features (search, list, context, daemon) work everywhere.","Only `recall semantic *` requires the on-device embedder.","","See: https://clauderecall.com/docs (Supported platforms) \u2014 or file an issue at","https://gitlab.com/clauderecallhq/clauderecallhq/-/issues with the platform line above."].join(`
641
+ `)),this.name="EmbedderUnavailableError",this.cause=t}}});import{Hono as Yb}from"hono";import{serve as Kb}from"@hono/node-server";Z();import{existsSync as Ju,readFileSync as Xu,writeFileSync as FT,unlinkSync as PT}from"node:fs";import{join as Gu}from"node:path";var Do=Gu($,"license.json");function St(){if(!Ju(Do))return null;try{let e=Xu(Do,"utf8"),t=JSON.parse(e);return typeof t.license_jwt!="string"||t.license_jwt.length===0?null:t}catch{return null}}import{jwtVerify as Yu,importSPKI as Ku}from"jose";var Fo=`-----BEGIN PUBLIC KEY-----
642
642
  MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEZysO2FffTLdyxQnTmnt78/ayvqz9
643
643
  kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
644
644
  -----END PUBLIC KEY-----
645
645
  `,wn="ES256",Po="clauderecall.com",Uo="clauderecall-cli";var ss=null;async function zu(){return ss||(ss=await Ku(Fo,wn),ss)}async function $o(e){try{let t=await zu(),{payload:s}=await Yu(e,t,{issuer:Po,audience:Uo,algorithms:[wn]});return{valid:!0,claims:s}}catch(t){return{valid:!1,reason:t instanceof Error?t.message:"verification failed"}}}import{createHash as Vu}from"node:crypto";import{hostname as Zu,userInfo as Qu,platform as ep,arch as tp}from"node:os";function Bo(){let e="unknown";try{e=Qu().username}catch{}let t=[Zu(),e,ep(),tp()];return Vu("sha256").update(t.join("\0")).digest("hex")}Z();import{existsSync as sp,readFileSync as np,writeFileSync as rp}from"node:fs";import{join as op}from"node:path";function Ho(){let e=process.env.RECALL_API_BASE;if(e&&e.length>0){let t=e.replace(/\/$/,""),s;try{s=new URL(t)}catch{throw new Error(`RECALL_API_BASE is not a valid URL: ${t}`)}let n=s.hostname==="127.0.0.1"||s.hostname==="localhost"||s.hostname==="::1";if(s.protocol==="https:"||s.protocol==="http:"&&n)return t;throw new Error(`RECALL_API_BASE must be HTTPS, or HTTP with loopback hostname. Got: ${t}`)}return"https://clauderecall.com"}var Rn=op($,"license-check.json"),ip=1440*60*1e3,ap=720*60*60*1e3,cp=1e4;function Wo(){if(!sp(Rn))return null;try{let e=JSON.parse(np(Rn,"utf8"));return typeof e.license_key!="string"||typeof e.last_checked_at!="string"||typeof e.revoked!="boolean"?null:e}catch{return null}}function lp(e){J(),rp(Rn,JSON.stringify(e,null,2)+`
646
- `,{mode:384})}async function dp(e,t){let s=null,n=null;try{s=new AbortController,n=setTimeout(()=>s?.abort(),cp);let r=await fetch(t,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({license_key:e}),signal:s.signal});if(!r.ok)return null;let o=await r.json();return typeof o?.revoked!="boolean"?null:o}catch{return null}finally{n&&clearTimeout(n)}}async function qo(e,t={}){let s=Wo(),n=t.apiUrl??`${Ho()}/api/license/check`,r=s?.license_key===e,o=!s||!r||Date.now()-new Date(s.last_checked_at).getTime()>=ip;if(!t.force&&!o)return s;let a=await dp(e,n);if(!a)return r?s:null;let c={license_key:e,last_checked_at:new Date().toISOString(),revoked:a.revoked,reason:a.reason??null};return lp(c),c}function Jo(e){let t=Wo();return!t||t.license_key!==e?null:t.revoked?{revoked:!0,reason:t.reason?`license revoked: ${t.reason}`:"license revoked by issuer"}:Date.now()-new Date(t.last_checked_at).getTime()>ap?{revoked:!0,reason:"license has not been validated with the server in 30+ days. Reconnect to the internet and run `recall license check`"}:null}var up=Date.UTC(2026,5,1,7,0,0);var pp=1440*60*1e3,ty=60*pp;async function Tt(){let e=St();if(!e)return{tier:"free"};let t=await $o(e.license_jwt);if(!t.valid||!t.claims)return{tier:"free",invalid_reason:t.reason};if(t.claims.machine_fp&&t.claims.machine_fp!==Bo())return{tier:"free",invalid_reason:"machine fingerprint mismatch \u2014 re-activate on this device"};let s=Jo(e.license_key);return s?.revoked?{tier:"free",invalid_reason:s.reason}:mp(e,t.claims)}async function Xo(e){let t=St();if(!t)return{ran:!1,revoked:!1,reason:null,last_checked_at:null};let s=await qo(t.license_key,{force:e?.force??!1});return s?{ran:!0,revoked:s.revoked,reason:s.reason,last_checked_at:s.last_checked_at}:{ran:!0,revoked:!1,reason:null,last_checked_at:null}}function mp(e,t){let s=t.test_mode===!0&&process.env.NODE_ENV==="production";return{tier:s?"free":"pro",key_short:e.key_short,customer_email:e.customer_email,activated_at:e.activated_at,test_mode:e.test_mode,...s?{test_mode_blocked:!0}:{},expires_at:typeof t.exp=="number"?new Date(t.exp*1e3).toISOString():null}}async function Go(){return(await Tt()).tier==="pro"}H();import{serveStatic as cu}from"@hono/node-server/serve-static";import{existsSync as Yb,readFileSync as hn}from"node:fs";import{stat as Kb,readFile as zb,realpath as Vb}from"node:fs/promises";import{timingSafeEqual as Zb}from"node:crypto";import{homedir as Qb}from"node:os";import{dirname as Eo,join as bn}from"node:path";import{fileURLToPath as bo}from"node:url";import{existsSync as ky,readFileSync as Ay,statSync as xy,statfsSync as fp}from"node:fs";import Se from"chalk";import{formatDistanceToNowStrict as Ty,parseISO as yy}from"date-fns";var ei={dim:Se.gray,bold:Se.bold,project:Se.cyan,user:Se.blue,assistant:Se.green,tool:Se.magenta,warn:Se.yellow,err:Se.red,ok:Se.green,accent:Se.hex("#f97316")};H();Z();var hp=["VS Code","VS Code Insiders","Cursor","Windsurf","Warp","iTerm","Terminal","WezTerm","Windows Terminal","Kitty","Alacritty"],Cy=new RegExp(`^(${hp.map(e=>e.replace(/ /g,"\\s")).join("|")})\\s\xB7\\s`);var Iy=5*6e4;function xn(){try{let e=fp($);return Number(e.bavail)*Number(e.bsize)}catch{return 0}}function ti(e){let{projects:t,sessions:s,messages:n,port:r,version:o}=e;return`<!DOCTYPE html>
646
+ `,{mode:384})}async function dp(e,t){let s=null,n=null;try{s=new AbortController,n=setTimeout(()=>s?.abort(),cp);let r=await fetch(t,{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({license_key:e}),signal:s.signal});if(!r.ok)return null;let o=await r.json();return typeof o?.revoked!="boolean"?null:o}catch{return null}finally{n&&clearTimeout(n)}}async function qo(e,t={}){let s=Wo(),n=t.apiUrl??`${Ho()}/api/license/check`,r=s?.license_key===e,o=!s||!r||Date.now()-new Date(s.last_checked_at).getTime()>=ip;if(!t.force&&!o)return s;let a=await dp(e,n);if(!a)return r?s:null;let c={license_key:e,last_checked_at:new Date().toISOString(),revoked:a.revoked,reason:a.reason??null};return lp(c),c}function Jo(e){let t=Wo();return!t||t.license_key!==e?null:t.revoked?{revoked:!0,reason:t.reason?`license revoked: ${t.reason}`:"license revoked by issuer"}:Date.now()-new Date(t.last_checked_at).getTime()>ap?{revoked:!0,reason:"license has not been validated with the server in 30+ days. Reconnect to the internet and run `recall license check`"}:null}var up=Date.UTC(2026,5,1,7,0,0);var pp=1440*60*1e3,ny=60*pp;async function Tt(){let e=St();if(!e)return{tier:"free"};let t=await $o(e.license_jwt);if(!t.valid||!t.claims)return{tier:"free",invalid_reason:t.reason};if(t.claims.machine_fp&&t.claims.machine_fp!==Bo())return{tier:"free",invalid_reason:"machine fingerprint mismatch \u2014 re-activate on this device"};let s=Jo(e.license_key);return s?.revoked?{tier:"free",invalid_reason:s.reason}:mp(e,t.claims)}async function Xo(e){let t=St();if(!t)return{ran:!1,revoked:!1,reason:null,last_checked_at:null};let s=await qo(t.license_key,{force:e?.force??!1});return s?{ran:!0,revoked:s.revoked,reason:s.reason,last_checked_at:s.last_checked_at}:{ran:!0,revoked:!1,reason:null,last_checked_at:null}}function mp(e,t){let s=t.test_mode===!0&&process.env.NODE_ENV==="production";return{tier:s?"free":"pro",key_short:e.key_short,customer_email:e.customer_email,activated_at:e.activated_at,test_mode:e.test_mode,...s?{test_mode_blocked:!0}:{},expires_at:typeof t.exp=="number"?new Date(t.exp*1e3).toISOString():null}}async function Go(){return(await Tt()).tier==="pro"}H();import{serveStatic as cu}from"@hono/node-server/serve-static";import{existsSync as zb,readFileSync as hn}from"node:fs";import{stat as Vb,readFile as Zb,realpath as Qb}from"node:fs/promises";import{timingSafeEqual as eS}from"node:crypto";import{homedir as tS}from"node:os";import{dirname as Eo,join as bn}from"node:path";import{fileURLToPath as bo}from"node:url";import{existsSync as xy,readFileSync as Ny,statSync as Oy,statfsSync as Ep}from"node:fs";import Se from"chalk";import{formatDistanceToNowStrict as wy,parseISO as Ry}from"date-fns";var ei={dim:Se.gray,bold:Se.bold,project:Se.cyan,user:Se.blue,assistant:Se.green,tool:Se.magenta,warn:Se.yellow,err:Se.red,ok:Se.green,accent:Se.hex("#f97316")};H();Z();var bp=["VS Code","VS Code Insiders","Cursor","Windsurf","Warp","iTerm","Terminal","WezTerm","Windows Terminal","Kitty","Alacritty"],vy=new RegExp(`^(${bp.map(e=>e.replace(/ /g,"\\s")).join("|")})\\s\xB7\\s`);var jy=5*6e4;function xn(){try{let e=Ep($);return Number(e.bavail)*Number(e.bsize)}catch{return 0}}function ti(e){let{projects:t,sessions:s,messages:n,port:r,version:o}=e;return`<!DOCTYPE html>
647
647
  <html lang="en">
648
648
  <head>
649
649
  <meta charset="utf-8" />
@@ -698,39 +698,39 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
698
698
  </footer>
699
699
  </main>
700
700
  </body>
701
- </html>`}var Ep=/<(local-command-caveat|local-command-stdout|command-name|command-message|command-args|system-reminder|user-prompt-submit-hook|task-notification)[\s\S]*?<\/\1>/gi,bp=/⚡ \*\*Tool call · `[^`]+`\*\*\s*\n+```json\n[\s\S]*?\n```/g,Sp=/\*\*Tool result\*\*\s*\n+```\n[\s\S]*?\n```/g;function Tp(e){return e.replace(Ep,"").trim()}function yp(e){let t=e.replace(bp,"[tool call]");return t=t.replace(Sp,"[tool result]"),t=t.replace(/_\(unknown block: thinking\)_/g,""),t=t.replace(/(?:\[tool call\]|\[tool result\])(?:\s*(?:\[tool call\]|\[tool result\]))+/g,"[tool activity]"),t=t.replace(/\n{3,}/g,`
701
+ </html>`}var Sp=/<(local-command-caveat|local-command-stdout|command-name|command-message|command-args|system-reminder|user-prompt-submit-hook|task-notification)[\s\S]*?<\/\1>/gi,Tp=/⚡ \*\*Tool call · `[^`]+`\*\*\s*\n+```json\n[\s\S]*?\n```/g,yp=/\*\*Tool result\*\*\s*\n+```\n[\s\S]*?\n```/g;function wp(e){return e.replace(Sp,"").trim()}function Rp(e){let t=e.replace(Tp,"[tool call]");return t=t.replace(yp,"[tool result]"),t=t.replace(/_\(unknown block: thinking\)_/g,""),t=t.replace(/(?:\[tool call\]|\[tool result\])(?:\s*(?:\[tool call\]|\[tool result\]))+/g,"[tool activity]"),t=t.replace(/\n{3,}/g,`
702
702
 
703
- `),t.trim()}function wp(e){return e.role??e.type??"message"}function si(e,t,s={}){let n=s.mode??"condensed",r=s.includeSidechain===!0,o=s.since?Date.parse(s.since):0,a=t.filter(g=>!(!r&&g.is_sidechain===1||o&&g.timestamp&&Date.parse(g.timestamp)<o)),c=[];s.prelude&&(c.push(s.prelude.trim()),c.push("")),c.push(`# Claude Recall, past session context (${n})`),c.push(""),c.push(`- **Project**: ${e.project_name}`),e.decoded_path&&c.push(`- **Path**: \`${e.decoded_path}\``),c.push(`- **Session ID**: \`${e.id}\``),e.started_at&&c.push(`- **Started**: ${e.started_at}`),e.ended_at&&c.push(`- **Ended**: ${e.ended_at}`),e.git_branch&&c.push(`- **Branch**: \`${e.git_branch}\``),c.push(`- **Messages**: ${a.length}`),c.push(""),c.push("> This is a transcript of a previous Claude Code session, included for context. Refer back to it when the user asks about past decisions, code written, or problems debugged in this work."),c.push(""),c.push("---"),c.push("");let d=0,u=0;for(let g of a){let h=g.content_text??"",b=Tp(h);n==="condensed"&&(b=yp(b));let S=b.length>0,y=!!g.tool_names&&g.tool_names.length>0;if(!S&&!y){u+=1;continue}let k=wp(g),w=g.timestamp?` \`${g.timestamp}\``:"";c.push(`## ${k}${w}`),c.push(""),y&&n==="condensed"&&(c.push(`_tools used: ${g.tool_names}_`),c.push("")),S&&(c.push(b),c.push("")),d+=1}return c.push("---"),c.push(""),c.push(`_${d} messages included_`+(u?`, ${u} empty skipped`:"")+(r?"":", subagent/sidechain hidden")+"."),c.join(`
704
- `)}H();Z();import{writeFileSync as Rp}from"node:fs";import{join as kp}from"node:path";var Ap=kp($,"aliases.json");function Nn(e){try{let t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return[]}function Te(e){return f().prepare("SELECT alias FROM session_aliases WHERE session_id = ?").get(e)?.alias??null}function xp(){return f().prepare("SELECT session_id, alias, updated_at, previous_aliases FROM session_aliases").all().map(t=>({session_id:t.session_id,alias:t.alias,updated_at:t.updated_at,previous_aliases:Nn(t.previous_aliases)}))}function me(e,t){let s=t.trim();if(!s)throw new Error("alias must be non-empty");let n=f(),r=new Date().toISOString(),o=n.prepare("SELECT alias, previous_aliases FROM session_aliases WHERE session_id = ?").get(e),a=[];return o&&(a=Nn(o.previous_aliases),o.alias!==s&&a.push({alias:o.alias,replaced_at:r})),n.prepare(`INSERT INTO session_aliases (session_id, alias, updated_at, previous_aliases)
703
+ `),t.trim()}function kp(e){return e.role??e.type??"message"}function si(e,t,s={}){let n=s.mode??"condensed",r=s.includeSidechain===!0,o=s.since?Date.parse(s.since):0,a=t.filter(g=>!(!r&&g.is_sidechain===1||o&&g.timestamp&&Date.parse(g.timestamp)<o)),c=[];s.prelude&&(c.push(s.prelude.trim()),c.push("")),c.push(`# Claude Recall, past session context (${n})`),c.push(""),c.push(`- **Project**: ${e.project_name}`),e.decoded_path&&c.push(`- **Path**: \`${e.decoded_path}\``),c.push(`- **Session ID**: \`${e.id}\``),e.started_at&&c.push(`- **Started**: ${e.started_at}`),e.ended_at&&c.push(`- **Ended**: ${e.ended_at}`),e.git_branch&&c.push(`- **Branch**: \`${e.git_branch}\``),c.push(`- **Messages**: ${a.length}`),c.push(""),c.push("> This is a transcript of a previous Claude Code session, included for context. Refer back to it when the user asks about past decisions, code written, or problems debugged in this work."),c.push(""),c.push("---"),c.push("");let d=0,u=0;for(let g of a){let h=g.content_text??"",b=wp(h);n==="condensed"&&(b=Rp(b));let S=b.length>0,y=!!g.tool_names&&g.tool_names.length>0;if(!S&&!y){u+=1;continue}let k=kp(g),w=g.timestamp?` \`${g.timestamp}\``:"";c.push(`## ${k}${w}`),c.push(""),y&&n==="condensed"&&(c.push(`_tools used: ${g.tool_names}_`),c.push("")),S&&(c.push(b),c.push("")),d+=1}return c.push("---"),c.push(""),c.push(`_${d} messages included_`+(u?`, ${u} empty skipped`:"")+(r?"":", subagent/sidechain hidden")+"."),c.join(`
704
+ `)}H();Z();import{writeFileSync as Ap}from"node:fs";import{join as xp}from"node:path";var Np=xp($,"aliases.json");function Nn(e){try{let t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return[]}function Te(e){return f().prepare("SELECT alias FROM session_aliases WHERE session_id = ?").get(e)?.alias??null}function Op(){return f().prepare("SELECT session_id, alias, updated_at, previous_aliases FROM session_aliases").all().map(t=>({session_id:t.session_id,alias:t.alias,updated_at:t.updated_at,previous_aliases:Nn(t.previous_aliases)}))}function me(e,t){let s=t.trim();if(!s)throw new Error("alias must be non-empty");let n=f(),r=new Date().toISOString(),o=n.prepare("SELECT alias, previous_aliases FROM session_aliases WHERE session_id = ?").get(e),a=[];return o&&(a=Nn(o.previous_aliases),o.alias!==s&&a.push({alias:o.alias,replaced_at:r})),n.prepare(`INSERT INTO session_aliases (session_id, alias, updated_at, previous_aliases)
705
705
  VALUES (?, ?, ?, ?)
706
706
  ON CONFLICT(session_id) DO UPDATE SET
707
707
  alias = excluded.alias,
708
708
  updated_at = excluded.updated_at,
709
709
  previous_aliases = excluded.previous_aliases`).run(e,s,r,JSON.stringify(a)),ni(),{session_id:e,alias:s,updated_at:r,previous_aliases:a}}function ns(e){let t=f(),s=new Date().toISOString(),n=t.prepare("SELECT alias, previous_aliases FROM session_aliases WHERE session_id = ?").get(e);if(!n)return;let r=Nn(n.previous_aliases);r.push({alias:n.alias,replaced_at:s}),t.prepare(`UPDATE session_aliases SET alias = '', updated_at = ?, previous_aliases = ?
710
- WHERE session_id = ?`).run(s,JSON.stringify(r),e),ni()}function ni(){try{J();let e=xp(),t={schema:"claude-recall.aliases.v1",backed_up_at:new Date().toISOString(),aliases:e};Rp(Ap,JSON.stringify(t,null,2))}catch(e){console.error("[aliases] backup failed:",e)}}function yt(e){if(!e.sessionStartedAt)return{allowed:!1,reason:"missing-session-started-at"};if(!e.terminalOpenedAt)return{allowed:!1,reason:"missing-terminal-opened-at"};let t=Date.parse(e.sessionStartedAt),s=Date.parse(e.terminalOpenedAt);return Number.isFinite(t)?Number.isFinite(s)?s-t>6e4?{allowed:!1,reason:"terminal-postdates-session"}:{allowed:!0}:{allowed:!1,reason:"missing-terminal-opened-at"}:{allowed:!1,reason:"missing-session-started-at"}}H();Z();import{writeFileSync as Zp,mkdirSync as Qp,existsSync as em}from"node:fs";import{join as ui}from"node:path";var jn=ui($,"notes"),di=200,tm=12e3,sm=800,nm=8e3;function pi(e){try{let t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return[]}function mi(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t.filter(s=>!!s&&typeof s=="object"&&typeof s.synopsis=="string"&&typeof s.replaced_at=="string"):[]}catch{return[]}}function rm(){J(),em(jn)||Qp(jn,{recursive:!0})}function om(e){return{session_id:e.session_id,content:e.content,updated_at:e.updated_at,previous_versions:pi(e.previous_versions),auto_synopsis:e.auto_synopsis??null,auto_synopsis_generated_at:e.auto_synopsis_generated_at??null,auto_synopsis_history:mi(e.auto_synopsis_history)}}var im="session_id, content, updated_at, previous_versions, auto_synopsis, auto_synopsis_generated_at, auto_synopsis_history";function is(e){let t=f().prepare(`SELECT ${im} FROM session_notes WHERE session_id = ?`).get(e);return t?om(t):null}function gi(e,t){let s=f(),n=new Date().toISOString(),r=s.prepare("SELECT content, previous_versions FROM session_notes WHERE session_id = ?").get(e),o=[];return r&&(o=pi(r.previous_versions),r.content!==t&&r.content.length>0&&o.push({content:r.content,replaced_at:n})),s.prepare(`INSERT INTO session_notes (session_id, content, updated_at, previous_versions)
710
+ WHERE session_id = ?`).run(s,JSON.stringify(r),e),ni()}function ni(){try{J();let e=Op(),t={schema:"claude-recall.aliases.v1",backed_up_at:new Date().toISOString(),aliases:e};Ap(Np,JSON.stringify(t,null,2))}catch(e){console.error("[aliases] backup failed:",e)}}function yt(e){if(!e.sessionStartedAt)return{allowed:!1,reason:"missing-session-started-at"};if(!e.terminalOpenedAt)return{allowed:!1,reason:"missing-terminal-opened-at"};let t=Date.parse(e.sessionStartedAt),s=Date.parse(e.terminalOpenedAt);return Number.isFinite(t)?Number.isFinite(s)?s-t>6e4?{allowed:!1,reason:"terminal-postdates-session"}:{allowed:!0}:{allowed:!1,reason:"missing-terminal-opened-at"}:{allowed:!1,reason:"missing-session-started-at"}}H();Z();import{writeFileSync as em,mkdirSync as tm,existsSync as sm}from"node:fs";import{join as ui}from"node:path";var jn=ui($,"notes"),di=200,nm=12e3,rm=800,om=8e3;function pi(e){try{let t=JSON.parse(e);if(Array.isArray(t))return t}catch{}return[]}function mi(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t.filter(s=>!!s&&typeof s=="object"&&typeof s.synopsis=="string"&&typeof s.replaced_at=="string"):[]}catch{return[]}}function im(){J(),sm(jn)||tm(jn,{recursive:!0})}function am(e){return{session_id:e.session_id,content:e.content,updated_at:e.updated_at,previous_versions:pi(e.previous_versions),auto_synopsis:e.auto_synopsis??null,auto_synopsis_generated_at:e.auto_synopsis_generated_at??null,auto_synopsis_history:mi(e.auto_synopsis_history)}}var cm="session_id, content, updated_at, previous_versions, auto_synopsis, auto_synopsis_generated_at, auto_synopsis_history";function is(e){let t=f().prepare(`SELECT ${cm} FROM session_notes WHERE session_id = ?`).get(e);return t?am(t):null}function gi(e,t){let s=f(),n=new Date().toISOString(),r=s.prepare("SELECT content, previous_versions FROM session_notes WHERE session_id = ?").get(e),o=[];return r&&(o=pi(r.previous_versions),r.content!==t&&r.content.length>0&&o.push({content:r.content,replaced_at:n})),s.prepare(`INSERT INTO session_notes (session_id, content, updated_at, previous_versions)
711
711
  VALUES (?, ?, ?, ?)
712
712
  ON CONFLICT(session_id) DO UPDATE SET
713
713
  content = excluded.content,
714
714
  updated_at = excluded.updated_at,
715
- previous_versions = excluded.previous_versions`).run(e,t,n,JSON.stringify(o)),cm(e,t,n),is(e)??{session_id:e,content:t,updated_at:n,previous_versions:o,auto_synopsis:null,auto_synopsis_generated_at:null,auto_synopsis_history:[]}}async function _i(e){let s=f().prepare(`SELECT rowid AS rid, role, content_text
715
+ previous_versions = excluded.previous_versions`).run(e,t,n,JSON.stringify(o)),dm(e,t,n),is(e)??{session_id:e,content:t,updated_at:n,previous_versions:o,auto_synopsis:null,auto_synopsis_generated_at:null,auto_synopsis_history:[]}}async function _i(e){let s=f().prepare(`SELECT rowid AS rid, role, content_text
716
716
  FROM messages
717
717
  WHERE session_id = ? AND is_sidechain = 0
718
718
  AND content_text IS NOT NULL AND content_text != ''
719
719
  AND role IN ('user', 'assistant')
720
720
  ORDER BY COALESCE(timestamp, '') DESC, rowid DESC
721
- LIMIT ?`).all(e,di);if(s.length===0)throw new Error("no messages available to summarise");let n=tm,r=[];for(let b of s){if(n<=0)break;let S=(b.content_text??"").slice(0,sm);r.push({rid:b.rid,role:b.role,content:S}),n-=S.length}r.reverse();let o=s.length===di||n<=0,a=r.map(b=>`**${b.role}**: ${b.content}`).join(`
721
+ LIMIT ?`).all(e,di);if(s.length===0)throw new Error("no messages available to summarise");let n=nm,r=[];for(let b of s){if(n<=0)break;let S=(b.content_text??"").slice(0,rm);r.push({rid:b.rid,role:b.role,content:S}),n-=S.length}r.reverse();let o=s.length===di||n<=0,a=r.map(b=>`**${b.role}**: ${b.content}`).join(`
722
722
 
723
723
  `),c=["You will receive a sampled chronological transcript from a Claude Code session.",o?"The sample is the most recent slice that fits in the context budget; older messages were dropped.":"The full session is included.","","Write a clean markdown synopsis of the session. Use these sections \u2014 omit any that genuinely have nothing to say:","","## Goal","One sentence \u2014 what the user was trying to accomplish.","","## What was done","Bullet list \u2014 concrete actions, code changes, decisions. Skip pleasantries.","","## Key decisions","Bullet list \u2014 non-obvious choices and the reason behind them.","","## Files touched","Bullet list \u2014 file paths mentioned in the conversation. Omit the section if none.","","## Open follow-ups","Bullet list \u2014 anything left undone or flagged for later. Omit the section if none.","","Output ONLY the markdown \u2014 no surrounding prose, no code fences around the whole thing, no closing summary.","","---","",a].join(`
724
- `),{spawnClaudePrompt:d,isClaudeCliAvailable:u}=await Promise.resolve().then(()=>(ge(),Pe));if(!u())throw new Error("claude CLI not found on PATH");let g=await d(c,[],{});if(!g.success)throw new Error(`claude CLI exited ${g.exitCode}: ${g.stderr.slice(-500)}`);let h=am(g.stdout);if(!h)throw new Error("claude CLI returned an empty synopsis");return h.slice(0,nm)}function am(e){let t=e.trim();if(!t)return"";try{let s=JSON.parse(t);if(s&&typeof s=="object"){let n=s.result;if(typeof n=="string")return n.trim()}}catch{}return t}function fi(e,t){let s=f(),n=new Date().toISOString(),r=Date.now(),o=s.prepare("SELECT auto_synopsis, auto_synopsis_history, content, updated_at FROM session_notes WHERE session_id = ?").get(e),a=mi(o?.auto_synopsis_history??null);return o?.auto_synopsis&&o.auto_synopsis!==t&&o.auto_synopsis.length>0&&a.push({synopsis:o.auto_synopsis,replaced_at:n}),o?s.prepare(`UPDATE session_notes
724
+ `),{spawnClaudePrompt:d,isClaudeCliAvailable:u}=await Promise.resolve().then(()=>(ge(),Pe));if(!u())throw new Error("claude CLI not found on PATH");let g=await d(c,[],{});if(!g.success)throw new Error(`claude CLI exited ${g.exitCode}: ${g.stderr.slice(-500)}`);let h=lm(g.stdout);if(!h)throw new Error("claude CLI returned an empty synopsis");return h.slice(0,om)}function lm(e){let t=e.trim();if(!t)return"";try{let s=JSON.parse(t);if(s&&typeof s=="object"){let n=s.result;if(typeof n=="string")return n.trim()}}catch{}return t}function fi(e,t){let s=f(),n=new Date().toISOString(),r=Date.now(),o=s.prepare("SELECT auto_synopsis, auto_synopsis_history, content, updated_at FROM session_notes WHERE session_id = ?").get(e),a=mi(o?.auto_synopsis_history??null);return o?.auto_synopsis&&o.auto_synopsis!==t&&o.auto_synopsis.length>0&&a.push({synopsis:o.auto_synopsis,replaced_at:n}),o?s.prepare(`UPDATE session_notes
725
725
  SET auto_synopsis = ?,
726
726
  auto_synopsis_generated_at = ?,
727
727
  auto_synopsis_history = ?
728
728
  WHERE session_id = ?`).run(t,r,JSON.stringify(a),e):s.prepare(`INSERT INTO session_notes
729
729
  (session_id, content, updated_at, previous_versions, auto_synopsis,
730
730
  auto_synopsis_generated_at, auto_synopsis_history)
731
- VALUES (?, '', ?, '[]', ?, ?, ?)`).run(e,n,t,r,JSON.stringify(a)),is(e)}function cm(e,t,s){try{rm();let n=ui(jn,`${e}.md`),r=`<!-- Claude Recall note \xB7 session ${e} \xB7 updated ${s} -->
732
- `;Zp(n,r+t)}catch(n){console.error("[notes] mirror write failed:",n)}}Ge();H();Z();import{randomUUID as lm}from"node:crypto";import{writeFileSync as dm,readFileSync as dw,existsSync as uw}from"node:fs";import{join as um}from"node:path";var pm=um($,"collections.json"),as=8;function cs(e){return{...e}}function _e(e,t,s,n=null,r=new Date().toISOString()){f().prepare(`INSERT INTO collection_events (collection_id, session_id, action, payload, at)
733
- VALUES (?, ?, ?, ?, ?)`).run(e,n,t,s?JSON.stringify(s):null,r)}function ls(e){let t=f().prepare("SELECT * FROM collections WHERE id = ?").get(e);if(!t)throw new Error(`collection not found: ${e}`);return t}function hi(e){if(!e)return 0;let t=0,s=e,n=new Set,r=f();for(;s;){if(n.has(s))throw new Error("collection cycle detected");n.add(s);let o=r.prepare("SELECT parent_id FROM collections WHERE id = ?").get(s);if(!o)break;t+=1,s=o.parent_id}return t}function mm(e,t){let s=f(),n=e,r=new Set;for(;n;){if(r.has(n))return!1;if(r.add(n),n===t)return!0;let o=s.prepare("SELECT parent_id FROM collections WHERE id = ?").get(n);if(!o)return!1;n=o.parent_id}return!1}function Ei(e=!1){return f().prepare(`SELECT c.*,
731
+ VALUES (?, '', ?, '[]', ?, ?, ?)`).run(e,n,t,r,JSON.stringify(a)),is(e)}function dm(e,t,s){try{im();let n=ui(jn,`${e}.md`),r=`<!-- Claude Recall note \xB7 session ${e} \xB7 updated ${s} -->
732
+ `;em(n,r+t)}catch(n){console.error("[notes] mirror write failed:",n)}}Ge();H();Z();import{randomUUID as um}from"node:crypto";import{writeFileSync as pm,readFileSync as pw,existsSync as mw}from"node:fs";import{join as mm}from"node:path";var gm=mm($,"collections.json"),as=8;function cs(e){return{...e}}function _e(e,t,s,n=null,r=new Date().toISOString()){f().prepare(`INSERT INTO collection_events (collection_id, session_id, action, payload, at)
733
+ VALUES (?, ?, ?, ?, ?)`).run(e,n,t,s?JSON.stringify(s):null,r)}function ls(e){let t=f().prepare("SELECT * FROM collections WHERE id = ?").get(e);if(!t)throw new Error(`collection not found: ${e}`);return t}function hi(e){if(!e)return 0;let t=0,s=e,n=new Set,r=f();for(;s;){if(n.has(s))throw new Error("collection cycle detected");n.add(s);let o=r.prepare("SELECT parent_id FROM collections WHERE id = ?").get(s);if(!o)break;t+=1,s=o.parent_id}return t}function _m(e,t){let s=f(),n=e,r=new Set;for(;n;){if(r.has(n))return!1;if(r.add(n),n===t)return!0;let o=s.prepare("SELECT parent_id FROM collections WHERE id = ?").get(n);if(!o)return!1;n=o.parent_id}return!1}function Ei(e=!1){return f().prepare(`SELECT c.*,
734
734
  (SELECT COUNT(*) FROM collection_sessions cs WHERE cs.collection_id = c.id) AS session_count
735
735
  FROM collections c
736
736
  ${e?"":"WHERE c.archived_at IS NULL"}
@@ -740,23 +740,23 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
740
740
  ORDER BY added_at DESC`).all(...n)}function Mn(e){let t=f(),s=[e],n=[e],r=new Set([e]);for(;n.length>0;){let o=n.map(()=>"?").join(","),a=t.prepare(`SELECT id FROM collections WHERE parent_id IN (${o})`).all(...n),c=[];for(let d of a)r.has(d.id)||(r.add(d.id),s.push(d.id),c.push(d.id));n=c}return s}function Si(e){return f().prepare(`SELECT c.* FROM collections c
741
741
  JOIN collection_sessions cs ON cs.collection_id = c.id
742
742
  WHERE cs.session_id = ? AND c.archived_at IS NULL
743
- ORDER BY LOWER(c.name)`).all(e)}function At(e){let t=(e.name??"").trim();if(!t)throw new Error("name required");if(t.length>120)throw new Error("name too long (max 120 chars)");let s=f(),n=new Date().toISOString(),r=lm();if(e.parent_id){if(!Ne(e.parent_id))throw new Error("parent collection not found");if(hi(e.parent_id)>=as-1)throw new Error(`max collection depth is ${as}`)}return s.transaction(()=>{s.prepare(`INSERT INTO collections
743
+ ORDER BY LOWER(c.name)`).all(e)}function At(e){let t=(e.name??"").trim();if(!t)throw new Error("name required");if(t.length>120)throw new Error("name too long (max 120 chars)");let s=f(),n=new Date().toISOString(),r=um();if(e.parent_id){if(!Ne(e.parent_id))throw new Error("parent collection not found");if(hi(e.parent_id)>=as-1)throw new Error(`max collection depth is ${as}`)}return s.transaction(()=>{s.prepare(`INSERT INTO collections
744
744
  (id, name, description, icon, color, parent_id, sort_key, created_at, updated_at, archived_at)
745
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)`).run(r,t,e.description??null,e.icon??null,e.color??null,e.parent_id??null,e.sort_key??"",n,n),_e(r,"create",{name:t,parent_id:e.parent_id??null,icon:e.icon??null,color:e.color??null},null,n)})(),Ue(),Ne(r)}function Ti(e,t){let s=f(),n=ls(e),r=new Date().toISOString(),o={name:t.name!==void 0?t.name.trim():n.name,description:t.description!==void 0?t.description:n.description,icon:t.icon!==void 0?t.icon:n.icon,color:t.color!==void 0?t.color:n.color,parent_id:t.parent_id!==void 0?t.parent_id:n.parent_id,sort_key:t.sort_key!==void 0?t.sort_key:n.sort_key};if(!o.name)throw new Error("name required");if(o.name.length>120)throw new Error("name too long (max 120 chars)");if(t.parent_id!==void 0&&t.parent_id!==n.parent_id&&t.parent_id){if(t.parent_id===e)throw new Error("cannot set parent to self");if(!Ne(t.parent_id))throw new Error("parent collection not found");if(mm(t.parent_id,e))throw new Error("cannot move collection into one of its descendants");if(hi(t.parent_id)>=as-1)throw new Error(`max collection depth is ${as}`)}return s.transaction(()=>{s.prepare(`UPDATE collections
745
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, NULL)`).run(r,t,e.description??null,e.icon??null,e.color??null,e.parent_id??null,e.sort_key??"",n,n),_e(r,"create",{name:t,parent_id:e.parent_id??null,icon:e.icon??null,color:e.color??null},null,n)})(),Ue(),Ne(r)}function Ti(e,t){let s=f(),n=ls(e),r=new Date().toISOString(),o={name:t.name!==void 0?t.name.trim():n.name,description:t.description!==void 0?t.description:n.description,icon:t.icon!==void 0?t.icon:n.icon,color:t.color!==void 0?t.color:n.color,parent_id:t.parent_id!==void 0?t.parent_id:n.parent_id,sort_key:t.sort_key!==void 0?t.sort_key:n.sort_key};if(!o.name)throw new Error("name required");if(o.name.length>120)throw new Error("name too long (max 120 chars)");if(t.parent_id!==void 0&&t.parent_id!==n.parent_id&&t.parent_id){if(t.parent_id===e)throw new Error("cannot set parent to self");if(!Ne(t.parent_id))throw new Error("parent collection not found");if(_m(t.parent_id,e))throw new Error("cannot move collection into one of its descendants");if(hi(t.parent_id)>=as-1)throw new Error(`max collection depth is ${as}`)}return s.transaction(()=>{s.prepare(`UPDATE collections
746
746
  SET name = ?, description = ?, icon = ?, color = ?,
747
747
  parent_id = ?, sort_key = ?, updated_at = ?
748
748
  WHERE id = ?`).run(o.name,o.description,o.icon,o.color,o.parent_id,o.sort_key,r,e),t.name!==void 0&&t.name!==n.name&&_e(e,"rename",{from:n.name,to:o.name},null,r),t.description!==void 0&&t.description!==n.description&&_e(e,"describe",{description:o.description},null,r),(t.icon!==void 0&&t.icon!==n.icon||t.color!==void 0&&t.color!==n.color)&&_e(e,"recolor",{icon:o.icon,color:o.color},null,r),t.parent_id!==void 0&&t.parent_id!==n.parent_id&&_e(e,"move",{from:n.parent_id,to:o.parent_id},null,r),t.sort_key!==void 0&&t.sort_key!==n.sort_key&&_e(e,"reorder",{from:n.sort_key,to:o.sort_key},null,r)})(),Ue(),Ne(e)}function yi(e){let t=f(),s=ls(e);if(s.archived_at)return cs(s);let n=new Date().toISOString();return t.transaction(()=>{t.prepare("UPDATE collections SET archived_at = ?, updated_at = ? WHERE id = ?").run(n,n,e),_e(e,"archive",{name:s.name},null,n)})(),Ue(),Ne(e)}function wi(e){let t=f(),s=ls(e);if(!s.archived_at)return cs(s);let n=new Date().toISOString();return t.transaction(()=>{t.prepare("UPDATE collections SET archived_at = NULL, updated_at = ? WHERE id = ?").run(n,e),_e(e,"restore",{name:s.name},null,n)})(),Ue(),Ne(e)}function xt(e,t,s=null,n={}){let r=f();if(ls(e),!r.prepare("SELECT 1 FROM sessions WHERE id = ?").get(t))throw new Error(`session not found: ${t}`);if(r.prepare("SELECT 1 FROM collection_sessions WHERE collection_id = ? AND session_id = ?").get(e,t))return{added:!1};let c=n.source??"manual",d=n.rule_id??null;if(c==="auto"&&!d)throw new Error("auto membership requires a rule_id");let u=new Date().toISOString();return r.transaction(()=>{r.prepare(`INSERT INTO collection_sessions (collection_id, session_id, added_at, note, source, rule_id)
749
749
  VALUES (?, ?, ?, ?, ?, ?)`).run(e,t,u,s,c,d),_e(e,"add",{note:s,source:c,rule_id:d},t,u)})(),Ue(),{added:!0}}function Ri(e,t){let s=f();if(!s.prepare("SELECT 1 FROM collection_sessions WHERE collection_id = ? AND session_id = ?").get(e,t))return{removed:!1};let r=new Date().toISOString();return s.transaction(()=>{s.prepare("DELETE FROM collection_sessions WHERE collection_id = ? AND session_id = ?").run(e,t),_e(e,"remove",null,t,r)})(),Ue(),{removed:!0}}function ds(e){let t=f(),s=t.prepare(`SELECT collection_id, session_id FROM collection_sessions
750
- WHERE rule_id = ?`).all(e);if(s.length===0)return{removed:0};let n=new Date().toISOString();return t.transaction(()=>{t.prepare("DELETE FROM collection_sessions WHERE rule_id = ?").run(e);for(let o of s)_e(o.collection_id,"remove",{rule_id:e},o.session_id,n)})(),Ue(),{removed:s.length}}function gm(){return f().prepare(`SELECT id, collection_id, session_id, action, payload, at
750
+ WHERE rule_id = ?`).all(e);if(s.length===0)return{removed:0};let n=new Date().toISOString();return t.transaction(()=>{t.prepare("DELETE FROM collection_sessions WHERE rule_id = ?").run(e);for(let o of s)_e(o.collection_id,"remove",{rule_id:e},o.session_id,n)})(),Ue(),{removed:s.length}}function fm(){return f().prepare(`SELECT id, collection_id, session_id, action, payload, at
751
751
  FROM collection_events
752
752
  ORDER BY at ASC, id ASC`).all()}function Ue(){try{J();let e=f(),t=e.prepare(`SELECT id, name, description, icon, color, parent_id, sort_key,
753
753
  created_at, updated_at, archived_at
754
754
  FROM collections
755
755
  ORDER BY COALESCE(parent_id, ''), sort_key, LOWER(name)`).all(),s=e.prepare(`SELECT collection_id, session_id, added_at, note, source, rule_id
756
756
  FROM collection_sessions
757
- ORDER BY collection_id, added_at`).all(),n=gm(),r={schema:"claude-recall.collections.v1",backed_up_at:new Date().toISOString(),collections:t,memberships:s,events:n};dm(pm,JSON.stringify(r,null,2))}catch(e){console.error("[collections] backup failed:",e)}}H();Z();import{randomUUID as Pn}from"node:crypto";import{existsSync as _m,mkdirSync as fm,writeFileSync as ki}from"node:fs";import{homedir as hm}from"node:os";import{basename as Em,join as Un}from"node:path";var us=Un($,"auto-rules"),bm=Un(us,"rules.json"),Sm=Un(us,"suggestions.json"),Dn="Repositories",Tm="Topics",Ai=3;var ym=5,wm=2,Rm=[/\bROADMAP\.md\b/g,/\bPROJECT\.md\b/g,/\bdocs\/[A-Za-z0-9._-]+\.md\b/g,/\.planning\/[A-Za-z0-9._\-/]+/g];function $n(e){return{id:e.id,name:e.name,type:e.type,pattern:e.pattern,collection_id:e.collection_id,priority:e.priority,enabled:e.enabled!==0,created_at:e.created_at,created_by:e.created_by}}function km(e){return{id:e.id,type:e.type,pattern:e.pattern,suggested_name:e.suggested_name,suggested_parent_collection_id:e.suggested_parent_collection_id,session_count:e.session_count,detected_at:e.detected_at,dismissed:e.dismissed!==0}}function Am(e){switch(e){case"cwd-prefix":case"project-id":case"git-branch-prefix":return Dn;case"tag":return Tm;case"plan-file":return null}}function xm(e){let s=f().prepare("SELECT id FROM collections WHERE name = ? AND parent_id IS NULL AND archived_at IS NULL").get(e);if(s)return s.id;let o=At({name:e,icon:e===Dn?"\u{1F4E6}":"\u{1F3F7}",sort_key:e===Dn?"0000-repos":"0001-topics"});return f().prepare(`INSERT INTO auto_collection_rules
757
+ ORDER BY collection_id, added_at`).all(),n=fm(),r={schema:"claude-recall.collections.v1",backed_up_at:new Date().toISOString(),collections:t,memberships:s,events:n};pm(gm,JSON.stringify(r,null,2))}catch(e){console.error("[collections] backup failed:",e)}}H();Z();import{randomUUID as Pn}from"node:crypto";import{existsSync as hm,mkdirSync as Em,writeFileSync as ki}from"node:fs";import{homedir as bm}from"node:os";import{basename as Sm,join as Un}from"node:path";var us=Un($,"auto-rules"),Tm=Un(us,"rules.json"),ym=Un(us,"suggestions.json"),Dn="Repositories",wm="Topics",Ai=3;var Rm=5,km=2,Am=[/\bROADMAP\.md\b/g,/\bPROJECT\.md\b/g,/\bdocs\/[A-Za-z0-9._-]+\.md\b/g,/\.planning\/[A-Za-z0-9._\-/]+/g];function $n(e){return{id:e.id,name:e.name,type:e.type,pattern:e.pattern,collection_id:e.collection_id,priority:e.priority,enabled:e.enabled!==0,created_at:e.created_at,created_by:e.created_by}}function xm(e){return{id:e.id,type:e.type,pattern:e.pattern,suggested_name:e.suggested_name,suggested_parent_collection_id:e.suggested_parent_collection_id,session_count:e.session_count,detected_at:e.detected_at,dismissed:e.dismissed!==0}}function Nm(e){switch(e){case"cwd-prefix":case"project-id":case"git-branch-prefix":return Dn;case"tag":return wm;case"plan-file":return null}}function Om(e){let s=f().prepare("SELECT id FROM collections WHERE name = ? AND parent_id IS NULL AND archived_at IS NULL").get(e);if(s)return s.id;let o=At({name:e,icon:e===Dn?"\u{1F4E6}":"\u{1F3F7}",sort_key:e===Dn?"0000-repos":"0001-topics"});return f().prepare(`INSERT INTO auto_collection_rules
758
758
  (id, name, type, pattern, collection_id, priority, enabled, created_at, created_by)
759
- VALUES (?, ?, 'cwd-prefix', '__seed__', ?, 1000, 0, ?, 'seed')`).run(Pn(),`seed:${e}`,o.id,new Date().toISOString()),o.id}function Nm(e,t,s){let n;if(s!==void 0)n=s;else{let o=Am(t);n=o?xm(o):null}return At({name:e,parent_id:n}).id}function ps(e){let t=f().prepare("SELECT * FROM auto_collection_rules WHERE id = ?").get(e);return t?$n(t):null}function Om(e){let t=f();switch(e.type){case"cwd-prefix":return t.prepare("SELECT id FROM sessions WHERE cwd IS NOT NULL AND cwd LIKE ? ESCAPE '\\'").all(ms(e.pattern)+"%").map(n=>n.id);case"git-branch-prefix":return t.prepare("SELECT id FROM sessions WHERE git_branch IS NOT NULL AND git_branch LIKE ? ESCAPE '\\'").all(ms(e.pattern)+"%").map(n=>n.id);case"project-id":{let s=Number(e.pattern);return Number.isFinite(s)?t.prepare("SELECT id FROM sessions WHERE project_id = ?").all(s).map(r=>r.id):[]}case"tag":return t.prepare("SELECT session_id FROM session_tags WHERE tag = ?").all(e.pattern).map(n=>n.session_id);case"plan-file":return t.prepare(`SELECT id, first_user_message FROM sessions
759
+ VALUES (?, ?, 'cwd-prefix', '__seed__', ?, 1000, 0, ?, 'seed')`).run(Pn(),`seed:${e}`,o.id,new Date().toISOString()),o.id}function Lm(e,t,s){let n;if(s!==void 0)n=s;else{let o=Nm(t);n=o?Om(o):null}return At({name:e,parent_id:n}).id}function ps(e){let t=f().prepare("SELECT * FROM auto_collection_rules WHERE id = ?").get(e);return t?$n(t):null}function Cm(e){let t=f();switch(e.type){case"cwd-prefix":return t.prepare("SELECT id FROM sessions WHERE cwd IS NOT NULL AND cwd LIKE ? ESCAPE '\\'").all(ms(e.pattern)+"%").map(n=>n.id);case"git-branch-prefix":return t.prepare("SELECT id FROM sessions WHERE git_branch IS NOT NULL AND git_branch LIKE ? ESCAPE '\\'").all(ms(e.pattern)+"%").map(n=>n.id);case"project-id":{let s=Number(e.pattern);return Number.isFinite(s)?t.prepare("SELECT id FROM sessions WHERE project_id = ?").all(s).map(r=>r.id):[]}case"tag":return t.prepare("SELECT session_id FROM session_tags WHERE tag = ?").all(e.pattern).map(n=>n.session_id);case"plan-file":return t.prepare(`SELECT id, first_user_message FROM sessions
760
760
  WHERE first_user_message IS NOT NULL AND first_user_message LIKE ?`).all("%"+e.pattern+"%").map(n=>n.id)}}function xi(e,t,s=3){let n=f(),r=`s.id AS id, s.cwd AS cwd, s.started_at AS started_at,
761
761
  sa.alias AS alias, s.auto_title AS auto_title, s.first_user_message AS first_user_message`,o="LEFT JOIN session_aliases sa ON sa.session_id = s.id",a=[];switch(e){case"cwd-prefix":a=n.prepare(`SELECT ${r} FROM sessions s ${o}
762
762
  WHERE s.cwd IS NOT NULL AND s.cwd LIKE ? ESCAPE '\\'
@@ -770,19 +770,19 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
770
770
  ORDER BY s.started_at DESC LIMIT ?`).all(t,s);break;case"plan-file":a=n.prepare(`SELECT ${r} FROM sessions s ${o}
771
771
  WHERE s.first_user_message IS NOT NULL
772
772
  AND s.first_user_message LIKE ?
773
- ORDER BY s.started_at DESC LIMIT ?`).all("%"+t+"%",s);break}return a.map(c=>({id:c.id,title:Lm(c),cwd:c.cwd,started_at:c.started_at}))}function Lm(e){if(e.alias&&e.alias.trim())return e.alias.trim();if(e.auto_title&&e.auto_title.trim())return e.auto_title.trim();let t=(e.first_user_message??"").trim();if(!t)return`session ${e.id.slice(0,8)}`;let s=t.split(`
774
- `)[0].trim();return s.length>80?s.slice(0,80)+"\u2026":s}function Cm(e,t,s=f()){switch(e.type){case"cwd-prefix":return!!t.cwd&&t.cwd.startsWith(e.pattern);case"git-branch-prefix":return!!t.git_branch&&t.git_branch.startsWith(e.pattern);case"project-id":{let n=Number(e.pattern);return Number.isFinite(n)&&t.project_id===n}case"tag":return!!s.prepare("SELECT 1 FROM session_tags WHERE session_id = ? AND tag = ?").get(t.id,e.pattern);case"plan-file":return!!t.first_user_message&&t.first_user_message.includes(e.pattern)}}function Ni(e){let t=f(),s=t.prepare("SELECT id, project_id, cwd, git_branch, first_user_message FROM sessions WHERE id = ?").get(e);if(!s)return{added:0};let n=t.prepare(`SELECT * FROM auto_collection_rules
773
+ ORDER BY s.started_at DESC LIMIT ?`).all("%"+t+"%",s);break}return a.map(c=>({id:c.id,title:Im(c),cwd:c.cwd,started_at:c.started_at}))}function Im(e){if(e.alias&&e.alias.trim())return e.alias.trim();if(e.auto_title&&e.auto_title.trim())return e.auto_title.trim();let t=(e.first_user_message??"").trim();if(!t)return`session ${e.id.slice(0,8)}`;let s=t.split(`
774
+ `)[0].trim();return s.length>80?s.slice(0,80)+"\u2026":s}function vm(e,t,s=f()){switch(e.type){case"cwd-prefix":return!!t.cwd&&t.cwd.startsWith(e.pattern);case"git-branch-prefix":return!!t.git_branch&&t.git_branch.startsWith(e.pattern);case"project-id":{let n=Number(e.pattern);return Number.isFinite(n)&&t.project_id===n}case"tag":return!!s.prepare("SELECT 1 FROM session_tags WHERE session_id = ? AND tag = ?").get(t.id,e.pattern);case"plan-file":return!!t.first_user_message&&t.first_user_message.includes(e.pattern)}}function Ni(e){let t=f(),s=t.prepare("SELECT id, project_id, cwd, git_branch, first_user_message FROM sessions WHERE id = ?").get(e);if(!s)return{added:0};let n=t.prepare(`SELECT * FROM auto_collection_rules
775
775
  WHERE enabled = 1 AND created_by != 'seed'
776
- ORDER BY priority, created_at`).all(),r=0;for(let o of n){let a=$n(o);if(Cm(a,s,t))try{xt(a.collection_id,e,null,{source:"auto",rule_id:a.id}).added&&(r+=1)}catch(c){console.error(`[auto-collections] failed to apply rule ${a.id} to session ${e}:`,c)}}return{added:r}}function Fn(e){if(!e.enabled)return{added:0};let t=0;for(let s of Om(e))try{xt(e.collection_id,s,null,{source:"auto",rule_id:e.id}).added&&(t+=1)}catch(n){console.error(`[auto-collections] backfill failed for rule ${e.id} / session ${s}:`,n)}return{added:t}}function Bn(e){let t=(e.name??"").trim();if(!t)throw new Error("name required");let s=(e.pattern??"").trim();if(!s)throw new Error("pattern required");let n=f(),r=new Date().toISOString(),o=Pn(),a=e.collection_id;a||(a=Nm(t,e.type,e.parent_collection_id)),n.prepare(`INSERT INTO auto_collection_rules
776
+ ORDER BY priority, created_at`).all(),r=0;for(let o of n){let a=$n(o);if(vm(a,s,t))try{xt(a.collection_id,e,null,{source:"auto",rule_id:a.id}).added&&(r+=1)}catch(c){console.error(`[auto-collections] failed to apply rule ${a.id} to session ${e}:`,c)}}return{added:r}}function Fn(e){if(!e.enabled)return{added:0};let t=0;for(let s of Cm(e))try{xt(e.collection_id,s,null,{source:"auto",rule_id:e.id}).added&&(t+=1)}catch(n){console.error(`[auto-collections] backfill failed for rule ${e.id} / session ${s}:`,n)}return{added:t}}function Bn(e){let t=(e.name??"").trim();if(!t)throw new Error("name required");let s=(e.pattern??"").trim();if(!s)throw new Error("pattern required");let n=f(),r=new Date().toISOString(),o=Pn(),a=e.collection_id;a||(a=Lm(t,e.type,e.parent_collection_id)),n.prepare(`INSERT INTO auto_collection_rules
777
777
  (id, name, type, pattern, collection_id, priority, enabled, created_at, created_by)
778
778
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`).run(o,t,e.type,s,a,e.priority??100,e.enabled===!1?0:1,r,e.created_by??"user"),n.prepare("DELETE FROM auto_collection_suggestions WHERE type = ? AND pattern = ?").run(e.type,s);let c=ps(o);return Fn(c),Ke(),c}function Oi(e={}){let t=e.includeSeed?"SELECT * FROM auto_collection_rules ORDER BY priority, created_at":"SELECT * FROM auto_collection_rules WHERE created_by != 'seed' ORDER BY priority, created_at";return f().prepare(t).all().map($n)}function Li(e,t){let s=f(),n=ps(e);if(!n)throw new Error(`rule not found: ${e}`);let r={name:t.name!==void 0?t.name.trim():n.name,pattern:t.pattern!==void 0?t.pattern.trim():n.pattern,enabled:t.enabled!==void 0?t.enabled:n.enabled,priority:t.priority!==void 0?t.priority:n.priority};if(!r.name)throw new Error("name required");if(!r.pattern)throw new Error("pattern required");s.prepare(`UPDATE auto_collection_rules
779
779
  SET name = ?, pattern = ?, enabled = ?, priority = ?
780
- WHERE id = ?`).run(r.name,r.pattern,r.enabled?1:0,r.priority,e);let o=ps(e);return t.pattern!==void 0&&t.pattern!==n.pattern?(ds(e),o.enabled&&Fn(o)):t.enabled!==void 0&&t.enabled!==n.enabled&&(o.enabled?Fn(o):ds(e)),Ke(),o}function Ci(e){let t=f();if(!ps(e))return{removed:0};let n=ds(e);return t.prepare("DELETE FROM auto_collection_rules WHERE id = ?").run(e),Ke(),n}function gs(e={}){let t=e.includeDismissed?"SELECT * FROM auto_collection_suggestions ORDER BY detected_at DESC":"SELECT * FROM auto_collection_suggestions WHERE dismissed = 0 ORDER BY detected_at DESC";return f().prepare(t).all().map(km)}function Ii(e){f().prepare("UPDATE auto_collection_suggestions SET dismissed = 1 WHERE id = ?").run(e),Ke()}function vi(e){let t=f(),s=t.prepare("SELECT * FROM auto_collection_suggestions WHERE id = ?").get(e);if(!s)throw new Error(`suggestion not found: ${e}`);if(s.dismissed)throw new Error(`suggestion already dismissed: ${e}`);let n=Bn({name:s.suggested_name,type:s.type,pattern:s.pattern,parent_collection_id:s.suggested_parent_collection_id===null?void 0:s.suggested_parent_collection_id,created_by:"suggestion-accepted"});return t.prepare("DELETE FROM auto_collection_suggestions WHERE id = ?").run(e),Ke(),n}function _s(){let e=f(),t=new Date().toISOString(),s=hm(),n=new Set(e.prepare("SELECT decoded_path FROM projects").all().map(c=>c.decoded_path)),r=[...Im(s,t).filter(c=>!n.has(c.pattern)),...vm(t),...jm(t)];if(e.prepare("DELETE FROM auto_collection_suggestions WHERE type = 'project-id'").run(),n.size>0){let c=Array.from(n).map(()=>"?").join(",");e.prepare(`DELETE FROM auto_collection_suggestions WHERE type = 'cwd-prefix' AND pattern IN (${c})`).run(...Array.from(n))}let o=e.prepare("SELECT type, pattern FROM auto_collection_rules").all(),a=new Set(o.map(c=>`${c.type}:${c.pattern}`));for(let c of r){let d=`${c.type}:${c.pattern}`;if(a.has(d))continue;let u=e.prepare("SELECT id FROM auto_collection_suggestions WHERE type = ? AND pattern = ?").get(c.type,c.pattern);u?e.prepare(`UPDATE auto_collection_suggestions
780
+ WHERE id = ?`).run(r.name,r.pattern,r.enabled?1:0,r.priority,e);let o=ps(e);return t.pattern!==void 0&&t.pattern!==n.pattern?(ds(e),o.enabled&&Fn(o)):t.enabled!==void 0&&t.enabled!==n.enabled&&(o.enabled?Fn(o):ds(e)),Ke(),o}function Ci(e){let t=f();if(!ps(e))return{removed:0};let n=ds(e);return t.prepare("DELETE FROM auto_collection_rules WHERE id = ?").run(e),Ke(),n}function gs(e={}){let t=e.includeDismissed?"SELECT * FROM auto_collection_suggestions ORDER BY detected_at DESC":"SELECT * FROM auto_collection_suggestions WHERE dismissed = 0 ORDER BY detected_at DESC";return f().prepare(t).all().map(xm)}function Ii(e){f().prepare("UPDATE auto_collection_suggestions SET dismissed = 1 WHERE id = ?").run(e),Ke()}function vi(e){let t=f(),s=t.prepare("SELECT * FROM auto_collection_suggestions WHERE id = ?").get(e);if(!s)throw new Error(`suggestion not found: ${e}`);if(s.dismissed)throw new Error(`suggestion already dismissed: ${e}`);let n=Bn({name:s.suggested_name,type:s.type,pattern:s.pattern,parent_collection_id:s.suggested_parent_collection_id===null?void 0:s.suggested_parent_collection_id,created_by:"suggestion-accepted"});return t.prepare("DELETE FROM auto_collection_suggestions WHERE id = ?").run(e),Ke(),n}function _s(){let e=f(),t=new Date().toISOString(),s=bm(),n=new Set(e.prepare("SELECT decoded_path FROM projects").all().map(c=>c.decoded_path)),r=[...jm(s,t).filter(c=>!n.has(c.pattern)),...Mm(t),...Dm(t)];if(e.prepare("DELETE FROM auto_collection_suggestions WHERE type = 'project-id'").run(),n.size>0){let c=Array.from(n).map(()=>"?").join(",");e.prepare(`DELETE FROM auto_collection_suggestions WHERE type = 'cwd-prefix' AND pattern IN (${c})`).run(...Array.from(n))}let o=e.prepare("SELECT type, pattern FROM auto_collection_rules").all(),a=new Set(o.map(c=>`${c.type}:${c.pattern}`));for(let c of r){let d=`${c.type}:${c.pattern}`;if(a.has(d))continue;let u=e.prepare("SELECT id FROM auto_collection_suggestions WHERE type = ? AND pattern = ?").get(c.type,c.pattern);u?e.prepare(`UPDATE auto_collection_suggestions
781
781
  SET session_count = ?, detected_at = ?, suggested_name = ?, suggested_parent_collection_id = ?
782
782
  WHERE id = ?`).run(c.session_count,t,c.suggested_name,c.suggested_parent_collection_id,u.id):e.prepare(`INSERT INTO auto_collection_suggestions
783
783
  (id, type, pattern, suggested_name, suggested_parent_collection_id, session_count, detected_at, dismissed)
784
- VALUES (?, ?, ?, ?, ?, ?, ?, 0)`).run(Pn(),c.type,c.pattern,c.suggested_name,c.suggested_parent_collection_id,c.session_count,t)}return Ke(),gs()}function Im(e,t){let n=f().prepare("SELECT id, cwd FROM sessions WHERE cwd IS NOT NULL AND cwd != ''").all(),r=new Map;for(let a of n){let c=a.cwd.split("/").filter(Boolean),d="";for(let u of c){if(d=`${d}/${u}`,d===e||d==="/")continue;let g=r.get(d);g||(g=new Set,r.set(d,g)),g.add(a.id)}}let o=[];for(let[a,c]of r.entries()){if(c.size<Ai)continue;let d=!1;for(let[u,g]of r.entries())if(u!==a&&u.startsWith(a+"/")&&g.size>=Ai){d=!0;break}d||o.push({type:"cwd-prefix",pattern:a,suggested_name:Em(a)||a,suggested_parent_collection_id:null,session_count:c.size,detected_at:t,dismissed:!1})}return o}function vm(e){return f().prepare("SELECT tag, COUNT(*) AS n FROM session_tags GROUP BY tag HAVING n >= ?").all(ym).map(s=>({type:"tag",pattern:s.tag,suggested_name:s.tag,suggested_parent_collection_id:null,session_count:s.n,detected_at:e,dismissed:!1}))}function jm(e){let t=f().prepare(`SELECT id, first_user_message FROM sessions
785
- WHERE first_user_message IS NOT NULL AND first_user_message != ''`).all(),s=new Map;for(let r of t)for(let o of Rm){o.lastIndex=0;let a=r.first_user_message.match(o);if(a)for(let c of a){let d=s.get(c);d||(d=new Set,s.set(c,d)),d.add(r.id)}}let n=[];for(let[r,o]of s.entries())o.size<wm||n.push({type:"plan-file",pattern:r,suggested_name:r,suggested_parent_collection_id:null,session_count:o.size,detected_at:e,dismissed:!1});return n}function ms(e){return e.replace(/[\\%_]/g,"\\$&")}function Ke(){try{J(),_m(us)||fm(us,{recursive:!0});let e=f(),t=e.prepare("SELECT * FROM auto_collection_rules ORDER BY created_at, id").all(),s=e.prepare("SELECT * FROM auto_collection_suggestions ORDER BY detected_at DESC, id").all();ki(bm,JSON.stringify({schema:"claude-recall.auto-rules.v1",backed_up_at:new Date().toISOString(),rules:t},null,2)),ki(Sm,JSON.stringify({schema:"claude-recall.auto-suggestions.v1",backed_up_at:new Date().toISOString(),suggestions:s},null,2))}catch(e){console.error("[auto-collections] backup failed:",e)}}function ji(){let e=f().prepare("SELECT DISTINCT collection_id FROM auto_collection_rules").all();return new Set(e.map(t=>t.collection_id))}H();Z();import{randomUUID as Mi}from"node:crypto";import{writeFileSync as Di,readFileSync as Aw,existsSync as Mm,mkdirSync as Dm}from"node:fs";import{join as Hn}from"node:path";var fs=Hn($,"threads"),Fm=Hn(fs,"index.json");function Fi(){J(),Mm(fs)||Dm(fs,{recursive:!0})}function Wn(e,t,s){return{id:e.id,name:e.name,summary:e.summary,created_at:e.created_at,closed_at:e.closed_at,archived:e.archived===1,session_count:t.session_count,origin_count:t.origin_count,project:s?.project??null,project_count:s?.project_count??0,folder_id:e.folder_id??null}}function Pi(e){let t=new Map;if(e.length===0)return t;let s=f(),n=e.map(()=>"?").join(","),r=s.prepare(`SELECT te.thread_id AS thread_id,
784
+ VALUES (?, ?, ?, ?, ?, ?, ?, 0)`).run(Pn(),c.type,c.pattern,c.suggested_name,c.suggested_parent_collection_id,c.session_count,t)}return Ke(),gs()}function jm(e,t){let n=f().prepare("SELECT id, cwd FROM sessions WHERE cwd IS NOT NULL AND cwd != ''").all(),r=new Map;for(let a of n){let c=a.cwd.split("/").filter(Boolean),d="";for(let u of c){if(d=`${d}/${u}`,d===e||d==="/")continue;let g=r.get(d);g||(g=new Set,r.set(d,g)),g.add(a.id)}}let o=[];for(let[a,c]of r.entries()){if(c.size<Ai)continue;let d=!1;for(let[u,g]of r.entries())if(u!==a&&u.startsWith(a+"/")&&g.size>=Ai){d=!0;break}d||o.push({type:"cwd-prefix",pattern:a,suggested_name:Sm(a)||a,suggested_parent_collection_id:null,session_count:c.size,detected_at:t,dismissed:!1})}return o}function Mm(e){return f().prepare("SELECT tag, COUNT(*) AS n FROM session_tags GROUP BY tag HAVING n >= ?").all(Rm).map(s=>({type:"tag",pattern:s.tag,suggested_name:s.tag,suggested_parent_collection_id:null,session_count:s.n,detected_at:e,dismissed:!1}))}function Dm(e){let t=f().prepare(`SELECT id, first_user_message FROM sessions
785
+ WHERE first_user_message IS NOT NULL AND first_user_message != ''`).all(),s=new Map;for(let r of t)for(let o of Am){o.lastIndex=0;let a=r.first_user_message.match(o);if(a)for(let c of a){let d=s.get(c);d||(d=new Set,s.set(c,d)),d.add(r.id)}}let n=[];for(let[r,o]of s.entries())o.size<km||n.push({type:"plan-file",pattern:r,suggested_name:r,suggested_parent_collection_id:null,session_count:o.size,detected_at:e,dismissed:!1});return n}function ms(e){return e.replace(/[\\%_]/g,"\\$&")}function Ke(){try{J(),hm(us)||Em(us,{recursive:!0});let e=f(),t=e.prepare("SELECT * FROM auto_collection_rules ORDER BY created_at, id").all(),s=e.prepare("SELECT * FROM auto_collection_suggestions ORDER BY detected_at DESC, id").all();ki(Tm,JSON.stringify({schema:"claude-recall.auto-rules.v1",backed_up_at:new Date().toISOString(),rules:t},null,2)),ki(ym,JSON.stringify({schema:"claude-recall.auto-suggestions.v1",backed_up_at:new Date().toISOString(),suggestions:s},null,2))}catch(e){console.error("[auto-collections] backup failed:",e)}}function ji(){let e=f().prepare("SELECT DISTINCT collection_id FROM auto_collection_rules").all();return new Set(e.map(t=>t.collection_id))}H();Z();import{randomUUID as Mi}from"node:crypto";import{writeFileSync as Di,readFileSync as Nw,existsSync as Fm,mkdirSync as Pm}from"node:fs";import{join as Hn}from"node:path";var fs=Hn($,"threads"),Um=Hn(fs,"index.json");function Fi(){J(),Fm(fs)||Pm(fs,{recursive:!0})}function Wn(e,t,s){return{id:e.id,name:e.name,summary:e.summary,created_at:e.created_at,closed_at:e.closed_at,archived:e.archived===1,session_count:t.session_count,origin_count:t.origin_count,project:s?.project??null,project_count:s?.project_count??0,folder_id:e.folder_id??null}}function Pi(e){let t=new Map;if(e.length===0)return t;let s=f(),n=e.map(()=>"?").join(","),r=s.prepare(`SELECT te.thread_id AS thread_id,
786
786
  p.name AS project,
787
787
  COUNT(*) AS n,
788
788
  SUM(CASE WHEN te.role = 'origin' THEN 1 ELSE 0 END) AS origin_n
@@ -801,7 +801,7 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
801
801
  LEFT JOIN projects p ON p.id = s.project_id`).get(e),n=s?.auto_title_source??null;return{alias:s?.alias??null,auto_title:s?.auto_title??null,auto_title_source:n==="agent"||n==="heuristic"?n:null,first_user_message:s?.first_user_message??null,project:s?.project??null}}function qn(e){let s=f().prepare(`SELECT
802
802
  COUNT(*) AS session_count,
803
803
  SUM(CASE WHEN role = 'origin' THEN 1 ELSE 0 END) AS origin_count
804
- FROM thread_edges WHERE thread_id = ?`).get(e);return{session_count:s?.session_count??0,origin_count:s?.origin_count??0}}function fe(e){let t=te(e);t&&(Fi(),Di(Hn(fs,`${e}.json`),JSON.stringify(t,null,2)),Bi())}function Bi(){Fi();let e=Jn({includeArchived:!0});Di(Fm,JSON.stringify({threads:e},null,2))}function hs(e){let t=e.name.trim();if(!t)throw new Error("thread name cannot be empty");let s=f(),n=Mi(),r=new Date().toISOString();s.prepare("INSERT INTO threads (id, name, summary, created_at) VALUES (?, ?, ?, ?)").run(n,t,e.summary?.trim()||null,r),e.originSessionId&&s.prepare(`INSERT INTO thread_edges (thread_id, session_id, parent_session_id, role, confidence, source, added_at)
804
+ FROM thread_edges WHERE thread_id = ?`).get(e);return{session_count:s?.session_count??0,origin_count:s?.origin_count??0}}function fe(e){let t=te(e);t&&(Fi(),Di(Hn(fs,`${e}.json`),JSON.stringify(t,null,2)),Bi())}function Bi(){Fi();let e=Jn({includeArchived:!0});Di(Um,JSON.stringify({threads:e},null,2))}function hs(e){let t=e.name.trim();if(!t)throw new Error("thread name cannot be empty");let s=f(),n=Mi(),r=new Date().toISOString();s.prepare("INSERT INTO threads (id, name, summary, created_at) VALUES (?, ?, ?, ?)").run(n,t,e.summary?.trim()||null,r),e.originSessionId&&s.prepare(`INSERT INTO thread_edges (thread_id, session_id, parent_session_id, role, confidence, source, added_at)
805
805
  VALUES (?, ?, NULL, 'origin', 1.0, 'manual', ?)`).run(n,e.originSessionId,r),fe(n);let o=te(n);if(!o)throw new Error("thread creation succeeded but read-back failed");return o}function Jn(e={}){let t=f(),s=e.includeArchived?"":"WHERE archived = 0",n=t.prepare(`SELECT * FROM threads ${s} ORDER BY created_at DESC`).all(),r=Pi(n.map(o=>o.id));return n.map(o=>Wn(o,qn(o.id),r.get(o.id)))}function te(e){let t=f(),s=t.prepare("SELECT * FROM threads WHERE id = ?").get(e);if(!s)return null;let n=t.prepare(`SELECT e.*,
806
806
  NULLIF(sa.alias, '') AS alias,
807
807
  s.auto_title AS auto_title,
@@ -835,11 +835,11 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
835
835
  confidence = MAX(thread_edges.confidence, excluded.confidence),
836
836
  source = thread_edges.source`).run(t,a.session_id,a.parent_session_id,a.role,a.confidence,a.source,n);s.prepare("DELETE FROM threads WHERE id = ?").run(e)})(),fe(t),Bi();let r=te(t);if(!r)throw new Error("merge destination disappeared");return r}function Ki(e){if(e.sessionIds.length===0)throw new Error("no sessions to split off");let t=f(),s=new Date().toISOString(),n=Mi();t.transaction(()=>{t.prepare("INSERT INTO threads (id, name, summary, created_at) VALUES (?, ?, NULL, ?)").run(n,e.newThreadName.trim(),s);for(let o of e.sessionIds){let a=t.prepare("SELECT * FROM thread_edges WHERE thread_id = ? AND session_id = ?").get(e.threadId,o);a&&(t.prepare(`INSERT INTO thread_edges
837
837
  (thread_id, session_id, parent_session_id, role, confidence, source, added_at)
838
- VALUES (?, ?, ?, ?, ?, ?, ?)`).run(n,o,a.parent_session_id,a.role,a.confidence,a.source,s),t.prepare("DELETE FROM thread_edges WHERE thread_id = ? AND session_id = ?").run(e.threadId,o))}})(),fe(e.threadId),fe(n);let r=te(n);if(!r)throw new Error("split destination disappeared");return r}H();import{execFile as Zm}from"node:child_process";import{promisify as Qm}from"node:util";import{readlink as eg,readFile as ea}from"node:fs/promises";import{platform as ws}from"node:os";import{readFileSync as Pm,statSync as Um}from"node:fs";var $m=200*1024*1024,Ss=.7,Ts=.5,Zi=Ts,Bm=[{maxGapMs:3600*1e3,weight:.7,label:"<1h gap"},{maxGapMs:14400*1e3,weight:.4,label:"<4h gap"},{maxGapMs:1440*60*1e3,weight:.2,label:"<24h gap"}],Hm=["let's commit","lets commit","now commit","inspect the diff","inspect this diff","review the diff","review this diff","diff of all changes","diff of changes","based on what we just did","based on the things done","based on all the things","continue from","continuing from","pick up where","next step","now fix","now lets","now let's","from the previous session","from our last session","from the last session"];function zi(e){if(!e)return null;if(e.startsWith("/")){let s=e.split(" \xB7 ");if(s.length>1)return s[1].trim().toLowerCase()}let t=e.split(" \xB7 ");return t.length>1?t[t.length-1].trim().toLowerCase():null}function Wm(e,t){let s=t-e;if(s<0)return{weight:0,label:null};for(let n of Bm)if(s<=n.maxGapMs)return{weight:n.weight,label:n.label};return{weight:0,label:null}}function qm(e){if(e.length===0)return{weight:0,matched:null,matchedIndex:-1};let t=[.4,.35,.3,.25,.2,.15,.1],s=Math.min(e.length,t.length);for(let n=0;n<s;n++){let r=e[n];if(!r)continue;let o=r.toLowerCase();for(let a of Hm)if(o.includes(a))return{weight:t[n],matched:a,matchedIndex:n}}return{weight:0,matched:null,matchedIndex:-1}}function Xn(e,t){if(!e||!t||e.length!==t.length)return 0;let s=0;for(let n=0;n<e.length;n++)s+=e[n]*t[n];return s<-1?-1:s>1?1:s}function Jm(e,t){if(e.length===0||t.length===0)return 0;let s=0;for(let n of e)for(let r of t){let o=Xn(n,r);o>s&&(s=o)}return s}function Xm(e,t){let s=Xn(e.mean_embedding,t.mean_embedding),n=Xn(e.tail_pool,t.head_pool),r=Jm(e.sample_chunks,t.sample_chunks),o=0,a=null;if(s>o&&(o=s,a="mean"),n>o&&(o=n,a="asymmetric"),r>o&&(o=r,a="max_pool"),o<.65)return{weight:0,cosine:o,mode:null};if(o>=.85)return{weight:.3,cosine:o,mode:a};let c=(o-.65)/.2*.3;return{weight:Math.round(c*100)/100,cosine:o,mode:a}}function Gm(e,t){return e.cluster_id===null||t.cluster_id===null?{weight:0,same:!1}:e.cluster_id!==t.cluster_id?{weight:0,same:!1}:{weight:.05,same:!0}}function Ym(e,t){if(e.size===0||t.size===0)return{weight:0,count:0};let s=0;for(let r of t)e.has(r)&&s++;return s===0?{weight:0,count:0}:{weight:Math.min(.4,s*.1),count:s}}function Km(e,t){let s=zi(e),n=zi(t);return s&&n&&s===n?{weight:.1,brand:s}:{weight:0,brand:null}}function Vi(e){return e.replace(/\s+/g," ").trim().toLowerCase()}function zm(e,t){let s=0,n=null,r=!1;if(e.authored_paths.size>0){let o=t.recent_user_messages.slice(0,3).join(`
839
- `).toLowerCase();for(let a of e.authored_paths){let c=a.toLowerCase();if(t.touched_files.has(a)||o.includes(c)){s+=.5,n=a;break}}}if(e.authored_content.length>0&&t.recent_user_messages[0]){let o=Vi(t.recent_user_messages[0]);if(o.length>=200)for(let a of e.authored_content){let c=Vi(a);if(c.length<200)continue;let d=Math.min(c.length,240),u=c.slice(0,d);if(o.includes(u)){s+=.4,r=!0;break}}}return{weight:Math.min(.6,s),pathMatch:n,contentMatch:r}}function Vm(e,t,s=Zi){if(t.started_at_ms<=e.started_at_ms)return null;let n=e.ended_at_ms??e.started_at_ms;if(t.started_at_ms<n)return null;let r=Wm(n,t.started_at_ms),o=t.recent_user_messages.length>0?t.recent_user_messages:t.first_user_message?[t.first_user_message]:[],a=qm(o),c=Ym(e.touched_files,t.touched_files),d=Km(e.auto_title,t.auto_title),u=Xm(e,t),g=Gm(e,t),h=zm(e,t),b=r.weight+a.weight+c.weight+d.weight+u.weight+g.weight+h.weight;if(b<s)return null;let S=[];if(r.label&&S.push(`temporal ${r.label} (+${r.weight})`),a.matched){let y=a.matchedIndex===0?"opening message":`message #${a.matchedIndex+1}`;S.push(`continuation phrase "${a.matched}" in ${y} (+${a.weight})`)}if(c.count>0&&S.push(`${c.count} file${c.count===1?"":"s"} overlap (+${c.weight.toFixed(1)})`),d.brand&&S.push(`shared brand "${d.brand}" (+${d.weight})`),u.weight>0&&u.mode&&S.push(`semantic ${u.mode==="asymmetric"?"tail\u2192head":u.mode==="max_pool"?"best-chunk":"mean"} ${u.cosine.toFixed(2)} (+${u.weight.toFixed(2)})`),g.same&&S.push(`same cluster (+${g.weight})`),h.weight>0){let y=[];h.pathMatch&&y.push(`opened authored path "${h.pathMatch.split("/").pop()}"`),h.contentMatch&&y.push("verbatim-paste of authored content"),S.push(`doc-authorship: ${y.join(" + ")} (+${h.weight.toFixed(2)})`)}return{parent_id:e.id,child_id:t.id,confidence:Math.min(1,b),signals:{temporal:r.weight,continuation:a.weight,file_overlap:c.weight,same_brand:d.weight,semantic:u.weight,cluster:g.weight,doc_authorship:h.weight},reasons:S}}function ze(e,t=Zi){let s=[];for(let n=0;n<e.length;n++){let r=e[n],o=null;for(let a=0;a<n;a++){let c=e[a],d=Vm(c,r,t);d&&(!o||d.confidence>o.confidence)&&(o=d)}o&&s.push(o)}return s}function Qi(e,t){let s=new Map,n=c=>{let d=c;for(;s.get(d)!==d;)d=s.get(d);let u=c;for(;s.get(u)!==d;){let g=s.get(u);s.set(u,d),u=g}return d},r=(c,d)=>{let u=n(c),g=n(d);u!==g&&s.set(u,g)};for(let c of e)s.has(c.parent_id)||s.set(c.parent_id,c.parent_id),s.has(c.child_id)||s.set(c.child_id,c.child_id),r(c.parent_id,c.child_id);let o=new Map;for(let c of s.keys()){let d=n(c),u=o.get(d);u||(u=[],o.set(d,u)),u.push(c)}let a=new Map;for(let c of t)a.set(c.id,c.started_at_ms);return Array.from(o.values()).map(c=>(c.sort((d,u)=>(a.get(d)??0)-(a.get(u)??0)),{rootId:c[0],sessionIds:c}))}function ys(e,t={}){let s=t.maxUserMessages??5,n=t.userMessageMaxLen??2e3,r=new Set,o=[],a=new Set,c=[],d;try{if(Um(e).size>$m)return{touched_files:r,recent_user_messages:o,authored_paths:a,authored_content:c};d=Pm(e,"utf8")}catch{return{touched_files:r,recent_user_messages:o,authored_paths:a,authored_content:c}}let u=0;for(;u<d.length;){let g=d.indexOf(`
840
- `,u),h=g===-1?d.length:g,b=d.slice(u,h);if(u=g===-1?d.length:g+1,!b.trim())continue;let S;try{S=JSON.parse(b)}catch{continue}let y=S;if(y.type==="user"&&y.message?.role==="user"&&typeof y.message.content=="string"&&o.length<s){let w=y.message.content.trim();w&&o.push(w.length>n?w.slice(0,n):w)}let k=y.message?.content;if(Array.isArray(k))for(let w of k){if(!w||typeof w!="object")continue;let D=w;if(D.type!=="tool_use")continue;let L=D.input??{},X=typeof L.file_path=="string"?L.file_path:null;if(X){let M=bs(X);M&&r.add(M)}if((D.name==="Write"||D.name==="Edit"||D.name==="MultiEdit")&&X){let M=bs(X);M&&a.add(M);let B=typeof L.content=="string"?L.content:typeof L.new_string=="string"?L.new_string:null;B&&B.length>=200&&c.push(B.length>4096?B.slice(0,4096):B)}if(D.name==="Bash"&&typeof L.command=="string")for(let M of L.command.matchAll(/(?:^|[\s'"`(=])((?:\.\.?\/|\/|src\/|test\/|docs\/|site\/)[A-Za-z0-9_./-]+)/g)){let B=bs(M[1]);B&&r.add(B)}if((D.name==="Glob"||D.name==="Grep")&&typeof L.pattern=="string"){let M=bs(L.pattern);M&&!M.includes("*")&&r.add(M)}}}return{touched_files:r,recent_user_messages:o,authored_paths:a,authored_content:c}}function bs(e){let t=e.trim().replace(/^['"]|['"]$/g,"");return!t||t.length<4||/[<>|;&\$`]/.test(t)?null:t}var Yn=Qm(Zm),tg=6,ta="Active ",sa=" sessions \u2014 ",sg=6e4;async function ng(){if(ws()==="win32")return[];for(let t of["/bin/ps","/usr/bin/ps"])try{let{stdout:s}=await Yn(t,["-eo","pid=,comm="],{timeout:2e3}),n=[];for(let r of s.split(`
841
- `)){let o=r.trim().match(/^(\d+)\s+(.+)$/);if(!o)continue;let a=Number(o[1]),c=o[2].trim();(c==="claude"||c.endsWith("/claude")||c.endsWith("/bin/claude"))&&Number.isFinite(a)&&n.push(a)}return n}catch{continue}return[]}async function rg(e){let t=ws();if(t==="linux")try{return(await eg(`/proc/${e}/cwd`)).replace(/\/+$/,"")}catch{return null}if(t==="darwin"||t==="freebsd"||t==="openbsd")for(let s of["/usr/sbin/lsof","/usr/bin/lsof"])try{let{stdout:n}=await Yn(s,["-a","-p",String(e),"-d","cwd","-Fn"],{timeout:2e3});for(let r of n.split(`
842
- `))if(r.startsWith("n"))return r.slice(1).replace(/\/+$/,"");return null}catch{continue}return null}async function og(e){let t=ws();if(t==="linux")try{let s=await ea(`/proc/${e}/stat`,"utf8"),n=s.lastIndexOf(")");if(n===-1)return null;let r=s.slice(n+1).trim().split(/\s+/),o=Number(r[19]);if(!Number.isFinite(o))return null;let a=await ea("/proc/uptime","utf8"),c=Number(a.split(/\s+/)[0]);return Number.isFinite(c)?Date.now()-c*1e3+o/100*1e3:null}catch{return null}if(t==="darwin"||t==="freebsd"||t==="openbsd")for(let s of["/bin/ps","/usr/bin/ps"])try{let{stdout:n}=await Yn(s,["-o","lstart=","-p",String(e)],{timeout:2e3}),r=Date.parse(n.trim());return Number.isFinite(r)?r:null}catch{continue}return null}async function ig(e,t){let s=await ng();if(s.length===0)return null;let n=e.replace(/\/+$/,""),r=[];for(let a of s){let c=await rg(a);if(c&&(c===n||c.startsWith(n+"/"))){let d=await og(a);r.push({pid:a,startMs:d})}}if(r.length===0)return new Set;let o=new Set;for(let{startMs:a}of r){if(a==null)continue;let c=null,d=sg;for(let u of t){if(o.has(u.session_id)||!u.started_at)continue;let g=Date.parse(u.started_at);if(!Number.isFinite(g))continue;let h=Math.abs(g-a);h<d&&(d=h,c=u)}c&&o.add(c.session_id)}return o}function ag(e){let s=f().prepare("SELECT id, name, decoded_path FROM projects WHERE id = ? LIMIT 1").get(e);if(!s)throw new Error(`project ${e} not found`);return s}function cg(e,t){let s=f(),n=`${ta}${t}${sa}%`,r=s.prepare(`SELECT t.id
838
+ VALUES (?, ?, ?, ?, ?, ?, ?)`).run(n,o,a.parent_session_id,a.role,a.confidence,a.source,s),t.prepare("DELETE FROM thread_edges WHERE thread_id = ? AND session_id = ?").run(e.threadId,o))}})(),fe(e.threadId),fe(n);let r=te(n);if(!r)throw new Error("split destination disappeared");return r}H();import{execFile as eg}from"node:child_process";import{promisify as tg}from"node:util";import{readlink as sg,readFile as ea}from"node:fs/promises";import{platform as ws}from"node:os";import{readFileSync as $m,statSync as Bm}from"node:fs";var Hm=200*1024*1024,Ss=.7,Ts=.5,Zi=Ts,Wm=[{maxGapMs:3600*1e3,weight:.7,label:"<1h gap"},{maxGapMs:14400*1e3,weight:.4,label:"<4h gap"},{maxGapMs:1440*60*1e3,weight:.2,label:"<24h gap"}],qm=["let's commit","lets commit","now commit","inspect the diff","inspect this diff","review the diff","review this diff","diff of all changes","diff of changes","based on what we just did","based on the things done","based on all the things","continue from","continuing from","pick up where","next step","now fix","now lets","now let's","from the previous session","from our last session","from the last session"];function zi(e){if(!e)return null;if(e.startsWith("/")){let s=e.split(" \xB7 ");if(s.length>1)return s[1].trim().toLowerCase()}let t=e.split(" \xB7 ");return t.length>1?t[t.length-1].trim().toLowerCase():null}function Jm(e,t){let s=t-e;if(s<0)return{weight:0,label:null};for(let n of Wm)if(s<=n.maxGapMs)return{weight:n.weight,label:n.label};return{weight:0,label:null}}function Xm(e){if(e.length===0)return{weight:0,matched:null,matchedIndex:-1};let t=[.4,.35,.3,.25,.2,.15,.1],s=Math.min(e.length,t.length);for(let n=0;n<s;n++){let r=e[n];if(!r)continue;let o=r.toLowerCase();for(let a of qm)if(o.includes(a))return{weight:t[n],matched:a,matchedIndex:n}}return{weight:0,matched:null,matchedIndex:-1}}function Xn(e,t){if(!e||!t||e.length!==t.length)return 0;let s=0;for(let n=0;n<e.length;n++)s+=e[n]*t[n];return s<-1?-1:s>1?1:s}function Gm(e,t){if(e.length===0||t.length===0)return 0;let s=0;for(let n of e)for(let r of t){let o=Xn(n,r);o>s&&(s=o)}return s}function Ym(e,t){let s=Xn(e.mean_embedding,t.mean_embedding),n=Xn(e.tail_pool,t.head_pool),r=Gm(e.sample_chunks,t.sample_chunks),o=0,a=null;if(s>o&&(o=s,a="mean"),n>o&&(o=n,a="asymmetric"),r>o&&(o=r,a="max_pool"),o<.65)return{weight:0,cosine:o,mode:null};if(o>=.85)return{weight:.3,cosine:o,mode:a};let c=(o-.65)/.2*.3;return{weight:Math.round(c*100)/100,cosine:o,mode:a}}function Km(e,t){return e.cluster_id===null||t.cluster_id===null?{weight:0,same:!1}:e.cluster_id!==t.cluster_id?{weight:0,same:!1}:{weight:.05,same:!0}}function zm(e,t){if(e.size===0||t.size===0)return{weight:0,count:0};let s=0;for(let r of t)e.has(r)&&s++;return s===0?{weight:0,count:0}:{weight:Math.min(.4,s*.1),count:s}}function Vm(e,t){let s=zi(e),n=zi(t);return s&&n&&s===n?{weight:.1,brand:s}:{weight:0,brand:null}}function Vi(e){return e.replace(/\s+/g," ").trim().toLowerCase()}function Zm(e,t){let s=0,n=null,r=!1;if(e.authored_paths.size>0){let o=t.recent_user_messages.slice(0,3).join(`
839
+ `).toLowerCase();for(let a of e.authored_paths){let c=a.toLowerCase();if(t.touched_files.has(a)||o.includes(c)){s+=.5,n=a;break}}}if(e.authored_content.length>0&&t.recent_user_messages[0]){let o=Vi(t.recent_user_messages[0]);if(o.length>=200)for(let a of e.authored_content){let c=Vi(a);if(c.length<200)continue;let d=Math.min(c.length,240),u=c.slice(0,d);if(o.includes(u)){s+=.4,r=!0;break}}}return{weight:Math.min(.6,s),pathMatch:n,contentMatch:r}}function Qm(e,t,s=Zi){if(t.started_at_ms<=e.started_at_ms)return null;let n=e.ended_at_ms??e.started_at_ms;if(t.started_at_ms<n)return null;let r=Jm(n,t.started_at_ms),o=t.recent_user_messages.length>0?t.recent_user_messages:t.first_user_message?[t.first_user_message]:[],a=Xm(o),c=zm(e.touched_files,t.touched_files),d=Vm(e.auto_title,t.auto_title),u=Ym(e,t),g=Km(e,t),h=Zm(e,t),b=r.weight+a.weight+c.weight+d.weight+u.weight+g.weight+h.weight;if(b<s)return null;let S=[];if(r.label&&S.push(`temporal ${r.label} (+${r.weight})`),a.matched){let y=a.matchedIndex===0?"opening message":`message #${a.matchedIndex+1}`;S.push(`continuation phrase "${a.matched}" in ${y} (+${a.weight})`)}if(c.count>0&&S.push(`${c.count} file${c.count===1?"":"s"} overlap (+${c.weight.toFixed(1)})`),d.brand&&S.push(`shared brand "${d.brand}" (+${d.weight})`),u.weight>0&&u.mode&&S.push(`semantic ${u.mode==="asymmetric"?"tail\u2192head":u.mode==="max_pool"?"best-chunk":"mean"} ${u.cosine.toFixed(2)} (+${u.weight.toFixed(2)})`),g.same&&S.push(`same cluster (+${g.weight})`),h.weight>0){let y=[];h.pathMatch&&y.push(`opened authored path "${h.pathMatch.split("/").pop()}"`),h.contentMatch&&y.push("verbatim-paste of authored content"),S.push(`doc-authorship: ${y.join(" + ")} (+${h.weight.toFixed(2)})`)}return{parent_id:e.id,child_id:t.id,confidence:Math.min(1,b),signals:{temporal:r.weight,continuation:a.weight,file_overlap:c.weight,same_brand:d.weight,semantic:u.weight,cluster:g.weight,doc_authorship:h.weight},reasons:S}}function ze(e,t=Zi){let s=[];for(let n=0;n<e.length;n++){let r=e[n],o=null;for(let a=0;a<n;a++){let c=e[a],d=Qm(c,r,t);d&&(!o||d.confidence>o.confidence)&&(o=d)}o&&s.push(o)}return s}function Qi(e,t){let s=new Map,n=c=>{let d=c;for(;s.get(d)!==d;)d=s.get(d);let u=c;for(;s.get(u)!==d;){let g=s.get(u);s.set(u,d),u=g}return d},r=(c,d)=>{let u=n(c),g=n(d);u!==g&&s.set(u,g)};for(let c of e)s.has(c.parent_id)||s.set(c.parent_id,c.parent_id),s.has(c.child_id)||s.set(c.child_id,c.child_id),r(c.parent_id,c.child_id);let o=new Map;for(let c of s.keys()){let d=n(c),u=o.get(d);u||(u=[],o.set(d,u)),u.push(c)}let a=new Map;for(let c of t)a.set(c.id,c.started_at_ms);return Array.from(o.values()).map(c=>(c.sort((d,u)=>(a.get(d)??0)-(a.get(u)??0)),{rootId:c[0],sessionIds:c}))}function ys(e,t={}){let s=t.maxUserMessages??5,n=t.userMessageMaxLen??2e3,r=new Set,o=[],a=new Set,c=[],d;try{if(Bm(e).size>Hm)return{touched_files:r,recent_user_messages:o,authored_paths:a,authored_content:c};d=$m(e,"utf8")}catch{return{touched_files:r,recent_user_messages:o,authored_paths:a,authored_content:c}}let u=0;for(;u<d.length;){let g=d.indexOf(`
840
+ `,u),h=g===-1?d.length:g,b=d.slice(u,h);if(u=g===-1?d.length:g+1,!b.trim())continue;let S;try{S=JSON.parse(b)}catch{continue}let y=S;if(y.type==="user"&&y.message?.role==="user"&&typeof y.message.content=="string"&&o.length<s){let w=y.message.content.trim();w&&o.push(w.length>n?w.slice(0,n):w)}let k=y.message?.content;if(Array.isArray(k))for(let w of k){if(!w||typeof w!="object")continue;let D=w;if(D.type!=="tool_use")continue;let L=D.input??{},X=typeof L.file_path=="string"?L.file_path:null;if(X){let M=bs(X);M&&r.add(M)}if((D.name==="Write"||D.name==="Edit"||D.name==="MultiEdit")&&X){let M=bs(X);M&&a.add(M);let B=typeof L.content=="string"?L.content:typeof L.new_string=="string"?L.new_string:null;B&&B.length>=200&&c.push(B.length>4096?B.slice(0,4096):B)}if(D.name==="Bash"&&typeof L.command=="string")for(let M of L.command.matchAll(/(?:^|[\s'"`(=])((?:\.\.?\/|\/|src\/|test\/|docs\/|site\/)[A-Za-z0-9_./-]+)/g)){let B=bs(M[1]);B&&r.add(B)}if((D.name==="Glob"||D.name==="Grep")&&typeof L.pattern=="string"){let M=bs(L.pattern);M&&!M.includes("*")&&r.add(M)}}}return{touched_files:r,recent_user_messages:o,authored_paths:a,authored_content:c}}function bs(e){let t=e.trim().replace(/^['"]|['"]$/g,"");return!t||t.length<4||/[<>|;&\$`]/.test(t)?null:t}var Yn=tg(eg),ng=6,ta="Active ",sa=" sessions \u2014 ",rg=6e4;async function og(){if(ws()==="win32")return[];for(let t of["/bin/ps","/usr/bin/ps"])try{let{stdout:s}=await Yn(t,["-eo","pid=,comm="],{timeout:2e3}),n=[];for(let r of s.split(`
841
+ `)){let o=r.trim().match(/^(\d+)\s+(.+)$/);if(!o)continue;let a=Number(o[1]),c=o[2].trim();(c==="claude"||c.endsWith("/claude")||c.endsWith("/bin/claude"))&&Number.isFinite(a)&&n.push(a)}return n}catch{continue}return[]}async function ig(e){let t=ws();if(t==="linux")try{return(await sg(`/proc/${e}/cwd`)).replace(/\/+$/,"")}catch{return null}if(t==="darwin"||t==="freebsd"||t==="openbsd")for(let s of["/usr/sbin/lsof","/usr/bin/lsof"])try{let{stdout:n}=await Yn(s,["-a","-p",String(e),"-d","cwd","-Fn"],{timeout:2e3});for(let r of n.split(`
842
+ `))if(r.startsWith("n"))return r.slice(1).replace(/\/+$/,"");return null}catch{continue}return null}async function ag(e){let t=ws();if(t==="linux")try{let s=await ea(`/proc/${e}/stat`,"utf8"),n=s.lastIndexOf(")");if(n===-1)return null;let r=s.slice(n+1).trim().split(/\s+/),o=Number(r[19]);if(!Number.isFinite(o))return null;let a=await ea("/proc/uptime","utf8"),c=Number(a.split(/\s+/)[0]);return Number.isFinite(c)?Date.now()-c*1e3+o/100*1e3:null}catch{return null}if(t==="darwin"||t==="freebsd"||t==="openbsd")for(let s of["/bin/ps","/usr/bin/ps"])try{let{stdout:n}=await Yn(s,["-o","lstart=","-p",String(e)],{timeout:2e3}),r=Date.parse(n.trim());return Number.isFinite(r)?r:null}catch{continue}return null}async function cg(e,t){let s=await og();if(s.length===0)return null;let n=e.replace(/\/+$/,""),r=[];for(let a of s){let c=await ig(a);if(c&&(c===n||c.startsWith(n+"/"))){let d=await ag(a);r.push({pid:a,startMs:d})}}if(r.length===0)return new Set;let o=new Set;for(let{startMs:a}of r){if(a==null)continue;let c=null,d=rg;for(let u of t){if(o.has(u.session_id)||!u.started_at)continue;let g=Date.parse(u.started_at);if(!Number.isFinite(g))continue;let h=Math.abs(g-a);h<d&&(d=h,c=u)}c&&o.add(c.session_id)}return o}function lg(e){let s=f().prepare("SELECT id, name, decoded_path FROM projects WHERE id = ? LIMIT 1").get(e);if(!s)throw new Error(`project ${e} not found`);return s}function dg(e,t){let s=f(),n=`${ta}${t}${sa}%`,r=s.prepare(`SELECT t.id
843
843
  FROM threads t
844
844
  WHERE t.archived = 0
845
845
  AND t.name LIKE ?
@@ -870,19 +870,19 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
870
870
  FROM sessions s
871
871
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
872
872
  WHERE s.project_id = ?
873
- ORDER BY s.started_at ASC`).all(e)}function lg(e){let t=f(),s=[];for(let n of e){if(!n.started_at)continue;let r=Date.parse(n.started_at);if(!Number.isFinite(r))continue;let o=t.prepare("SELECT file_path, ended_at FROM sessions WHERE id = ?").get(n.session_id);if(!o?.file_path)continue;let a=o.ended_at?Date.parse(o.ended_at):null,c=ys(o.file_path,{maxUserMessages:7});s.push({id:n.session_id,started_at_ms:r,ended_at_ms:Number.isFinite(a)?a:null,first_user_message:n.first_user_message,recent_user_messages:c.recent_user_messages,auto_title:n.auto_title,touched_files:c.touched_files,mean_embedding:null,head_pool:null,tail_pool:null,sample_chunks:[],cluster_id:null,authored_paths:c.authored_paths,authored_content:c.authored_content})}return s}function dg(e){let s=f().prepare(`SELECT session_id, parent_session_id, source
873
+ ORDER BY s.started_at ASC`).all(e)}function ug(e){let t=f(),s=[];for(let n of e){if(!n.started_at)continue;let r=Date.parse(n.started_at);if(!Number.isFinite(r))continue;let o=t.prepare("SELECT file_path, ended_at FROM sessions WHERE id = ?").get(n.session_id);if(!o?.file_path)continue;let a=o.ended_at?Date.parse(o.ended_at):null,c=ys(o.file_path,{maxUserMessages:7});s.push({id:n.session_id,started_at_ms:r,ended_at_ms:Number.isFinite(a)?a:null,first_user_message:n.first_user_message,recent_user_messages:c.recent_user_messages,auto_title:n.auto_title,touched_files:c.touched_files,mean_embedding:null,head_pool:null,tail_pool:null,sample_chunks:[],cluster_id:null,authored_paths:c.authored_paths,authored_content:c.authored_content})}return s}function pg(e){let s=f().prepare(`SELECT session_id, parent_session_id, source
874
874
  FROM thread_edges
875
- WHERE thread_id = ?`).all(e),n=new Map;for(let r of s)n.set(r.session_id,{parent_session_id:r.parent_session_id,source:r.source});return n}async function ra(e,t={}){let s=ag(e),n=t.windowHours??tg,r=t.scoreThreshold??Ts,o=t.useLivePids??!0,a=[],c=[];if(o&&s.decoded_path){let k=Gn(e,0),w=await ig(s.decoded_path,k);if(w===null){let L=ws()==="win32"?"Windows live-PID detection is not yet supported \u2014 falling back to the rolling mtime window.":"No live `claude` processes detected \u2014 falling back to the rolling mtime window. Output may include sessions that are no longer open.";a.push(L),c=Gn(e,n)}else w.size===0?(a.push(`No active terminals open in ${s.name} (cwd=${s.decoded_path}). Open a Claude terminal in this repo and re-run.`),c=[]):c=k.filter(D=>w.has(D.session_id))}else c=Gn(e,n);c.length===0&&!a.length&&a.push(`No active sessions in ${s.name} within the last ${n}h.`);let d=cg(e,s.name),u=new Set(d?d.edges.map(k=>k.session_id):[]),g=c.filter(k=>!u.has(k.session_id)),h=lg(c);h.sort((k,w)=>k.started_at_ms-w.started_at_ms);let b=ze(h,r),S=d?d.edges.filter(k=>k.source!=="auto-active"&&(k.parent_session_id||k.role==="origin")).map(k=>({session_id:k.session_id,parent_session_id:k.parent_session_id})):[],y=d?d.name:`${ta}${s.name}${sa}${na(t.todayIso)}`;return{project:s,thread:{id:d?.id??null,name:y,exists:!!d,existing_session_count:d?.edges.length??0},candidates:c,proposed_additions:g,proposed_edges:b,preserved_manual_edges:S,warnings:a}}function oa(e){let t={thread_id:"",added:0,edges_set:0,preserved_manual:e.preserved_manual_edges.length},s;e.thread.exists&&e.thread.id?s=e.thread.id:s=hs({name:e.thread.name,summary:`Auto-captured by sync-active on ${na()}. Members are sessions in ${e.project.name} that were active within the rolling window. Re-runnable: subsequent runs append new active sessions and never overwrite manual edges.`}).id,t.thread_id=s;let n=dg(s);for(let a of e.candidates)n.has(a.session_id)||(Es({threadId:s,sessionId:a.session_id,source:"auto-active",confidence:.5}),t.added++,n.set(a.session_id,{parent_session_id:null,source:"auto-active"}));for(let a of e.proposed_edges){let c=n.get(a.child_id);if(c&&c.source==="auto-active"&&c.parent_session_id!==a.parent_id&&n.has(a.parent_id))try{Nt(s,a.child_id,a.parent_id),t.edges_set++,n.set(a.child_id,{parent_session_id:a.parent_id,source:c.source})}catch{}}let o=f().prepare(`SELECT session_id FROM thread_edges
875
+ WHERE thread_id = ?`).all(e),n=new Map;for(let r of s)n.set(r.session_id,{parent_session_id:r.parent_session_id,source:r.source});return n}async function ra(e,t={}){let s=lg(e),n=t.windowHours??ng,r=t.scoreThreshold??Ts,o=t.useLivePids??!0,a=[],c=[];if(o&&s.decoded_path){let k=Gn(e,0),w=await cg(s.decoded_path,k);if(w===null){let L=ws()==="win32"?"Windows live-PID detection is not yet supported \u2014 falling back to the rolling mtime window.":"No live `claude` processes detected \u2014 falling back to the rolling mtime window. Output may include sessions that are no longer open.";a.push(L),c=Gn(e,n)}else w.size===0?(a.push(`No active terminals open in ${s.name} (cwd=${s.decoded_path}). Open a Claude terminal in this repo and re-run.`),c=[]):c=k.filter(D=>w.has(D.session_id))}else c=Gn(e,n);c.length===0&&!a.length&&a.push(`No active sessions in ${s.name} within the last ${n}h.`);let d=dg(e,s.name),u=new Set(d?d.edges.map(k=>k.session_id):[]),g=c.filter(k=>!u.has(k.session_id)),h=ug(c);h.sort((k,w)=>k.started_at_ms-w.started_at_ms);let b=ze(h,r),S=d?d.edges.filter(k=>k.source!=="auto-active"&&(k.parent_session_id||k.role==="origin")).map(k=>({session_id:k.session_id,parent_session_id:k.parent_session_id})):[],y=d?d.name:`${ta}${s.name}${sa}${na(t.todayIso)}`;return{project:s,thread:{id:d?.id??null,name:y,exists:!!d,existing_session_count:d?.edges.length??0},candidates:c,proposed_additions:g,proposed_edges:b,preserved_manual_edges:S,warnings:a}}function oa(e){let t={thread_id:"",added:0,edges_set:0,preserved_manual:e.preserved_manual_edges.length},s;e.thread.exists&&e.thread.id?s=e.thread.id:s=hs({name:e.thread.name,summary:`Auto-captured by sync-active on ${na()}. Members are sessions in ${e.project.name} that were active within the rolling window. Re-runnable: subsequent runs append new active sessions and never overwrite manual edges.`}).id,t.thread_id=s;let n=pg(s);for(let a of e.candidates)n.has(a.session_id)||(Es({threadId:s,sessionId:a.session_id,source:"auto-active",confidence:.5}),t.added++,n.set(a.session_id,{parent_session_id:null,source:"auto-active"}));for(let a of e.proposed_edges){let c=n.get(a.child_id);if(c&&c.source==="auto-active"&&c.parent_session_id!==a.parent_id&&n.has(a.parent_id))try{Nt(s,a.child_id,a.parent_id),t.edges_set++,n.set(a.child_id,{parent_session_id:a.parent_id,source:c.source})}catch{}}let o=f().prepare(`SELECT session_id FROM thread_edges
876
876
  WHERE thread_id = ?
877
877
  AND source = 'auto-active'
878
878
  AND parent_session_id IS NULL
879
- AND role = 'child'`).all(s);for(let a of o)try{Nt(s,a.session_id,null)}catch{}return t}H();Z();import{randomUUID as ug}from"node:crypto";import{writeFileSync as pg}from"node:fs";import{join as mg}from"node:path";var gg=mg($,"thread-folders.json");function ia(e){return{id:e.id,name:e.name,parent_folder_id:e.parent_folder_id,project_scope:e.project_scope,created_at:e.created_at,archived:e.archived===1,sort_order:e.sort_order}}function Ot(){try{J();let e=Kn({includeArchived:!0});pg(gg,JSON.stringify({folders:e},null,2))}catch{}}function Kn(e={}){let t=e.includeArchived?"":"WHERE archived = 0";return f().prepare(`SELECT * FROM thread_folders ${t} ORDER BY sort_order, name`).all().map(ia)}function $e(e){let t=f().prepare("SELECT * FROM thread_folders WHERE id = ?").get(e);return t?ia(t):null}function aa(e){let t=e.name.trim();if(!t)throw new Error("folder name cannot be empty");if(t.length>200)throw new Error("folder name too long (200 char max)");let s=e.parentFolderId??null,n=e.projectScope??null;if(s){let c=$e(s);if(!c)throw new Error(`parent folder ${s} not found`);n=c.project_scope}let r=ug(),o=new Date().toISOString(),a=ca(s,n);return f().prepare(`INSERT INTO thread_folders (id, name, parent_folder_id, project_scope, created_at, archived, sort_order)
879
+ AND role = 'child'`).all(s);for(let a of o)try{Nt(s,a.session_id,null)}catch{}return t}H();Z();import{randomUUID as mg}from"node:crypto";import{writeFileSync as gg}from"node:fs";import{join as _g}from"node:path";var fg=_g($,"thread-folders.json");function ia(e){return{id:e.id,name:e.name,parent_folder_id:e.parent_folder_id,project_scope:e.project_scope,created_at:e.created_at,archived:e.archived===1,sort_order:e.sort_order}}function Ot(){try{J();let e=Kn({includeArchived:!0});gg(fg,JSON.stringify({folders:e},null,2))}catch{}}function Kn(e={}){let t=e.includeArchived?"":"WHERE archived = 0";return f().prepare(`SELECT * FROM thread_folders ${t} ORDER BY sort_order, name`).all().map(ia)}function $e(e){let t=f().prepare("SELECT * FROM thread_folders WHERE id = ?").get(e);return t?ia(t):null}function aa(e){let t=e.name.trim();if(!t)throw new Error("folder name cannot be empty");if(t.length>200)throw new Error("folder name too long (200 char max)");let s=e.parentFolderId??null,n=e.projectScope??null;if(s){let c=$e(s);if(!c)throw new Error(`parent folder ${s} not found`);n=c.project_scope}let r=mg(),o=new Date().toISOString(),a=ca(s,n);return f().prepare(`INSERT INTO thread_folders (id, name, parent_folder_id, project_scope, created_at, archived, sort_order)
880
880
  VALUES (?, ?, ?, ?, ?, 0, ?)`).run(r,t,s,n,o,a),Ot(),{id:r,name:t,parent_folder_id:s,project_scope:n,created_at:o,archived:!1,sort_order:a}}function ca(e,t){return f().prepare(`SELECT COALESCE(MAX(sort_order), -100) + 100 AS next
881
881
  FROM thread_folders
882
882
  WHERE parent_folder_id IS ?
883
883
  AND project_scope IS ?`).get(e,t)?.next??0}function la(e,t){let s=t.trim();if(!s)throw new Error("folder name cannot be empty");if(s.length>200)throw new Error("folder name too long (200 char max)");let n=$e(e);if(!n)throw new Error(`folder ${e} not found`);return f().prepare("UPDATE thread_folders SET name = ? WHERE id = ?").run(s,e),Ot(),{...n,name:s}}function da(e,t){let s=$e(e);if(!s)throw new Error(`folder ${e} not found`);if(t===e)throw new Error("cannot move a folder under itself");let n=s.project_scope;if(t!==null){let o=$e(t);if(!o)throw new Error(`parent folder ${t} not found`);let a=o.parent_folder_id,c=0;for(;a!==null&&c<1024;){if(a===e)throw new Error("cannot move a folder into one of its own descendants (cycle)");let d=$e(a);if(!d)break;a=d.parent_folder_id,c++}n=o.project_scope}let r=ca(t,n);return f().prepare("UPDATE thread_folders SET parent_folder_id = ?, project_scope = ?, sort_order = ? WHERE id = ?").run(t,n,r,e),Ot(),{...s,parent_folder_id:t,project_scope:n,sort_order:r}}function ua(e,t,s){if(!Array.isArray(s)||s.length===0)throw new Error("ordered_ids must be a non-empty array");let n=new Set;for(let u of s){if(typeof u!="string"||!u)throw new Error("ordered_ids must contain non-empty strings");if(n.has(u))throw new Error(`duplicate id in ordered_ids: ${u}`);n.add(u)}let r=f(),o=r.prepare(`SELECT id FROM thread_folders
884
884
  WHERE parent_folder_id IS ?
885
- AND project_scope IS ?`).all(e,t),a=new Set(o.map(u=>u.id));if(a.size!==s.length)throw new Error(`ordered_ids length ${s.length} does not match sibling count ${a.size}`);for(let u of s)if(!a.has(u))throw new Error(`folder ${u} is not in the named sibling bucket`);let c=r.prepare("UPDATE thread_folders SET sort_order = ? WHERE id = ?");r.transaction(u=>{u.forEach((g,h)=>c.run(h*100,g))})(s),Ot()}function pa(e){if(!$e(e))throw new Error(`folder ${e} not found`);f().prepare("DELETE FROM thread_folders WHERE id = ?").run(e),Ot()}function ma(e,t){if(t!==null&&!$e(t))throw new Error(`folder ${t} not found`);if(f().prepare("UPDATE threads SET folder_id = ? WHERE id = ?").run(t,e).changes===0)throw new Error(`thread ${e} not found`)}H();Z();import{writeFileSync as ga,readFileSync as Yw,existsSync as _a,mkdirSync as fa,readdirSync as Kw}from"node:fs";import{join as Rs}from"node:path";var _g=new Set(["citation","similar","skill_track","bug_pattern","wiki_link","temporal_proximity"]),ha=new Set(["regex","llm","embedding","manual","auto","citation","git","terminal-registry"]),fg=new Set(["pending","approved","rejected"]),hg=new Set(["L1","L2","L3","L4","user"]),zn=Rs($,"links"),Vn=Rs($,"suggestions"),Eg=Rs(Vn,"index.json");function bg(){J(),_a(zn)||fa(zn,{recursive:!0})}function Sg(){J(),_a(Vn)||fa(Vn,{recursive:!0})}function Ea(e){try{return JSON.parse(e)}catch{return e}}function ks(e){return{id:e.id,source_session_id:e.source_session_id,target_session_id:e.target_session_id,link_type:e.link_type,confidence:e.confidence,source:e.source,evidence:Ea(e.evidence),approved:e.approved===1,created_at:e.created_at,updated_at:e.updated_at}}function Zn(e){return{id:e.id,source_session_id:e.source_session_id,target_session_id:e.target_session_id,link_type:e.link_type,confidence:e.confidence,evidence:Ea(e.evidence),status:e.status,inferred_by:e.inferred_by,created_at:e.created_at,decided_at:e.decided_at}}function ba(e){if(!Number.isFinite(e)||e<0||e>1)throw new Error("confidence must be a number in [0, 1]")}function Qn(e){if(!_g.has(e))throw new Error(`invalid link_type: ${e}`)}function Tg(e){if(!ha.has(e))throw new Error(`invalid source: ${e}`)}function Sa(e){if(!hg.has(e))throw new Error(`invalid inferred_by: ${e}`)}function Ta(e,t){if(!e||!t)throw new Error("source_session_id and target_session_id are required");if(e===t)throw new Error("a session cannot link to itself")}function ya(e){Ta(e.source_session_id,e.target_session_id),Qn(e.link_type),Tg(e.source),ba(e.confidence);let t=f(),s=new Date().toISOString(),n=JSON.stringify(e.evidence??null),r=e.approved?1:0;t.prepare(`INSERT INTO session_links
885
+ AND project_scope IS ?`).all(e,t),a=new Set(o.map(u=>u.id));if(a.size!==s.length)throw new Error(`ordered_ids length ${s.length} does not match sibling count ${a.size}`);for(let u of s)if(!a.has(u))throw new Error(`folder ${u} is not in the named sibling bucket`);let c=r.prepare("UPDATE thread_folders SET sort_order = ? WHERE id = ?");r.transaction(u=>{u.forEach((g,h)=>c.run(h*100,g))})(s),Ot()}function pa(e){if(!$e(e))throw new Error(`folder ${e} not found`);f().prepare("DELETE FROM thread_folders WHERE id = ?").run(e),Ot()}function ma(e,t){if(t!==null&&!$e(t))throw new Error(`folder ${t} not found`);if(f().prepare("UPDATE threads SET folder_id = ? WHERE id = ?").run(t,e).changes===0)throw new Error(`thread ${e} not found`)}H();Z();import{writeFileSync as ga,readFileSync as zw,existsSync as _a,mkdirSync as fa,readdirSync as Vw}from"node:fs";import{join as Rs}from"node:path";var hg=new Set(["citation","similar","skill_track","bug_pattern","wiki_link","temporal_proximity"]),ha=new Set(["regex","llm","embedding","manual","auto","citation","git","terminal-registry"]),Eg=new Set(["pending","approved","rejected"]),bg=new Set(["L1","L2","L3","L4","user"]),zn=Rs($,"links"),Vn=Rs($,"suggestions"),Sg=Rs(Vn,"index.json");function Tg(){J(),_a(zn)||fa(zn,{recursive:!0})}function yg(){J(),_a(Vn)||fa(Vn,{recursive:!0})}function Ea(e){try{return JSON.parse(e)}catch{return e}}function ks(e){return{id:e.id,source_session_id:e.source_session_id,target_session_id:e.target_session_id,link_type:e.link_type,confidence:e.confidence,source:e.source,evidence:Ea(e.evidence),approved:e.approved===1,created_at:e.created_at,updated_at:e.updated_at}}function Zn(e){return{id:e.id,source_session_id:e.source_session_id,target_session_id:e.target_session_id,link_type:e.link_type,confidence:e.confidence,evidence:Ea(e.evidence),status:e.status,inferred_by:e.inferred_by,created_at:e.created_at,decided_at:e.decided_at}}function ba(e){if(!Number.isFinite(e)||e<0||e>1)throw new Error("confidence must be a number in [0, 1]")}function Qn(e){if(!hg.has(e))throw new Error(`invalid link_type: ${e}`)}function wg(e){if(!ha.has(e))throw new Error(`invalid source: ${e}`)}function Sa(e){if(!bg.has(e))throw new Error(`invalid inferred_by: ${e}`)}function Ta(e,t){if(!e||!t)throw new Error("source_session_id and target_session_id are required");if(e===t)throw new Error("a session cannot link to itself")}function ya(e){Ta(e.source_session_id,e.target_session_id),Qn(e.link_type),wg(e.source),ba(e.confidence);let t=f(),s=new Date().toISOString(),n=JSON.stringify(e.evidence??null),r=e.approved?1:0;t.prepare(`INSERT INTO session_links
886
886
  (source_session_id, target_session_id, link_type,
887
887
  confidence, source, evidence, approved,
888
888
  created_at, updated_at)
@@ -919,7 +919,7 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
919
919
  WHERE source_session_id = ?
920
920
  AND target_session_id = ?
921
921
  AND link_type = ?
922
- AND inferred_by = ?`).get(e.source_session_id,e.target_session_id,e.link_type,e.inferred_by);if(!r)throw new Error("createSuggestion succeeded but read-back failed");return Ra(),Zn(r)}function Ve(e={}){let t=f(),s=[],n=[];if(e.status){if(!fg.has(e.status))throw new Error(`invalid status: ${e.status}`);s.push("status = ?"),n.push(e.status)}e.sourceSessionId&&(s.push("source_session_id = ?"),n.push(e.sourceSessionId)),e.targetSessionId&&(s.push("target_session_id = ?"),n.push(e.targetSessionId)),e.inferredBy&&(Sa(e.inferredBy),s.push("inferred_by = ?"),n.push(e.inferredBy));let r=s.length?`WHERE ${s.join(" AND ")}`:"",o=Math.max(1,Math.min(5e3,e.limit??1e3));return t.prepare(`SELECT * FROM session_link_suggestions ${r}
922
+ AND inferred_by = ?`).get(e.source_session_id,e.target_session_id,e.link_type,e.inferred_by);if(!r)throw new Error("createSuggestion succeeded but read-back failed");return Ra(),Zn(r)}function Ve(e={}){let t=f(),s=[],n=[];if(e.status){if(!Eg.has(e.status))throw new Error(`invalid status: ${e.status}`);s.push("status = ?"),n.push(e.status)}e.sourceSessionId&&(s.push("source_session_id = ?"),n.push(e.sourceSessionId)),e.targetSessionId&&(s.push("target_session_id = ?"),n.push(e.targetSessionId)),e.inferredBy&&(Sa(e.inferredBy),s.push("inferred_by = ?"),n.push(e.inferredBy));let r=s.length?`WHERE ${s.join(" AND ")}`:"",o=Math.max(1,Math.min(5e3,e.limit??1e3));return t.prepare(`SELECT * FROM session_link_suggestions ${r}
923
923
  ORDER BY confidence DESC, created_at DESC
924
924
  LIMIT ?`).all(...n,o).map(Zn)}function er(e,t,s={}){if(t!=="approved"&&t!=="rejected")throw new Error(`invalid decision: ${t}`);let n=s.source??"manual";if(!ha.has(n))throw new Error(`invalid source: ${n}`);let r=f(),o=r.prepare("SELECT * FROM session_link_suggestions WHERE id = ?").get(e);if(!o)throw new Error(`suggestion ${e} not found`);if(o.status!=="pending")throw new Error(`suggestion ${e} already decided as ${o.status}`);let a=new Date().toISOString(),c;r.transaction(()=>{r.prepare(`UPDATE session_link_suggestions
925
925
  SET status = ?, decided_at = ?
@@ -936,7 +936,7 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
936
936
  updated_at = excluded.updated_at`).run(o.source_session_id,o.target_session_id,o.link_type,o.confidence,n,o.evidence,a,a),c=r.prepare(`SELECT * FROM session_links
937
937
  WHERE source_session_id = ?
938
938
  AND target_session_id = ?
939
- AND link_type = ?`).get(o.source_session_id,o.target_session_id,o.link_type))})(),Ra(),t==="approved"&&tr(o.source_session_id);let d=r.prepare("SELECT * FROM session_link_suggestions WHERE id = ?").get(e);return{suggestion:Zn(d),link:c?ks(c):null}}function tr(e){try{bg();let t=As({sourceSessionId:e}),s=Rs(zn,`${e}.json`);if(t.length===0)return;let n={schema:"claude-recall.session-links.v1",source_session_id:e,backed_up_at:new Date().toISOString(),links:t};ga(s,JSON.stringify(n,null,2))}catch(t){console.error("[session-links] backup failed:",t)}}function Ra(){try{Sg();let e=Ve({limit:5e3}),t={schema:"claude-recall.session-link-suggestions.v1",backed_up_at:new Date().toISOString(),suggestions:e};ga(Eg,JSON.stringify(t,null,2))}catch(e){console.error("[session-links] suggestions backup failed:",e)}}function ka(e,t){let s=new Set,n=[];for(let r of t){if(s.has(r.id))continue;let o=null,a="";if(r.source_session_id===e)o="outbound",a=r.target_session_id;else if(r.target_session_id===e)o="inbound",a=r.source_session_id;else continue;s.add(r.id),n.push({linkId:r.id,otherSessionId:a,direction:o,updatedAt:r.updated_at,link:r})}return n.sort((r,o)=>r.updatedAt<o.updatedAt?1:r.updatedAt>o.updatedAt?-1:0),n}H();Z();import{writeFileSync as yg,readFileSync as s0,existsSync as wg,mkdirSync as Rg,readdirSync as n0}from"node:fs";import{join as Aa}from"node:path";var sr=Aa($,"output-index");function kg(){J(),wg(sr)||Rg(sr,{recursive:!0})}function It(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function Ag(e){if(!e)return null;try{return JSON.parse(e)}catch{return e}}function xa(e){return{session_id:e.session_id,files_written:It(e.files_written),brands_mentioned:It(e.brands_mentioned),terms_introduced:It(e.terms_introduced),plan_ids_referenced:It(e.plan_ids_referenced),bug_signatures:It(e.bug_signatures),raw_extraction:Ag(e.raw_extraction),extracted_at:e.extracted_at,extractor_version:e.extractor_version}}function Na(e){if(!e.session_id)throw new Error("session_id is required");let t=f(),s=new Date().toISOString(),n=JSON.stringify(e.files_written??[]),r=JSON.stringify(e.brands_mentioned??[]),o=JSON.stringify(e.terms_introduced??[]),a=JSON.stringify(e.plan_ids_referenced??[]),c=JSON.stringify(e.bug_signatures??[]),d=e.raw_extraction===void 0?null:JSON.stringify(e.raw_extraction),u=Math.max(1,Math.floor(e.extractor_version??1));t.prepare(`INSERT INTO session_output_index
939
+ AND link_type = ?`).get(o.source_session_id,o.target_session_id,o.link_type))})(),Ra(),t==="approved"&&tr(o.source_session_id);let d=r.prepare("SELECT * FROM session_link_suggestions WHERE id = ?").get(e);return{suggestion:Zn(d),link:c?ks(c):null}}function tr(e){try{Tg();let t=As({sourceSessionId:e}),s=Rs(zn,`${e}.json`);if(t.length===0)return;let n={schema:"claude-recall.session-links.v1",source_session_id:e,backed_up_at:new Date().toISOString(),links:t};ga(s,JSON.stringify(n,null,2))}catch(t){console.error("[session-links] backup failed:",t)}}function Ra(){try{yg();let e=Ve({limit:5e3}),t={schema:"claude-recall.session-link-suggestions.v1",backed_up_at:new Date().toISOString(),suggestions:e};ga(Sg,JSON.stringify(t,null,2))}catch(e){console.error("[session-links] suggestions backup failed:",e)}}function ka(e,t){let s=new Set,n=[];for(let r of t){if(s.has(r.id))continue;let o=null,a="";if(r.source_session_id===e)o="outbound",a=r.target_session_id;else if(r.target_session_id===e)o="inbound",a=r.source_session_id;else continue;s.add(r.id),n.push({linkId:r.id,otherSessionId:a,direction:o,updatedAt:r.updated_at,link:r})}return n.sort((r,o)=>r.updatedAt<o.updatedAt?1:r.updatedAt>o.updatedAt?-1:0),n}H();Z();import{writeFileSync as Rg,readFileSync as r0,existsSync as kg,mkdirSync as Ag,readdirSync as o0}from"node:fs";import{join as Aa}from"node:path";var sr=Aa($,"output-index");function xg(){J(),kg(sr)||Ag(sr,{recursive:!0})}function It(e){if(!e)return[];try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function Ng(e){if(!e)return null;try{return JSON.parse(e)}catch{return e}}function xa(e){return{session_id:e.session_id,files_written:It(e.files_written),brands_mentioned:It(e.brands_mentioned),terms_introduced:It(e.terms_introduced),plan_ids_referenced:It(e.plan_ids_referenced),bug_signatures:It(e.bug_signatures),raw_extraction:Ng(e.raw_extraction),extracted_at:e.extracted_at,extractor_version:e.extractor_version}}function Na(e){if(!e.session_id)throw new Error("session_id is required");let t=f(),s=new Date().toISOString(),n=JSON.stringify(e.files_written??[]),r=JSON.stringify(e.brands_mentioned??[]),o=JSON.stringify(e.terms_introduced??[]),a=JSON.stringify(e.plan_ids_referenced??[]),c=JSON.stringify(e.bug_signatures??[]),d=e.raw_extraction===void 0?null:JSON.stringify(e.raw_extraction),u=Math.max(1,Math.floor(e.extractor_version??1));t.prepare(`INSERT INTO session_output_index
940
940
  (session_id, files_written, brands_mentioned, terms_introduced,
941
941
  plan_ids_referenced, bug_signatures, raw_extraction,
942
942
  extracted_at, extractor_version)
@@ -949,7 +949,7 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
949
949
  bug_signatures = excluded.bug_signatures,
950
950
  raw_extraction = excluded.raw_extraction,
951
951
  extracted_at = excluded.extracted_at,
952
- extractor_version = excluded.extractor_version`).run(e.session_id,n,r,o,a,c,d,s,u);let g=t.prepare("SELECT * FROM session_output_index WHERE session_id = ?").get(e.session_id);if(!g)throw new Error("setOutputIndex succeeded but read-back failed");let h=xa(g);return xg(e.session_id),h}function Be(e){let s=f().prepare("SELECT * FROM session_output_index WHERE session_id = ?").get(e);return s?xa(s):null}function xg(e){try{kg();let t=Be(e);if(!t)return;let s=Aa(sr,`${e}.json`),n={schema:"claude-recall.session-output-index.v1",backed_up_at:new Date().toISOString(),...t};yg(s,JSON.stringify(n,null,2))}catch(t){console.error("[output-index] backup failed:",t)}}H();var Ng=4e3,Og=2,Lg=30,Cg=.2,Ig={citation:1,wiki_link:.9,similar:.7,skill_track:.5,bug_pattern:.4,temporal_proximity:.3};function xs(e){return e?Math.ceil(e.length/4):0}function Oa(e){if(!Number.isFinite(e)||e<0)return 1;let t=Math.exp(-e/Lg);return Math.max(Cg,t)}function La(e,t){if(!e||!t)return 0;let s=Date.parse(e),n=Date.parse(t);return!Number.isFinite(s)||!Number.isFinite(n)?0:Math.abs(n-s)/(1e3*60*60*24)}function Ca(e){return f().prepare(`SELECT s.id,
952
+ extractor_version = excluded.extractor_version`).run(e.session_id,n,r,o,a,c,d,s,u);let g=t.prepare("SELECT * FROM session_output_index WHERE session_id = ?").get(e.session_id);if(!g)throw new Error("setOutputIndex succeeded but read-back failed");let h=xa(g);return Og(e.session_id),h}function Be(e){let s=f().prepare("SELECT * FROM session_output_index WHERE session_id = ?").get(e);return s?xa(s):null}function Og(e){try{xg();let t=Be(e);if(!t)return;let s=Aa(sr,`${e}.json`),n={schema:"claude-recall.session-output-index.v1",backed_up_at:new Date().toISOString(),...t};Rg(s,JSON.stringify(n,null,2))}catch(t){console.error("[output-index] backup failed:",t)}}H();var Lg=4e3,Cg=2,Ig=30,vg=.2,jg={citation:1,wiki_link:.9,similar:.7,skill_track:.5,bug_pattern:.4,temporal_proximity:.3};function xs(e){return e?Math.ceil(e.length/4):0}function Oa(e){if(!Number.isFinite(e)||e<0)return 1;let t=Math.exp(-e/Ig);return Math.max(vg,t)}function La(e,t){if(!e||!t)return 0;let s=Date.parse(e),n=Date.parse(t);return!Number.isFinite(s)||!Number.isFinite(n)?0:Math.abs(n-s)/(1e3*60*60*24)}function Ca(e){return f().prepare(`SELECT s.id,
953
953
  NULLIF(sa.alias, '') AS alias,
954
954
  s.auto_title,
955
955
  s.auto_title_source,
@@ -960,18 +960,18 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
960
960
  FROM sessions s
961
961
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
962
962
  LEFT JOIN projects p ON p.id = s.project_id
963
- WHERE s.id = ?`).get(e)??null}function Ia(e){let s=f().prepare("SELECT summary FROM session_semantic WHERE session_id = ?").get(e);if(!s||!s.summary)return null;let n=s.summary.trim();return n.length>0?n:null}function va(e){let t=e.alias?.trim(),s=e.auto_title?.trim(),n=e.first_user_message?.trim();return s&&e.auto_title_source==="agent"?s:t||s||(n?n.slice(0,80):e.id.slice(0,8))}function vg(e){let s=f().prepare(`SELECT id, auto_title, started_at
963
+ WHERE s.id = ?`).get(e)??null}function Ia(e){let s=f().prepare("SELECT summary FROM session_semantic WHERE session_id = ?").get(e);if(!s||!s.summary)return null;let n=s.summary.trim();return n.length>0?n:null}function va(e){let t=e.alias?.trim(),s=e.auto_title?.trim(),n=e.first_user_message?.trim();return s&&e.auto_title_source==="agent"?s:t||s||(n?n.slice(0,80):e.id.slice(0,8))}function Mg(e){let s=f().prepare(`SELECT id, auto_title, started_at
964
964
  FROM sessions
965
965
  WHERE project_id = ?
966
- ORDER BY COALESCE(started_at, ''), id`).all(e),n=new Set,r=new Set,o=[];for(let b of s){if(!b.auto_title||!b.auto_title.startsWith("/")){o.push({id:b.id,brand:null,skill:null});continue}let S=b.auto_title.split(" \xB7 "),y=S[0].trim(),k=S.length>1?S.slice(1).join(" \xB7 ").trim():null;o.push({id:b.id,brand:k||null,skill:y||null}),k&&n.add(k),y&&r.add(y)}let a=[...n].sort(),c=new Map;a.forEach((b,S)=>c.set(b,S));let d=[...r].sort(),u=new Map;d.forEach((b,S)=>u.set(b,S));let g=new Map,h=new Map;for(let b of o){if(!b.brand||!b.skill)continue;let S=c.get(b.brand),y=u.get(b.skill);if(S===void 0||y===void 0)continue;let k=`${S}.${y}`,w=(g.get(k)??0)+1;g.set(k,w),h.set(b.id,`${S}.${y}.${w}`)}return{byId:h}}function jg(e){return{table:e!==null?vg(e):null,originProjectId:e,cache:new Map}}function Ns(e,t){let s=e.cache.get(t);if(s)return s;let n=Ca(t);if(!n)return null;let r=e.table&&n.project_id===e.originProjectId?e.table.byId.get(t)??null:null,o={session_id:n.id,title:va(n),decimal:r,summary:Ia(n.id),project:n.project,started_at:n.started_at};return e.cache.set(t,o),o}function Mg(e,t){let n=f().prepare(`SELECT DISTINCT te.parent_session_id AS pid
966
+ ORDER BY COALESCE(started_at, ''), id`).all(e),n=new Set,r=new Set,o=[];for(let b of s){if(!b.auto_title||!b.auto_title.startsWith("/")){o.push({id:b.id,brand:null,skill:null});continue}let S=b.auto_title.split(" \xB7 "),y=S[0].trim(),k=S.length>1?S.slice(1).join(" \xB7 ").trim():null;o.push({id:b.id,brand:k||null,skill:y||null}),k&&n.add(k),y&&r.add(y)}let a=[...n].sort(),c=new Map;a.forEach((b,S)=>c.set(b,S));let d=[...r].sort(),u=new Map;d.forEach((b,S)=>u.set(b,S));let g=new Map,h=new Map;for(let b of o){if(!b.brand||!b.skill)continue;let S=c.get(b.brand),y=u.get(b.skill);if(S===void 0||y===void 0)continue;let k=`${S}.${y}`,w=(g.get(k)??0)+1;g.set(k,w),h.set(b.id,`${S}.${y}.${w}`)}return{byId:h}}function Dg(e){return{table:e!==null?Mg(e):null,originProjectId:e,cache:new Map}}function Ns(e,t){let s=e.cache.get(t);if(s)return s;let n=Ca(t);if(!n)return null;let r=e.table&&n.project_id===e.originProjectId?e.table.byId.get(t)??null:null,o={session_id:n.id,title:va(n),decimal:r,summary:Ia(n.id),project:n.project,started_at:n.started_at};return e.cache.set(t,o),o}function Fg(e,t){let n=f().prepare(`SELECT DISTINCT te.parent_session_id AS pid
967
967
  FROM thread_edges te
968
968
  WHERE te.session_id = ?
969
- AND te.parent_session_id IS NOT NULL`).all(t),r=[];for(let o of n){if(!o.pid)continue;let a=Ns(e,o.pid);a&&r.push(a)}return r}function Dg(e,t){let n=f().prepare(`SELECT DISTINCT te.session_id AS sid
969
+ AND te.parent_session_id IS NOT NULL`).all(t),r=[];for(let o of n){if(!o.pid)continue;let a=Ns(e,o.pid);a&&r.push(a)}return r}function Pg(e,t){let n=f().prepare(`SELECT DISTINCT te.session_id AS sid
970
970
  FROM thread_edges te
971
- WHERE te.parent_session_id = ?`).all(t),r=[];for(let o of n){if(!o.sid)continue;let a=Ns(e,o.sid);a&&r.push(a)}return r}function ja(e){let t=Ig[e.linkType]??.5,s=Ze(e.confidence),n=t*s,r=Oa(e.daysApart),o=e.embeddingCosine??.5,a=Ze(e.pagerank);if(e.scoring==="pagerank")return Ze(a);if(e.scoring==="embedding-rerank")return e.embeddingCosine===null?Ze(n):Ze(o);let c=.35*n+.2*r+.2*o+.25*a;return Ze(c)}function Ze(e){return!Number.isFinite(e)||e<0?0:e>1?1:e}function Fg(e,t,s,n,r){let o=new Map;function a(c,d){if(c===d)return;let u=o.get(c);u||(u=new Set,o.set(c,u)),u.add(d)}for(let c of t)a(c.source_session_id,c.target_session_id),a(c.target_session_id,c.source_session_id);for(let c of s)a(e,c.session_id);for(let c of s)a(c.session_id,e);for(let c of n)a(e,c.session_id);for(let c of n)a(c.session_id,e);if(r>1){let c=new Set([e]),d=new Set([e]);for(let u=1;u<r;u++){let g=new Set;for(let h of c){let b=o.get(h);if(b)for(let S of b){if(d.has(S))continue;let y=Lt(S).filter(k=>k.approved);for(let k of y)a(k.source_session_id,k.target_session_id),a(k.target_session_id,k.source_session_id);d.add(S),g.add(S)}}if(g.size===0)break;for(let h of g)c.add(h)}}return{edges:o}}function Pg(e,t={}){let s=t.iterations??12,n=t.damping??.85,r=Array.from(e.edges.keys());if(r.length===0)return new Map;let o=1/r.length,a=new Map(r.map(u=>[u,o]));for(let u=0;u<s;u++){let g=new Map(r.map(h=>[h,(1-n)/r.length]));for(let h of r){let b=e.edges.get(h);if(!b||b.size===0)continue;let S=(a.get(h)??0)/b.size;for(let y of b)g.set(y,(g.get(y)??0)+n*S)}a=g}let c=0;for(let u of a.values())u>c&&(c=u);if(c<=0)return a;let d=new Map;for(let[u,g]of a)d.set(u,g/c);return d}var Ma=240;function Da(e,t){let s=e.replace(/\s+/g," ").trim();return s.length<=t?s:`${s.slice(0,t-1).trimEnd()}\u2026`}function Ug(e){let t=e.decimal?`${e.decimal} `:"",s=e.session_id.slice(0,8),n="evidence"in e&&e.evidence?` \u2014 ${e.evidence}`:"",r=`- ${t}${e.title} (${s})${n}`;if(e.summary){let o=Da(e.summary,Ma);return`${r}
972
- ${o}`}return r}function $g(e,t,s){let n=[],r=[],o=0,a=e.decimal?`${e.decimal}: `:"",c=`# Neighborhood for ${e.session_id} (${a}${e.title})`;if(n.push(c),o+=xs(c),e.summary){let d=Da(e.summary,Ma*4);n.push(d),o+=xs(d)}n.push("");for(let d of t){if(d.refs.length===0)continue;let u=`## ${d.heading}`,g=xs(u),h=[],b=0;for(let S of d.refs){let y=Ug(S),k=xs(y);if(o+g+b+k>s){r.push({session_id:S.session_id,title:S.title,decimal:S.decimal,summary:S.summary,project:S.project,started_at:S.started_at});continue}h.push(y),b+=k}if(h.length>0){n.push(u);for(let S of h)n.push(S);n.push(""),o+=g+b}}for(;n.length>0&&n[n.length-1]==="";)n.pop();return{bundle:n.join(`
971
+ WHERE te.parent_session_id = ?`).all(t),r=[];for(let o of n){if(!o.sid)continue;let a=Ns(e,o.sid);a&&r.push(a)}return r}function ja(e){let t=jg[e.linkType]??.5,s=Ze(e.confidence),n=t*s,r=Oa(e.daysApart),o=e.embeddingCosine??.5,a=Ze(e.pagerank);if(e.scoring==="pagerank")return Ze(a);if(e.scoring==="embedding-rerank")return e.embeddingCosine===null?Ze(n):Ze(o);let c=.35*n+.2*r+.2*o+.25*a;return Ze(c)}function Ze(e){return!Number.isFinite(e)||e<0?0:e>1?1:e}function Ug(e,t,s,n,r){let o=new Map;function a(c,d){if(c===d)return;let u=o.get(c);u||(u=new Set,o.set(c,u)),u.add(d)}for(let c of t)a(c.source_session_id,c.target_session_id),a(c.target_session_id,c.source_session_id);for(let c of s)a(e,c.session_id);for(let c of s)a(c.session_id,e);for(let c of n)a(e,c.session_id);for(let c of n)a(c.session_id,e);if(r>1){let c=new Set([e]),d=new Set([e]);for(let u=1;u<r;u++){let g=new Set;for(let h of c){let b=o.get(h);if(b)for(let S of b){if(d.has(S))continue;let y=Lt(S).filter(k=>k.approved);for(let k of y)a(k.source_session_id,k.target_session_id),a(k.target_session_id,k.source_session_id);d.add(S),g.add(S)}}if(g.size===0)break;for(let h of g)c.add(h)}}return{edges:o}}function $g(e,t={}){let s=t.iterations??12,n=t.damping??.85,r=Array.from(e.edges.keys());if(r.length===0)return new Map;let o=1/r.length,a=new Map(r.map(u=>[u,o]));for(let u=0;u<s;u++){let g=new Map(r.map(h=>[h,(1-n)/r.length]));for(let h of r){let b=e.edges.get(h);if(!b||b.size===0)continue;let S=(a.get(h)??0)/b.size;for(let y of b)g.set(y,(g.get(y)??0)+n*S)}a=g}let c=0;for(let u of a.values())u>c&&(c=u);if(c<=0)return a;let d=new Map;for(let[u,g]of a)d.set(u,g/c);return d}var Ma=240;function Da(e,t){let s=e.replace(/\s+/g," ").trim();return s.length<=t?s:`${s.slice(0,t-1).trimEnd()}\u2026`}function Bg(e){let t=e.decimal?`${e.decimal} `:"",s=e.session_id.slice(0,8),n="evidence"in e&&e.evidence?` \u2014 ${e.evidence}`:"",r=`- ${t}${e.title} (${s})${n}`;if(e.summary){let o=Da(e.summary,Ma);return`${r}
972
+ ${o}`}return r}function Hg(e,t,s){let n=[],r=[],o=0,a=e.decimal?`${e.decimal}: `:"",c=`# Neighborhood for ${e.session_id} (${a}${e.title})`;if(n.push(c),o+=xs(c),e.summary){let d=Da(e.summary,Ma*4);n.push(d),o+=xs(d)}n.push("");for(let d of t){if(d.refs.length===0)continue;let u=`## ${d.heading}`,g=xs(u),h=[],b=0;for(let S of d.refs){let y=Bg(S),k=xs(y);if(o+g+b+k>s){r.push({session_id:S.session_id,title:S.title,decimal:S.decimal,summary:S.summary,project:S.project,started_at:S.started_at});continue}h.push(y),b+=k}if(h.length>0){n.push(u);for(let S of h)n.push(S);n.push(""),o+=g+b}}for(;n.length>0&&n[n.length-1]==="";)n.pop();return{bundle:n.join(`
973
973
  `)+`
974
- `,budgetUsed:o,truncated:r}}function Bg(e,t,s,n,r,o){let a=[];for(let c of s){if(n&&!n.has(c.link_type))continue;let d=null;if(c.source_session_id===t.session_id?d=c.target_session_id:c.target_session_id===t.session_id&&(d=c.source_session_id),!d)continue;let u=Ns(e,d);if(!u)continue;let g=La(t.started_at,u.started_at),h=ja({confidence:c.confidence,linkType:c.link_type,daysApart:g,embeddingCosine:null,pagerank:o.get(d)??0,scoring:r});a.push({...u,score:h,evidence:`(suggestion, ${c.inferred_by}) confidence=${c.confidence.toFixed(2)} ${Math.round(g)}d apart`,link_type:c.link_type})}return a}function Os(e,t={}){let s=Math.max(100,Math.floor(t.budget??Ng)),n=t.scoring??"hybrid",r=Math.max(1,Math.min(5,t.maxDepth??Og)),o=t.includeWikiLinks??!0,a=t.includeSuggestions??!1,c=t.edgeTypes?new Set(t.edgeTypes):null,d=Ca(e);if(!d)throw new Error(`session not found: ${e}`);let u=jg(d.project_id),g={session_id:d.id,title:va(d),decimal:u.table?.byId.get(d.id)??null,summary:Ia(d.id),project:d.project,started_at:d.started_at};u.cache.set(d.id,g);let h=Mg(u,e),b=Dg(u,e),S=Lt(e).filter(i=>i.approved).filter(i=>!c||c.has(i.link_type)).filter(i=>o||i.link_type!=="wiki_link"),y=Fg(e,S,h,b,r),k=Pg(y),w=[],D=[],L=[],X=[];for(let i of S){let l=i.source_session_id===e?i.target_session_id:i.source_session_id,p=Ns(u,l);if(!p)continue;let m=La(g.started_at,p.started_at),_=ja({confidence:i.confidence,linkType:i.link_type,daysApart:m,embeddingCosine:null,pagerank:k.get(l)??0,scoring:n}),E=Oa(m),T=`${i.link_type} confidence=${i.confidence.toFixed(2)} recency=${E.toFixed(2)} (${Math.round(m)}d apart)`,R={...p,score:_,evidence:T,link_type:i.link_type};i.link_type==="citation"?w.push(R):i.link_type==="similar"?D.push(R):i.link_type==="wiki_link"?X.push(R):L.push(R)}if(a){let i=Ve({sourceSessionId:e,status:"pending",limit:100}),l=Ve({targetSessionId:e,status:"pending",limit:100}),p=[...i,...l],m=new Set,_=p.filter(T=>m.has(T.id)?!1:(m.add(T.id),!0)),E=Bg(u,g,_,c,n,k);for(let T of E)T.link_type==="citation"?w.push(T):T.link_type==="similar"?D.push(T):T.link_type==="wiki_link"?X.push(T):L.push(T)}let M=(i,l)=>l.score-i.score;w.sort(M),D.sort(M),L.sort(M),X.sort(M);let se=$g(g,[{heading:"Parents",refs:h},{heading:"Children",refs:b},{heading:"Citations (approved)",refs:w},{heading:"Similar sessions",refs:D},{heading:"Cousins (skill track + temporal)",refs:L},{heading:"Wiki links (manual)",refs:X}],s);return{origin:g,parents:h,children:b,citations:w,similar:D,cousins:L,wikiLinks:X,bundle:se.bundle,budgetUsed:se.budgetUsed,budgetRemaining:Math.max(0,s-se.budgetUsed),truncated:se.truncated}}H();Z();import{writeFileSync as Hg,readFileSync as p0,existsSync as Wg,mkdirSync as qg,readdirSync as m0,unlinkSync as g0}from"node:fs";import{join as Fa}from"node:path";import{randomUUID as Pa}from"node:crypto";var nr=Fa($,"bug-patterns");function Jg(){J(),Wg(nr)||qg(nr,{recursive:!0})}function Oe(e){return{id:e.id,signature_hash:e.signature_hash,example_message:e.example_message,occurrence_count:e.occurrence_count,first_seen_at:e.first_seen_at,last_seen_at:e.last_seen_at,resolved_in_session_id:e.resolved_in_session_id,fix_summary:e.fix_summary}}function Ua(e){return{cluster_id:e.cluster_id,session_id:e.session_id,matched_at:e.matched_at}}function $a(e){if(!e.signature_hash)throw new Error("signature_hash is required");if(!e.example_message)throw new Error("example_message is required");if(!Array.isArray(e.member_session_ids)||e.member_session_ids.length===0)throw new Error("at least one member_session_id is required");let t=f(),s=new Date().toISOString(),n=e.id??Pa(),r=e.first_seen_at??s,o=e.last_seen_at??s,a=Array.from(new Set(e.member_session_ids));t.transaction(()=>{t.prepare(`INSERT INTO bug_pattern_clusters
974
+ `,budgetUsed:o,truncated:r}}function Wg(e,t,s,n,r,o){let a=[];for(let c of s){if(n&&!n.has(c.link_type))continue;let d=null;if(c.source_session_id===t.session_id?d=c.target_session_id:c.target_session_id===t.session_id&&(d=c.source_session_id),!d)continue;let u=Ns(e,d);if(!u)continue;let g=La(t.started_at,u.started_at),h=ja({confidence:c.confidence,linkType:c.link_type,daysApart:g,embeddingCosine:null,pagerank:o.get(d)??0,scoring:r});a.push({...u,score:h,evidence:`(suggestion, ${c.inferred_by}) confidence=${c.confidence.toFixed(2)} ${Math.round(g)}d apart`,link_type:c.link_type})}return a}function Os(e,t={}){let s=Math.max(100,Math.floor(t.budget??Lg)),n=t.scoring??"hybrid",r=Math.max(1,Math.min(5,t.maxDepth??Cg)),o=t.includeWikiLinks??!0,a=t.includeSuggestions??!1,c=t.edgeTypes?new Set(t.edgeTypes):null,d=Ca(e);if(!d)throw new Error(`session not found: ${e}`);let u=Dg(d.project_id),g={session_id:d.id,title:va(d),decimal:u.table?.byId.get(d.id)??null,summary:Ia(d.id),project:d.project,started_at:d.started_at};u.cache.set(d.id,g);let h=Fg(u,e),b=Pg(u,e),S=Lt(e).filter(i=>i.approved).filter(i=>!c||c.has(i.link_type)).filter(i=>o||i.link_type!=="wiki_link"),y=Ug(e,S,h,b,r),k=$g(y),w=[],D=[],L=[],X=[];for(let i of S){let l=i.source_session_id===e?i.target_session_id:i.source_session_id,p=Ns(u,l);if(!p)continue;let m=La(g.started_at,p.started_at),_=ja({confidence:i.confidence,linkType:i.link_type,daysApart:m,embeddingCosine:null,pagerank:k.get(l)??0,scoring:n}),E=Oa(m),T=`${i.link_type} confidence=${i.confidence.toFixed(2)} recency=${E.toFixed(2)} (${Math.round(m)}d apart)`,R={...p,score:_,evidence:T,link_type:i.link_type};i.link_type==="citation"?w.push(R):i.link_type==="similar"?D.push(R):i.link_type==="wiki_link"?X.push(R):L.push(R)}if(a){let i=Ve({sourceSessionId:e,status:"pending",limit:100}),l=Ve({targetSessionId:e,status:"pending",limit:100}),p=[...i,...l],m=new Set,_=p.filter(T=>m.has(T.id)?!1:(m.add(T.id),!0)),E=Wg(u,g,_,c,n,k);for(let T of E)T.link_type==="citation"?w.push(T):T.link_type==="similar"?D.push(T):T.link_type==="wiki_link"?X.push(T):L.push(T)}let M=(i,l)=>l.score-i.score;w.sort(M),D.sort(M),L.sort(M),X.sort(M);let se=Hg(g,[{heading:"Parents",refs:h},{heading:"Children",refs:b},{heading:"Citations (approved)",refs:w},{heading:"Similar sessions",refs:D},{heading:"Cousins (skill track + temporal)",refs:L},{heading:"Wiki links (manual)",refs:X}],s);return{origin:g,parents:h,children:b,citations:w,similar:D,cousins:L,wikiLinks:X,bundle:se.bundle,budgetUsed:se.budgetUsed,budgetRemaining:Math.max(0,s-se.budgetUsed),truncated:se.truncated}}H();Z();import{writeFileSync as qg,readFileSync as g0,existsSync as Jg,mkdirSync as Xg,readdirSync as _0,unlinkSync as f0}from"node:fs";import{join as Fa}from"node:path";import{randomUUID as Pa}from"node:crypto";var nr=Fa($,"bug-patterns");function Gg(){J(),Jg(nr)||Xg(nr,{recursive:!0})}function Oe(e){return{id:e.id,signature_hash:e.signature_hash,example_message:e.example_message,occurrence_count:e.occurrence_count,first_seen_at:e.first_seen_at,last_seen_at:e.last_seen_at,resolved_in_session_id:e.resolved_in_session_id,fix_summary:e.fix_summary}}function Ua(e){return{cluster_id:e.cluster_id,session_id:e.session_id,matched_at:e.matched_at}}function $a(e){if(!e.signature_hash)throw new Error("signature_hash is required");if(!e.example_message)throw new Error("example_message is required");if(!Array.isArray(e.member_session_ids)||e.member_session_ids.length===0)throw new Error("at least one member_session_id is required");let t=f(),s=new Date().toISOString(),n=e.id??Pa(),r=e.first_seen_at??s,o=e.last_seen_at??s,a=Array.from(new Set(e.member_session_ids));t.transaction(()=>{t.prepare(`INSERT INTO bug_pattern_clusters
975
975
  (id, signature_hash, example_message, occurrence_count,
976
976
  first_seen_at, last_seen_at, resolved_in_session_id, fix_summary)
977
977
  VALUES (?, ?, ?, ?, ?, ?, NULL, NULL)`).run(n,e.signature_hash,e.example_message,a.length,r,o);let d=t.prepare(`INSERT INTO bug_pattern_members (cluster_id, session_id, matched_at)
@@ -987,7 +987,7 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
987
987
  WHERE m.cluster_id = c.id AND p.name = ?
988
988
  )`),n.push(e.project));let r=s.length>0?`WHERE ${s.join(" AND ")}`:"",o=t.prepare(`SELECT COUNT(*) AS n FROM bug_pattern_clusters c ${r}`).get(...n),a=Math.max(1,Math.min(5e3,e.limit??100)),c=Math.max(0,Math.floor(e.offset??0));return{clusters:t.prepare(`SELECT c.* FROM bug_pattern_clusters c ${r}
989
989
  ORDER BY c.occurrence_count DESC, c.last_seen_at DESC
990
- LIMIT ? OFFSET ?`).all(...n,a,c).map(Oe),total:o.n}}function Xg(e){let t=e.first_user_message?e.first_user_message.slice(0,80):null,s=e.alias??e.auto_title??t??e.session_id.slice(0,8);return{cluster_id:e.cluster_id,session_id:e.session_id,matched_at:e.matched_at,title:s,alias:e.alias,auto_title:e.auto_title,project:e.project,started_at:e.started_at}}function qa(e){let t=f(),s=t.prepare("SELECT * FROM bug_pattern_clusters WHERE id = ?").get(e);if(!s)return null;let n=t.prepare(`SELECT m.cluster_id, m.session_id, m.matched_at,
990
+ LIMIT ? OFFSET ?`).all(...n,a,c).map(Oe),total:o.n}}function Yg(e){let t=e.first_user_message?e.first_user_message.slice(0,80):null,s=e.alias??e.auto_title??t??e.session_id.slice(0,8);return{cluster_id:e.cluster_id,session_id:e.session_id,matched_at:e.matched_at,title:s,alias:e.alias,auto_title:e.auto_title,project:e.project,started_at:e.started_at}}function qa(e){let t=f(),s=t.prepare("SELECT * FROM bug_pattern_clusters WHERE id = ?").get(e);if(!s)return null;let n=t.prepare(`SELECT m.cluster_id, m.session_id, m.matched_at,
991
991
  NULLIF(sa.alias, '') AS alias,
992
992
  s.auto_title,
993
993
  s.first_user_message,
@@ -998,26 +998,26 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
998
998
  LEFT JOIN session_aliases sa ON sa.session_id = m.session_id
999
999
  LEFT JOIN projects p ON p.id = s.project_id
1000
1000
  WHERE m.cluster_id = ?
1001
- ORDER BY COALESCE(s.started_at, ''), m.matched_at, m.session_id`).all(e);return{cluster:Oe(s),members:n.map(Xg)}}function Ja(e,t,s){if(!e)throw new Error("clusterId is required");if(!t)throw new Error("sessionId is required");if(typeof s!="string"||!s.trim())throw new Error("fixSummary is required");let n=f();if(!n.prepare("SELECT 1 FROM bug_pattern_clusters WHERE id = ?").get(e))throw new Error(`cluster ${e} not found`);if(!n.prepare("SELECT 1 FROM bug_pattern_members WHERE cluster_id = ? AND session_id = ?").get(e,t))throw new Error(`session ${t} is not a member of cluster ${e}`);n.prepare(`UPDATE bug_pattern_clusters
1001
+ ORDER BY COALESCE(s.started_at, ''), m.matched_at, m.session_id`).all(e);return{cluster:Oe(s),members:n.map(Yg)}}function Ja(e,t,s){if(!e)throw new Error("clusterId is required");if(!t)throw new Error("sessionId is required");if(typeof s!="string"||!s.trim())throw new Error("fixSummary is required");let n=f();if(!n.prepare("SELECT 1 FROM bug_pattern_clusters WHERE id = ?").get(e))throw new Error(`cluster ${e} not found`);if(!n.prepare("SELECT 1 FROM bug_pattern_members WHERE cluster_id = ? AND session_id = ?").get(e,t))throw new Error(`session ${t} is not a member of cluster ${e}`);n.prepare(`UPDATE bug_pattern_clusters
1002
1002
  SET resolved_in_session_id = ?, fix_summary = ?
1003
1003
  WHERE id = ?`).run(t,s.trim(),e),vt(e);let a=n.prepare("SELECT * FROM bug_pattern_clusters WHERE id = ?").get(e);return{cluster:Oe(a)}}function Xa(e,t){if(!e)throw new Error("clusterId is required");if(!Array.isArray(t)||t.length===0)throw new Error("memberSessionIds must be a non-empty array");let s=f(),n=s.prepare("SELECT * FROM bug_pattern_clusters WHERE id = ?").get(e);if(!n)throw new Error(`cluster ${e} not found`);let r=Array.from(new Set(t)),o=r.map(()=>"?").join(","),a=s.prepare(`SELECT session_id, matched_at FROM bug_pattern_members
1004
1004
  WHERE cluster_id = ? AND session_id IN (${o})`).all(e,...r);if(a.length===0)throw new Error(`none of the supplied session_ids are members of cluster ${e}`);let c=s.prepare("SELECT COUNT(*) AS n FROM bug_pattern_members WHERE cluster_id = ?").get(e).n;if(a.length>=c)throw new Error(`cannot split: would leave the original cluster empty (move ${a.length} of ${c})`);let d=Pa(),u=new Date().toISOString(),g=[];s.transaction(()=>{s.prepare(`INSERT INTO bug_pattern_clusters
1005
1005
  (id, signature_hash, example_message, occurrence_count,
1006
1006
  first_seen_at, last_seen_at, resolved_in_session_id, fix_summary)
1007
1007
  VALUES (?, ?, ?, ?, ?, ?, NULL, NULL)`).run(d,n.signature_hash,n.example_message,a.length,n.first_seen_at,u);let S=s.prepare(`INSERT INTO bug_pattern_members (cluster_id, session_id, matched_at)
1008
- VALUES (?, ?, ?)`),y=s.prepare("DELETE FROM bug_pattern_members WHERE cluster_id = ? AND session_id = ?");for(let w of a)S.run(d,w.session_id,w.matched_at),y.run(e,w.session_id);let k=c-a.length;s.prepare("UPDATE bug_pattern_clusters SET occurrence_count = ? WHERE id = ?").run(k,e),g=s.prepare("SELECT * FROM bug_pattern_members WHERE cluster_id = ?").all(d)})(),vt(e),vt(d);let h=s.prepare("SELECT * FROM bug_pattern_clusters WHERE id = ?").get(e),b=s.prepare("SELECT * FROM bug_pattern_clusters WHERE id = ?").get(d);return{original:Oe(h),split:Oe(b),movedMembers:g.map(Ua)}}function vt(e){try{Jg();let t=Ba(e);if(!t)return;let s=Fa(nr,`${e}.json`),n={schema:"claude-recall.bug-pattern-cluster.v1",cluster:t.cluster,members:t.members,backed_up_at:new Date().toISOString()};Hg(s,JSON.stringify(n,null,2))}catch(t){console.error("[bug-patterns] backup failed:",t)}}function Ga(e){return e?f().prepare(`SELECT * FROM bug_pattern_clusters
1008
+ VALUES (?, ?, ?)`),y=s.prepare("DELETE FROM bug_pattern_members WHERE cluster_id = ? AND session_id = ?");for(let w of a)S.run(d,w.session_id,w.matched_at),y.run(e,w.session_id);let k=c-a.length;s.prepare("UPDATE bug_pattern_clusters SET occurrence_count = ? WHERE id = ?").run(k,e),g=s.prepare("SELECT * FROM bug_pattern_members WHERE cluster_id = ?").all(d)})(),vt(e),vt(d);let h=s.prepare("SELECT * FROM bug_pattern_clusters WHERE id = ?").get(e),b=s.prepare("SELECT * FROM bug_pattern_clusters WHERE id = ?").get(d);return{original:Oe(h),split:Oe(b),movedMembers:g.map(Ua)}}function vt(e){try{Gg();let t=Ba(e);if(!t)return;let s=Fa(nr,`${e}.json`),n={schema:"claude-recall.bug-pattern-cluster.v1",cluster:t.cluster,members:t.members,backed_up_at:new Date().toISOString()};qg(s,JSON.stringify(n,null,2))}catch(t){console.error("[bug-patterns] backup failed:",t)}}function Ga(e){return e?f().prepare(`SELECT * FROM bug_pattern_clusters
1009
1009
  WHERE signature_hash = ?
1010
1010
  ORDER BY last_seen_at DESC, id ASC`).all(e).map(Oe):[]}function Ya(e){if(!e)return new Set;let s=f().prepare(`SELECT DISTINCT m.session_id
1011
1011
  FROM bug_pattern_members m
1012
1012
  JOIN bug_pattern_clusters c ON c.id = m.cluster_id
1013
- WHERE c.signature_hash = ?`).all(e);return new Set(s.map(n=>n.session_id))}import{randomUUID as x_}from"node:crypto";H();Z();import{writeFileSync as Zg,mkdirSync as Qg,existsSync as e_}from"node:fs";import{join as nc}from"node:path";H();var Ka=80;function za(e){if(e.alias&&e.alias.trim())return e.alias.trim();if(e.auto_title&&e.auto_title.trim())return e.auto_title.trim();let t=(e.first_user_message??"").trim();if(!t)return e.id.slice(0,8);let s=t.split(`
1014
- `)[0].trim();return s.length>Ka?s.slice(0,Ka)+"\u2026":s}function Gg(e){return f().prepare(`SELECT s.id AS id,
1013
+ WHERE c.signature_hash = ?`).all(e);return new Set(s.map(n=>n.session_id))}import{randomUUID as O_}from"node:crypto";H();Z();import{writeFileSync as e_,mkdirSync as t_,existsSync as s_}from"node:fs";import{join as nc}from"node:path";H();var Ka=80;function za(e){if(e.alias&&e.alias.trim())return e.alias.trim();if(e.auto_title&&e.auto_title.trim())return e.auto_title.trim();let t=(e.first_user_message??"").trim();if(!t)return e.id.slice(0,8);let s=t.split(`
1014
+ `)[0].trim();return s.length>Ka?s.slice(0,Ka)+"\u2026":s}function Kg(e){return f().prepare(`SELECT s.id AS id,
1015
1015
  sa.alias AS alias,
1016
1016
  s.auto_title AS auto_title,
1017
1017
  s.first_user_message AS first_user_message
1018
1018
  FROM sessions s
1019
1019
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
1020
- WHERE s.id = ?`).get(e)??null}function Yg(e){let t=Gg(e);return t?za(t):e.slice(0,8)}function Va(e){if(!e)return null;let t=f(),s=t.prepare(`SELECT e.thread_id AS thread_id,
1020
+ WHERE s.id = ?`).get(e)??null}function zg(e){let t=Kg(e);return t?za(t):e.slice(0,8)}function Va(e){if(!e)return null;let t=f(),s=t.prepare(`SELECT e.thread_id AS thread_id,
1021
1021
  t.name AS thread_name,
1022
1022
  e.parent_session_id AS parent_session_id,
1023
1023
  e.added_at AS added_at
@@ -1026,7 +1026,7 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
1026
1026
  WHERE e.session_id = ?
1027
1027
  AND t.archived = 0
1028
1028
  ORDER BY e.added_at DESC
1029
- LIMIT 1`).get(e);if(!s)return null;let n=s.parent_session_id?{id:s.parent_session_id,title:Yg(s.parent_session_id)}:null,r=s.parent_session_id?[e,s.parent_session_id]:[e],o=r.map(()=>"?").join(", "),c=t.prepare(`SELECT e.session_id AS session_id,
1029
+ LIMIT 1`).get(e);if(!s)return null;let n=s.parent_session_id?{id:s.parent_session_id,title:zg(s.parent_session_id)}:null,r=s.parent_session_id?[e,s.parent_session_id]:[e],o=r.map(()=>"?").join(", "),c=t.prepare(`SELECT e.session_id AS session_id,
1030
1030
  s.id AS id,
1031
1031
  sa.alias AS alias,
1032
1032
  s.auto_title AS auto_title,
@@ -1036,7 +1036,7 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
1036
1036
  LEFT JOIN session_aliases sa ON sa.session_id = e.session_id
1037
1037
  WHERE e.thread_id = ?
1038
1038
  AND e.session_id NOT IN (${o})
1039
- ORDER BY e.added_at ASC`).all(s.thread_id,...r).map(d=>({id:d.session_id,title:d.id?za(d):d.session_id.slice(0,8)}));return{thread_id:s.thread_id,thread_name:s.thread_name,parent_session:n,siblings:c}}var Za=[/^You will receive a sample of user messages from a Claude Cod/i,/^You will receive the first \d+ user messages from a Claude/i,/^Base directory for this skill:/i,/^You are Claude Code in a fresh terminal/i,/^You are extracting a structured Output Index from a Claude/i];function rr(e){return Za.some(t=>t.test(e))}var Kg=[/^Score this person'?s relevance/i,/^You are a [^\n.]{1,60}co-pilot/i,/^Return ONLY valid JSON/i],zg=[/^Draft (a|an|marketing) [a-z]/i,/^Read the file at /i,/^Read this and then begin/i,/^read this and then begin/i],Vg=20;function jt(e){if(e.auto_title_source==="agent"&&e.auto_title)return"agent";if(e.has_alias)return"manual_alias";if(e.auto_title&&e.auto_title.includes(" \xB7 "))return"fixed_v0.16.1";if(!e.auto_title||e.auto_title.length<Vg)return"low_signal";for(let t of Za)if(t.test(e.auto_title))return"recursive_meta";for(let t of Kg)if(t.test(e.auto_title))return"programmatic";for(let t of zg)if(t.test(e.auto_title))return"template_pending";return"clean"}function Ls(e){if(!e)return"";let t=e.split("|")[0];return t=t.replace(/\s*\([^)]*\)\s*$/,""),t=t.replace(/\s+/g," ").trim(),t}function Qa(e){if(!e)return e;let t=e.lastIndexOf(" \xB7 ");if(t===-1)return e;let s=e.slice(0,t),n=e.slice(t+3),r=Ls(n);return!r||r===n?e:`${s} \xB7 ${r}`}var ar=nc($,"titles"),t_=80,s_=60,n_=100,r_=50,Mt=5,Cs=15,o_=500;function rc(e){if(!e)return[];try{let t=JSON.parse(e);if(Array.isArray(t))return t.filter(s=>!!s&&typeof s=="object"&&typeof s.title=="string"&&typeof s.replaced_at=="string")}catch{}return[]}function et(e){if(!e)return null;let t=e;if(t=t.replace(/```[\s\S]*?```/g," "),t=t.replace(/`[^`]+`/g," "),t=t.replace(/https?:\/\/\S+/g,"[url]"),t=t.replace(/\s+/g," ").trim(),!t)return null;let s=i_(t,e);if(s)return s;let n=t.match(/^[^.!?\n]{8,}?[.!?]/)?.[0]?.trim();return(n&&n.length<=t_?n:t.slice(0,s_)).trim()||null}function i_(e,t){let s=e.match(/^\/([A-Za-z0-9][A-Za-z0-9_-]*)\s+([\s\S]*)$/);if(s){let n=`/${s[1]}`,r=t.replace(/^\s*\/[A-Za-z0-9][A-Za-z0-9_-]*\s+/,""),o=cr(r);return o?Qe(`${n} \xB7 ${o}`):n}for(let n of a_){if(!e.match(n.match))continue;let o=n.prefix,a=n.extract?n.extract(e,t):cr(t);return a?n.completeFromExtract?Qe(a):Qe(`${o} \xB7 ${a}`):o}for(let n of d_){if(!e.match(n.match))continue;let o=n.extract?n.extract(e,t):Is(t);return o?n.completeFromExtract?Qe(o):Qe(`${n.prefix} \xB7 ${o}`):n.prefix}return null}var a_=[{match:/^Draft (?:a|an) brand brief\b/i,prefix:"Draft brand brief"},{match:/^Draft (?:a|an) sales brief\b/i,prefix:"Draft sales brief"},{match:/^Draft (?:a|an) leave-behind\b/i,prefix:"Draft leave-behind"},{match:/^Draft (?:a|an) audio identity brief\b/i,prefix:"Draft audio identity brief"},{match:/^Draft marketing ideas\b/i,prefix:"Draft marketing ideas"},{match:/^Draft (?:a|an) ([a-z]{3,30}(?:\s+[a-z]{3,30}){0,2})\b/i,prefix:"Draft",extract:(e,t)=>{let n=e.match(/^Draft (?:a|an) ([a-z]{3,30}(?:\s+[a-z]{3,30}){0,2})\b/i)?.[1]?.trim(),r=cr(t);return n&&r?`${n} \xB7 ${r}`:n||r}},{match:/^Read the file at /i,prefix:"Read",extract:e=>{let s=e.match(/^Read the file at\s+([^\s]+)/i)?.[1];return s?s.split("/").filter(Boolean).slice(-2).join("/")||s:null}},{match:/^(?:read|inspect) this and then begin\b/i,prefix:"Begin from preamble",completeFromExtract:!0,extract:(e,t)=>l_(t)},{match:/^Base directory for this skill:/i,prefix:"[skill]",completeFromExtract:!0,extract:(e,t)=>{let s=t.match(/\.claude\/skills\/([^/\s]+)/);return s?.[1]?`[skill] ${s[1]}`:null}},{match:/^You are extracting a structured Output Index/i,prefix:"[output-index]",completeFromExtract:!0,extract:(e,t)=>c_(t)},{match:/^You will receive a sample of user messages from a Claude Code session:/i,prefix:"[meta]",completeFromExtract:!0,extract:(e,t)=>ec(t,"[meta] auto-title (full-arc)")},{match:/^You will receive the first \d+ user messages from a Claude Code session/i,prefix:"[meta]",completeFromExtract:!0,extract:(e,t)=>ec(t,"[meta] auto-title (initial)")},{match:/^You are implementing v\d+\.\d+/i,prefix:"Implementing",completeFromExtract:!0,extract:e=>{let t=e.match(/^You are implementing (v\d+\.\d+\w*)\s*(?:\(([^)]+)\))?/i);if(!t)return null;let s=t[1],n=t[2]?.trim();return n?`Implementing ${s} \xB7 ${n}`:`Implementing ${s}`}}];function c_(e){if(!e)return"[output-index] extractor";let t=e.match(/^Session:\s*([0-9a-f]{8})\b/im),s=e.match(/^Opening prompt:\s*([^\n]{1,140})/im),n=t?.[1]?.trim(),r=s?.[1]?.trim().replace(/\s+/g," "),o=r&&r.length>70?r.slice(0,67)+"\u2026":r;return n&&o?`[output-index] \xB7 ${n} \xB7 ${o}`:n?`[output-index] \xB7 ${n}`:o?`[output-index] \xB7 ${o}`:"[output-index] extractor"}function ec(e,t){if(!e)return t;let s=e.indexOf("Messages:");if(s===-1)return t;let n=e.slice(s+9),r=/^\s*\d+\.\s*([^\n]+)/gm;for(let o of n.matchAll(r)){let a=o[1]?.trim()??"";if(!a)continue;let c=a.replace(/^<[^>]+>[\s\S]*?<\/[^>]+>\s*/g,"").replace(/^\[Pasted text[^\]]*\]\s*/i,"").trim();if(!c||/^<local-command-/.test(c))continue;let d=c.length>60?c.slice(0,57)+"\u2026":c;return`${t} \xB7 ${d}`}return t}function l_(e){if(!e)return null;let t=e.match(/([\/\w.\-]+\.(?:md|markdown|txt|json|yaml|yml|toml|ts|tsx|js|jsx|py|sql))(?=[\s,;:)\]"'`]|$)/i);if(!t)return null;let s=t[1].split("/").filter(Boolean);return(s[s.length-1]??"").replace(/\.[^.]+$/,"")||null}var d_=[{match:/^Score this person'?s relevance/i,prefix:"Score relevance",extract:(e,t)=>Is(t)},{match:/^You are a [^\n.]{1,60}co-pilot/i,prefix:"co-pilot",completeFromExtract:!0,extract:(e,t)=>{let n=e.match(/^You are a ([^\n.]{1,60}?)co-pilot/i)?.[1]?.trim(),r=n?`${n} co-pilot`:"co-pilot",o=Is(t);return o?`${r} \xB7 ${o}`:r}},{match:/^Return ONLY valid JSON/i,prefix:"JSON-only",extract:(e,t)=>Is(t)}];function Is(e){let t=/^\s*(Name|Company|Prospect|Author|Brand|Client)\s*:\s*([^\n]+)/gim,s;for(;(s=t.exec(e))!==null;){let n=s[2].trim();if(!n||/^(null|none|n\/a|—|-)$/i.test(n))continue;let r=n.replace(/\s+/g," ");return Ls(r)||r}return null}function Qe(e){return e.slice(0,n_).trim()}var u_=[/^deep research$/i,/^reference(?: spec)?$/i,/^canonical spec/i,/^product context/i,/^services?(?: overview)?$/i,/^overview$/i,/^(?:introduction|template|instructions|context)$/i],p_=[/^(?:brand|brand brief|brand summary)$/i,/^(?:known facts?|facts)$/i,/^(?:client|prospect|customer|account)$/i,/^(?:topic|subject|brief|task)$/i,/^(?:about|for|re)$/i];function or(e){let t=e.trim();return t.length<3?!0:u_.some(s=>s.test(t))}function m_(e){let t=e.trim().replace(/\s*\([^)]*\)\s*$/,"").trim();return p_.some(s=>s.test(t))}function cr(e){let t=g_(e);return t===null?null:Ls(t)||t}function g_(e){if(/^\s*Skill smoke test\b/i.test(e))return"smoke test";let t=/(^|\n)#{1,3}\s+([^\n]+?)\s+(?:—|–|-|:)\s+([^\n]{2,80})/g,s,n=[];for(;(s=t.exec(e))!==null;){let d=s[2].trim(),u=s[3].trim().replace(/\s+/g," ");if(!or(u)){if(m_(d))return u;n.push(u)}}if(n.length>0)return n[0];let r=e.match(/\b(?:Topic|Subject|Brand|About|Client|For|Re)\s*:\s*([^\n]{2,80})/i);if(r?.[1]&&!or(r[1]))return r[1].trim().replace(/\s+/g," ");let o=/===\s*([^=\n]{2,120}?)\s*===/g;for(;(s=o.exec(e))!==null;){let d=s[1].trim().replace(/\.(md|txt|json)$/i,""),u=d.replace(/\s*\([^)]*\)\s*$/,"").trim();if(u&&!or(u)&&!/product context|reference/i.test(d))return u}let a=e.replace(/^Context for this run[^:]*:\s*/i,"");if(a!==e){let d=a.split(`
1039
+ ORDER BY e.added_at ASC`).all(s.thread_id,...r).map(d=>({id:d.session_id,title:d.id?za(d):d.session_id.slice(0,8)}));return{thread_id:s.thread_id,thread_name:s.thread_name,parent_session:n,siblings:c}}var Za=[/^You will receive a sample of user messages from a Claude Cod/i,/^You will receive the first \d+ user messages from a Claude/i,/^Base directory for this skill:/i,/^You are Claude Code in a fresh terminal/i,/^You are extracting a structured Output Index from a Claude/i];function rr(e){return Za.some(t=>t.test(e))}var Vg=[/^Score this person'?s relevance/i,/^You are a [^\n.]{1,60}co-pilot/i,/^Return ONLY valid JSON/i],Zg=[/^Draft (a|an|marketing) [a-z]/i,/^Read the file at /i,/^Read this and then begin/i,/^read this and then begin/i],Qg=20;function jt(e){if(e.auto_title_source==="agent"&&e.auto_title)return"agent";if(e.has_alias)return"manual_alias";if(e.auto_title&&e.auto_title.includes(" \xB7 "))return"fixed_v0.16.1";if(!e.auto_title||e.auto_title.length<Qg)return"low_signal";for(let t of Za)if(t.test(e.auto_title))return"recursive_meta";for(let t of Vg)if(t.test(e.auto_title))return"programmatic";for(let t of Zg)if(t.test(e.auto_title))return"template_pending";return"clean"}function Ls(e){if(!e)return"";let t=e.split("|")[0];return t=t.replace(/\s*\([^)]*\)\s*$/,""),t=t.replace(/\s+/g," ").trim(),t}function Qa(e){if(!e)return e;let t=e.lastIndexOf(" \xB7 ");if(t===-1)return e;let s=e.slice(0,t),n=e.slice(t+3),r=Ls(n);return!r||r===n?e:`${s} \xB7 ${r}`}var ar=nc($,"titles"),n_=80,r_=60,o_=100,i_=50,Mt=5,Cs=15,a_=500;function rc(e){if(!e)return[];try{let t=JSON.parse(e);if(Array.isArray(t))return t.filter(s=>!!s&&typeof s=="object"&&typeof s.title=="string"&&typeof s.replaced_at=="string")}catch{}return[]}function et(e){if(!e)return null;let t=e;if(t=t.replace(/```[\s\S]*?```/g," "),t=t.replace(/`[^`]+`/g," "),t=t.replace(/https?:\/\/\S+/g,"[url]"),t=t.replace(/\s+/g," ").trim(),!t)return null;let s=c_(t,e);if(s)return s;let n=t.match(/^[^.!?\n]{8,}?[.!?]/)?.[0]?.trim();return(n&&n.length<=n_?n:t.slice(0,r_)).trim()||null}function c_(e,t){let s=e.match(/^\/([A-Za-z0-9][A-Za-z0-9_-]*)\s+([\s\S]*)$/);if(s){let n=`/${s[1]}`,r=t.replace(/^\s*\/[A-Za-z0-9][A-Za-z0-9_-]*\s+/,""),o=cr(r);return o?Qe(`${n} \xB7 ${o}`):n}for(let n of l_){if(!e.match(n.match))continue;let o=n.prefix,a=n.extract?n.extract(e,t):cr(t);return a?n.completeFromExtract?Qe(a):Qe(`${o} \xB7 ${a}`):o}for(let n of p_){if(!e.match(n.match))continue;let o=n.extract?n.extract(e,t):Is(t);return o?n.completeFromExtract?Qe(o):Qe(`${n.prefix} \xB7 ${o}`):n.prefix}return null}var l_=[{match:/^Draft (?:a|an) brand brief\b/i,prefix:"Draft brand brief"},{match:/^Draft (?:a|an) sales brief\b/i,prefix:"Draft sales brief"},{match:/^Draft (?:a|an) leave-behind\b/i,prefix:"Draft leave-behind"},{match:/^Draft (?:a|an) audio identity brief\b/i,prefix:"Draft audio identity brief"},{match:/^Draft marketing ideas\b/i,prefix:"Draft marketing ideas"},{match:/^Draft (?:a|an) ([a-z]{3,30}(?:\s+[a-z]{3,30}){0,2})\b/i,prefix:"Draft",extract:(e,t)=>{let n=e.match(/^Draft (?:a|an) ([a-z]{3,30}(?:\s+[a-z]{3,30}){0,2})\b/i)?.[1]?.trim(),r=cr(t);return n&&r?`${n} \xB7 ${r}`:n||r}},{match:/^Read the file at /i,prefix:"Read",extract:e=>{let s=e.match(/^Read the file at\s+([^\s]+)/i)?.[1];return s?s.split("/").filter(Boolean).slice(-2).join("/")||s:null}},{match:/^(?:read|inspect) this and then begin\b/i,prefix:"Begin from preamble",completeFromExtract:!0,extract:(e,t)=>u_(t)},{match:/^Base directory for this skill:/i,prefix:"[skill]",completeFromExtract:!0,extract:(e,t)=>{let s=t.match(/\.claude\/skills\/([^/\s]+)/);return s?.[1]?`[skill] ${s[1]}`:null}},{match:/^You are extracting a structured Output Index/i,prefix:"[output-index]",completeFromExtract:!0,extract:(e,t)=>d_(t)},{match:/^You will receive a sample of user messages from a Claude Code session:/i,prefix:"[meta]",completeFromExtract:!0,extract:(e,t)=>ec(t,"[meta] auto-title (full-arc)")},{match:/^You will receive the first \d+ user messages from a Claude Code session/i,prefix:"[meta]",completeFromExtract:!0,extract:(e,t)=>ec(t,"[meta] auto-title (initial)")},{match:/^You are implementing v\d+\.\d+/i,prefix:"Implementing",completeFromExtract:!0,extract:e=>{let t=e.match(/^You are implementing (v\d+\.\d+\w*)\s*(?:\(([^)]+)\))?/i);if(!t)return null;let s=t[1],n=t[2]?.trim();return n?`Implementing ${s} \xB7 ${n}`:`Implementing ${s}`}}];function d_(e){if(!e)return"[output-index] extractor";let t=e.match(/^Session:\s*([0-9a-f]{8})\b/im),s=e.match(/^Opening prompt:\s*([^\n]{1,140})/im),n=t?.[1]?.trim(),r=s?.[1]?.trim().replace(/\s+/g," "),o=r&&r.length>70?r.slice(0,67)+"\u2026":r;return n&&o?`[output-index] \xB7 ${n} \xB7 ${o}`:n?`[output-index] \xB7 ${n}`:o?`[output-index] \xB7 ${o}`:"[output-index] extractor"}function ec(e,t){if(!e)return t;let s=e.indexOf("Messages:");if(s===-1)return t;let n=e.slice(s+9),r=/^\s*\d+\.\s*([^\n]+)/gm;for(let o of n.matchAll(r)){let a=o[1]?.trim()??"";if(!a)continue;let c=a.replace(/^<[^>]+>[\s\S]*?<\/[^>]+>\s*/g,"").replace(/^\[Pasted text[^\]]*\]\s*/i,"").trim();if(!c||/^<local-command-/.test(c))continue;let d=c.length>60?c.slice(0,57)+"\u2026":c;return`${t} \xB7 ${d}`}return t}function u_(e){if(!e)return null;let t=e.match(/([\/\w.\-]+\.(?:md|markdown|txt|json|yaml|yml|toml|ts|tsx|js|jsx|py|sql))(?=[\s,;:)\]"'`]|$)/i);if(!t)return null;let s=t[1].split("/").filter(Boolean);return(s[s.length-1]??"").replace(/\.[^.]+$/,"")||null}var p_=[{match:/^Score this person'?s relevance/i,prefix:"Score relevance",extract:(e,t)=>Is(t)},{match:/^You are a [^\n.]{1,60}co-pilot/i,prefix:"co-pilot",completeFromExtract:!0,extract:(e,t)=>{let n=e.match(/^You are a ([^\n.]{1,60}?)co-pilot/i)?.[1]?.trim(),r=n?`${n} co-pilot`:"co-pilot",o=Is(t);return o?`${r} \xB7 ${o}`:r}},{match:/^Return ONLY valid JSON/i,prefix:"JSON-only",extract:(e,t)=>Is(t)}];function Is(e){let t=/^\s*(Name|Company|Prospect|Author|Brand|Client)\s*:\s*([^\n]+)/gim,s;for(;(s=t.exec(e))!==null;){let n=s[2].trim();if(!n||/^(null|none|n\/a|—|-)$/i.test(n))continue;let r=n.replace(/\s+/g," ");return Ls(r)||r}return null}function Qe(e){return e.slice(0,o_).trim()}var m_=[/^deep research$/i,/^reference(?: spec)?$/i,/^canonical spec/i,/^product context/i,/^services?(?: overview)?$/i,/^overview$/i,/^(?:introduction|template|instructions|context)$/i],g_=[/^(?:brand|brand brief|brand summary)$/i,/^(?:known facts?|facts)$/i,/^(?:client|prospect|customer|account)$/i,/^(?:topic|subject|brief|task)$/i,/^(?:about|for|re)$/i];function or(e){let t=e.trim();return t.length<3?!0:m_.some(s=>s.test(t))}function __(e){let t=e.trim().replace(/\s*\([^)]*\)\s*$/,"").trim();return g_.some(s=>s.test(t))}function cr(e){let t=f_(e);return t===null?null:Ls(t)||t}function f_(e){if(/^\s*Skill smoke test\b/i.test(e))return"smoke test";let t=/(^|\n)#{1,3}\s+([^\n]+?)\s+(?:—|–|-|:)\s+([^\n]{2,80})/g,s,n=[];for(;(s=t.exec(e))!==null;){let d=s[2].trim(),u=s[3].trim().replace(/\s+/g," ");if(!or(u)){if(__(d))return u;n.push(u)}}if(n.length>0)return n[0];let r=e.match(/\b(?:Topic|Subject|Brand|About|Client|For|Re)\s*:\s*([^\n]{2,80})/i);if(r?.[1]&&!or(r[1]))return r[1].trim().replace(/\s+/g," ");let o=/===\s*([^=\n]{2,120}?)\s*===/g;for(;(s=o.exec(e))!==null;){let d=s[1].trim().replace(/\.(md|txt|json)$/i,""),u=d.replace(/\s*\([^)]*\)\s*$/,"").trim();if(u&&!or(u)&&!/product context|reference/i.test(d))return u}let a=e.replace(/^Context for this run[^:]*:\s*/i,"");if(a!==e){let d=a.split(`
1040
1040
  `).map(u=>u.trim()).find(u=>u.length>=4);if(d)return d.slice(0,60)}let c=e.split(`
1041
1041
  `).map(d=>d.trim()).find(d=>d.length>=4);return c?c.slice(0,60):null}function lr(e){let t=f(),s=t.prepare(`SELECT rowid AS rid, content_text
1042
1042
  FROM messages
@@ -1048,17 +1048,17 @@ kEgDDGWLdQN7jrx/W+Nxz9yOJbwTPDI4jv24IztWSEtJuqH+0KvrDbdfFA==
1048
1048
  WHERE session_id = ? AND role = 'user' AND is_sidechain = 0
1049
1049
  AND content_text IS NOT NULL AND content_text != ''
1050
1050
  ORDER BY COALESCE(timestamp, '') DESC, rowid DESC
1051
- LIMIT ?`).all(e,Cs),r=new Map;for(let g of s)r.set(g.rid,g.content_text);for(let g of n)r.set(g.rid,g.content_text);if(r.size===0)throw new Error("no user messages available to summarise");let o=Array.from(r.entries()).sort((g,h)=>g[0]-h[0]).map(([,g])=>({content_text:g})),a=s.length===Mt&&n.length===Cs&&r.size===Mt+Cs,c=o.map((g,h)=>{let b=(g.content_text??"").slice(0,o_);return a&&h===Mt?`--- (middle of session omitted) ---
1051
+ LIMIT ?`).all(e,Cs),r=new Map;for(let g of s)r.set(g.rid,g.content_text);for(let g of n)r.set(g.rid,g.content_text);if(r.size===0)throw new Error("no user messages available to summarise");let o=Array.from(r.entries()).sort((g,h)=>g[0]-h[0]).map(([,g])=>({content_text:g})),a=s.length===Mt&&n.length===Cs&&r.size===Mt+Cs,c=o.map((g,h)=>{let b=(g.content_text??"").slice(0,a_);return a&&h===Mt?`--- (middle of session omitted) ---
1052
1052
  ${h+1}. ${b}`:`${h+1}. ${b}`}).join(`
1053
- `),d=null;try{d=Va(e)}catch(g){console.error("[autoTitle] thread context resolution failed:",g),d=null}let u=[];return d&&(u.push(__(d)),u.push("")),u.push(`You will receive a sample of user messages from a Claude Code session: the first ${Mt}`,`messages (initial intent) and the last ${Cs} messages (current direction).`,"Write a single descriptive title, max 50 characters, focused on what the user is","currently trying to accomplish. If initial intent and current direction differ, prefer","the current direction. Output ONLY the title, with no quotes and no trailing punctuation.","","Messages:",c),u.join(`
1054
- `)}var ir=5;function __(e){let t=[];t.push("Thread context:"),t.push(`- This session is part of thread "${e.thread_name}".`),e.parent_session&&t.push(`- Parent session: "${e.parent_session.title}"`);let s=e.siblings.length;if(s>0){let r=e.siblings.slice(0,ir).map(a=>`"${a.title}"`).join(", "),o=s>ir?`, and ${s-ir} more`:"";t.push(`- Sibling sessions (${s}): ${r}${o}`)}return t.push(""),t.push("Generate a title that reflects this session's role in the thread."),t.push('If siblings use a pattern like "Phase A / Phase B" or "Wave 1 of 4",'),t.push("follow the same pattern."),t.join(`
1055
- `)}async function oc(e){let t=lr(e),{spawnClaudePrompt:s,isClaudeCliAvailable:n}=await Promise.resolve().then(()=>(ge(),Pe));if(!n())throw new Error("claude CLI not found on PATH");let r=await s(t,[],{});if(!r.success)throw new Error(`claude CLI exited ${r.exitCode}: ${r.stderr.slice(-500)}`);let o=f_(r.stdout);if(!o)throw new Error("claude CLI returned an empty title");return o.slice(0,r_)}function f_(e){let t=e.trim();if(!t)return"";try{let s=JSON.parse(t);if(s&&typeof s=="object"){let n=s.result;if(typeof n=="string")return tc(n)}}catch{}return tc(t)}function tc(e){return e.trim().replace(/^["'`]+|["'`]+$/g,"").replace(/\s+/g," ").replace(/[.!?]+$/g,"").trim()}function de(e,t,s){let n=t.trim();if(!n)return;let r=f(),o=r.prepare(`SELECT auto_title, auto_title_source, auto_title_generated_at, auto_title_history
1053
+ `),d=null;try{d=Va(e)}catch(g){console.error("[autoTitle] thread context resolution failed:",g),d=null}let u=[];return d&&(u.push(h_(d)),u.push("")),u.push(`You will receive a sample of user messages from a Claude Code session: the first ${Mt}`,`messages (initial intent) and the last ${Cs} messages (current direction).`,"Write a single descriptive title, max 50 characters, focused on what the user is","currently trying to accomplish. If initial intent and current direction differ, prefer","the current direction. Output ONLY the title, with no quotes and no trailing punctuation.","","Messages:",c),u.join(`
1054
+ `)}var ir=5;function h_(e){let t=[];t.push("Thread context:"),t.push(`- This session is part of thread "${e.thread_name}".`),e.parent_session&&t.push(`- Parent session: "${e.parent_session.title}"`);let s=e.siblings.length;if(s>0){let r=e.siblings.slice(0,ir).map(a=>`"${a.title}"`).join(", "),o=s>ir?`, and ${s-ir} more`:"";t.push(`- Sibling sessions (${s}): ${r}${o}`)}return t.push(""),t.push("Generate a title that reflects this session's role in the thread."),t.push('If siblings use a pattern like "Phase A / Phase B" or "Wave 1 of 4",'),t.push("follow the same pattern."),t.join(`
1055
+ `)}async function oc(e){let t=lr(e),{spawnClaudePrompt:s,isClaudeCliAvailable:n}=await Promise.resolve().then(()=>(ge(),Pe));if(!n())throw new Error("claude CLI not found on PATH");let r=await s(t,[],{});if(!r.success)throw new Error(`claude CLI exited ${r.exitCode}: ${r.stderr.slice(-500)}`);let o=E_(r.stdout);if(!o)throw new Error("claude CLI returned an empty title");return o.slice(0,i_)}function E_(e){let t=e.trim();if(!t)return"";try{let s=JSON.parse(t);if(s&&typeof s=="object"){let n=s.result;if(typeof n=="string")return tc(n)}}catch{}return tc(t)}function tc(e){return e.trim().replace(/^["'`]+|["'`]+$/g,"").replace(/\s+/g," ").replace(/[.!?]+$/g,"").trim()}function de(e,t,s){let n=t.trim();if(!n)return;let r=f(),o=r.prepare(`SELECT auto_title, auto_title_source, auto_title_generated_at, auto_title_history
1056
1056
  FROM sessions WHERE id = ?`).get(e);if(!o||s==="heuristic"&&o.auto_title_source==="agent"&&o.auto_title||o.auto_title===n&&o.auto_title_source===s)return;let a=rc(o.auto_title_history),c=new Date().toISOString();o.auto_title&&o.auto_title_source&&a.push({title:o.auto_title,source:o.auto_title_source,replaced_at:c}),r.prepare(`UPDATE sessions
1057
1057
  SET auto_title = ?,
1058
1058
  auto_title_source = ?,
1059
1059
  auto_title_generated_at = ?,
1060
1060
  auto_title_history = ?
1061
- WHERE id = ?`).run(n,s,Date.now(),JSON.stringify(a),e),S_(e,n,s,c)}function ye(e){let t=f().prepare(`SELECT auto_title, auto_title_source, auto_title_generated_at, auto_title_history
1061
+ WHERE id = ?`).run(n,s,Date.now(),JSON.stringify(a),e),y_(e,n,s,c)}function ye(e){let t=f().prepare(`SELECT auto_title, auto_title_source, auto_title_generated_at, auto_title_history
1062
1062
  FROM sessions WHERE id = ?`).get(e);return t?{auto_title:t.auto_title,auto_title_source:t.auto_title_source??null,auto_title_generated_at:t.auto_title_generated_at,auto_title_history:rc(t.auto_title_history)}:null}function ic(){let t=f().prepare(`SELECT id, first_user_message
1063
1063
  FROM sessions
1064
1064
  WHERE auto_title IS NULL
@@ -1130,31 +1130,31 @@ ${h+1}. ${b}`:`${h+1}. ${b}`}).join(`
1130
1130
  AND content_text IS NOT NULL
1131
1131
  AND content_text != ''
1132
1132
  ORDER BY COALESCE(timestamp, ''), rowid ASC
1133
- LIMIT 10`),a=0,c=0;for(let d of r){a+=1;let u=o.all(d.id),g=h_(u,d.auto_title);g&&(de(d.id,g,"heuristic"),c+=1)}return{scanned:a,updated:c}}function h_(e,t){for(let s of e){let n=E_(s.content_text);if(!n||rr(n))continue;let r=et(n);if(r){if(r===t)return null;if(!rr(r))return r}}return t.startsWith("[meta]")?null:Qe(`[meta] ${t}`)}function lc(e){let t=f(),s=e?.projectId?" AND s.project_id = ?":"",n=e?.projectId?[e.projectId]:[],r=t.prepare(`SELECT s.id, s.auto_title
1133
+ LIMIT 10`),a=0,c=0;for(let d of r){a+=1;let u=o.all(d.id),g=b_(u,d.auto_title);g&&(de(d.id,g,"heuristic"),c+=1)}return{scanned:a,updated:c}}function b_(e,t){for(let s of e){let n=S_(s.content_text);if(!n||rr(n))continue;let r=et(n);if(r){if(r===t)return null;if(!rr(r))return r}}return t.startsWith("[meta]")?null:Qe(`[meta] ${t}`)}function lc(e){let t=f(),s=e?.projectId?" AND s.project_id = ?":"",n=e?.projectId?[e.projectId]:[],r=t.prepare(`SELECT s.id, s.auto_title
1134
1134
  FROM sessions s
1135
1135
  WHERE s.auto_title_source = 'heuristic'${s}
1136
1136
  AND s.auto_title IS NOT NULL
1137
1137
  AND s.auto_title LIKE '% \xB7 %'
1138
- AND (s.auto_title LIKE '%|%' OR s.auto_title LIKE '%(%')`).all(...n),o=0,a=0;for(let c of r){o+=1;let d=Qa(c.auto_title);d!==c.auto_title&&(de(c.id,d,"heuristic"),a+=1)}return{scanned:o,updated:a}}function E_(e){return e.replace(/<command-(?:name|message|args|stdout|stderr)>[\s\S]*?<\/command-(?:name|message|args|stdout|stderr)>/g,"").replace(/<local-command-(?:stdout|stderr|caveat)>[\s\S]*?<\/local-command-(?:stdout|stderr|caveat)>/g,"").trim()}function b_(){J(),e_(ar)||Qg(ar,{recursive:!0})}function S_(e,t,s,n){try{b_();let r=nc(ar,`${e}.txt`),o=`# Claude Recall auto-title \xB7 session ${e} \xB7 source ${s} \xB7 updated ${n}
1139
- `;Zg(r,o+t+`
1140
- `)}catch(r){console.error("[autoTitle] mirror write failed:",r)}}var T_=50;function y_(e){if(e.length===0)return[];let t=[...e].sort((d,u)=>d.added_at<u.added_at?-1:d.added_at>u.added_at?1:0),s=new Map,n=new Set,r=[];for(let d of t)if(d.parent_session_id){let u=s.get(d.parent_session_id)??[];u.push(d),s.set(d.parent_session_id,u)}let o=t.filter(d=>d.role==="origin"),c=[...o.length>0?o:t.filter(d=>!d.parent_session_id)];for(;c.length>0;){let d=c.shift();if(n.has(d.session_id))continue;n.add(d.session_id),r.push(d.session_id);let u=s.get(d.session_id)??[];for(let g of u)n.has(g.session_id)||c.push(g)}for(let d of t)n.has(d.session_id)||(n.add(d.session_id),r.push(d.session_id));return r}function w_(e){let t=lr(e.sessionId),s=["",`BULK CONTEXT: You are titling session ${e.current} of ${e.total} in this thread.`,"The parent and earlier siblings already have titles (shown above). YOUR JOB:","",'1. Identify the naming pattern. If parent is "Build Feature X" and earlier',' siblings are "Phase A: API design" and "Phase B: client wiring", the pattern',' is "Phase {LETTER}: {topic}".',"2. If no pattern is yet established (this is the first child), INVENT a pattern",' that will scale to N children. Good patterns: "Phase A/B/C", "Wave 1 of M",',' "Step N", or a domain-specific structure if the thread name suggests one.',"3. Output a title that follows the pattern AND describes what THIS session"," does in 50 characters max.","","Output ONLY the title, no quotes, no trailing punctuation."].join(`
1138
+ AND (s.auto_title LIKE '%|%' OR s.auto_title LIKE '%(%')`).all(...n),o=0,a=0;for(let c of r){o+=1;let d=Qa(c.auto_title);d!==c.auto_title&&(de(c.id,d,"heuristic"),a+=1)}return{scanned:o,updated:a}}function S_(e){return e.replace(/<command-(?:name|message|args|stdout|stderr)>[\s\S]*?<\/command-(?:name|message|args|stdout|stderr)>/g,"").replace(/<local-command-(?:stdout|stderr|caveat)>[\s\S]*?<\/local-command-(?:stdout|stderr|caveat)>/g,"").trim()}function T_(){J(),s_(ar)||t_(ar,{recursive:!0})}function y_(e,t,s,n){try{T_();let r=nc(ar,`${e}.txt`),o=`# Claude Recall auto-title \xB7 session ${e} \xB7 source ${s} \xB7 updated ${n}
1139
+ `;e_(r,o+t+`
1140
+ `)}catch(r){console.error("[autoTitle] mirror write failed:",r)}}var w_=50;function R_(e){if(e.length===0)return[];let t=[...e].sort((d,u)=>d.added_at<u.added_at?-1:d.added_at>u.added_at?1:0),s=new Map,n=new Set,r=[];for(let d of t)if(d.parent_session_id){let u=s.get(d.parent_session_id)??[];u.push(d),s.set(d.parent_session_id,u)}let o=t.filter(d=>d.role==="origin"),c=[...o.length>0?o:t.filter(d=>!d.parent_session_id)];for(;c.length>0;){let d=c.shift();if(n.has(d.session_id))continue;n.add(d.session_id),r.push(d.session_id);let u=s.get(d.session_id)??[];for(let g of u)n.has(g.session_id)||c.push(g)}for(let d of t)n.has(d.session_id)||(n.add(d.session_id),r.push(d.session_id));return r}function k_(e){let t=lr(e.sessionId),s=["",`BULK CONTEXT: You are titling session ${e.current} of ${e.total} in this thread.`,"The parent and earlier siblings already have titles (shown above). YOUR JOB:","",'1. Identify the naming pattern. If parent is "Build Feature X" and earlier',' siblings are "Phase A: API design" and "Phase B: client wiring", the pattern',' is "Phase {LETTER}: {topic}".',"2. If no pattern is yet established (this is the first child), INVENT a pattern",' that will scale to N children. Good patterns: "Phase A/B/C", "Wave 1 of M",',' "Step N", or a domain-specific structure if the thread name suggests one.',"3. Output a title that follows the pattern AND describes what THIS session"," does in 50 characters max.","","Output ONLY the title, no quotes, no trailing punctuation."].join(`
1141
1141
  `);return`${t}
1142
- ${s}`}function R_(e){return ye(e)?.auto_title_source??null}async function k_(e){let{spawnClaudePrompt:t,isClaudeCliAvailable:s}=await Promise.resolve().then(()=>(ge(),Pe));if(!s())throw new Error("claude CLI not found on PATH");let n=await t(e.prompt,[],{model:e.model});if(!n.success)throw new Error(`claude CLI exited ${n.exitCode}: ${n.stderr.slice(-500)}`);let r=A_(n.stdout);if(!r)throw new Error("claude CLI returned an empty title");return r.slice(0,T_)}function A_(e){let t=e.trim();if(!t)return"";try{let s=JSON.parse(t);if(s&&typeof s=="object"){let n=s.result;if(typeof n=="string")return dc(n)}}catch{}return dc(t)}function dc(e){return e.trim().replace(/^["'`]+|["'`]+$/g,"").replace(/\s+/g," ").replace(/[.!?]+$/g,"").trim()}async function pc(e,t={}){let s=te(e);if(!s)throw new Error(`thread not found: ${e}`);let n=y_(s.edges),r=n.length,o=t.force??!1,a=t.signal,c=[],d=[],u=[];for(let g=0;g<n.length;g++){let h=n[g],b=g+1;if(a?.aborted){let y={sessionId:h,reason:"cancelled"};d.push(y),t.onSkipped?.(y);continue}if(!o&&R_(h)==="agent"){let y={sessionId:h,reason:"already-titled"};d.push(y),t.onSkipped?.(y);continue}let S;try{if(uc)S=await uc({sessionId:h,current:b,total:r});else{let y=w_({sessionId:h,current:b,total:r});S=await k_({prompt:y,model:t.model})}}catch(y){let k=y instanceof Error?y.message:String(y??"unknown error"),w={sessionId:h,error:k};u.push(w),t.onFailed?.(w);continue}try{de(h,S,"agent")}catch(y){let k=y instanceof Error?y.message:String(y??"unknown error"),w={sessionId:h,error:`setAutoTitle failed: ${k}`};u.push(w),t.onFailed?.(w);continue}c.push(h),t.onProgress?.({current:b,total:r,sessionId:h,title:S})}return{generated:c,skipped:d,failed:u}}var uc=null;var Ft=new Map,N_=300*1e3;function Dt(e,t,s){let n=e.events.length+1;e.events.push({id:n,kind:t,data:s});for(let r of e.waiters)r.resolve();e.waiters.clear()}function O_(e){e.cleanupTimer&&clearTimeout(e.cleanupTimer),e.cleanupTimer=setTimeout(()=>{Ft.delete(e.jobId)},N_)}function L_(e){let t=0,s=0,n=0;for(let r of e.events)r.kind==="progress"&&(t+=1),r.kind==="skipped"&&(s+=1),r.kind==="error"&&(n+=1);return{jobId:e.jobId,threadId:e.threadId,status:e.status,startedAt:e.startedAt,endedAt:e.endedAt,total:e.total,done:t,skipped:s,failed:n,result:e.result}}function mc(e){let t=x_(),s=new AbortController,n={jobId:t,threadId:e.threadId,status:"running",startedAt:new Date().toISOString(),endedAt:null,total:0,events:[],waiters:new Set,controller:s,result:null,cleanupTimer:null};return Ft.set(t,n),(async()=>{await Promise.resolve();try{let r=await pc(e.threadId,{force:e.force??!1,signal:s.signal,model:e.model,onProgress:o=>{n.total=o.total,Dt(n,"progress",o)},onSkipped:o=>{Dt(n,"skipped",o)},onFailed:o=>{Dt(n,"error",o)}});n.result=r,n.status=s.signal.aborted?"cancelled":"done",n.endedAt=new Date().toISOString(),Dt(n,"done",r)}catch(r){let o=r instanceof Error?r.message:String(r??"unknown error");n.result={generated:[],skipped:[],failed:[{sessionId:e.threadId,error:o}]},n.status="failed",n.endedAt=new Date().toISOString(),Dt(n,"done",n.result)}finally{O_(n)}})(),t}async function*gc(e,t=0){let s=Ft.get(e);if(!s)return;let n=t;for(;;){for(;n<s.events.length;){let r=s.events[n];if(n+=1,yield r,r.kind==="done")return}if(s.endedAt)return;await new Promise(r=>{s.waiters.add({resolve:r})})}}function _c(e){let t=Ft.get(e);return!t||t.status!=="running"?!1:(t.controller.abort(),!0)}function dr(e){let t=Ft.get(e);return t?L_(t):null}Z();import{existsSync as C_,readFileSync as I_,writeFileSync as v_}from"node:fs";import{join as j_}from"node:path";import{z as ae}from"zod";var ur=j_($,"terminals.json"),fc=1440*60*1e3,M_=3e4,D_=6e4,F_=ae.object({shell_pid:ae.number(),tab_name:ae.string(),cwd:ae.string().nullable().optional(),opened_at:ae.string(),last_seen_at:ae.string()}),P_=ae.object({schema:ae.string().optional(),saved_at:ae.string().optional(),terminals:ae.array(F_).max(500).default([]),sessions_by_pid:ae.record(ae.string(),ae.array(ae.string()).max(50)).optional().default({})}),hc=/^[⠀-⣿✳\s]+/,Ec=/^\d+(\.\d+){1,3}$/;function ne(e){let t=e.trim();return!!(!t||hc.test(t)||Ec.test(t))}function tt(e){let t=e.trim();if(!t||Ec.test(t))return null;let s=t.replace(hc,"").trim();return s.length>0?s:null}function pr(e,t){if(!ne(e))return e;let s=tt(e);return s||(t&&!ne(t)?t:e)}function U_(e){let t=e.now-e.withinMs,s=e.pending.filter(n=>{let r=Date.parse(n.started_at);return Number.isFinite(r)&&r>=t});if(s.length===0)return{kind:"none"};if(e.shellPid!=null){let n=s.find(r=>r.shell_pid===e.shellPid);if(n)return{kind:"pid-match",entry:n}}if(e.cwd){let n=e.cwd.replace(/\/+$/,""),r=s.filter(o=>o.cwd&&o.cwd.replace(/\/+$/,"")===n);if(r.length===1)return{kind:"singleton-cwd",entry:r[0]};if(r.length>=2)return{kind:"ambiguous",candidates:r}}return{kind:"none"}}var mr=class{entries=new Map;origins=new Map;sessionsByPid=new Map;pendingClaudeStarts=[];deferredLinks=new Map;pidOwnership=new Map;loaded=!1;ensureLoaded(){if(!this.loaded&&(this.loaded=!0,!!C_(ur)))try{let t=I_(ur,"utf8"),s=JSON.parse(t),n=P_.safeParse(s);if(!n.success){console.warn("[terminal-registry] terminals.json failed validation, starting with empty registry:",n.error.issues);return}let r=n.data;for(let o of r.terminals)this.entries.set(o.shell_pid,{shell_pid:o.shell_pid,tab_name:o.tab_name,cwd:o.cwd??null,opened_at:o.opened_at,last_seen_at:o.last_seen_at});for(let[o,a]of Object.entries(r.sessions_by_pid??{})){let c=Number(o);if(!Number.isFinite(c))continue;let d=new Set;for(let u of a)u.length>0&&d.add(u);d.size>0&&this.sessionsByPid.set(c,d)}this.gc()}catch{}}save(){try{J();let t={schema:"claude-recall.terminals.v1",saved_at:new Date().toISOString(),terminals:Array.from(this.entries.values()),sessions_by_pid:Object.fromEntries(Array.from(this.sessionsByPid.entries()).map(([s,n])=>[String(s),Array.from(n)]))};v_(ur,JSON.stringify(t,null,2))}catch{}}upsert(t){this.ensureLoaded();let s=new Date().toISOString(),n=this.entries.get(t.shell_pid),r=pr(t.tab_name,n?.tab_name),o=n?.opened_at??t.opened_at,a={...t,tab_name:r,opened_at:o,last_seen_at:s};return this.entries.set(t.shell_pid,a),this.gc(),this.save(),a}rename(t,s){this.ensureLoaded();let n=this.entries.get(t);if(!n)return null;let r=pr(s,n.tab_name),o={...n,tab_name:r,last_seen_at:new Date().toISOString()};return this.entries.set(t,o),this.save(),o}remove(t){this.ensureLoaded();let s=this.entries.delete(t),n=this.sessionsByPid.delete(t);return this.outputTails.delete(t),this.pidOwnership.delete(t),(s||n)&&this.save(),s}claimPidOwnership(t,s,n=Date.now()){if(this.ensureLoaded(),!s)return"anonymous";let r=this.pidOwnership.get(t);return r?r.instance_id===s?(r.last_claim_at=n,"refreshed"):n-r.last_claim_at>D_?(this.pidOwnership.set(t,{instance_id:s,last_claim_at:n}),"claimed"):"rejected":(this.pidOwnership.set(t,{instance_id:s,last_claim_at:n}),"claimed")}pidOwnershipSnapshot(){return this.ensureLoaded(),Array.from(this.pidOwnership.entries()).map(([t,s])=>({shell_pid:t,instance_id:s.instance_id,last_claim_at:s.last_claim_at}))}sync(t){this.ensureLoaded();let s=new Date().toISOString(),n=0,r=0;for(let o of t){let a=this.entries.get(o.shell_pid),c=pr(o.tab_name,a?.tab_name),d=a?.opened_at??o.opened_at;this.entries.set(o.shell_pid,{...o,tab_name:c,opened_at:d,last_seen_at:s}),a?(a.tab_name!==c||a.cwd!==o.cwd)&&r++:n++}return this.gc(),this.save(),{added:n,updated:r,removed:0}}get(t){return this.ensureLoaded(),this.entries.get(t)??null}all(){return this.ensureLoaded(),this.gc(),Array.from(this.entries.values())}size(){return this.ensureLoaded(),this.entries.size}linkSession(t,s){this.ensureLoaded();let n=this.sessionsByPid.get(s);n||(n=new Set,this.sessionsByPid.set(s,n)),n.has(t)||(n.add(t),this.save())}sessionsFor(t){return this.ensureLoaded(),Array.from(this.sessionsByPid.get(t)??[])}isSessionAutoLinked(t){this.ensureLoaded();for(let s of this.sessionsByPid.values())if(s.has(t))return!0;return!1}unlinkSession(t){this.ensureLoaded();let s=!1;for(let[n,r]of this.sessionsByPid)r.delete(t)&&(s=!0,r.size===0&&this.sessionsByPid.delete(n));return s&&this.save(),s}pushPending(t){this.ensureLoaded(),this.gcPending(),this.pendingClaudeStarts.push({...t})}takePendingMatched(t){this.ensureLoaded(),this.gcPending();let s=U_({pending:this.pendingClaudeStarts,shellPid:t.shellPid,cwd:t.cwd,withinMs:t.withinMs,now:Date.now()});if(s.kind==="pid-match"||s.kind==="singleton-cwd"){let n=this.pendingClaudeStarts.indexOf(s.entry);n>=0&&this.pendingClaudeStarts.splice(n,1)}return s}pendingSize(){return this.ensureLoaded(),this.gcPending(),this.pendingClaudeStarts.length}deferSessionLink(t,s,n,r){this.ensureLoaded(),this.gcDeferredLinks(),this.deferredLinks.set(t,{parent_shell_pid:s,queued_at:Date.now(),cwd:n,git_branch:r})}allDeferredLinks(){return this.ensureLoaded(),this.gcDeferredLinks(),Array.from(this.deferredLinks.entries()).map(([t,s])=>({session_id:t,...s}))}resolveDeferredLink(t){return this.deferredLinks.delete(t)}deferredLinkSize(){return this.ensureLoaded(),this.gcDeferredLinks(),this.deferredLinks.size}gcDeferredLinks(){let t=Date.now()-9e4;for(let[s,n]of this.deferredLinks)n.queued_at<t&&this.deferredLinks.delete(s)}gcPending(){let t=Date.now()-M_;this.pendingClaudeStarts.length!==0&&(this.pendingClaudeStarts=this.pendingClaudeStarts.filter(s=>{let n=Date.parse(s.started_at);return Number.isFinite(n)&&n>=t}))}outputTails=new Map;setOutputTail(t,s,n){this.ensureLoaded(),this.outputTails.set(t,{text:s,captured_at:n})}getOutputTail(t){return this.ensureLoaded(),this.outputTails.get(t)??null}allOutputTails(){return this.ensureLoaded(),new Map(this.outputTails)}removeOutputTail(t){return this.outputTails.delete(t)}setOrigin(t,s){this.ensureLoaded(),this.origins.set(t,s),this.gcOrigins()}getOrigin(t){return this.ensureLoaded(),this.origins.get(t)??null}removeOrigin(t){return this.ensureLoaded(),this.origins.delete(t)}allOrigins(){return this.ensureLoaded(),this.gcOrigins(),new Map(this.origins)}originSize(){return this.ensureLoaded(),this.origins.size}gc(){let t=Date.now()-fc;for(let[s,n]of this.entries){let r=Date.parse(n.last_seen_at);!Number.isNaN(r)&&r<t&&this.entries.delete(s)}}gcOrigins(){let t=Date.now()-fc;for(let[s,n]of this.origins)n.detectedAt<t&&this.origins.delete(s)}reapStaleLinks(t=10080*60*1e3){this.ensureLoaded();let n=Date.now()-t,r=0,o=0;for(let[a,c]of this.sessionsByPid){let d=this.entries.get(a);if(d){let u=Date.parse(d.last_seen_at);if(Number.isFinite(u)&&u>=n)continue}o+=c.size,this.sessionsByPid.delete(a),d&&(this.entries.delete(a),r++)}return(r||o)&&this.save(),{pruned_pids:r,pruned_sessions:o}}gcDeadPids(){this.ensureLoaded();let t=0,s=0;for(let n of[...this.entries.keys()]){let r=!0;try{process.kill(n,0)}catch(a){a.code==="ESRCH"&&(r=!1)}if(r)continue;this.entries.delete(n),t++;let o=this.sessionsByPid.get(n);o&&(s+=o.size,this.sessionsByPid.delete(n)),this.outputTails.delete(n),this.pidOwnership.delete(n)}return(t||s)&&this.save(),{pruned_pids:t,pruned_sessions:s}}},I=new mr;import{execFile as K_}from"node:child_process";import{promisify as z_}from"node:util";import{existsSync as V_}from"node:fs";import{basename as Z_}from"node:path";H();import{execFile as $_}from"node:child_process";import{readFile as B_}from"node:fs/promises";import{promisify as H_}from"node:util";var W_=H_($_),bc=["CURSOR_TRACE_ID","VSCODE_PID","VSCODE_INJECTION","TERM_PROGRAM","TERM_PROGRAM_VERSION","TERM","WT_SESSION","KITTY_WINDOW_ID","ALACRITTY_SOCKET","WARP_HONOR_PS1"];function q_(e){let t={};for(let s of bc){let n=e[s];typeof n=="string"&&n.length>0&&(t[s]=n)}return t}function J_(e){let t=Date.now();if(e.CURSOR_TRACE_ID)return{editor:"cursor",label:"Cursor",detectedAt:t};if(e.VSCODE_PID||e.VSCODE_INJECTION)return{editor:"vscode",label:"VS Code",detectedAt:t};let s=e.TERM_PROGRAM;return s==="WarpTerminal"?{editor:"warp",label:"Warp",detectedAt:t}:s==="iTerm.app"?{editor:"iterm",label:"iTerm",detectedAt:t}:s==="Apple_Terminal"?{editor:"apple-terminal",label:"Terminal",detectedAt:t}:s==="WezTerm"?{editor:"wezterm",label:"WezTerm",detectedAt:t}:e.WT_SESSION?{editor:"windows-terminal",label:"Windows Terminal",detectedAt:t}:e.KITTY_WINDOW_ID?{editor:"kitty",label:"Kitty",detectedAt:t}:e.TERM==="alacritty"||e.ALACRITTY_SOCKET?{editor:"alacritty",label:"Alacritty",detectedAt:t}:null}async function X_(e){if(process.platform==="linux")try{let t=await B_(`/proc/${e}/environ`,"utf8");return G_(t)}catch{return{}}try{let{stdout:t}=await W_("/bin/ps",["eww","-o","command=","-p",String(e)],{timeout:2e3,maxBuffer:1048576});return Y_(t)}catch{return{}}}function G_(e){let t={};for(let s of e.split("\0")){if(!s)continue;let n=s.indexOf("=");if(n<=0)continue;let r=s.slice(0,n),o=s.slice(n+1);t[r]=o}return t}function Y_(e){let t={},s=new Set(bc),n=e.replace(/\s+/g," ").trim().split(" ");for(let r of n){let o=r.indexOf("=");if(o<=0)continue;let a=r.slice(0,o);s.has(a)&&(t[a]=r.slice(o+1))}return t}async function Sc(e){if(!Number.isFinite(e)||e<=0)return null;try{let t=await X_(e),s=q_(t);return J_(s)}catch{return null}}var js=z_(K_),vs;function Q_(){if(vs!==void 0)return vs;let e=["/usr/sbin/lsof","/usr/bin/lsof","/opt/homebrew/bin/lsof"];for(let t of e)if(V_(t))return vs=t,t;return vs=null,null}async function ef(e){let t=Q_();if(!t)return null;try{let{stdout:s}=await js(t,["-Fpc",e],{timeout:2e3}),n=s.split(`
1143
- `),r=null,o=null,a=null;for(let c of n)c.startsWith("p")?(a=Number(c.slice(1)),Number.isFinite(a)&&a>0?r==null&&(r=a):a=null):c.startsWith("c")&&a!=null&&c.slice(1).trim()==="claude"&&o==null&&(o=a);return o??r}catch{return null}}async function Tc(e){try{let{stdout:t}=await js("/bin/ps",["-o","ppid=","-p",String(e)],{timeout:2e3}),s=Number(t.trim());return Number.isFinite(s)&&s>0?s:null}catch{return null}}async function tf(e){try{let{stdout:t}=await js("/bin/ps",["-o","lstart=","-p",String(e)],{timeout:2e3}),s=Date.parse(t.trim());return Number.isFinite(s)?s:null}catch{return null}}var sf=new Set(["zsh","bash","fish","sh","dash","ksh","tcsh","csh","pwsh","powershell","cmd","nu","node","deno","bun","python","python3","ruby","ts-node","tsx","go","cargo","java","php","irb","pry","iex","terminal","shell","console"]);function re(e){let t=e.trim().toLowerCase();if(!t)return!0;let s=t.replace(/^[-/]+/,"").replace(/^.*\//,"").replace(/\s*\(\d+\)\s*$/,"").trim();return sf.has(s)}function st(e){let t=e.tabName?.trim();return t&&!re(t)&&!ne(t)?t:null}function nf(e){try{return f().prepare("SELECT cwd, git_branch FROM sessions WHERE id = ?").get(e)??null}catch{return null}}async function Ms(e){let t=Z_(e,".jsonl");if(Te(t))return;let s=nf(t),n=await ef(e),r=n?await Tc(n):null,o=n?await Sc(n):null;o&&I.setOrigin(t,o);let a=null,c=null,d=null,u=I.takePendingMatched({shellPid:r,cwd:s?.cwd??null,withinMs:3e4});if(u.kind==="ambiguous"){console.log(`[correlator] ambiguous pending for ${t.slice(0,8)} (${u.candidates.length} candidates in ${s?.cwd??"?"}) \u2014 refusing to guess; heuristic title will display`);return}if(u.kind==="pid-match"||u.kind==="singleton-cwd"){let y=u.entry;c=y.shell_pid,d=u.kind==="pid-match"?"pending-pid":"pending-cwd",a=I.get(y.shell_pid)??{shell_pid:y.shell_pid,tab_name:y.tab_name,cwd:y.cwd,opened_at:y.started_at,last_seen_at:y.started_at}}let g=null;if(!a&&n){let y=n;for(let k=0;k<4&&y!=null;k++){let w=await Tc(y);if(!w)break;let D=I.get(w);if(D){a=D,c=w,d="ppid";break}g==null&&(g=w),y=w}}if(!a&&s?.cwd){let y=s.cwd.replace(/\/+$/,""),k=I.all().filter(w=>w.cwd&&w.cwd.replace(/\/+$/,"")===y);k.length===1?(a=k[0],c=a.shell_pid,d="cwd"):k.length>=2&&console.log(`[correlator] ${k.length} registered terminals in ${y} for ${t.slice(0,8)} \u2014 refusing to guess; heuristic title will display`)}let h=null;if(a?.tab_name&&!re(a.tab_name)&&!ne(a.tab_name))h=a.tab_name;else if(a?.tab_name&&ne(a.tab_name)){let y=tt(a.tab_name);y&&!re(y)&&(h=y)}if(!h&&!(d==="pending-pid"||d==="pending-cwd")&&a&&s?.cwd){let y=s.cwd.replace(/\/+$/,""),k=I.all().filter(w=>w.shell_pid!==c&&w.cwd&&w.cwd.replace(/\/+$/,"")===y&&!re(w.tab_name)&&!ne(w.tab_name)).sort((w,D)=>Date.parse(D.last_seen_at)-Date.parse(w.last_seen_at))[0];k&&(h=k.tab_name)}let S=st({tabName:h,origin:o,cwd:s?.cwd??null,gitBranch:s?.git_branch??null});if(g!=null&&!c&&I.deferSessionLink(t,g,s?.cwd??null,s?.git_branch??null),!!S)try{me(t,S);let y=!!h&&!re(h)&&!ne(h)&&S===h.trim();c!=null&&I.linkSession(t,c);let k=d==="pending-pid"?"pending PID-exact match":d==="pending-cwd"?"pending cwd-singleton match":d??"unknown";console.log(`[correlator] auto-aliased ${t.slice(0,8)} \u2192 "${S}"`+(y?` (tab name via ${k}, shell pid ${c})`:a?` (generic shell name "${a.tab_name}" \u2192 ${o?.editor??"origin"} fallback, shell pid ${c})`:o?` (${o.editor} origin \u2014 no terminal match)`:""))}catch{}}async function rf(){try{let{stdout:e}=await js("/bin/ps",["-eo","pid=,ppid=,comm="],{timeout:2e3}),t=new Map;for(let s of e.split(`
1144
- `)){let n=s.trim();if(!n)continue;let r=n.match(/^(\d+)\s+(\d+)\s+(.+)$/);if(!r)continue;let o=Number(r[1]),a=Number(r[2]),c=r[3].trim();(c==="claude"||c.endsWith("/claude")||c.endsWith("/bin/claude"))&&(!Number.isFinite(o)||!Number.isFinite(a)||t.set(o,a))}return t}catch{return new Map}}var of=9e4;function af(e){let t=(Date.now()-of)/1e3,s=e.replace(/\/+$/,"");return f().prepare(`SELECT s.id, NULLIF(sa.alias, '') AS alias, s.started_at AS started_at
1142
+ ${s}`}function A_(e){return ye(e)?.auto_title_source??null}async function x_(e){let{spawnClaudePrompt:t,isClaudeCliAvailable:s}=await Promise.resolve().then(()=>(ge(),Pe));if(!s())throw new Error("claude CLI not found on PATH");let n=await t(e.prompt,[],{model:e.model});if(!n.success)throw new Error(`claude CLI exited ${n.exitCode}: ${n.stderr.slice(-500)}`);let r=N_(n.stdout);if(!r)throw new Error("claude CLI returned an empty title");return r.slice(0,w_)}function N_(e){let t=e.trim();if(!t)return"";try{let s=JSON.parse(t);if(s&&typeof s=="object"){let n=s.result;if(typeof n=="string")return dc(n)}}catch{}return dc(t)}function dc(e){return e.trim().replace(/^["'`]+|["'`]+$/g,"").replace(/\s+/g," ").replace(/[.!?]+$/g,"").trim()}async function pc(e,t={}){let s=te(e);if(!s)throw new Error(`thread not found: ${e}`);let n=R_(s.edges),r=n.length,o=t.force??!1,a=t.signal,c=[],d=[],u=[];for(let g=0;g<n.length;g++){let h=n[g],b=g+1;if(a?.aborted){let y={sessionId:h,reason:"cancelled"};d.push(y),t.onSkipped?.(y);continue}if(!o&&A_(h)==="agent"){let y={sessionId:h,reason:"already-titled"};d.push(y),t.onSkipped?.(y);continue}let S;try{if(uc)S=await uc({sessionId:h,current:b,total:r});else{let y=k_({sessionId:h,current:b,total:r});S=await x_({prompt:y,model:t.model})}}catch(y){let k=y instanceof Error?y.message:String(y??"unknown error"),w={sessionId:h,error:k};u.push(w),t.onFailed?.(w);continue}try{de(h,S,"agent")}catch(y){let k=y instanceof Error?y.message:String(y??"unknown error"),w={sessionId:h,error:`setAutoTitle failed: ${k}`};u.push(w),t.onFailed?.(w);continue}c.push(h),t.onProgress?.({current:b,total:r,sessionId:h,title:S})}return{generated:c,skipped:d,failed:u}}var uc=null;var Ft=new Map,L_=300*1e3;function Dt(e,t,s){let n=e.events.length+1;e.events.push({id:n,kind:t,data:s});for(let r of e.waiters)r.resolve();e.waiters.clear()}function C_(e){e.cleanupTimer&&clearTimeout(e.cleanupTimer),e.cleanupTimer=setTimeout(()=>{Ft.delete(e.jobId)},L_)}function I_(e){let t=0,s=0,n=0;for(let r of e.events)r.kind==="progress"&&(t+=1),r.kind==="skipped"&&(s+=1),r.kind==="error"&&(n+=1);return{jobId:e.jobId,threadId:e.threadId,status:e.status,startedAt:e.startedAt,endedAt:e.endedAt,total:e.total,done:t,skipped:s,failed:n,result:e.result}}function mc(e){let t=O_(),s=new AbortController,n={jobId:t,threadId:e.threadId,status:"running",startedAt:new Date().toISOString(),endedAt:null,total:0,events:[],waiters:new Set,controller:s,result:null,cleanupTimer:null};return Ft.set(t,n),(async()=>{await Promise.resolve();try{let r=await pc(e.threadId,{force:e.force??!1,signal:s.signal,model:e.model,onProgress:o=>{n.total=o.total,Dt(n,"progress",o)},onSkipped:o=>{Dt(n,"skipped",o)},onFailed:o=>{Dt(n,"error",o)}});n.result=r,n.status=s.signal.aborted?"cancelled":"done",n.endedAt=new Date().toISOString(),Dt(n,"done",r)}catch(r){let o=r instanceof Error?r.message:String(r??"unknown error");n.result={generated:[],skipped:[],failed:[{sessionId:e.threadId,error:o}]},n.status="failed",n.endedAt=new Date().toISOString(),Dt(n,"done",n.result)}finally{C_(n)}})(),t}async function*gc(e,t=0){let s=Ft.get(e);if(!s)return;let n=t;for(;;){for(;n<s.events.length;){let r=s.events[n];if(n+=1,yield r,r.kind==="done")return}if(s.endedAt)return;await new Promise(r=>{s.waiters.add({resolve:r})})}}function _c(e){let t=Ft.get(e);return!t||t.status!=="running"?!1:(t.controller.abort(),!0)}function dr(e){let t=Ft.get(e);return t?I_(t):null}Z();import{existsSync as v_,readFileSync as j_,writeFileSync as M_}from"node:fs";import{join as D_}from"node:path";import{z as ae}from"zod";var ur=D_($,"terminals.json"),fc=1440*60*1e3,F_=3e4,P_=6e4,U_=ae.object({shell_pid:ae.number(),tab_name:ae.string(),cwd:ae.string().nullable().optional(),opened_at:ae.string(),last_seen_at:ae.string()}),$_=ae.object({schema:ae.string().optional(),saved_at:ae.string().optional(),terminals:ae.array(U_).max(500).default([]),sessions_by_pid:ae.record(ae.string(),ae.array(ae.string()).max(50)).optional().default({})}),hc=/^[⠀-⣿✳\s]+/,Ec=/^\d+(\.\d+){1,3}$/;function ne(e){let t=e.trim();return!!(!t||hc.test(t)||Ec.test(t))}function tt(e){let t=e.trim();if(!t||Ec.test(t))return null;let s=t.replace(hc,"").trim();return s.length>0?s:null}function pr(e,t){if(!ne(e))return e;let s=tt(e);return s||(t&&!ne(t)?t:e)}function B_(e){let t=e.now-e.withinMs,s=e.pending.filter(n=>{let r=Date.parse(n.started_at);return Number.isFinite(r)&&r>=t});if(s.length===0)return{kind:"none"};if(e.shellPid!=null){let n=s.find(r=>r.shell_pid===e.shellPid);if(n)return{kind:"pid-match",entry:n}}if(e.cwd){let n=e.cwd.replace(/\/+$/,""),r=s.filter(o=>o.cwd&&o.cwd.replace(/\/+$/,"")===n);if(r.length===1)return{kind:"singleton-cwd",entry:r[0]};if(r.length>=2)return{kind:"ambiguous",candidates:r}}return{kind:"none"}}var mr=class{entries=new Map;origins=new Map;sessionsByPid=new Map;pendingClaudeStarts=[];deferredLinks=new Map;pidOwnership=new Map;loaded=!1;ensureLoaded(){if(!this.loaded&&(this.loaded=!0,!!v_(ur)))try{let t=j_(ur,"utf8"),s=JSON.parse(t),n=$_.safeParse(s);if(!n.success){console.warn("[terminal-registry] terminals.json failed validation, starting with empty registry:",n.error.issues);return}let r=n.data;for(let o of r.terminals)this.entries.set(o.shell_pid,{shell_pid:o.shell_pid,tab_name:o.tab_name,cwd:o.cwd??null,opened_at:o.opened_at,last_seen_at:o.last_seen_at});for(let[o,a]of Object.entries(r.sessions_by_pid??{})){let c=Number(o);if(!Number.isFinite(c))continue;let d=new Set;for(let u of a)u.length>0&&d.add(u);d.size>0&&this.sessionsByPid.set(c,d)}this.gc()}catch{}}save(){try{J();let t={schema:"claude-recall.terminals.v1",saved_at:new Date().toISOString(),terminals:Array.from(this.entries.values()),sessions_by_pid:Object.fromEntries(Array.from(this.sessionsByPid.entries()).map(([s,n])=>[String(s),Array.from(n)]))};M_(ur,JSON.stringify(t,null,2))}catch{}}upsert(t){this.ensureLoaded();let s=new Date().toISOString(),n=this.entries.get(t.shell_pid),r=pr(t.tab_name,n?.tab_name),o=n?.opened_at??t.opened_at,a={...t,tab_name:r,opened_at:o,last_seen_at:s};return this.entries.set(t.shell_pid,a),this.gc(),this.save(),a}rename(t,s){this.ensureLoaded();let n=this.entries.get(t);if(!n)return null;let r=pr(s,n.tab_name),o={...n,tab_name:r,last_seen_at:new Date().toISOString()};return this.entries.set(t,o),this.save(),o}remove(t){this.ensureLoaded();let s=this.entries.delete(t),n=this.sessionsByPid.delete(t);return this.outputTails.delete(t),this.pidOwnership.delete(t),(s||n)&&this.save(),s}claimPidOwnership(t,s,n=Date.now()){if(this.ensureLoaded(),!s)return"anonymous";let r=this.pidOwnership.get(t);return r?r.instance_id===s?(r.last_claim_at=n,"refreshed"):n-r.last_claim_at>P_?(this.pidOwnership.set(t,{instance_id:s,last_claim_at:n}),"claimed"):"rejected":(this.pidOwnership.set(t,{instance_id:s,last_claim_at:n}),"claimed")}pidOwnershipSnapshot(){return this.ensureLoaded(),Array.from(this.pidOwnership.entries()).map(([t,s])=>({shell_pid:t,instance_id:s.instance_id,last_claim_at:s.last_claim_at}))}sync(t){this.ensureLoaded();let s=new Date().toISOString(),n=0,r=0;for(let o of t){let a=this.entries.get(o.shell_pid),c=pr(o.tab_name,a?.tab_name),d=a?.opened_at??o.opened_at;this.entries.set(o.shell_pid,{...o,tab_name:c,opened_at:d,last_seen_at:s}),a?(a.tab_name!==c||a.cwd!==o.cwd)&&r++:n++}return this.gc(),this.save(),{added:n,updated:r,removed:0}}get(t){return this.ensureLoaded(),this.entries.get(t)??null}all(){return this.ensureLoaded(),this.gc(),Array.from(this.entries.values())}size(){return this.ensureLoaded(),this.entries.size}linkSession(t,s){this.ensureLoaded();let n=this.sessionsByPid.get(s);n||(n=new Set,this.sessionsByPid.set(s,n)),n.has(t)||(n.add(t),this.save())}sessionsFor(t){return this.ensureLoaded(),Array.from(this.sessionsByPid.get(t)??[])}isSessionAutoLinked(t){this.ensureLoaded();for(let s of this.sessionsByPid.values())if(s.has(t))return!0;return!1}unlinkSession(t){this.ensureLoaded();let s=!1;for(let[n,r]of this.sessionsByPid)r.delete(t)&&(s=!0,r.size===0&&this.sessionsByPid.delete(n));return s&&this.save(),s}pushPending(t){this.ensureLoaded(),this.gcPending(),this.pendingClaudeStarts.push({...t})}takePendingMatched(t){this.ensureLoaded(),this.gcPending();let s=B_({pending:this.pendingClaudeStarts,shellPid:t.shellPid,cwd:t.cwd,withinMs:t.withinMs,now:Date.now()});if(s.kind==="pid-match"||s.kind==="singleton-cwd"){let n=this.pendingClaudeStarts.indexOf(s.entry);n>=0&&this.pendingClaudeStarts.splice(n,1)}return s}pendingSize(){return this.ensureLoaded(),this.gcPending(),this.pendingClaudeStarts.length}deferSessionLink(t,s,n,r){this.ensureLoaded(),this.gcDeferredLinks(),this.deferredLinks.set(t,{parent_shell_pid:s,queued_at:Date.now(),cwd:n,git_branch:r})}allDeferredLinks(){return this.ensureLoaded(),this.gcDeferredLinks(),Array.from(this.deferredLinks.entries()).map(([t,s])=>({session_id:t,...s}))}resolveDeferredLink(t){return this.deferredLinks.delete(t)}deferredLinkSize(){return this.ensureLoaded(),this.gcDeferredLinks(),this.deferredLinks.size}gcDeferredLinks(){let t=Date.now()-9e4;for(let[s,n]of this.deferredLinks)n.queued_at<t&&this.deferredLinks.delete(s)}gcPending(){let t=Date.now()-F_;this.pendingClaudeStarts.length!==0&&(this.pendingClaudeStarts=this.pendingClaudeStarts.filter(s=>{let n=Date.parse(s.started_at);return Number.isFinite(n)&&n>=t}))}outputTails=new Map;setOutputTail(t,s,n){this.ensureLoaded(),this.outputTails.set(t,{text:s,captured_at:n})}getOutputTail(t){return this.ensureLoaded(),this.outputTails.get(t)??null}allOutputTails(){return this.ensureLoaded(),new Map(this.outputTails)}removeOutputTail(t){return this.outputTails.delete(t)}setOrigin(t,s){this.ensureLoaded(),this.origins.set(t,s),this.gcOrigins()}getOrigin(t){return this.ensureLoaded(),this.origins.get(t)??null}removeOrigin(t){return this.ensureLoaded(),this.origins.delete(t)}allOrigins(){return this.ensureLoaded(),this.gcOrigins(),new Map(this.origins)}originSize(){return this.ensureLoaded(),this.origins.size}gc(){let t=Date.now()-fc;for(let[s,n]of this.entries){let r=Date.parse(n.last_seen_at);!Number.isNaN(r)&&r<t&&this.entries.delete(s)}}gcOrigins(){let t=Date.now()-fc;for(let[s,n]of this.origins)n.detectedAt<t&&this.origins.delete(s)}reapStaleLinks(t=10080*60*1e3){this.ensureLoaded();let n=Date.now()-t,r=0,o=0;for(let[a,c]of this.sessionsByPid){let d=this.entries.get(a);if(d){let u=Date.parse(d.last_seen_at);if(Number.isFinite(u)&&u>=n)continue}o+=c.size,this.sessionsByPid.delete(a),d&&(this.entries.delete(a),r++)}return(r||o)&&this.save(),{pruned_pids:r,pruned_sessions:o}}gcDeadPids(){this.ensureLoaded();let t=0,s=0;for(let n of[...this.entries.keys()]){let r=!0;try{process.kill(n,0)}catch(a){a.code==="ESRCH"&&(r=!1)}if(r)continue;this.entries.delete(n),t++;let o=this.sessionsByPid.get(n);o&&(s+=o.size,this.sessionsByPid.delete(n)),this.outputTails.delete(n),this.pidOwnership.delete(n)}return(t||s)&&this.save(),{pruned_pids:t,pruned_sessions:s}}},I=new mr;import{execFile as V_}from"node:child_process";import{promisify as Z_}from"node:util";import{existsSync as Q_}from"node:fs";import{basename as ef}from"node:path";H();import{execFile as H_}from"node:child_process";import{readFile as W_}from"node:fs/promises";import{promisify as q_}from"node:util";var J_=q_(H_),bc=["CURSOR_TRACE_ID","VSCODE_PID","VSCODE_INJECTION","TERM_PROGRAM","TERM_PROGRAM_VERSION","TERM","WT_SESSION","KITTY_WINDOW_ID","ALACRITTY_SOCKET","WARP_HONOR_PS1"];function X_(e){let t={};for(let s of bc){let n=e[s];typeof n=="string"&&n.length>0&&(t[s]=n)}return t}function G_(e){let t=Date.now();if(e.CURSOR_TRACE_ID)return{editor:"cursor",label:"Cursor",detectedAt:t};if(e.VSCODE_PID||e.VSCODE_INJECTION)return{editor:"vscode",label:"VS Code",detectedAt:t};let s=e.TERM_PROGRAM;return s==="WarpTerminal"?{editor:"warp",label:"Warp",detectedAt:t}:s==="iTerm.app"?{editor:"iterm",label:"iTerm",detectedAt:t}:s==="Apple_Terminal"?{editor:"apple-terminal",label:"Terminal",detectedAt:t}:s==="WezTerm"?{editor:"wezterm",label:"WezTerm",detectedAt:t}:e.WT_SESSION?{editor:"windows-terminal",label:"Windows Terminal",detectedAt:t}:e.KITTY_WINDOW_ID?{editor:"kitty",label:"Kitty",detectedAt:t}:e.TERM==="alacritty"||e.ALACRITTY_SOCKET?{editor:"alacritty",label:"Alacritty",detectedAt:t}:null}async function Y_(e){if(process.platform==="linux")try{let t=await W_(`/proc/${e}/environ`,"utf8");return K_(t)}catch{return{}}try{let{stdout:t}=await J_("/bin/ps",["eww","-o","command=","-p",String(e)],{timeout:2e3,maxBuffer:1048576});return z_(t)}catch{return{}}}function K_(e){let t={};for(let s of e.split("\0")){if(!s)continue;let n=s.indexOf("=");if(n<=0)continue;let r=s.slice(0,n),o=s.slice(n+1);t[r]=o}return t}function z_(e){let t={},s=new Set(bc),n=e.replace(/\s+/g," ").trim().split(" ");for(let r of n){let o=r.indexOf("=");if(o<=0)continue;let a=r.slice(0,o);s.has(a)&&(t[a]=r.slice(o+1))}return t}async function Sc(e){if(!Number.isFinite(e)||e<=0)return null;try{let t=await Y_(e),s=X_(t);return G_(s)}catch{return null}}var js=Z_(V_),vs;function tf(){if(vs!==void 0)return vs;let e=["/usr/sbin/lsof","/usr/bin/lsof","/opt/homebrew/bin/lsof"];for(let t of e)if(Q_(t))return vs=t,t;return vs=null,null}async function sf(e){let t=tf();if(!t)return null;try{let{stdout:s}=await js(t,["-Fpc",e],{timeout:2e3}),n=s.split(`
1143
+ `),r=null,o=null,a=null;for(let c of n)c.startsWith("p")?(a=Number(c.slice(1)),Number.isFinite(a)&&a>0?r==null&&(r=a):a=null):c.startsWith("c")&&a!=null&&c.slice(1).trim()==="claude"&&o==null&&(o=a);return o??r}catch{return null}}async function Tc(e){try{let{stdout:t}=await js("/bin/ps",["-o","ppid=","-p",String(e)],{timeout:2e3}),s=Number(t.trim());return Number.isFinite(s)&&s>0?s:null}catch{return null}}async function nf(e){try{let{stdout:t}=await js("/bin/ps",["-o","lstart=","-p",String(e)],{timeout:2e3}),s=Date.parse(t.trim());return Number.isFinite(s)?s:null}catch{return null}}var rf=new Set(["zsh","bash","fish","sh","dash","ksh","tcsh","csh","pwsh","powershell","cmd","nu","node","deno","bun","python","python3","ruby","ts-node","tsx","go","cargo","java","php","irb","pry","iex","terminal","shell","console"]);function re(e){let t=e.trim().toLowerCase();if(!t)return!0;let s=t.replace(/^[-/]+/,"").replace(/^.*\//,"").replace(/\s*\(\d+\)\s*$/,"").trim();return rf.has(s)}function st(e){let t=e.tabName?.trim();return t&&!re(t)&&!ne(t)?t:null}function of(e){try{return f().prepare("SELECT cwd, git_branch FROM sessions WHERE id = ?").get(e)??null}catch{return null}}async function Ms(e){let t=ef(e,".jsonl");if(Te(t))return;let s=of(t),n=await sf(e),r=n?await Tc(n):null,o=n?await Sc(n):null;o&&I.setOrigin(t,o);let a=null,c=null,d=null,u=I.takePendingMatched({shellPid:r,cwd:s?.cwd??null,withinMs:3e4});if(u.kind==="ambiguous"){console.log(`[correlator] ambiguous pending for ${t.slice(0,8)} (${u.candidates.length} candidates in ${s?.cwd??"?"}) \u2014 refusing to guess; heuristic title will display`);return}if(u.kind==="pid-match"||u.kind==="singleton-cwd"){let y=u.entry;c=y.shell_pid,d=u.kind==="pid-match"?"pending-pid":"pending-cwd",a=I.get(y.shell_pid)??{shell_pid:y.shell_pid,tab_name:y.tab_name,cwd:y.cwd,opened_at:y.started_at,last_seen_at:y.started_at}}let g=null;if(!a&&n){let y=n;for(let k=0;k<4&&y!=null;k++){let w=await Tc(y);if(!w)break;let D=I.get(w);if(D){a=D,c=w,d="ppid";break}g==null&&(g=w),y=w}}if(!a&&s?.cwd){let y=s.cwd.replace(/\/+$/,""),k=I.all().filter(w=>w.cwd&&w.cwd.replace(/\/+$/,"")===y);k.length===1?(a=k[0],c=a.shell_pid,d="cwd"):k.length>=2&&console.log(`[correlator] ${k.length} registered terminals in ${y} for ${t.slice(0,8)} \u2014 refusing to guess; heuristic title will display`)}let h=null;if(a?.tab_name&&!re(a.tab_name)&&!ne(a.tab_name))h=a.tab_name;else if(a?.tab_name&&ne(a.tab_name)){let y=tt(a.tab_name);y&&!re(y)&&(h=y)}if(!h&&!(d==="pending-pid"||d==="pending-cwd")&&a&&s?.cwd){let y=s.cwd.replace(/\/+$/,""),k=I.all().filter(w=>w.shell_pid!==c&&w.cwd&&w.cwd.replace(/\/+$/,"")===y&&!re(w.tab_name)&&!ne(w.tab_name)).sort((w,D)=>Date.parse(D.last_seen_at)-Date.parse(w.last_seen_at))[0];k&&(h=k.tab_name)}let S=st({tabName:h,origin:o,cwd:s?.cwd??null,gitBranch:s?.git_branch??null});if(g!=null&&!c&&I.deferSessionLink(t,g,s?.cwd??null,s?.git_branch??null),!!S)try{me(t,S);let y=!!h&&!re(h)&&!ne(h)&&S===h.trim();c!=null&&I.linkSession(t,c);let k=d==="pending-pid"?"pending PID-exact match":d==="pending-cwd"?"pending cwd-singleton match":d??"unknown";console.log(`[correlator] auto-aliased ${t.slice(0,8)} \u2192 "${S}"`+(y?` (tab name via ${k}, shell pid ${c})`:a?` (generic shell name "${a.tab_name}" \u2192 ${o?.editor??"origin"} fallback, shell pid ${c})`:o?` (${o.editor} origin \u2014 no terminal match)`:""))}catch{}}async function af(){try{let{stdout:e}=await js("/bin/ps",["-eo","pid=,ppid=,comm="],{timeout:2e3}),t=new Map;for(let s of e.split(`
1144
+ `)){let n=s.trim();if(!n)continue;let r=n.match(/^(\d+)\s+(\d+)\s+(.+)$/);if(!r)continue;let o=Number(r[1]),a=Number(r[2]),c=r[3].trim();(c==="claude"||c.endsWith("/claude")||c.endsWith("/bin/claude"))&&(!Number.isFinite(o)||!Number.isFinite(a)||t.set(o,a))}return t}catch{return new Map}}var cf=9e4;function lf(e){let t=(Date.now()-cf)/1e3,s=e.replace(/\/+$/,"");return f().prepare(`SELECT s.id, NULLIF(sa.alias, '') AS alias, s.started_at AS started_at
1145
1145
  FROM sessions s
1146
1146
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
1147
- WHERE s.cwd = ? AND s.file_mtime > ?`).all(s,t).map(r=>({id:r.id,alias:r.alias,started_at_ms:r.started_at?Date.parse(r.started_at):null}))}async function cf(e){let t=await import("node:fs/promises"),s="";try{let r=await t.open(e,"r");try{let o=Buffer.alloc(32768),{bytesRead:a}=await r.read(o,0,o.length,0);s=o.toString("utf8",0,a)}finally{await r.close()}}catch{return[]}let n=[];for(let r of s.split(`
1147
+ WHERE s.cwd = ? AND s.file_mtime > ?`).all(s,t).map(r=>({id:r.id,alias:r.alias,started_at_ms:r.started_at?Date.parse(r.started_at):null}))}async function df(e){let t=await import("node:fs/promises"),s="";try{let r=await t.open(e,"r");try{let o=Buffer.alloc(32768),{bytesRead:a}=await r.read(o,0,o.length,0);s=o.toString("utf8",0,a)}finally{await r.close()}}catch{return[]}let n=[];for(let r of s.split(`
1148
1148
  `)){if(!r.trim())continue;let o;try{o=JSON.parse(r)}catch{continue}let a=o;if(!a||a.type!=="user"&&a.type!=="assistant")continue;let c=a.message?.content,d="";if(typeof c=="string")d=c;else if(Array.isArray(c))for(let u of c)u&&typeof u=="object"&&"text"in u&&typeof u.text=="string"&&(d+=u.text+`
1149
- `);if(d){for(let u of d.split(/\r?\n/)){let g=u.trim();g.length>=60&&g.length<=400&&n.push(g)}if(n.length>=8)break}}return n}async function yc(e){if(Te(e))return null;let t=f().prepare("SELECT cwd, file_path FROM sessions WHERE id = ?").get(e);if(!t?.cwd||!t.file_path)return null;let s=await cf(t.file_path);if(s.length===0)return null;let n=t.cwd.replace(/\/+$/,""),r=I.allOutputTails(),o=[];for(let[a,c]of r){let d=I.get(a);if(!d||!d.cwd||d.cwd.replace(/\/+$/,"")!==n||re(d.tab_name)||ne(d.tab_name))continue;let u=0;for(let g of s)c.text.includes(g)&&u++;u>0&&o.push({shell_pid:a,tab_name:d.tab_name,matched_fingerprints:u})}return o.length===0||(o.sort((a,c)=>c.matched_fingerprints-a.matched_fingerprints),o.length>1&&o[0].matched_fingerprints===o[1].matched_fingerprints)?null:o[0]}var lf=3e4;function wc(){let e=Date.now(),t=I.all(),s=o=>{let a=Date.parse(o.last_seen_at);return!Number.isFinite(a)||e-a>lf},n=new Map;for(let o of t){if(s(o)||!o.cwd||re(o.tab_name)||ne(o.tab_name))continue;let a=`${o.cwd.replace(/\/+$/,"")}::${o.tab_name}`,c=n.get(a);c||(c=[],n.set(a,c)),c.push({shell_pid:o.shell_pid,tab_name:o.tab_name,cwd:o.cwd})}let r={rebound:0,ghosts:0,ambiguous:0};for(let o of t){if(!s(o))continue;let a=I.sessionsFor(o.shell_pid);if(a.length!==0){r.ghosts++;for(let c of a){let d=Te(c);if(!d)continue;let u=f().prepare("SELECT cwd FROM sessions WHERE id = ?").get(c);if(!u?.cwd)continue;let g=`${u.cwd.replace(/\/+$/,"")}::${d}`,h=n.get(g)??[];if(h.length===0)continue;if(h.length>1){r.ambiguous++;continue}let b=h[0];b.shell_pid!==o.shell_pid&&(I.unlinkSession(c),I.linkSession(c,b.shell_pid),r.rebound++)}}}return r}function Rc(){let e={resolved:0,expired:0},t=I.allDeferredLinks();for(let s of t){let n=I.get(s.parent_shell_pid);if(!n||re(n.tab_name)||ne(n.tab_name))continue;let r=Te(s.session_id);if(r&&!I.isSessionAutoLinked(s.session_id)){I.resolveDeferredLink(s.session_id);continue}let o=I.getOrigin(s.session_id),a=st({tabName:n.tab_name,origin:o??null,cwd:s.cwd,gitBranch:s.git_branch});if(!a){I.resolveDeferredLink(s.session_id);continue}r!==a&&me(s.session_id,a),I.linkSession(s.session_id,s.parent_shell_pid),I.resolveDeferredLink(s.session_id),e.resolved++}return e}var df=6e4;async function Ds(){let e=await rf(),t={scanned:e.size,linked:0,renamed:0,skipped_manual:0,ambiguous_cwd:0};if(e.size===0)return t;let s=[];for(let[a,c]of e){let d=I.get(c);if(!d||!d.cwd||re(d.tab_name)||ne(d.tab_name))continue;let u=d.tab_name.trim();if(!u)continue;let g=await tf(a);s.push({claudePid:a,shellPid:c,cwd:d.cwd.replace(/\/+$/,""),target:u,startTimeMs:g})}let n=new Map,r=a=>{let c=n.get(a);if(c)return c;let d=af(a);return n.set(a,d),d},o=new Set;for(let a of s){let c=r(a.cwd).filter(u=>!o.has(u.id));if(c.length===0)continue;let d=null;if(a.startTimeMs!=null){let u=df;for(let g of c){if(g.started_at_ms==null)continue;let h=Math.abs(g.started_at_ms-a.startTimeMs);h<u&&(u=h,d=g)}}if(!d&&c.length===1&&(d=c[0]),!d){t.ambiguous_cwd++;continue}if(o.add(d.id),d.alias&&!I.isSessionAutoLinked(d.id)){t.skipped_manual++;continue}if(d.alias===a.target){I.linkSession(d.id,a.shellPid);continue}try{me(d.id,a.target),I.linkSession(d.id,a.shellPid),d.alias?t.renamed++:t.linked++,console.log(`[correlator] linked ${d.id.slice(0,8)} \u2192 "${a.target}" (live sweep, claude pid ${a.claudePid}, shell pid ${a.shellPid})`)}catch{}}return t}import{existsSync as kc,mkdirSync as uf,readFileSync as pf,writeFileSync as mf,chmodSync as gf}from"node:fs";import{homedir as _f}from"node:os";import{join as Ac}from"node:path";import{z as Le}from"zod";function xc(){return process.env.RECALL_HOME??Ac(_f(),".recall")}function ff(){let e=xc();kc(e)||uf(e,{recursive:!0})}function Nc(){return Ac(xc(),"config.json")}var Ps=Le.object({enabled:Le.boolean().default(!1),backend:Le.enum(["api","mcp"]).default("api"),apiKey:Le.string().optional(),model:Le.string().default("claude-opus-4-7"),maxTagsPerSession:Le.number().int().min(1).max(10).default(4),minTagsPerSession:Le.number().int().min(1).max(10).default(2),autopilot:Le.boolean().default(!1)}),Fs={enabled:!1,backend:"api",model:"claude-opus-4-7",maxTagsPerSession:4,minTagsPerSession:2,autopilot:!1};function Oc(){let e=Nc();if(!kc(e))return{};try{return JSON.parse(pf(e,"utf8"))}catch(t){return console.error("[auto-tag-config] failed to parse config.json, using defaults:",t),{}}}function Re(){let e=Oc().autoTag;if(!e)return{...Fs};let t=Ps.safeParse({...Fs,...e});return t.success?t.data:{...Fs}}function Lc(e){ff();let t=Oc(),s=Ps.parse({...Fs,...t.autoTag??{},...e}),n={...t,autoTag:s},r=Nc();mf(r,JSON.stringify(n,null,2));try{gf(r,384)}catch(o){console.error("[auto-tag-config] chmod 0600 failed (continuing):",o)}return s}function gr(e){let{apiKey:t,...s}=e;return{...s,apiKey:t?"sk-ant-\u2026":null,hasApiKey:!!t}}import{existsSync as Cc,mkdirSync as hf,readFileSync as Ef,writeFileSync as bf}from"node:fs";import{homedir as Sf}from"node:os";import{join as Ic}from"node:path";import{z as _r}from"zod";function vc(){return process.env.RECALL_HOME??Ic(Sf(),".recall")}function Tf(){let e=vc();Cc(e)||hf(e,{recursive:!0})}function jc(){return Ic(vc(),"config.json")}var $s=_r.object({heuristicEnabled:_r.boolean().default(!0),agentEnabled:_r.boolean().default(!1)}),Us={heuristicEnabled:!0,agentEnabled:!1};function Mc(){let e=jc();if(!Cc(e))return{};try{return JSON.parse(Ef(e,"utf8"))}catch(t){return console.error("[auto-title-config] failed to parse config.json, using defaults:",t),{}}}function He(){let e=Mc().autoTitle;if(!e)return{...Us};let t=$s.safeParse({...Us,...e});return t.success?t.data:{...Us}}function Dc(e){Tf();let t=Mc(),s=$s.parse({...Us,...t.autoTitle??{},...e}),n={...t,autoTitle:s};return bf(jc(),JSON.stringify(n,null,2)),s}H();var Bs="claude-haiku-4-5-20251001",Fc=80,yf=2e3,nt=class extends Error{sessionId;constructor(t){super(`no neighborhood context available for session ${t}`),this.name="NoContextAvailableError",this.sessionId=t}},Pc=null;async function wf(e,t){if(Pc)return Pc(e,t);let{spawnClaudePrompt:s,isClaudeCliAvailable:n}=await Promise.resolve().then(()=>(ge(),Pe));return n()?s(e,[],{model:t}):{success:!1,stdout:"",stderr:"claude CLI not found on PATH",exitCode:null}}function Rf(e){let s=f().prepare(`SELECT s.id,
1149
+ `);if(d){for(let u of d.split(/\r?\n/)){let g=u.trim();g.length>=60&&g.length<=400&&n.push(g)}if(n.length>=8)break}}return n}async function yc(e){if(Te(e))return null;let t=f().prepare("SELECT cwd, file_path FROM sessions WHERE id = ?").get(e);if(!t?.cwd||!t.file_path)return null;let s=await df(t.file_path);if(s.length===0)return null;let n=t.cwd.replace(/\/+$/,""),r=I.allOutputTails(),o=[];for(let[a,c]of r){let d=I.get(a);if(!d||!d.cwd||d.cwd.replace(/\/+$/,"")!==n||re(d.tab_name)||ne(d.tab_name))continue;let u=0;for(let g of s)c.text.includes(g)&&u++;u>0&&o.push({shell_pid:a,tab_name:d.tab_name,matched_fingerprints:u})}return o.length===0||(o.sort((a,c)=>c.matched_fingerprints-a.matched_fingerprints),o.length>1&&o[0].matched_fingerprints===o[1].matched_fingerprints)?null:o[0]}var uf=3e4;function wc(){let e=Date.now(),t=I.all(),s=o=>{let a=Date.parse(o.last_seen_at);return!Number.isFinite(a)||e-a>uf},n=new Map;for(let o of t){if(s(o)||!o.cwd||re(o.tab_name)||ne(o.tab_name))continue;let a=`${o.cwd.replace(/\/+$/,"")}::${o.tab_name}`,c=n.get(a);c||(c=[],n.set(a,c)),c.push({shell_pid:o.shell_pid,tab_name:o.tab_name,cwd:o.cwd})}let r={rebound:0,ghosts:0,ambiguous:0};for(let o of t){if(!s(o))continue;let a=I.sessionsFor(o.shell_pid);if(a.length!==0){r.ghosts++;for(let c of a){let d=Te(c);if(!d)continue;let u=f().prepare("SELECT cwd FROM sessions WHERE id = ?").get(c);if(!u?.cwd)continue;let g=`${u.cwd.replace(/\/+$/,"")}::${d}`,h=n.get(g)??[];if(h.length===0)continue;if(h.length>1){r.ambiguous++;continue}let b=h[0];b.shell_pid!==o.shell_pid&&(I.unlinkSession(c),I.linkSession(c,b.shell_pid),r.rebound++)}}}return r}function Rc(){let e={resolved:0,expired:0},t=I.allDeferredLinks();for(let s of t){let n=I.get(s.parent_shell_pid);if(!n||re(n.tab_name)||ne(n.tab_name))continue;let r=Te(s.session_id);if(r&&!I.isSessionAutoLinked(s.session_id)){I.resolveDeferredLink(s.session_id);continue}let o=I.getOrigin(s.session_id),a=st({tabName:n.tab_name,origin:o??null,cwd:s.cwd,gitBranch:s.git_branch});if(!a){I.resolveDeferredLink(s.session_id);continue}r!==a&&me(s.session_id,a),I.linkSession(s.session_id,s.parent_shell_pid),I.resolveDeferredLink(s.session_id),e.resolved++}return e}var pf=6e4;async function Ds(){let e=await af(),t={scanned:e.size,linked:0,renamed:0,skipped_manual:0,ambiguous_cwd:0};if(e.size===0)return t;let s=[];for(let[a,c]of e){let d=I.get(c);if(!d||!d.cwd||re(d.tab_name)||ne(d.tab_name))continue;let u=d.tab_name.trim();if(!u)continue;let g=await nf(a);s.push({claudePid:a,shellPid:c,cwd:d.cwd.replace(/\/+$/,""),target:u,startTimeMs:g})}let n=new Map,r=a=>{let c=n.get(a);if(c)return c;let d=lf(a);return n.set(a,d),d},o=new Set;for(let a of s){let c=r(a.cwd).filter(u=>!o.has(u.id));if(c.length===0)continue;let d=null;if(a.startTimeMs!=null){let u=pf;for(let g of c){if(g.started_at_ms==null)continue;let h=Math.abs(g.started_at_ms-a.startTimeMs);h<u&&(u=h,d=g)}}if(!d&&c.length===1&&(d=c[0]),!d){t.ambiguous_cwd++;continue}if(o.add(d.id),d.alias&&!I.isSessionAutoLinked(d.id)){t.skipped_manual++;continue}if(d.alias===a.target){I.linkSession(d.id,a.shellPid);continue}try{me(d.id,a.target),I.linkSession(d.id,a.shellPid),d.alias?t.renamed++:t.linked++,console.log(`[correlator] linked ${d.id.slice(0,8)} \u2192 "${a.target}" (live sweep, claude pid ${a.claudePid}, shell pid ${a.shellPid})`)}catch{}}return t}import{existsSync as kc,mkdirSync as mf,readFileSync as gf,writeFileSync as _f,chmodSync as ff}from"node:fs";import{homedir as hf}from"node:os";import{join as Ac}from"node:path";import{z as Le}from"zod";function xc(){return process.env.RECALL_HOME??Ac(hf(),".recall")}function Ef(){let e=xc();kc(e)||mf(e,{recursive:!0})}function Nc(){return Ac(xc(),"config.json")}var Ps=Le.object({enabled:Le.boolean().default(!1),backend:Le.enum(["api","mcp"]).default("api"),apiKey:Le.string().optional(),model:Le.string().default("claude-opus-4-7"),maxTagsPerSession:Le.number().int().min(1).max(10).default(4),minTagsPerSession:Le.number().int().min(1).max(10).default(2),autopilot:Le.boolean().default(!1)}),Fs={enabled:!1,backend:"api",model:"claude-opus-4-7",maxTagsPerSession:4,minTagsPerSession:2,autopilot:!1};function Oc(){let e=Nc();if(!kc(e))return{};try{return JSON.parse(gf(e,"utf8"))}catch(t){return console.error("[auto-tag-config] failed to parse config.json, using defaults:",t),{}}}function Re(){let e=Oc().autoTag;if(!e)return{...Fs};let t=Ps.safeParse({...Fs,...e});return t.success?t.data:{...Fs}}function Lc(e){Ef();let t=Oc(),s=Ps.parse({...Fs,...t.autoTag??{},...e}),n={...t,autoTag:s},r=Nc();_f(r,JSON.stringify(n,null,2));try{ff(r,384)}catch(o){console.error("[auto-tag-config] chmod 0600 failed (continuing):",o)}return s}function gr(e){let{apiKey:t,...s}=e;return{...s,apiKey:t?"sk-ant-\u2026":null,hasApiKey:!!t}}import{existsSync as Cc,mkdirSync as bf,readFileSync as Sf,writeFileSync as Tf}from"node:fs";import{homedir as yf}from"node:os";import{join as Ic}from"node:path";import{z as _r}from"zod";function vc(){return process.env.RECALL_HOME??Ic(yf(),".recall")}function wf(){let e=vc();Cc(e)||bf(e,{recursive:!0})}function jc(){return Ic(vc(),"config.json")}var $s=_r.object({heuristicEnabled:_r.boolean().default(!0),agentEnabled:_r.boolean().default(!1)}),Us={heuristicEnabled:!0,agentEnabled:!1};function Mc(){let e=jc();if(!Cc(e))return{};try{return JSON.parse(Sf(e,"utf8"))}catch(t){return console.error("[auto-title-config] failed to parse config.json, using defaults:",t),{}}}function He(){let e=Mc().autoTitle;if(!e)return{...Us};let t=$s.safeParse({...Us,...e});return t.success?t.data:{...Us}}function Dc(e){wf();let t=Mc(),s=$s.parse({...Us,...t.autoTitle??{},...e}),n={...t,autoTitle:s};return Tf(jc(),JSON.stringify(n,null,2)),s}H();var Bs="claude-haiku-4-5-20251001",Fc=80,Rf=2e3,nt=class extends Error{sessionId;constructor(t){super(`no neighborhood context available for session ${t}`),this.name="NoContextAvailableError",this.sessionId=t}},Pc=null;async function kf(e,t){if(Pc)return Pc(e,t);let{spawnClaudePrompt:s,isClaudeCliAvailable:n}=await Promise.resolve().then(()=>(ge(),Pe));return n()?s(e,[],{model:t}):{success:!1,stdout:"",stderr:"claude CLI not found on PATH",exitCode:null}}function Af(e){let s=f().prepare(`SELECT s.id,
1150
1150
  s.auto_title,
1151
1151
  s.auto_title_source,
1152
1152
  CASE WHEN sa.alias IS NOT NULL AND sa.alias != ''
1153
1153
  THEN 1 ELSE 0 END AS has_alias_int
1154
1154
  FROM sessions s
1155
1155
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
1156
- WHERE s.id = ?`).get(e);return s?{id:s.id,auto_title:s.auto_title,auto_title_source:s.auto_title_source??null,has_alias:s.has_alias_int===1}:null}function kf(e){return e.parents.length===0&&e.children.length===0&&e.citations.length===0&&e.similar.length===0&&e.cousins.length===0&&e.wikiLinks.length===0}function Af(e,t){if(e.has_alias)return{eligible:!1,reason:"manual_alias"};let s=jt({auto_title:e.auto_title,auto_title_source:e.auto_title_source,has_alias:e.has_alias});if(t)return{eligible:!0};switch(s){case"low_signal":case"recursive_meta":case"programmatic":return{eligible:!0};case"agent":return{eligible:!1,reason:"agent_titled"};case"manual_alias":return{eligible:!1,reason:"manual_alias"};default:return{eligible:!1,reason:"clean"}}}function xf(e){return["You are renaming a Claude Code session. Below is its NEIGHBORHOOD: parent","sessions, child sessions, related sessions, and citations \u2014 assembled by","Claude Recall's cog-graph. The session itself has a low-signal or","self-referential title that needs replacement.","","Read the neighborhood, then mint a single descriptive title that","reflects this session's role in the surrounding work. Constraints:","","- Maximum 80 characters.","- No quotes, no trailing punctuation.","- Output ONLY a JSON object with two fields:",' { "title": "<\u226480 char title>", "evidence": "<one sentence why>" }',"- No markdown, no preface, no commentary outside the JSON.","","--- NEIGHBORHOOD BUNDLE ---",e,"--- END NEIGHBORHOOD BUNDLE ---"].join(`
1157
- `)}function Nf(e){let t=e.trim();if(!t)return null;let s=t;try{let o=JSON.parse(t);if(o&&typeof o=="object"){let a=o;if(typeof a.result=="string")s=a.result.trim();else if(typeof a.title=="string")return Uc(a)}}catch{}let n=s.match(/```(?:json)?\s*\n([\s\S]*?)\n?```/i);n&&(s=n[1].trim());let r=null;try{r=JSON.parse(s)}catch{let o=s.indexOf("{"),a=s.lastIndexOf("}");if(o>=0&&a>o)try{r=JSON.parse(s.slice(o,a+1))}catch{return null}else return null}return!r||typeof r!="object"?null:Uc(r)}function Uc(e){let t=e.title;if(typeof t!="string")return null;let s=Of(t).trim();if(!s)return null;let n=e.evidence,r=typeof n=="string"?n.trim():"";return{title:s,evidence:r}}function Of(e){return e.replace(/^["'`]+|["'`]+$/g,"")}function Lf(e){let t=e.replace(/\s+/g," ").trim().replace(/[.!?]+$/g,"").trim();return t.length<=Fc?t:t.slice(0,Fc)}function Cf(e,t){let s=e.auto_title??"";return!s&&e.has_alias&&(s=f().prepare("SELECT alias FROM session_aliases WHERE session_id = ?").get(e.id)?.alias??""),{session_id:e.id,title:s,source:e.auto_title_source,confidence:0,evidence:`skipped: ${t}`,written:!1,skipped:t}}async function fr(e,t={}){if(t.signal?.aborted)return{session_id:e,title:"",source:null,confidence:0,evidence:"aborted before start",written:!1,skipped:"aborted"};let s=Rf(e);if(!s)throw new Error(`session not found: ${e}`);let n=Af(s,t.force===!0);if(!n.eligible)return Cf(s,n.reason);let r=t.budget??yf,o=Os(e,{budget:r});if(kf(o))throw new nt(e);if(t.signal?.aborted)return{session_id:e,title:s.auto_title??"",source:s.auto_title_source,confidence:0,evidence:"aborted before CLI call",written:!1,skipped:"aborted"};let a=xf(o.bundle),c=t.model??Bs,d=await wf(a,c);if(!d.success){let S=d.stderr.slice(-300);throw new Error(`claude CLI exited ${d.exitCode}: ${S||"no stderr captured"}`)}let u=Nf(d.stdout);if(!u)throw new Error("failed to parse regeneration output: not valid JSON {title, evidence}");if(!u.title||!u.title.trim())throw new Error("regeneration produced empty title");let g=Lf(u.title);if(!g)throw new Error("regeneration produced empty title after clamp");de(e,g,"agent");let b=ye(e)?.auto_title??g;return{session_id:e,title:b,source:"agent",confidence:vf(o),evidence:u.evidence||`regenerated from neighborhood (${If(o)})`,written:!0}}function If(e){let t=[];return e.parents.length&&t.push(`${e.parents.length} parents`),e.children.length&&t.push(`${e.children.length} children`),e.citations.length&&t.push(`${e.citations.length} citations`),e.similar.length&&t.push(`${e.similar.length} similar`),e.cousins.length&&t.push(`${e.cousins.length} cousins`),e.wikiLinks.length&&t.push(`${e.wikiLinks.length} wiki-links`),t.join(", ")}function vf(e){let t=e.parents.length,s=e.children.length,n=e.citations.length,r=e.similar.length,o=e.cousins.length,a=e.wikiLinks.length,c=.25*Math.min(1,t)+.15*Math.min(1,s)+.2*Math.min(1,n/2)+.15*Math.min(1,r/3)+.1*Math.min(1,o/3)+.15*Math.min(1,a);return Math.min(.95,c)}import{streamSSE as Me}from"hono/streaming";import{bodyLimit as iS}from"hono/body-limit";import{z as j}from"zod";H();ge();import{createHash as jf}from"node:crypto";var br=1,We="claude-haiku-4-5-20251001",Mf=3,Df=32e3,$c=2e3,Ff=30,Pf=30,Uf=30,$f=30;function Bf(e){let s=f().prepare(`SELECT s.id,
1156
+ WHERE s.id = ?`).get(e);return s?{id:s.id,auto_title:s.auto_title,auto_title_source:s.auto_title_source??null,has_alias:s.has_alias_int===1}:null}function xf(e){return e.parents.length===0&&e.children.length===0&&e.citations.length===0&&e.similar.length===0&&e.cousins.length===0&&e.wikiLinks.length===0}function Nf(e,t){if(e.has_alias)return{eligible:!1,reason:"manual_alias"};let s=jt({auto_title:e.auto_title,auto_title_source:e.auto_title_source,has_alias:e.has_alias});if(t)return{eligible:!0};switch(s){case"low_signal":case"recursive_meta":case"programmatic":return{eligible:!0};case"agent":return{eligible:!1,reason:"agent_titled"};case"manual_alias":return{eligible:!1,reason:"manual_alias"};default:return{eligible:!1,reason:"clean"}}}function Of(e){return["You are renaming a Claude Code session. Below is its NEIGHBORHOOD: parent","sessions, child sessions, related sessions, and citations \u2014 assembled by","Claude Recall's cog-graph. The session itself has a low-signal or","self-referential title that needs replacement.","","Read the neighborhood, then mint a single descriptive title that","reflects this session's role in the surrounding work. Constraints:","","- Maximum 80 characters.","- No quotes, no trailing punctuation.","- Output ONLY a JSON object with two fields:",' { "title": "<\u226480 char title>", "evidence": "<one sentence why>" }',"- No markdown, no preface, no commentary outside the JSON.","","--- NEIGHBORHOOD BUNDLE ---",e,"--- END NEIGHBORHOOD BUNDLE ---"].join(`
1157
+ `)}function Lf(e){let t=e.trim();if(!t)return null;let s=t;try{let o=JSON.parse(t);if(o&&typeof o=="object"){let a=o;if(typeof a.result=="string")s=a.result.trim();else if(typeof a.title=="string")return Uc(a)}}catch{}let n=s.match(/```(?:json)?\s*\n([\s\S]*?)\n?```/i);n&&(s=n[1].trim());let r=null;try{r=JSON.parse(s)}catch{let o=s.indexOf("{"),a=s.lastIndexOf("}");if(o>=0&&a>o)try{r=JSON.parse(s.slice(o,a+1))}catch{return null}else return null}return!r||typeof r!="object"?null:Uc(r)}function Uc(e){let t=e.title;if(typeof t!="string")return null;let s=Cf(t).trim();if(!s)return null;let n=e.evidence,r=typeof n=="string"?n.trim():"";return{title:s,evidence:r}}function Cf(e){return e.replace(/^["'`]+|["'`]+$/g,"")}function If(e){let t=e.replace(/\s+/g," ").trim().replace(/[.!?]+$/g,"").trim();return t.length<=Fc?t:t.slice(0,Fc)}function vf(e,t){let s=e.auto_title??"";return!s&&e.has_alias&&(s=f().prepare("SELECT alias FROM session_aliases WHERE session_id = ?").get(e.id)?.alias??""),{session_id:e.id,title:s,source:e.auto_title_source,confidence:0,evidence:`skipped: ${t}`,written:!1,skipped:t}}async function fr(e,t={}){if(t.signal?.aborted)return{session_id:e,title:"",source:null,confidence:0,evidence:"aborted before start",written:!1,skipped:"aborted"};let s=Af(e);if(!s)throw new Error(`session not found: ${e}`);let n=Nf(s,t.force===!0);if(!n.eligible)return vf(s,n.reason);let r=t.budget??Rf,o=Os(e,{budget:r});if(xf(o))throw new nt(e);if(t.signal?.aborted)return{session_id:e,title:s.auto_title??"",source:s.auto_title_source,confidence:0,evidence:"aborted before CLI call",written:!1,skipped:"aborted"};let a=Of(o.bundle),c=t.model??Bs,d=await kf(a,c);if(!d.success){let S=d.stderr.slice(-300);throw new Error(`claude CLI exited ${d.exitCode}: ${S||"no stderr captured"}`)}let u=Lf(d.stdout);if(!u)throw new Error("failed to parse regeneration output: not valid JSON {title, evidence}");if(!u.title||!u.title.trim())throw new Error("regeneration produced empty title");let g=If(u.title);if(!g)throw new Error("regeneration produced empty title after clamp");de(e,g,"agent");let b=ye(e)?.auto_title??g;return{session_id:e,title:b,source:"agent",confidence:Mf(o),evidence:u.evidence||`regenerated from neighborhood (${jf(o)})`,written:!0}}function jf(e){let t=[];return e.parents.length&&t.push(`${e.parents.length} parents`),e.children.length&&t.push(`${e.children.length} children`),e.citations.length&&t.push(`${e.citations.length} citations`),e.similar.length&&t.push(`${e.similar.length} similar`),e.cousins.length&&t.push(`${e.cousins.length} cousins`),e.wikiLinks.length&&t.push(`${e.wikiLinks.length} wiki-links`),t.join(", ")}function Mf(e){let t=e.parents.length,s=e.children.length,n=e.citations.length,r=e.similar.length,o=e.cousins.length,a=e.wikiLinks.length,c=.25*Math.min(1,t)+.15*Math.min(1,s)+.2*Math.min(1,n/2)+.15*Math.min(1,r/3)+.1*Math.min(1,o/3)+.15*Math.min(1,a);return Math.min(.95,c)}import{streamSSE as Me}from"hono/streaming";import{bodyLimit as cS}from"hono/body-limit";import{z as j}from"zod";H();ge();import{createHash as Df}from"node:crypto";var br=1,We="claude-haiku-4-5-20251001",Ff=3,Pf=32e3,$c=2e3,Uf=30,$f=30,Bf=30,Hf=30;function Wf(e){let s=f().prepare(`SELECT s.id,
1158
1158
  NULLIF(sa.alias, '') AS alias,
1159
1159
  s.auto_title,
1160
1160
  s.auto_title_source,
@@ -1165,15 +1165,15 @@ ${s}`}function R_(e){return ye(e)?.auto_title_source??null}async function k_(e){
1165
1165
  FROM sessions s
1166
1166
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
1167
1167
  LEFT JOIN projects p ON p.id = s.project_id
1168
- WHERE s.id = ?`).get(e);return s?{...s,alias_source:s.alias?"manual":null}:null}function Bc(e,t={}){if(e.message_count<Mf)return{eligible:!1,reason:"too-short"};let s=e.title_quality;if(s==="programmatic"||s==="recursive_meta")return{eligible:!1,reason:"low-signal-title"};if(e.auto_title_source==="agent"&&!e.alias)return{eligible:!1,reason:"agent-titled-no-override"};if(!t.force){let n=Be(e.id);if(n&&n.extractor_version>=br)return{eligible:!1,reason:"already-extracted"}}return{eligible:!0}}function Hf(e){let t=Bf(e);if(!t)return null;let n=f().prepare(`SELECT role, content_text
1168
+ WHERE s.id = ?`).get(e);return s?{...s,alias_source:s.alias?"manual":null}:null}function Bc(e,t={}){if(e.message_count<Ff)return{eligible:!1,reason:"too-short"};let s=e.title_quality;if(s==="programmatic"||s==="recursive_meta")return{eligible:!1,reason:"low-signal-title"};if(e.auto_title_source==="agent"&&!e.alias)return{eligible:!1,reason:"agent-titled-no-override"};if(!t.force){let n=Be(e.id);if(n&&n.extractor_version>=br)return{eligible:!1,reason:"already-extracted"}}return{eligible:!0}}function qf(e){let t=Wf(e);if(!t)return null;let n=f().prepare(`SELECT role, content_text
1169
1169
  FROM messages
1170
1170
  WHERE session_id = ?
1171
1171
  AND is_sidechain = 0
1172
1172
  AND content_text IS NOT NULL
1173
- ORDER BY COALESCE(timestamp, ''), rowid`).all(e),r=[],o=0;for(let a of n){let c=a.role??"system",d=a.content_text.trim();if(!d)continue;let u=d.length>$c?d.slice(0,$c)+"\u2026":d,g=`${c}: ${u}`;if(o+g.length>Df)break;r.push(g),o+=g.length}return{meta:t,excerpt:r.join(`
1173
+ ORDER BY COALESCE(timestamp, ''), rowid`).all(e),r=[],o=0;for(let a of n){let c=a.role??"system",d=a.content_text.trim();if(!d)continue;let u=d.length>$c?d.slice(0,$c)+"\u2026":d,g=`${c}: ${u}`;if(o+g.length>Pf)break;r.push(g),o+=g.length}return{meta:t,excerpt:r.join(`
1174
1174
 
1175
- `)}}function Wf(e){let{meta:t}=e;return["You are extracting a structured Output Index from a Claude Code session for a local knowledge graph.","","Read the transcript and produce a single JSON object with EXACTLY these fields. Output JSON only \u2014 no Markdown fences, no commentary, no explanation.","","Fields (every field MUST appear; use [] for empty):","- files_written: array of strings. Relative or absolute file paths the assistant created, edited, or extensively discussed (Write/Edit tool calls or paths quoted verbatim).",'- brands_mentioned: array of strings. Distinct proper-noun company / product / brand names mentioned. Examples of valid: "Glaser Group", "Apollo", "TikTok", "Cloudflare R2". NOT generic terms like "the company" or "users".','- terms_introduced: array of objects { "term": "<lowercase phrase>", "freq": <int> }. Distinctive multi-word noun phrases the session introduced or extensively discussed. Skip generic words. Cap at 30 entries.','- plan_ids_referenced: array of strings. Planning identifiers like "v0.18.A", "Phase D", "L3", "MASTER-PLAN-cognitive-graph". Empty array if none.','- bug_signatures: array of objects { "error_type": "<class or null>", "snippet": "<first line of the error>", "file": "<path or null>" }. Errors actually encountered in the session (not hypothetical). The error_type is the exception class (e.g. "TypeError", "ReferenceError") or null if unspecified.',"","Hard constraints:","- Do NOT fabricate. If a field has no concrete content from the transcript, output an empty array.","- Output JSON ONLY. No backticks, no markdown, no preamble.","- terms_introduced \u2264 30 entries; brands_mentioned \u2264 30 distinct entries; plan_ids_referenced \u2264 30; bug_signatures \u2264 30.","",`Session: ${t.alias??t.id.slice(0,8)}`,`Project: ${t.project??"unknown"}`,t.first_user_message?`Opening prompt: ${t.first_user_message.slice(0,500)}`:"","","Transcript excerpt (may be truncated):","---",e.excerpt,"---"].filter(Boolean).join(`
1176
- `)}function qf(e){return Array.isArray(e)&&e.every(t=>typeof t=="string")}function hr(e,t,s=!1){if(!Array.isArray(e))return[];let n=new Set,r=[];for(let o of e){if(typeof o!="string")continue;let a=s?o.trim().toLowerCase():o.trim();if(!(!a||a.length>256)&&!n.has(a)&&(n.add(a),r.push(a),r.length>=t))break}return r}function Jf(e,t){if(!Array.isArray(e))return[];let s=new Set,n=[];for(let r of e){if(!r||typeof r!="object")continue;let o=r.term,a=r.freq;if(typeof o!="string")continue;let c=o.trim().toLowerCase();if(!c||c.length>128||s.has(c))continue;s.add(c);let d=typeof a=="number"&&Number.isFinite(a)&&a>0?Math.floor(a):1;if(n.push({term:c,frequency:d}),n.length>=t)break}return n}function Xf(e,t){if(!Array.isArray(e))return[];let s=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n.error_type,o=n.snippet,a=n.file,c=typeof r=="string"&&r.trim().length>0?r.trim().slice(0,64):"unknown",d=typeof o=="string"?o.trim().replace(/\s+/g," ").slice(0,256):"";if(!d)continue;let u=typeof a=="string"&&a.trim().length>0?a.trim().slice(0,256):null,g=jf("sha256").update(`${c}::${d}`).digest("hex").slice(0,12);if(s.push({error_type:c,message_hash:g,snippet:d,file:u}),s.length>=t)break}return s}function Gf(e){let t=e.trim();try{let b=JSON.parse(t);typeof b.result=="string"&&(t=b.result.trim())}catch{}t=t.replace(/^```(?:json)?\s*/i,"").replace(/```\s*$/i,"").trim();let s=t.indexOf("{"),n=t.lastIndexOf("}");if(s===-1||n===-1||n<=s)return null;let r=t.slice(s,n+1),o;try{o=JSON.parse(r)}catch{return null}let a=hr(o.files_written,200),c=hr(o.brands_mentioned,Pf),d=Jf(o.terms_introduced,Ff),u=hr(o.plan_ids_referenced,Uf),g=Xf(o.bug_signatures,$f);return a.length===0&&c.length===0&&d.length===0&&u.length===0&&g.length===0&&!qf(o.files_written)?null:{files_written:a,brands_mentioned:c,terms_introduced:d,plan_ids_referenced:u,bug_signatures:g}}var Er=null;async function Yf(e,t){return Er?Er(e,t):Fe(e,[],{model:t})}async function Sr(e,t={}){if(t.signal?.aborted)return{session_id:e,ok:!1,failed:"aborted"};let s=Hf(e);if(!s)return{session_id:e,ok:!1,skipped:"session-not-found"};let n=Bc(s.meta,{force:t.force});if(!n.eligible)return{session_id:e,ok:!1,skipped:n.reason};if(!Er&&!oe())return{session_id:e,ok:!1,failed:"claude-cli-missing"};let r=Wf(s),o=t.model??We,a=await Yf(r,o);if(!a.success)return{session_id:e,ok:!1,failed:"claude-cli-error",exit_code:a.exitCode};let c=Gf(a.stdout);if(!c)return{session_id:e,ok:!1,failed:"parse-failed",exit_code:a.exitCode};let d=Kf(a.stdout),u=Na({session_id:e,files_written:c.files_written,brands_mentioned:c.brands_mentioned,terms_introduced:c.terms_introduced,plan_ids_referenced:c.plan_ids_referenced,bug_signatures:c.bug_signatures,raw_extraction:{model:o,usage:d,raw_response_excerpt:a.stdout.slice(0,4e3)},extractor_version:br});return{session_id:e,ok:!0,index:u,usage:d}}function Kf(e){try{let t=JSON.parse(e.trim());if(t&&typeof t=="object"&&t.usage){let s=t.usage,n={};return typeof s.input_tokens=="number"&&(n.input_tokens=s.input_tokens),typeof s.output_tokens=="number"&&(n.output_tokens=s.output_tokens),n}}catch{}return null}function rt(e={}){let t=f(),s=[],n=[];typeof e.projectId=="number"&&(s.push("s.project_id = ?"),n.push(e.projectId));let r=Math.max(1,Math.min(1e4,e.limit??1e3)),o=s.length?`WHERE ${s.join(" AND ")}`:"",a=t.prepare(`SELECT s.id,
1175
+ `)}}function Jf(e){let{meta:t}=e;return["You are extracting a structured Output Index from a Claude Code session for a local knowledge graph.","","Read the transcript and produce a single JSON object with EXACTLY these fields. Output JSON only \u2014 no Markdown fences, no commentary, no explanation.","","Fields (every field MUST appear; use [] for empty):","- files_written: array of strings. Relative or absolute file paths the assistant created, edited, or extensively discussed (Write/Edit tool calls or paths quoted verbatim).",'- brands_mentioned: array of strings. Distinct proper-noun company / product / brand names mentioned. Examples of valid: "Glaser Group", "Apollo", "TikTok", "Cloudflare R2". NOT generic terms like "the company" or "users".','- terms_introduced: array of objects { "term": "<lowercase phrase>", "freq": <int> }. Distinctive multi-word noun phrases the session introduced or extensively discussed. Skip generic words. Cap at 30 entries.','- plan_ids_referenced: array of strings. Planning identifiers like "v0.18.A", "Phase D", "L3", "MASTER-PLAN-cognitive-graph". Empty array if none.','- bug_signatures: array of objects { "error_type": "<class or null>", "snippet": "<first line of the error>", "file": "<path or null>" }. Errors actually encountered in the session (not hypothetical). The error_type is the exception class (e.g. "TypeError", "ReferenceError") or null if unspecified.',"","Hard constraints:","- Do NOT fabricate. If a field has no concrete content from the transcript, output an empty array.","- Output JSON ONLY. No backticks, no markdown, no preamble.","- terms_introduced \u2264 30 entries; brands_mentioned \u2264 30 distinct entries; plan_ids_referenced \u2264 30; bug_signatures \u2264 30.","",`Session: ${t.alias??t.id.slice(0,8)}`,`Project: ${t.project??"unknown"}`,t.first_user_message?`Opening prompt: ${t.first_user_message.slice(0,500)}`:"","","Transcript excerpt (may be truncated):","---",e.excerpt,"---"].filter(Boolean).join(`
1176
+ `)}function Xf(e){return Array.isArray(e)&&e.every(t=>typeof t=="string")}function hr(e,t,s=!1){if(!Array.isArray(e))return[];let n=new Set,r=[];for(let o of e){if(typeof o!="string")continue;let a=s?o.trim().toLowerCase():o.trim();if(!(!a||a.length>256)&&!n.has(a)&&(n.add(a),r.push(a),r.length>=t))break}return r}function Gf(e,t){if(!Array.isArray(e))return[];let s=new Set,n=[];for(let r of e){if(!r||typeof r!="object")continue;let o=r.term,a=r.freq;if(typeof o!="string")continue;let c=o.trim().toLowerCase();if(!c||c.length>128||s.has(c))continue;s.add(c);let d=typeof a=="number"&&Number.isFinite(a)&&a>0?Math.floor(a):1;if(n.push({term:c,frequency:d}),n.length>=t)break}return n}function Yf(e,t){if(!Array.isArray(e))return[];let s=[];for(let n of e){if(!n||typeof n!="object")continue;let r=n.error_type,o=n.snippet,a=n.file,c=typeof r=="string"&&r.trim().length>0?r.trim().slice(0,64):"unknown",d=typeof o=="string"?o.trim().replace(/\s+/g," ").slice(0,256):"";if(!d)continue;let u=typeof a=="string"&&a.trim().length>0?a.trim().slice(0,256):null,g=Df("sha256").update(`${c}::${d}`).digest("hex").slice(0,12);if(s.push({error_type:c,message_hash:g,snippet:d,file:u}),s.length>=t)break}return s}function Kf(e){let t=e.trim();try{let b=JSON.parse(t);typeof b.result=="string"&&(t=b.result.trim())}catch{}t=t.replace(/^```(?:json)?\s*/i,"").replace(/```\s*$/i,"").trim();let s=t.indexOf("{"),n=t.lastIndexOf("}");if(s===-1||n===-1||n<=s)return null;let r=t.slice(s,n+1),o;try{o=JSON.parse(r)}catch{return null}let a=hr(o.files_written,200),c=hr(o.brands_mentioned,$f),d=Gf(o.terms_introduced,Uf),u=hr(o.plan_ids_referenced,Bf),g=Yf(o.bug_signatures,Hf);return a.length===0&&c.length===0&&d.length===0&&u.length===0&&g.length===0&&!Xf(o.files_written)?null:{files_written:a,brands_mentioned:c,terms_introduced:d,plan_ids_referenced:u,bug_signatures:g}}var Er=null;async function zf(e,t){return Er?Er(e,t):Fe(e,[],{model:t})}async function Sr(e,t={}){if(t.signal?.aborted)return{session_id:e,ok:!1,failed:"aborted"};let s=qf(e);if(!s)return{session_id:e,ok:!1,skipped:"session-not-found"};let n=Bc(s.meta,{force:t.force});if(!n.eligible)return{session_id:e,ok:!1,skipped:n.reason};if(!Er&&!oe())return{session_id:e,ok:!1,failed:"claude-cli-missing"};let r=Jf(s),o=t.model??We,a=await zf(r,o);if(!a.success)return{session_id:e,ok:!1,failed:"claude-cli-error",exit_code:a.exitCode};let c=Kf(a.stdout);if(!c)return{session_id:e,ok:!1,failed:"parse-failed",exit_code:a.exitCode};let d=Vf(a.stdout),u=Na({session_id:e,files_written:c.files_written,brands_mentioned:c.brands_mentioned,terms_introduced:c.terms_introduced,plan_ids_referenced:c.plan_ids_referenced,bug_signatures:c.bug_signatures,raw_extraction:{model:o,usage:d,raw_response_excerpt:a.stdout.slice(0,4e3)},extractor_version:br});return{session_id:e,ok:!0,index:u,usage:d}}function Vf(e){try{let t=JSON.parse(e.trim());if(t&&typeof t=="object"&&t.usage){let s=t.usage,n={};return typeof s.input_tokens=="number"&&(n.input_tokens=s.input_tokens),typeof s.output_tokens=="number"&&(n.output_tokens=s.output_tokens),n}}catch{}return null}function rt(e={}){let t=f(),s=[],n=[];typeof e.projectId=="number"&&(s.push("s.project_id = ?"),n.push(e.projectId));let r=Math.max(1,Math.min(1e4,e.limit??1e3)),o=s.length?`WHERE ${s.join(" AND ")}`:"",a=t.prepare(`SELECT s.id,
1177
1177
  NULLIF(sa.alias, '') AS alias,
1178
1178
  s.auto_title,
1179
1179
  s.auto_title_source,
@@ -1192,9 +1192,9 @@ ${s}`}function R_(e){return ye(e)?.auto_title_source??null}async function k_(e){
1192
1192
  resolved_in_session_id = excluded.resolved_in_session_id,
1193
1193
  fix_summary = excluded.fix_summary,
1194
1194
  resolved_at = excluded.resolved_at,
1195
- unresolved_at = NULL`).run(e.messageHash,e.resolvedInSessionId??null,e.fixSummary??null,s),eh(e.messageHash)}function Yc(e){f().prepare(`UPDATE bug_signature_resolutions
1195
+ unresolved_at = NULL`).run(e.messageHash,e.resolvedInSessionId??null,e.fixSummary??null,s),sh(e.messageHash)}function Yc(e){f().prepare(`UPDATE bug_signature_resolutions
1196
1196
  SET unresolved_at = ?
1197
- WHERE message_hash = ?`).run(new Date().toISOString(),e)}function eh(e){return f().prepare("SELECT * FROM bug_signature_resolutions WHERE message_hash = ?").get(e)??null}function yr(e){if(e.length===0)return new Map;let t=f(),s=e.map(()=>"?").join(","),n=t.prepare(`SELECT * FROM bug_signature_resolutions
1197
+ WHERE message_hash = ?`).run(new Date().toISOString(),e)}function sh(e){return f().prepare("SELECT * FROM bug_signature_resolutions WHERE message_hash = ?").get(e)??null}function yr(e){if(e.length===0)return new Map;let t=f(),s=e.map(()=>"?").join(","),n=t.prepare(`SELECT * FROM bug_signature_resolutions
1198
1198
  WHERE message_hash IN (${s})`).all(...e),r=new Map;for(let o of n)r.set(o.message_hash,o);return r}function wr(e){return!!e&&e.unresolved_at===null}H();function Ht(){return new Date().toISOString()}function Rr(){let e=f(),t=e.prepare(`SELECT id, name, description, created_at, updated_at
1199
1199
  FROM macro_repos
1200
1200
  ORDER BY name COLLATE NOCASE`).all();if(t.length===0)return[];let s=t.map(a=>a.id),n=s.map(()=>"?").join(","),r=e.prepare(`SELECT m.macro_repo_id, m.project_id, p.name AS project_name
@@ -1218,18 +1218,18 @@ ${s}`}function R_(e){return ye(e)?.auto_title_source??null}async function k_(e){
1218
1218
  LIMIT ?`).all(...n,o).map(sl)}function rl(e){let s=f().prepare(`SELECT target_id, COUNT(*) AS n
1219
1219
  FROM bug_synthesis_results
1220
1220
  WHERE scope = ?
1221
- GROUP BY target_id`).all(e),n=new Map;for(let r of s)n.set(r.target_id,r.n);return n}function ol(e){f().prepare("DELETE FROM bug_synthesis_results WHERE id = ?").run(e)}import{randomBytes as th,timingSafeEqual as sh}from"node:crypto";var nh=6e4,rh=new Set(["127.0.0.1","localhost"]),Wt=new Map;function Ar(){return Date.now()}function il(){let e=Ar();for(let[t,s]of Wt)(s.expiresAt<=e||s.used)&&Wt.delete(t)}function we(e){let t=e.req.header("origin")??"";if(t)try{let r=new URL(t);if(!rh.has(r.hostname))return e.json({error:"forbidden: cross-origin launcher request rejected"},403)}catch{return e.json({error:"forbidden: invalid Origin header"},403)}let s=e.req.header("sec-fetch-site");return s&&s!=="same-origin"&&s!=="none"?e.json({error:"forbidden: Sec-Fetch-Site indicates cross-origin"},403):e.req.header("x-recall-launcher")!=="1"?e.json({error:"forbidden: missing X-Recall-Launcher header (this endpoint is callable only from the Recall web UI)"},403):null}function xr(e){il();let t=th(32).toString("hex"),s=Ar()+nh;return Wt.set(t,{token:t,intent:e,expiresAt:s,used:!1}),{token:t,expiresAt:s}}function Nr(e){if(il(),typeof e!="string"||e.length!==64)return null;let t;try{t=Buffer.from(e,"hex")}catch{return null}if(t.length!==32)return null;for(let s of Wt.values()){if(s.used||s.expiresAt<=Ar())continue;let n;try{n=Buffer.from(s.token,"hex")}catch{continue}if(n.length===t.length&&sh(n,t))return s.used=!0,Wt.delete(s.token),s.intent}return null}import{existsSync as dh,mkdirSync as qR,readFileSync as uh,writeFileSync as JR}from"node:fs";import{homedir as ph}from"node:os";import{join as ml}from"node:path";import{z as Or}from"zod";import{appendFileSync as oh,existsSync as al,mkdirSync as ih,readFileSync as ah}from"node:fs";import{homedir as ch}from"node:os";import{join as cl}from"node:path";function ll(){return process.env.RECALL_HOME??cl(ch(),".recall")}function lh(){let e=ll();al(e)||ih(e,{recursive:!0})}function dl(){return cl(ll(),"launcher-audit.log")}function ee(e){lh();let t={ts:new Date().toISOString(),...e};try{oh(dl(),JSON.stringify(t)+`
1222
- `,"utf8")}catch(s){console.error("[launcher-audit] failed to append:",s)}}function ul(e){let t=dl();if(!al(t))return{input_tokens:0,output_tokens:0,records_counted:0};let s=Date.now()-e,n=0,r=0,o=0,a;try{a=ah(t,"utf8")}catch{return{input_tokens:0,output_tokens:0,records_counted:0}}for(let c of a.split(`
1223
- `)){if(!c.trim())continue;let d;try{d=JSON.parse(c)}catch{continue}if(d.kind!=="run-completed"&&d.kind!=="synth-completed")continue;let u=Date.parse(d.ts);!Number.isFinite(u)||u<s||(n+=Number(d.input_tokens??0),r+=Number(d.output_tokens??0),o+=1)}return{input_tokens:n,output_tokens:r,records_counted:o}}var mh=1440*60*1e3,gh=Or.object({dailyTokenBudget:Or.number().int().nonnegative().default(1e6),sessionCeiling:Or.number().int().positive().max(1e4).default(500)}),Lr={dailyTokenBudget:1e6,sessionCeiling:500};function _h(){return process.env.RECALL_HOME??ml(ph(),".recall")}function fh(){return ml(_h(),"config.json")}function hh(){let e=fh();if(!dh(e))return{};try{return JSON.parse(uh(e,"utf8"))}catch(t){return console.error("[launcher-budget] failed to parse config.json, using defaults:",t),{}}}function Cr(){let e=hh().launcher;if(!e)return{...Lr};let t=gh.safeParse({...Lr,...e});return t.success?t.data:{...Lr}}function at(){let e=Cr(),t=ul(mh),s=t.input_tokens+t.output_tokens,n=Math.max(0,e.dailyTokenBudget-s);return{daily_token_budget:e.dailyTokenBudget,session_ceiling:e.sessionCeiling,spent_input_tokens_24h:t.input_tokens,spent_output_tokens_24h:t.output_tokens,spent_total_tokens_24h:s,remaining_tokens_24h:n}}function Ir(e){return{estimated_input_tokens_max:e*2e4,estimated_output_tokens_max:e*1e3}}function vr(e){let t=e.mode==="root_cause"?800:2e3;if(e.scope==="cluster")return{estimated_input_tokens_max:5e3+Math.min(8,Math.max(1,e.member_session_count??1))*3e3,estimated_output_tokens_max:t};let s=Math.max(1,e.cluster_count??1);return{estimated_input_tokens_max:Math.min(5e4,1e3*s),estimated_output_tokens_max:t}}var pl={pro:45,"max-5x":225,"max-20x":900};function Eh(e){let t=e.toLowerCase();return t.includes("haiku")?1:t.includes("sonnet")?5:t.includes("opus")?10:5}var bh=4e3;function gl(e){return Math.max(1,Math.ceil(e/bh))}function Ce(e,t){let s=Eh(t),n=e*s,r=Object.keys(pl).map(o=>{let a=n/pl[o];return{plan:o,fraction:a,pct:Math.round(a*1e3)/10,would_exhaust_window:a>1}});return{model:t,model_multiplier:s,per_plan:r,caveat:"Estimates use Anthropic\u2019s public approximate caps and assume a multiplier of ~1x for Haiku, ~5x for Sonnet, ~10x for Opus. Anthropic adjusts these limits without notice; actual consumption depends on session size. Treat as planning guidance, not a contract."}}import{randomUUID as Sh}from"node:crypto";var ct=new Map,qt=new Map,Th=300*1e3;function qs(e,t,s){e.events.push({id:e.events.length+1,kind:t,data:s});for(let n of e.waiters)n();e.waiters.clear()}function yh(e){e.cleanupTimer||(e.cleanupTimer=setTimeout(()=>{ct.delete(e.jobId),qt.get(e.project)===e.jobId&&qt.delete(e.project)},Th),e.cleanupTimer.unref?.())}function jr(e){return{jobId:e.jobId,project:e.project,model:e.model,status:e.status,startedAt:e.startedAt,endedAt:e.endedAt,total:e.progress.total,processed:e.progress.processed,ok:e.progress.ok,failed:e.progress.failed,skipped:e.progress.skipped,total_input_tokens:e.progress.total_input_tokens,total_output_tokens:e.progress.total_output_tokens,current_session_id:e.progress.current_session_id,error:e.error}}function _l(e){let t=Bt(e.project);if(!t)return{error:`project "${e.project}" not found`};let s=qt.get(t.name);if(s){let g=ct.get(s);if(g&&g.status==="running")return{jobId:s,reused:!0};qt.delete(t.name)}let n=Sh(),r=e.model??We,o=Math.max(1,e.limit??200),a=e.force??!1,c=new AbortController,d=new Date().toISOString(),u={jobId:n,project:t.name,projectId:t.id,model:r,limit:o,force:a,status:"running",startedAt:d,endedAt:null,events:[],waiters:new Set,controller:c,progress:{total:0,processed:0,ok:0,failed:0,skipped:0,current_session_id:null,total_input_tokens:0,total_output_tokens:0},error:null,cleanupTimer:null};return ct.set(n,u),qt.set(t.name,n),ee({kind:"run-launched",job_id:n,project:t.name,model:r,limit:o,origin:e.origin??null}),(async()=>{await Promise.resolve();try{await Hc({projectId:t.id,limit:o,force:a,model:r,signal:c.signal,onProgress:g=>{u.progress=g,qs(u,"progress",g)},onResult:g=>{!g.ok&&!g.skipped&&qs(u,"error",{session_id:g.session_id,reason:g.failed??"unknown"})}}),u.status=c.signal.aborted?"cancelled":"done",u.endedAt=new Date().toISOString(),qs(u,"done",jr(u)),ee({kind:u.status==="cancelled"?"run-cancelled":"run-completed",job_id:n,project:t.name,model:r,limit:o,origin:e.origin??null,input_tokens:u.progress.total_input_tokens,output_tokens:u.progress.total_output_tokens,sessions_processed:u.progress.processed})}catch(g){let h=g instanceof Error?g.message:String(g??"unknown error");u.status="failed",u.endedAt=new Date().toISOString(),u.error=h,qs(u,"done",jr(u)),ee({kind:"run-failed",job_id:n,project:t.name,model:r,limit:o,origin:e.origin??null,reason:h,input_tokens:u.progress.total_input_tokens,output_tokens:u.progress.total_output_tokens})}finally{yh(u)}})(),{jobId:n,reused:!1}}async function*fl(e,t=0){let s=ct.get(e);if(!s)return;let n=t;for(;;){for(;n<s.events.length;){let r=s.events[n];if(!r)break;if(n+=1,yield r,r.kind==="done")return}if(s.status!=="running")return;await new Promise(r=>s.waiters.add(r))}}function hl(e){let t=ct.get(e);return!t||t.status!=="running"?!1:(t.controller.abort(),!0)}function Mr(e){let t=ct.get(e);return t?jr(t):null}H();import{randomUUID as wh}from"node:crypto";import{spawn as Rh}from"node:child_process";import{execSync as kh}from"node:child_process";var El="claude-haiku-4-5-20251001",dt=new Map,Gt=new Map,Ah=300*1e3;function bl(e){return`${e.scope}:${e.target_id}:${e.mode}`}function Jt(e,t,s){e.events.push({id:e.events.length+1,kind:t,data:s});for(let n of e.waiters)n();e.waiters.clear()}function xh(e){e.cleanupTimer||(e.cleanupTimer=setTimeout(()=>{dt.delete(e.jobId);let t=bl(e.intent);Gt.get(t)===e.jobId&&Gt.delete(t)},Ah),e.cleanupTimer.unref?.())}function lt(e){return{jobId:e.jobId,scope:e.intent.scope,target_id:e.intent.target_id,mode:e.intent.mode,model:e.intent.model,status:e.status,output_markdown:e.output_markdown,input_tokens:e.input_tokens,output_tokens:e.output_tokens,startedAt:e.startedAt,endedAt:e.endedAt,error:e.error,context_summary:e.context_summary}}function Sl(){return f().prepare(`SELECT s.id AS session_id, p.name AS project, s.auto_title,
1221
+ GROUP BY target_id`).all(e),n=new Map;for(let r of s)n.set(r.target_id,r.n);return n}function ol(e){f().prepare("DELETE FROM bug_synthesis_results WHERE id = ?").run(e)}import{randomBytes as nh,timingSafeEqual as rh}from"node:crypto";var oh=6e4,ih=new Set(["127.0.0.1","localhost"]),Wt=new Map;function Ar(){return Date.now()}function il(){let e=Ar();for(let[t,s]of Wt)(s.expiresAt<=e||s.used)&&Wt.delete(t)}function we(e){let t=e.req.header("origin")??"";if(t)try{let r=new URL(t);if(!ih.has(r.hostname))return e.json({error:"forbidden: cross-origin launcher request rejected"},403)}catch{return e.json({error:"forbidden: invalid Origin header"},403)}let s=e.req.header("sec-fetch-site");return s&&s!=="same-origin"&&s!=="none"?e.json({error:"forbidden: Sec-Fetch-Site indicates cross-origin"},403):e.req.header("x-recall-launcher")!=="1"?e.json({error:"forbidden: missing X-Recall-Launcher header (this endpoint is callable only from the Recall web UI)"},403):null}function xr(e){il();let t=nh(32).toString("hex"),s=Ar()+oh;return Wt.set(t,{token:t,intent:e,expiresAt:s,used:!1}),{token:t,expiresAt:s}}function Nr(e){if(il(),typeof e!="string"||e.length!==64)return null;let t;try{t=Buffer.from(e,"hex")}catch{return null}if(t.length!==32)return null;for(let s of Wt.values()){if(s.used||s.expiresAt<=Ar())continue;let n;try{n=Buffer.from(s.token,"hex")}catch{continue}if(n.length===t.length&&rh(n,t))return s.used=!0,Wt.delete(s.token),s.intent}return null}import{existsSync as ph,mkdirSync as XR,readFileSync as mh,writeFileSync as GR}from"node:fs";import{homedir as gh}from"node:os";import{join as ml}from"node:path";import{z as Or}from"zod";import{appendFileSync as ah,existsSync as al,mkdirSync as ch,readFileSync as lh}from"node:fs";import{homedir as dh}from"node:os";import{join as cl}from"node:path";function ll(){return process.env.RECALL_HOME??cl(dh(),".recall")}function uh(){let e=ll();al(e)||ch(e,{recursive:!0})}function dl(){return cl(ll(),"launcher-audit.log")}function ee(e){uh();let t={ts:new Date().toISOString(),...e};try{ah(dl(),JSON.stringify(t)+`
1222
+ `,"utf8")}catch(s){console.error("[launcher-audit] failed to append:",s)}}function ul(e){let t=dl();if(!al(t))return{input_tokens:0,output_tokens:0,records_counted:0};let s=Date.now()-e,n=0,r=0,o=0,a;try{a=lh(t,"utf8")}catch{return{input_tokens:0,output_tokens:0,records_counted:0}}for(let c of a.split(`
1223
+ `)){if(!c.trim())continue;let d;try{d=JSON.parse(c)}catch{continue}if(d.kind!=="run-completed"&&d.kind!=="synth-completed")continue;let u=Date.parse(d.ts);!Number.isFinite(u)||u<s||(n+=Number(d.input_tokens??0),r+=Number(d.output_tokens??0),o+=1)}return{input_tokens:n,output_tokens:r,records_counted:o}}var _h=1440*60*1e3,fh=Or.object({dailyTokenBudget:Or.number().int().nonnegative().default(1e6),sessionCeiling:Or.number().int().positive().max(1e4).default(500)}),Lr={dailyTokenBudget:1e6,sessionCeiling:500};function hh(){return process.env.RECALL_HOME??ml(gh(),".recall")}function Eh(){return ml(hh(),"config.json")}function bh(){let e=Eh();if(!ph(e))return{};try{return JSON.parse(mh(e,"utf8"))}catch(t){return console.error("[launcher-budget] failed to parse config.json, using defaults:",t),{}}}function Cr(){let e=bh().launcher;if(!e)return{...Lr};let t=fh.safeParse({...Lr,...e});return t.success?t.data:{...Lr}}function at(){let e=Cr(),t=ul(_h),s=t.input_tokens+t.output_tokens,n=Math.max(0,e.dailyTokenBudget-s);return{daily_token_budget:e.dailyTokenBudget,session_ceiling:e.sessionCeiling,spent_input_tokens_24h:t.input_tokens,spent_output_tokens_24h:t.output_tokens,spent_total_tokens_24h:s,remaining_tokens_24h:n}}function Ir(e){return{estimated_input_tokens_max:e*2e4,estimated_output_tokens_max:e*1e3}}function vr(e){let t=e.mode==="root_cause"?800:2e3;if(e.scope==="cluster")return{estimated_input_tokens_max:5e3+Math.min(8,Math.max(1,e.member_session_count??1))*3e3,estimated_output_tokens_max:t};let s=Math.max(1,e.cluster_count??1);return{estimated_input_tokens_max:Math.min(5e4,1e3*s),estimated_output_tokens_max:t}}var pl={pro:45,"max-5x":225,"max-20x":900};function Sh(e){let t=e.toLowerCase();return t.includes("haiku")?1:t.includes("sonnet")?5:t.includes("opus")?10:5}var Th=4e3;function gl(e){return Math.max(1,Math.ceil(e/Th))}function Ce(e,t){let s=Sh(t),n=e*s,r=Object.keys(pl).map(o=>{let a=n/pl[o];return{plan:o,fraction:a,pct:Math.round(a*1e3)/10,would_exhaust_window:a>1}});return{model:t,model_multiplier:s,per_plan:r,caveat:"Estimates use Anthropic\u2019s public approximate caps and assume a multiplier of ~1x for Haiku, ~5x for Sonnet, ~10x for Opus. Anthropic adjusts these limits without notice; actual consumption depends on session size. Treat as planning guidance, not a contract."}}import{randomUUID as yh}from"node:crypto";var ct=new Map,qt=new Map,wh=300*1e3;function qs(e,t,s){e.events.push({id:e.events.length+1,kind:t,data:s});for(let n of e.waiters)n();e.waiters.clear()}function Rh(e){e.cleanupTimer||(e.cleanupTimer=setTimeout(()=>{ct.delete(e.jobId),qt.get(e.project)===e.jobId&&qt.delete(e.project)},wh),e.cleanupTimer.unref?.())}function jr(e){return{jobId:e.jobId,project:e.project,model:e.model,status:e.status,startedAt:e.startedAt,endedAt:e.endedAt,total:e.progress.total,processed:e.progress.processed,ok:e.progress.ok,failed:e.progress.failed,skipped:e.progress.skipped,total_input_tokens:e.progress.total_input_tokens,total_output_tokens:e.progress.total_output_tokens,current_session_id:e.progress.current_session_id,error:e.error}}function _l(e){let t=Bt(e.project);if(!t)return{error:`project "${e.project}" not found`};let s=qt.get(t.name);if(s){let g=ct.get(s);if(g&&g.status==="running")return{jobId:s,reused:!0};qt.delete(t.name)}let n=yh(),r=e.model??We,o=Math.max(1,e.limit??200),a=e.force??!1,c=new AbortController,d=new Date().toISOString(),u={jobId:n,project:t.name,projectId:t.id,model:r,limit:o,force:a,status:"running",startedAt:d,endedAt:null,events:[],waiters:new Set,controller:c,progress:{total:0,processed:0,ok:0,failed:0,skipped:0,current_session_id:null,total_input_tokens:0,total_output_tokens:0},error:null,cleanupTimer:null};return ct.set(n,u),qt.set(t.name,n),ee({kind:"run-launched",job_id:n,project:t.name,model:r,limit:o,origin:e.origin??null}),(async()=>{await Promise.resolve();try{await Hc({projectId:t.id,limit:o,force:a,model:r,signal:c.signal,onProgress:g=>{u.progress=g,qs(u,"progress",g)},onResult:g=>{!g.ok&&!g.skipped&&qs(u,"error",{session_id:g.session_id,reason:g.failed??"unknown"})}}),u.status=c.signal.aborted?"cancelled":"done",u.endedAt=new Date().toISOString(),qs(u,"done",jr(u)),ee({kind:u.status==="cancelled"?"run-cancelled":"run-completed",job_id:n,project:t.name,model:r,limit:o,origin:e.origin??null,input_tokens:u.progress.total_input_tokens,output_tokens:u.progress.total_output_tokens,sessions_processed:u.progress.processed})}catch(g){let h=g instanceof Error?g.message:String(g??"unknown error");u.status="failed",u.endedAt=new Date().toISOString(),u.error=h,qs(u,"done",jr(u)),ee({kind:"run-failed",job_id:n,project:t.name,model:r,limit:o,origin:e.origin??null,reason:h,input_tokens:u.progress.total_input_tokens,output_tokens:u.progress.total_output_tokens})}finally{Rh(u)}})(),{jobId:n,reused:!1}}async function*fl(e,t=0){let s=ct.get(e);if(!s)return;let n=t;for(;;){for(;n<s.events.length;){let r=s.events[n];if(!r)break;if(n+=1,yield r,r.kind==="done")return}if(s.status!=="running")return;await new Promise(r=>s.waiters.add(r))}}function hl(e){let t=ct.get(e);return!t||t.status!=="running"?!1:(t.controller.abort(),!0)}function Mr(e){let t=ct.get(e);return t?jr(t):null}H();import{randomUUID as kh}from"node:crypto";import{spawn as Ah}from"node:child_process";import{execSync as xh}from"node:child_process";var El="claude-haiku-4-5-20251001",dt=new Map,Gt=new Map,Nh=300*1e3;function bl(e){return`${e.scope}:${e.target_id}:${e.mode}`}function Jt(e,t,s){e.events.push({id:e.events.length+1,kind:t,data:s});for(let n of e.waiters)n();e.waiters.clear()}function Oh(e){e.cleanupTimer||(e.cleanupTimer=setTimeout(()=>{dt.delete(e.jobId);let t=bl(e.intent);Gt.get(t)===e.jobId&&Gt.delete(t)},Nh),e.cleanupTimer.unref?.())}function lt(e){return{jobId:e.jobId,scope:e.intent.scope,target_id:e.intent.target_id,mode:e.intent.mode,model:e.intent.model,status:e.status,output_markdown:e.output_markdown,input_tokens:e.input_tokens,output_tokens:e.output_tokens,startedAt:e.startedAt,endedAt:e.endedAt,error:e.error,context_summary:e.context_summary}}function Sl(){return f().prepare(`SELECT s.id AS session_id, p.name AS project, s.auto_title,
1224
1224
  oi.bug_signatures
1225
1225
  FROM session_output_index oi
1226
1226
  JOIN sessions s ON s.id = oi.session_id
1227
1227
  JOIN projects p ON p.id = s.project_id
1228
1228
  WHERE oi.bug_signatures IS NOT NULL
1229
- AND oi.bug_signatures != '[]'`).all()}function Tl(e){try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function Nh(e){let t=Sl(),s=[];for(let a of t)for(let c of Tl(a.bug_signatures)){let d=c.message_hash??`nohash:${(c.snippet??"").slice(0,64)}`;(c.message_hash===e||d===e)&&s.push({sig:c,session_id:a.session_id,project:a.project,auto_title:a.auto_title})}if(s.length===0)return null;let n=s[0],r=Array.from(new Set(s.map(a=>a.session_id))),o=Array.from(new Set(s.map(a=>a.project))).sort();return{message_hash:n.sig.message_hash??null,error_type:n.sig.error_type??null,snippet:(n.sig.snippet??"").slice(0,400),file:n.sig.file??null,occurrence_count:s.length,projects:o,member_session_ids:r}}function Oh(e){let t=Sl().filter(o=>o.project===e),s=new Map;for(let o of t)for(let a of Tl(o.bug_signatures)){let c=a.message_hash??`nohash:${(a.snippet??"").slice(0,64)}`,d=s.get(c);d?(d.sigs.push(a),d.sessions.add(o.session_id)):s.set(c,{sigs:[a],first:a,sessions:new Set([o.session_id])})}let n=new Map;try{let o=Array.from(s.keys()).filter(a=>!a.startsWith("nohash:"));if(o.length>0){let a=f(),c=o.map(()=>"?").join(","),d=a.prepare(`SELECT message_hash, fix_summary
1229
+ AND oi.bug_signatures != '[]'`).all()}function Tl(e){try{let t=JSON.parse(e);return Array.isArray(t)?t:[]}catch{return[]}}function Lh(e){let t=Sl(),s=[];for(let a of t)for(let c of Tl(a.bug_signatures)){let d=c.message_hash??`nohash:${(c.snippet??"").slice(0,64)}`;(c.message_hash===e||d===e)&&s.push({sig:c,session_id:a.session_id,project:a.project,auto_title:a.auto_title})}if(s.length===0)return null;let n=s[0],r=Array.from(new Set(s.map(a=>a.session_id))),o=Array.from(new Set(s.map(a=>a.project))).sort();return{message_hash:n.sig.message_hash??null,error_type:n.sig.error_type??null,snippet:(n.sig.snippet??"").slice(0,400),file:n.sig.file??null,occurrence_count:s.length,projects:o,member_session_ids:r}}function Ch(e){let t=Sl().filter(o=>o.project===e),s=new Map;for(let o of t)for(let a of Tl(o.bug_signatures)){let c=a.message_hash??`nohash:${(a.snippet??"").slice(0,64)}`,d=s.get(c);d?(d.sigs.push(a),d.sessions.add(o.session_id)):s.set(c,{sigs:[a],first:a,sessions:new Set([o.session_id])})}let n=new Map;try{let o=Array.from(s.keys()).filter(a=>!a.startsWith("nohash:"));if(o.length>0){let a=f(),c=o.map(()=>"?").join(","),d=a.prepare(`SELECT message_hash, fix_summary
1230
1230
  FROM bug_signature_resolutions
1231
1231
  WHERE message_hash IN (${c})
1232
- AND unresolved_at IS NULL`).all(...o);for(let u of d)n.set(u.message_hash,{fix_summary:u.fix_summary})}}catch{}let r=[];for(let[o,a]of s){let c=a.first.message_hash??null,d=c?n.get(c)??null:null;r.push({cluster_id:c??o,error_type:a.first.error_type??null,snippet:(a.first.snippet??"").slice(0,200),file:a.first.file??null,occurrence_count:a.sessions.size,resolved:d!==null,fix_summary:d?.fix_summary??null})}return r.sort((o,a)=>a.occurrence_count-o.occurrence_count),r}function Lh(e){let t=e.replace(/\s+/g," ").trim();return t.length===0?"":t.slice(0,Math.min(30,t.length))}function Ch(e,t){let s=f(),n=Lh(t),r=[];for(let o of e.slice(0,8)){let a=s.prepare(`SELECT s.id, p.name AS project, s.auto_title
1232
+ AND unresolved_at IS NULL`).all(...o);for(let u of d)n.set(u.message_hash,{fix_summary:u.fix_summary})}}catch{}let r=[];for(let[o,a]of s){let c=a.first.message_hash??null,d=c?n.get(c)??null:null;r.push({cluster_id:c??o,error_type:a.first.error_type??null,snippet:(a.first.snippet??"").slice(0,200),file:a.first.file??null,occurrence_count:a.sessions.size,resolved:d!==null,fix_summary:d?.fix_summary??null})}return r.sort((o,a)=>a.occurrence_count-o.occurrence_count),r}function Ih(e){let t=e.replace(/\s+/g," ").trim();return t.length===0?"":t.slice(0,Math.min(30,t.length))}function vh(e,t){let s=f(),n=Ih(t),r=[];for(let o of e.slice(0,8)){let a=s.prepare(`SELECT s.id, p.name AS project, s.auto_title
1233
1233
  FROM sessions s
1234
1234
  JOIN projects p ON p.id = s.project_id
1235
1235
  WHERE s.id = ?`).get(o);if(!a)continue;let c=[];if(n.length>0){let d=s.prepare(`SELECT rowid FROM messages
@@ -1241,9 +1241,9 @@ ${s}`}function R_(e){return ye(e)?.auto_title_source??null}async function k_(e){
1241
1241
  WHERE session_id = ?
1242
1242
  AND is_sidechain = 0
1243
1243
  AND rowid BETWEEN ? AND ?
1244
- ORDER BY rowid`).all(o,h.rowid-2,h.rowid+2);for(let S of b){if(u.has(S.rowid))continue;u.add(S.rowid);let y=(S.content_text??"").slice(0,800);if(g+y.length>4e3)break;g+=y.length,c.push({role:S.role??"unknown",content:y})}if(g>=4e3)break}}r.push({session_id:o,short_id:o.slice(0,8),project:a.project,auto_title:a.auto_title,excerpts:c})}return r}var Ih="You are analyzing extracted bug findings from a developer's past Claude Code sessions. You are NOT being asked to fix code. You are being asked to synthesize patterns, identify likely root causes, or prioritize concerns based ONLY on the structured findings you are given. Output Markdown only, no preamble, no apologies, no questions.";function vh(e,t){let s=[];s.push("[CONTEXT]"),s.push("Bug fingerprint:"),s.push(`- error_type: ${e.error_type??"unknown"}`),s.push(`- description: ${e.snippet||"(no snippet)"}`),s.push(`- file: ${e.file??"(no file recorded)"}`),s.push(`- occurrences: ${e.occurrence_count} sessions`),s.push(`- projects: ${e.projects.join(", ")}`),s.push(`- finding_id: ${e.message_hash??"(no hash)"}`),s.push(""),s.push("Member session excerpts:");for(let n of t){let r=n.auto_title??"(untitled)";if(s.push(`=== Session ${n.short_id} | ${n.project} | "${r}" ===`),n.excerpts.length===0)s.push("(no surrounding messages found for this snippet)");else for(let o of n.excerpts)s.push(`${o.role}: ${o.content}`);s.push("")}return s.join(`
1245
- `)}function jh(e,t,s){let n=[];n.push("[CONTEXT]"),n.push(`Project: ${e}`),n.push(`Total clusters: ${s}`),n.push(""),n.push("Clusters (sorted by occurrence_count desc):");for(let r of t)n.push(`- cluster_id: ${r.cluster_id}`),n.push(` error_type: ${r.error_type??"unknown"}`),n.push(` snippet: ${r.snippet||"(none)"}`),r.file&&n.push(` file: ${r.file}`),n.push(` occurrence_count: ${r.occurrence_count}`),n.push(` resolved: ${r.resolved?"true":"false"}`),r.fix_summary&&n.push(` fix_summary: ${r.fix_summary}`),n.push("");return t.length<s&&n.push(`(Showing top ${t.length} of ${s} clusters by occurrence.)`),n.join(`
1246
- `)}var Mh=`[TASK]
1244
+ ORDER BY rowid`).all(o,h.rowid-2,h.rowid+2);for(let S of b){if(u.has(S.rowid))continue;u.add(S.rowid);let y=(S.content_text??"").slice(0,800);if(g+y.length>4e3)break;g+=y.length,c.push({role:S.role??"unknown",content:y})}if(g>=4e3)break}}r.push({session_id:o,short_id:o.slice(0,8),project:a.project,auto_title:a.auto_title,excerpts:c})}return r}var jh="You are analyzing extracted bug findings from a developer's past Claude Code sessions. You are NOT being asked to fix code. You are being asked to synthesize patterns, identify likely root causes, or prioritize concerns based ONLY on the structured findings you are given. Output Markdown only, no preamble, no apologies, no questions.";function Mh(e,t){let s=[];s.push("[CONTEXT]"),s.push("Bug fingerprint:"),s.push(`- error_type: ${e.error_type??"unknown"}`),s.push(`- description: ${e.snippet||"(no snippet)"}`),s.push(`- file: ${e.file??"(no file recorded)"}`),s.push(`- occurrences: ${e.occurrence_count} sessions`),s.push(`- projects: ${e.projects.join(", ")}`),s.push(`- finding_id: ${e.message_hash??"(no hash)"}`),s.push(""),s.push("Member session excerpts:");for(let n of t){let r=n.auto_title??"(untitled)";if(s.push(`=== Session ${n.short_id} | ${n.project} | "${r}" ===`),n.excerpts.length===0)s.push("(no surrounding messages found for this snippet)");else for(let o of n.excerpts)s.push(`${o.role}: ${o.content}`);s.push("")}return s.join(`
1245
+ `)}function Dh(e,t,s){let n=[];n.push("[CONTEXT]"),n.push(`Project: ${e}`),n.push(`Total clusters: ${s}`),n.push(""),n.push("Clusters (sorted by occurrence_count desc):");for(let r of t)n.push(`- cluster_id: ${r.cluster_id}`),n.push(` error_type: ${r.error_type??"unknown"}`),n.push(` snippet: ${r.snippet||"(none)"}`),r.file&&n.push(` file: ${r.file}`),n.push(` occurrence_count: ${r.occurrence_count}`),n.push(` resolved: ${r.resolved?"true":"false"}`),r.fix_summary&&n.push(` fix_summary: ${r.fix_summary}`),n.push("");return t.length<s&&n.push(`(Showing top ${t.length} of ${s} clusters by occurrence.)`),n.join(`
1246
+ `)}var Fh=`[TASK]
1247
1247
  Output a Markdown synopsis with these sections:
1248
1248
 
1249
1249
  ## What this bug is
@@ -1265,7 +1265,7 @@ prefer "consider <pattern>" over "do <action>" unless the evidence
1265
1265
  is overwhelming.
1266
1266
 
1267
1267
  ## Confidence
1268
- One of: high / medium / low. With one sentence justifying the level.`,Dh=`[TASK]
1268
+ One of: high / medium / low. With one sentence justifying the level.`,Ph=`[TASK]
1269
1269
  Output a Markdown response with these sections:
1270
1270
 
1271
1271
  ## Most likely root cause
@@ -1282,7 +1282,7 @@ list is acceptable but explicitly say "(none found)".
1282
1282
  At most 2 alternatives, each with one sentence why it is less likely.
1283
1283
 
1284
1284
  ## Confidence
1285
- high / medium / low + one-sentence justification.`,Fh=`[TASK]
1285
+ high / medium / low + one-sentence justification.`,Uh=`[TASK]
1286
1286
  Output a Markdown response with these sections:
1287
1287
 
1288
1288
  ## Top 5 recurring concerns
@@ -1300,20 +1300,20 @@ Clusters that look small + high-confidence-fix. Empty list is fine.
1300
1300
  Clusters that suggest deeper issues (multiple files, repeated patterns).
1301
1301
 
1302
1302
  ## Confidence
1303
- high / medium / low.`;function Ph(e,t){let s;return e.scope==="cluster"?s=e.mode==="root_cause"?Dh:Mh:s=Fh,[Ih,"",t,"",s].join(`
1304
- `)}var Uh=null;var Xt;function $h(){if(Xt)return Xt;try{Xt=kh("which claude",{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{Xt="claude"}return Xt}function Bh(e){let t="";return s=>{t+=s.toString("utf8");let n=t.indexOf(`
1303
+ high / medium / low.`;function $h(e,t){let s;return e.scope==="cluster"?s=e.mode==="root_cause"?Ph:Fh:s=Uh,[jh,"",t,"",s].join(`
1304
+ `)}var Bh=null;var Xt;function Hh(){if(Xt)return Xt;try{Xt=xh("which claude",{encoding:"utf8",stdio:["ignore","pipe","ignore"]}).trim()}catch{Xt="claude"}return Xt}function Wh(e){let t="";return s=>{t+=s.toString("utf8");let n=t.indexOf(`
1305
1305
  `);for(;n!==-1;){let r=t.slice(0,n);t=t.slice(n+1),r.length>0&&e(r),n=t.indexOf(`
1306
- `)}}}function Hh(e){return new Promise(t=>{let s=["-p",e.prompt,"--output-format","stream-json","--verbose","--allowedTools","","--permission-mode","bypassPermissions","--model",e.model],n="",r=0,o=0,a=null,c=Rh($h(),s,{stdio:["ignore","pipe","pipe"]}),d=()=>{try{c.kill("SIGTERM")}catch{}};e.signal.addEventListener("abort",d,{once:!0});let g=Bh(b=>{let S=b.trim();if(!S.startsWith("{"))return;let y;try{y=JSON.parse(S)}catch{return}if(!y||typeof y!="object")return;let k=y;if(k.type==="assistant"&&k.message?.content){for(let D of k.message.content)D?.type==="text"&&typeof D.text=="string"&&(n+=D.text,e.onPartial(D.text,n));let w=k.message?.usage;w&&(typeof w.input_tokens=="number"&&(r=Math.max(r,w.input_tokens)),typeof w.output_tokens=="number"&&(o=Math.max(o,w.output_tokens)))}});c.stdout.on("data",b=>g(b)),c.stderr.on("data",b=>{let S=b.toString("utf8");S.trim()&&(a=(a??"")+S)});let h=setTimeout(()=>{try{c.kill("SIGKILL")}catch{}},1800*1e3);c.on("close",b=>{clearTimeout(h),e.signal.removeEventListener("abort",d);let S=b===0?null:a&&a.trim()||(e.signal.aborted?null:`claude CLI exited with code ${b}`);t({output_markdown:n,input_tokens:r,output_tokens:o,error:S})}),c.on("error",b=>{clearTimeout(h),e.signal.removeEventListener("abort",d),t({output_markdown:n,input_tokens:r,output_tokens:o,error:b instanceof Error?b.message:String(b)})})})}function Js(e){if(e.scope==="cluster"){let r=Nh(e.target_id);return r?{cluster:r,context_summary:{cluster_count:1,session_count:r.member_session_ids.length,findings_count:r.occurrence_count}}:null}let t=Oh(e.target_id);if(t.length===0)return null;let s=t.slice(0,30),n=t.reduce((r,o)=>r+o.occurrence_count,0);return{project_clusters:s,total_project_clusters:t.length,context_summary:{cluster_count:t.length,session_count:0,findings_count:n}}}function yl(e){let t=Js(e.intent);if(!t)return{error:e.intent.scope==="cluster"?`cluster "${e.intent.target_id}" not found in any extracted findings`:`project "${e.intent.target_id}" has no extracted findings to synthesize`};let s=bl(e.intent),n=Gt.get(s);if(n){let d=dt.get(n);if(d&&d.status==="running")return{jobId:n,reused:!0};Gt.delete(s)}let r=wh(),o=new AbortController,a=new Date().toISOString(),c={jobId:r,intent:e.intent,status:"running",startedAt:a,endedAt:null,events:[],waiters:new Set,controller:o,output_markdown:"",input_tokens:0,output_tokens:0,error:null,context_summary:t.context_summary,cleanupTimer:null};return dt.set(r,c),Gt.set(s,r),ee({kind:"synth-launched",job_id:r,project:e.intent.scope==="project"?e.intent.target_id:null,model:e.intent.model,limit:null,origin:e.origin??null,reason:`${e.intent.scope}/${e.intent.mode}/${e.intent.target_id}`}),(async()=>{await Promise.resolve();try{let d;if(e.intent.scope==="cluster"&&t.cluster){let b=Ch(t.cluster.member_session_ids,t.cluster.snippet);d=vh(t.cluster,b)}else if(e.intent.scope==="project"&&t.project_clusters)d=jh(e.intent.target_id,t.project_clusters,t.total_project_clusters??t.project_clusters.length);else throw new Error("inconsistent prepared context");let u=Ph(e.intent,d),h=await(Uh??Hh)({prompt:u,model:e.intent.model,signal:o.signal,onPartial:(b,S)=>{c.output_markdown=S,Jt(c,"partial",lt(c))}});if(c.output_markdown=h.output_markdown,c.input_tokens=h.input_tokens,c.output_tokens=h.output_tokens,o.signal.aborted)c.status="cancelled",c.endedAt=new Date().toISOString(),Jt(c,"done",lt(c)),ee({kind:"synth-cancelled",job_id:r,project:e.intent.scope==="project"?e.intent.target_id:null,model:e.intent.model,limit:null,origin:e.origin??null,input_tokens:c.input_tokens,output_tokens:c.output_tokens});else if(h.error)c.status="failed",c.endedAt=new Date().toISOString(),c.error=h.error,Jt(c,"done",lt(c)),ee({kind:"synth-failed",job_id:r,project:e.intent.scope==="project"?e.intent.target_id:null,model:e.intent.model,limit:null,origin:e.origin??null,reason:h.error,input_tokens:c.input_tokens,output_tokens:c.output_tokens});else{c.status="done",c.endedAt=new Date().toISOString(),Jt(c,"done",lt(c)),ee({kind:"synth-completed",job_id:r,project:e.intent.scope==="project"?e.intent.target_id:null,model:e.intent.model,limit:null,origin:e.origin??null,input_tokens:c.input_tokens,output_tokens:c.output_tokens});try{tl({scope:e.intent.scope,target_id:e.intent.target_id,mode:e.intent.mode,model:e.intent.model,output_markdown:c.output_markdown,input_tokens:c.input_tokens,output_tokens:c.output_tokens,job_id:r})}catch(b){console.error("[synthesize-jobs] failed to persist synthesis result:",b)}}}catch(d){let u=d instanceof Error?d.message:String(d??"unknown error");c.status="failed",c.endedAt=new Date().toISOString(),c.error=u,Jt(c,"done",lt(c)),ee({kind:"synth-failed",job_id:r,project:e.intent.scope==="project"?e.intent.target_id:null,model:e.intent.model,limit:null,origin:e.origin??null,reason:u,input_tokens:c.input_tokens,output_tokens:c.output_tokens})}finally{xh(c)}})(),{jobId:r,reused:!1}}async function*wl(e,t=0){let s=dt.get(e);if(!s)return;let n=t;for(;;){for(;n<s.events.length;){let r=s.events[n];if(!r)break;if(n+=1,yield r,r.kind==="done")return}if(s.status!=="running")return;await new Promise(r=>s.waiters.add(r))}}function Rl(e){let t=dt.get(e);return!t||t.status!=="running"?!1:(t.controller.abort(),!0)}function Dr(e){let t=dt.get(e);return t?lt(t):null}import{randomUUID as tE}from"node:crypto";H();import{randomUUID as Vh}from"node:crypto";H();var kl=10,Al=20;function Wh(e){if(!e)return!1;let t=e.split(`
1307
- `);if(t.length<4)return!1;let s=0,n=0;for(let r of t)/^\s*\d{1,5}\t/.test(r)?s++:/^\s*\/[A-Za-z0-9_./-]+/.test(r.trim())&&n++;return s/t.length>.7||n/t.length>.5}function qh(e){let t=e.byteLength/4;if(!Number.isInteger(t)||t<=0)return null;let s=new Float32Array(t),n=new Float32Array(e.buffer,e.byteOffset,t);return s.set(n),s}function xl(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];if(t<=0)return!1;let s=1/Math.sqrt(t);for(let n=0;n<e.length;n++)e[n]*=s;return!0}function Fr(e){if(e.length===0)return null;let t=e[0].length,s=new Float32Array(t);for(let n of e)if(n.length===t)for(let r=0;r<t;r++)s[r]+=n[r];for(let n=0;n<t;n++)s[n]/=e.length;return xl(s)?s:null}function Nl(e){let t=new Map;if(e.length===0)return t;let s=f(),n=e.map(()=>"?").join(","),r=[];try{r=s.prepare(`SELECT cm.rowid AS rowid, cm.session_id AS session_id,
1306
+ `)}}}function qh(e){return new Promise(t=>{let s=["-p",e.prompt,"--output-format","stream-json","--verbose","--allowedTools","","--permission-mode","bypassPermissions","--model",e.model],n="",r=0,o=0,a=null,c=Ah(Hh(),s,{stdio:["ignore","pipe","pipe"]}),d=()=>{try{c.kill("SIGTERM")}catch{}};e.signal.addEventListener("abort",d,{once:!0});let g=Wh(b=>{let S=b.trim();if(!S.startsWith("{"))return;let y;try{y=JSON.parse(S)}catch{return}if(!y||typeof y!="object")return;let k=y;if(k.type==="assistant"&&k.message?.content){for(let D of k.message.content)D?.type==="text"&&typeof D.text=="string"&&(n+=D.text,e.onPartial(D.text,n));let w=k.message?.usage;w&&(typeof w.input_tokens=="number"&&(r=Math.max(r,w.input_tokens)),typeof w.output_tokens=="number"&&(o=Math.max(o,w.output_tokens)))}});c.stdout.on("data",b=>g(b)),c.stderr.on("data",b=>{let S=b.toString("utf8");S.trim()&&(a=(a??"")+S)});let h=setTimeout(()=>{try{c.kill("SIGKILL")}catch{}},1800*1e3);c.on("close",b=>{clearTimeout(h),e.signal.removeEventListener("abort",d);let S=b===0?null:a&&a.trim()||(e.signal.aborted?null:`claude CLI exited with code ${b}`);t({output_markdown:n,input_tokens:r,output_tokens:o,error:S})}),c.on("error",b=>{clearTimeout(h),e.signal.removeEventListener("abort",d),t({output_markdown:n,input_tokens:r,output_tokens:o,error:b instanceof Error?b.message:String(b)})})})}function Js(e){if(e.scope==="cluster"){let r=Lh(e.target_id);return r?{cluster:r,context_summary:{cluster_count:1,session_count:r.member_session_ids.length,findings_count:r.occurrence_count}}:null}let t=Ch(e.target_id);if(t.length===0)return null;let s=t.slice(0,30),n=t.reduce((r,o)=>r+o.occurrence_count,0);return{project_clusters:s,total_project_clusters:t.length,context_summary:{cluster_count:t.length,session_count:0,findings_count:n}}}function yl(e){let t=Js(e.intent);if(!t)return{error:e.intent.scope==="cluster"?`cluster "${e.intent.target_id}" not found in any extracted findings`:`project "${e.intent.target_id}" has no extracted findings to synthesize`};let s=bl(e.intent),n=Gt.get(s);if(n){let d=dt.get(n);if(d&&d.status==="running")return{jobId:n,reused:!0};Gt.delete(s)}let r=kh(),o=new AbortController,a=new Date().toISOString(),c={jobId:r,intent:e.intent,status:"running",startedAt:a,endedAt:null,events:[],waiters:new Set,controller:o,output_markdown:"",input_tokens:0,output_tokens:0,error:null,context_summary:t.context_summary,cleanupTimer:null};return dt.set(r,c),Gt.set(s,r),ee({kind:"synth-launched",job_id:r,project:e.intent.scope==="project"?e.intent.target_id:null,model:e.intent.model,limit:null,origin:e.origin??null,reason:`${e.intent.scope}/${e.intent.mode}/${e.intent.target_id}`}),(async()=>{await Promise.resolve();try{let d;if(e.intent.scope==="cluster"&&t.cluster){let b=vh(t.cluster.member_session_ids,t.cluster.snippet);d=Mh(t.cluster,b)}else if(e.intent.scope==="project"&&t.project_clusters)d=Dh(e.intent.target_id,t.project_clusters,t.total_project_clusters??t.project_clusters.length);else throw new Error("inconsistent prepared context");let u=$h(e.intent,d),h=await(Bh??qh)({prompt:u,model:e.intent.model,signal:o.signal,onPartial:(b,S)=>{c.output_markdown=S,Jt(c,"partial",lt(c))}});if(c.output_markdown=h.output_markdown,c.input_tokens=h.input_tokens,c.output_tokens=h.output_tokens,o.signal.aborted)c.status="cancelled",c.endedAt=new Date().toISOString(),Jt(c,"done",lt(c)),ee({kind:"synth-cancelled",job_id:r,project:e.intent.scope==="project"?e.intent.target_id:null,model:e.intent.model,limit:null,origin:e.origin??null,input_tokens:c.input_tokens,output_tokens:c.output_tokens});else if(h.error)c.status="failed",c.endedAt=new Date().toISOString(),c.error=h.error,Jt(c,"done",lt(c)),ee({kind:"synth-failed",job_id:r,project:e.intent.scope==="project"?e.intent.target_id:null,model:e.intent.model,limit:null,origin:e.origin??null,reason:h.error,input_tokens:c.input_tokens,output_tokens:c.output_tokens});else{c.status="done",c.endedAt=new Date().toISOString(),Jt(c,"done",lt(c)),ee({kind:"synth-completed",job_id:r,project:e.intent.scope==="project"?e.intent.target_id:null,model:e.intent.model,limit:null,origin:e.origin??null,input_tokens:c.input_tokens,output_tokens:c.output_tokens});try{tl({scope:e.intent.scope,target_id:e.intent.target_id,mode:e.intent.mode,model:e.intent.model,output_markdown:c.output_markdown,input_tokens:c.input_tokens,output_tokens:c.output_tokens,job_id:r})}catch(b){console.error("[synthesize-jobs] failed to persist synthesis result:",b)}}}catch(d){let u=d instanceof Error?d.message:String(d??"unknown error");c.status="failed",c.endedAt=new Date().toISOString(),c.error=u,Jt(c,"done",lt(c)),ee({kind:"synth-failed",job_id:r,project:e.intent.scope==="project"?e.intent.target_id:null,model:e.intent.model,limit:null,origin:e.origin??null,reason:u,input_tokens:c.input_tokens,output_tokens:c.output_tokens})}finally{Oh(c)}})(),{jobId:r,reused:!1}}async function*wl(e,t=0){let s=dt.get(e);if(!s)return;let n=t;for(;;){for(;n<s.events.length;){let r=s.events[n];if(!r)break;if(n+=1,yield r,r.kind==="done")return}if(s.status!=="running")return;await new Promise(r=>s.waiters.add(r))}}function Rl(e){let t=dt.get(e);return!t||t.status!=="running"?!1:(t.controller.abort(),!0)}function Dr(e){let t=dt.get(e);return t?lt(t):null}import{randomUUID as nE}from"node:crypto";H();import{randomUUID as Qh}from"node:crypto";H();var kl=10,Al=20;function Jh(e){if(!e)return!1;let t=e.split(`
1307
+ `);if(t.length<4)return!1;let s=0,n=0;for(let r of t)/^\s*\d{1,5}\t/.test(r)?s++:/^\s*\/[A-Za-z0-9_./-]+/.test(r.trim())&&n++;return s/t.length>.7||n/t.length>.5}function Xh(e){let t=e.byteLength/4;if(!Number.isInteger(t)||t<=0)return null;let s=new Float32Array(t),n=new Float32Array(e.buffer,e.byteOffset,t);return s.set(n),s}function xl(e){let t=0;for(let n=0;n<e.length;n++)t+=e[n]*e[n];if(t<=0)return!1;let s=1/Math.sqrt(t);for(let n=0;n<e.length;n++)e[n]*=s;return!0}function Fr(e){if(e.length===0)return null;let t=e[0].length,s=new Float32Array(t);for(let n of e)if(n.length===t)for(let r=0;r<t;r++)s[r]+=n[r];for(let n=0;n<t;n++)s[n]/=e.length;return xl(s)?s:null}function Nl(e){let t=new Map;if(e.length===0)return t;let s=f(),n=e.map(()=>"?").join(","),r=[];try{r=s.prepare(`SELECT cm.rowid AS rowid, cm.session_id AS session_id,
1308
1308
  cm.text AS text, v.embedding AS embedding
1309
1309
  FROM chunk_meta cm
1310
1310
  JOIN vec_chunks v ON v.rowid = cm.rowid
1311
1311
  WHERE cm.stale = 0
1312
1312
  AND cm.session_id IN (${n})
1313
- ORDER BY cm.session_id, cm.rowid ASC`).all(...e)}catch{return t}if(r.length===0)return t;let o=new Map;for(let a of r){let c=o.get(a.session_id);c||(c=[],o.set(a.session_id,c)),c.push(a)}for(let[a,c]of o){let d=c.filter(M=>!Wh(M.text)),u=d.length>0?d:c,g=[];for(let M of u){let B=qh(M.embedding);B&&xl(B)&&g.push(B)}if(g.length===0)continue;let h=Math.min(kl,g.length),b=Math.max(0,g.length-kl),S=g.slice(0,h),y=g.slice(b),k=Fr(S),w=Fr(y),D=Fr(g),L=new Map;for(let M=0;M<S.length&&L.size<Al;M++)L.set(M,S[M]);for(let M=0;M<y.length&&L.size<Al;M++)L.set(b+M,y[M]);let X=Array.from(L.values());t.set(a,{session_id:a,full_mean:D,head_pool:k,tail_pool:w,sample_chunks:X})}return t}function Jh(e,t){if(e.length!==t.length)return 0;let s=0;for(let n=0;n<e.length;n++)s+=e[n]*t[n];return s<-1?-1:s>1?1:s}function Ol(e,t=.8){let s=new Map,n=[],r=[];for(let[u,g]of e)g.full_mean&&(n.push(u),r.push(g.full_mean));if(n.length===0)return s;let o=new Int32Array(n.length);for(let u=0;u<o.length;u++)o[u]=u;let a=u=>{let g=u;for(;o[g]!==g;)g=o[g];let h=u;for(;o[h]!==g;){let b=o[h];o[h]=g,h=b}return g},c=(u,g)=>{let h=a(u),b=a(g);h!==b&&(o[h]=b)};for(let u=0;u<n.length;u++)for(let g=u+1;g<n.length;g++)Jh(r[u],r[g])>=t&&c(u,g);let d=new Map;for(let u=0;u<n.length;u++){let g=a(u),h=d.get(g);h===void 0&&(h=d.size,d.set(g,h)),s.set(n[u],h)}return s}var Ae={lo:.4,hi:.7},ut="claude-haiku-4-5-20251001",pt=50,Ll=1500,Cl=50,Xh={same_workflow:.15,unrelated:-.2,unsure:0};function Il(e,t,s=Ae){if(s.lo>s.hi)throw new Error(`borderline band invalid: lo=${s.lo} > hi=${s.hi}`);let n=[];for(let r of e){if(r.confidence<s.lo||r.confidence>s.hi)continue;let o=t.get(r.parent_id),a=t.get(r.child_id);!o||!a||n.push({parent:o,child:a,step1:r})}return n.sort((r,o)=>r.child.started_at_ms-o.child.started_at_ms),n}function vl(e,t=Ae){let s=0;for(let n of e)n.confidence>=t.lo&&n.confidence<=t.hi&&s++;return s}function Gh(e,t){let s=e.replace(/\s+/g," ").trim();return s.length>t?s.slice(0,t-1)+"\u2026":s}function Yh(e,t){if(e===null)return"unknown";let s=t-e;if(s<0)return"overlap";let n=Math.round(s/6e4);if(n<60)return`${n}m`;let r=Math.round(s/36e5);return r<24?`${r}h`:`${Math.round(s/864e5)}d`}function Kh(e){let s=e.parent.recent_user_messages,n=e.child.recent_user_messages,r=s.slice(0,3),o=s.length>3?s.slice(-3):[],a=n.slice(0,3),c=u=>u.length===0?" (none captured)":u.map(g=>` - ${Gh(g,500)}`).join(`
1314
- `),d=Yh(e.parent.ended_at_ms??e.parent.started_at_ms,e.child.started_at_ms);return["You are evaluating whether two Claude Code sessions belong to the same continuous workflow.","","A deterministic scorer rated this pair in the borderline band. Its signals:",e.step1.reasons.length===0?" (no signals fired strongly)":e.step1.reasons.map(u=>` - ${u}`).join(`
1313
+ ORDER BY cm.session_id, cm.rowid ASC`).all(...e)}catch{return t}if(r.length===0)return t;let o=new Map;for(let a of r){let c=o.get(a.session_id);c||(c=[],o.set(a.session_id,c)),c.push(a)}for(let[a,c]of o){let d=c.filter(M=>!Jh(M.text)),u=d.length>0?d:c,g=[];for(let M of u){let B=Xh(M.embedding);B&&xl(B)&&g.push(B)}if(g.length===0)continue;let h=Math.min(kl,g.length),b=Math.max(0,g.length-kl),S=g.slice(0,h),y=g.slice(b),k=Fr(S),w=Fr(y),D=Fr(g),L=new Map;for(let M=0;M<S.length&&L.size<Al;M++)L.set(M,S[M]);for(let M=0;M<y.length&&L.size<Al;M++)L.set(b+M,y[M]);let X=Array.from(L.values());t.set(a,{session_id:a,full_mean:D,head_pool:k,tail_pool:w,sample_chunks:X})}return t}function Gh(e,t){if(e.length!==t.length)return 0;let s=0;for(let n=0;n<e.length;n++)s+=e[n]*t[n];return s<-1?-1:s>1?1:s}function Ol(e,t=.8){let s=new Map,n=[],r=[];for(let[u,g]of e)g.full_mean&&(n.push(u),r.push(g.full_mean));if(n.length===0)return s;let o=new Int32Array(n.length);for(let u=0;u<o.length;u++)o[u]=u;let a=u=>{let g=u;for(;o[g]!==g;)g=o[g];let h=u;for(;o[h]!==g;){let b=o[h];o[h]=g,h=b}return g},c=(u,g)=>{let h=a(u),b=a(g);h!==b&&(o[h]=b)};for(let u=0;u<n.length;u++)for(let g=u+1;g<n.length;g++)Gh(r[u],r[g])>=t&&c(u,g);let d=new Map;for(let u=0;u<n.length;u++){let g=a(u),h=d.get(g);h===void 0&&(h=d.size,d.set(g,h)),s.set(n[u],h)}return s}var Ae={lo:.4,hi:.7},ut="claude-haiku-4-5-20251001",pt=50,Ll=1500,Cl=50,Yh={same_workflow:.15,unrelated:-.2,unsure:0};function Il(e,t,s=Ae){if(s.lo>s.hi)throw new Error(`borderline band invalid: lo=${s.lo} > hi=${s.hi}`);let n=[];for(let r of e){if(r.confidence<s.lo||r.confidence>s.hi)continue;let o=t.get(r.parent_id),a=t.get(r.child_id);!o||!a||n.push({parent:o,child:a,step1:r})}return n.sort((r,o)=>r.child.started_at_ms-o.child.started_at_ms),n}function vl(e,t=Ae){let s=0;for(let n of e)n.confidence>=t.lo&&n.confidence<=t.hi&&s++;return s}function Kh(e,t){let s=e.replace(/\s+/g," ").trim();return s.length>t?s.slice(0,t-1)+"\u2026":s}function zh(e,t){if(e===null)return"unknown";let s=t-e;if(s<0)return"overlap";let n=Math.round(s/6e4);if(n<60)return`${n}m`;let r=Math.round(s/36e5);return r<24?`${r}h`:`${Math.round(s/864e5)}d`}function Vh(e){let s=e.parent.recent_user_messages,n=e.child.recent_user_messages,r=s.slice(0,3),o=s.length>3?s.slice(-3):[],a=n.slice(0,3),c=u=>u.length===0?" (none captured)":u.map(g=>` - ${Kh(g,500)}`).join(`
1314
+ `),d=zh(e.parent.ended_at_ms??e.parent.started_at_ms,e.child.started_at_ms);return["You are evaluating whether two Claude Code sessions belong to the same continuous workflow.","","A deterministic scorer rated this pair in the borderline band. Its signals:",e.step1.reasons.length===0?" (no signals fired strongly)":e.step1.reasons.map(u=>` - ${u}`).join(`
1315
1315
  `),` step1_confidence: ${e.step1.confidence.toFixed(2)}`,"","PARENT SESSION","First user messages:",c(r),"Last user messages:",c(o),"",`CHILD SESSION (gap from parent: ${d})`,"First user messages:",c(a),"","Reply with EXACTLY one JSON object on a single line, no prose, no markdown:",'{"verdict":"same_workflow"|"unrelated"|"unsure","reason":"<one short sentence>"}',"","Guidance:",'- "same_workflow" = the child is clearly continuing what the parent was doing.','- "unrelated" = different problem, different files, different intent.','- "unsure" = could go either way; do not force a verdict.'].join(`
1316
- `)}function zh(e){if(!e)return null;let t=e.trim();if(!t)return null;let s=t;try{let d=JSON.parse(t);typeof d.result=="string"&&(s=d.result.trim())}catch{}let n=s.match(/\{[\s\S]*\}/);if(!n)return null;let r;try{r=JSON.parse(n[0])}catch{return null}if(!r||typeof r!="object")return null;let o=r,a=typeof o.verdict=="string"?o.verdict.toLowerCase():"";if(a!=="same_workflow"&&a!=="unrelated"&&a!=="unsure")return null;let c=typeof o.reason=="string"&&o.reason.trim()?o.reason.trim():"";return{verdict:a,reason:c,delta:Xh[a]}}async function jl(e,t={}){if(t.signal?.aborted)return null;let s=t.model??ut,n=Kh(e),r=t.spawn;if(!r)try{let a=await Promise.resolve().then(()=>(ge(),Pe));if(!a.isClaudeCliAvailable())return null;r=(c,d)=>a.spawnClaudePrompt(c,[],d)}catch{return null}let o;try{o=await Promise.race([r(n,{model:s}),new Promise(a=>{t.signal&&t.signal.addEventListener("abort",()=>a({success:!1,stdout:""}),{once:!0})})])}catch{return null}return!o.success||!o.stdout?null:zh(o.stdout)}function Ml(e){let t=[];for(let s of e.proposals){let n=`${s.parent_id}::${s.child_id}`,r=e.rescored.get(n);if(!r){t.push(s);continue}let o=Math.max(0,Math.min(1,s.confidence+r.delta));if(o<e.applyThreshold)continue;let a=`LLM: ${r.verdict}${r.reason?` \u2014 ${r.reason}`:""} (${r.delta>=0?"+":""}${r.delta.toFixed(2)})`;t.push({...s,confidence:o,reasons:[...s.reasons,a]})}return t}function Dl(e){return`${e.parent_id}::${e.child_id}`}async function Zh(e){if(e.signal?.aborted)return null;let t,s;try{({spawnClaudePrompt:t,isClaudeCliAvailable:s}=await Promise.resolve().then(()=>(ge(),Pe)))}catch{return null}if(!s())return null;let n=[];for(let o of e.sessionIds){let a=e.rowById.get(o);if(!a)continue;let c=a.alias||a.auto_title||(a.first_user_message?a.first_user_message.slice(0,120).replace(/\n/g," "):"(no title)");n.push(`- ${c}`)}let r=`Below is a chronological list of related Claude Code sessions that form one continuous workflow. Generate a single short descriptive name for the workflow as a whole. Requirements:
1316
+ `)}function Zh(e){if(!e)return null;let t=e.trim();if(!t)return null;let s=t;try{let d=JSON.parse(t);typeof d.result=="string"&&(s=d.result.trim())}catch{}let n=s.match(/\{[\s\S]*\}/);if(!n)return null;let r;try{r=JSON.parse(n[0])}catch{return null}if(!r||typeof r!="object")return null;let o=r,a=typeof o.verdict=="string"?o.verdict.toLowerCase():"";if(a!=="same_workflow"&&a!=="unrelated"&&a!=="unsure")return null;let c=typeof o.reason=="string"&&o.reason.trim()?o.reason.trim():"";return{verdict:a,reason:c,delta:Yh[a]}}async function jl(e,t={}){if(t.signal?.aborted)return null;let s=t.model??ut,n=Vh(e),r=t.spawn;if(!r)try{let a=await Promise.resolve().then(()=>(ge(),Pe));if(!a.isClaudeCliAvailable())return null;r=(c,d)=>a.spawnClaudePrompt(c,[],d)}catch{return null}let o;try{o=await Promise.race([r(n,{model:s}),new Promise(a=>{t.signal&&t.signal.addEventListener("abort",()=>a({success:!1,stdout:""}),{once:!0})})])}catch{return null}return!o.success||!o.stdout?null:Zh(o.stdout)}function Ml(e){let t=[];for(let s of e.proposals){let n=`${s.parent_id}::${s.child_id}`,r=e.rescored.get(n);if(!r){t.push(s);continue}let o=Math.max(0,Math.min(1,s.confidence+r.delta));if(o<e.applyThreshold)continue;let a=`LLM: ${r.verdict}${r.reason?` \u2014 ${r.reason}`:""} (${r.delta>=0?"+":""}${r.delta.toFixed(2)})`;t.push({...s,confidence:o,reasons:[...s.reasons,a]})}return t}function Dl(e){return`${e.parent_id}::${e.child_id}`}async function eE(e){if(e.signal?.aborted)return null;let t,s;try{({spawnClaudePrompt:t,isClaudeCliAvailable:s}=await Promise.resolve().then(()=>(ge(),Pe)))}catch{return null}if(!s())return null;let n=[];for(let o of e.sessionIds){let a=e.rowById.get(o);if(!a)continue;let c=a.alias||a.auto_title||(a.first_user_message?a.first_user_message.slice(0,120).replace(/\n/g," "):"(no title)");n.push(`- ${c}`)}let r=`Below is a chronological list of related Claude Code sessions that form one continuous workflow. Generate a single short descriptive name for the workflow as a whole. Requirements:
1317
1317
  - 4 to 8 words
1318
1318
  - Title-case, no trailing punctuation
1319
1319
  - Capture the WORKFLOW (e.g., "Update Remotion deps + lint cleanup"), not any one session
@@ -1324,12 +1324,12 @@ Sessions:
1324
1324
  `+n.join(`
1325
1325
  `)+`
1326
1326
 
1327
- Return ONLY the workflow name on a single line.`;try{let o=t(r,[],e.model?{model:e.model}:{}),a=null,c=new Promise(h=>{e.signal&&(a=()=>h(null),e.signal.addEventListener("abort",a,{once:!0}))}),d=await Promise.race([o,c]);if(a&&e.signal&&e.signal.removeEventListener("abort",a),!d||!d.success)return null;let u=d.stdout.trim();if(!u)return null;let g;try{let h=JSON.parse(u);g=typeof h.result=="string"?h.result:u}catch{g=u}return g=g.trim().replace(/^["'`]+|["'`]+$/g,"").replace(/[.!?]+$/g,"").trim(),g?g.length>80?g.slice(0,77)+"...":g:null}catch{return null}}function Pr(e){return Qh(e)}function Ur(e){let t=new Map;for(let o of e){let a=t.get(o.project);a||(a=[],t.set(o.project,a)),a.push(o)}let s=e.map(o=>o.id),n=new Map;try{n=Nl(s)}catch{n=new Map}let r=new Map;for(let[o,a]of t){let c=new Map;for(let g of a){let h=n.get(g.id);h&&c.set(g.id,h)}let d=Ol(c,.8),u=[];for(let g of a){let h=eE(g,n,d);h&&u.push(h)}r.set(o,u)}return{byProject:t,scannablesByProject:r}}function Pl(e){return f().prepare(`SELECT COUNT(DISTINCT t.id) AS n
1327
+ Return ONLY the workflow name on a single line.`;try{let o=t(r,[],e.model?{model:e.model}:{}),a=null,c=new Promise(h=>{e.signal&&(a=()=>h(null),e.signal.addEventListener("abort",a,{once:!0}))}),d=await Promise.race([o,c]);if(a&&e.signal&&e.signal.removeEventListener("abort",a),!d||!d.success)return null;let u=d.stdout.trim();if(!u)return null;let g;try{let h=JSON.parse(u);g=typeof h.result=="string"?h.result:u}catch{g=u}return g=g.trim().replace(/^["'`]+|["'`]+$/g,"").replace(/[.!?]+$/g,"").trim(),g?g.length>80?g.slice(0,77)+"...":g:null}catch{return null}}function Pr(e){return tE(e)}function Ur(e){let t=new Map;for(let o of e){let a=t.get(o.project);a||(a=[],t.set(o.project,a)),a.push(o)}let s=e.map(o=>o.id),n=new Map;try{n=Nl(s)}catch{n=new Map}let r=new Map;for(let[o,a]of t){let c=new Map;for(let g of a){let h=n.get(g.id);h&&c.set(g.id,h)}let d=Ol(c,.8),u=[];for(let g of a){let h=sE(g,n,d);h&&u.push(h)}r.set(o,u)}return{byProject:t,scannablesByProject:r}}function Pl(e){return f().prepare(`SELECT COUNT(DISTINCT t.id) AS n
1328
1328
  FROM threads t
1329
1329
  JOIN thread_edges te ON te.thread_id = t.id
1330
1330
  JOIN sessions s ON s.id = te.session_id
1331
1331
  JOIN projects p ON p.id = s.project_id
1332
- WHERE t.id LIKE 'auto-scan-%' AND p.name = ?`).get(e)?.n??0}function Qh(e){let t=f(),s={},n="1=1 AND s.message_count > 2";return n+=" AND COALESCE(s.auto_title, '') NOT LIKE '[meta]%' AND COALESCE(s.auto_title, '') NOT LIKE '[output-index]%' AND COALESCE(s.auto_title, '') NOT LIKE '[skill]%'",e.project&&(n+=" AND p.name = @project",s.project=e.project),t.prepare(`SELECT s.id, p.name AS project, s.started_at, s.ended_at,
1332
+ WHERE t.id LIKE 'auto-scan-%' AND p.name = ?`).get(e)?.n??0}function tE(e){let t=f(),s={},n="1=1 AND s.message_count > 2";return n+=" AND COALESCE(s.auto_title, '') NOT LIKE '[meta]%' AND COALESCE(s.auto_title, '') NOT LIKE '[output-index]%' AND COALESCE(s.auto_title, '') NOT LIKE '[skill]%'",e.project&&(n+=" AND p.name = @project",s.project=e.project),t.prepare(`SELECT s.id, p.name AS project, s.started_at, s.ended_at,
1333
1333
  s.first_user_message, s.auto_title,
1334
1334
  NULLIF(sa.alias, '') AS alias,
1335
1335
  s.file_path
@@ -1337,14 +1337,14 @@ Return ONLY the workflow name on a single line.`;try{let o=t(r,[],e.model?{model
1337
1337
  JOIN projects p ON p.id = s.project_id
1338
1338
  LEFT JOIN session_aliases sa ON sa.session_id = s.id
1339
1339
  WHERE ${n}
1340
- ORDER BY p.name ASC, s.started_at ASC`).all(s)}function eE(e,t,s){if(!e.started_at)return null;let n=Date.parse(e.started_at);if(!Number.isFinite(n))return null;let r=e.ended_at?Date.parse(e.ended_at):null,o=ys(e.file_path,{maxUserMessages:7}),a=t?.get(e.id);return{id:e.id,started_at_ms:n,ended_at_ms:Number.isFinite(r)?r:null,first_user_message:e.first_user_message,recent_user_messages:o.recent_user_messages,auto_title:e.auto_title,touched_files:o.touched_files,mean_embedding:a?.full_mean??null,head_pool:a?.head_pool??null,tail_pool:a?.tail_pool??null,sample_chunks:a?.sample_chunks??[],cluster_id:s?.get(e.id)??null,authored_paths:o.authored_paths,authored_content:o.authored_content}}function Fl(e){let t=e.alias||e.auto_title||(e.first_user_message?e.first_user_message.slice(0,60).replace(/\n/g," ").trim():`thread from ${e.id.slice(0,8)}`);return t.length>80?t.slice(0,77)+"...":t}async function Ul(e){if(!e.rescore.enabled)return{proposals:e.proposals,ran:!1,considered:0,promoted:0,demoted:0,unsure:0,failed:0,capped:!1};let t=e.rescore.band??Ae,s=e.rescore.cap??pt,n=e.rescore.model??ut,r=new Map(e.scannables.map(b=>[b.id,b])),o=Il(e.proposals,r,t);if(o.length===0)return{proposals:e.proposals,ran:!0,considered:0,promoted:0,demoted:0,unsure:0,failed:0,capped:!1};if(o.length>s)return{proposals:e.proposals,ran:!1,considered:o.length,promoted:0,demoted:0,unsure:0,failed:0,capped:!0};let a=new Map,c=0,d=0,u=0,g=0;for(let b=0;b<o.length&&!e.signal?.aborted;b++){let S=o[b],y=await jl(S,{model:n,signal:e.signal});y?(a.set(Dl(S.step1),y),y.verdict==="same_workflow"?c++:y.verdict==="unrelated"?d++:u++):g++,e.onProgress?.({phase:"rescoring",current:b+1,total:o.length,verdict:y?.verdict??"failed"})}return{proposals:Ml({proposals:e.proposals,rescored:a,applyThreshold:e.applyThreshold}),ran:!0,considered:o.length,promoted:c,demoted:d,unsure:u,failed:g,capped:!1}}async function $l(e){let t=f(),s=new Map(e.rows.map(u=>[u.id,u])),n=Qi(e.edges,e.scannables),r=new Date().toISOString(),o=[],a=new Map,c=0;for(let u of n){if(c++,e.signal?.aborted)break;let g=s.get(u.rootId),h=Fl(g);if(!e.llmNames){a.set(u.rootId,h),e.onProgress?.({phase:"naming",current:c,total:n.length,thread_name:h});continue}let S=await Zh({rootRow:g,sessionIds:u.sessionIds,rowById:s,signal:e.signal,model:e.model})??h;a.set(u.rootId,S),e.onProgress?.({phase:"naming",current:c,total:n.length,thread_name:S})}return t.transaction(()=>{for(let u of n){if(!a.has(u.rootId))continue;let g=s.get(u.rootId),h=`auto-scan-${Vh()}`,b=a.get(u.rootId)??Fl(g),S=`Auto-detected workflow chain (${u.sessionIds.length} sessions). Source: auto-scan-v1.`;t.prepare("INSERT INTO threads (id, name, summary, created_at) VALUES (?, ?, ?, ?)").run(h,b,S,r),t.prepare(`INSERT INTO thread_edges
1340
+ ORDER BY p.name ASC, s.started_at ASC`).all(s)}function sE(e,t,s){if(!e.started_at)return null;let n=Date.parse(e.started_at);if(!Number.isFinite(n))return null;let r=e.ended_at?Date.parse(e.ended_at):null,o=ys(e.file_path,{maxUserMessages:7}),a=t?.get(e.id);return{id:e.id,started_at_ms:n,ended_at_ms:Number.isFinite(r)?r:null,first_user_message:e.first_user_message,recent_user_messages:o.recent_user_messages,auto_title:e.auto_title,touched_files:o.touched_files,mean_embedding:a?.full_mean??null,head_pool:a?.head_pool??null,tail_pool:a?.tail_pool??null,sample_chunks:a?.sample_chunks??[],cluster_id:s?.get(e.id)??null,authored_paths:o.authored_paths,authored_content:o.authored_content}}function Fl(e){let t=e.alias||e.auto_title||(e.first_user_message?e.first_user_message.slice(0,60).replace(/\n/g," ").trim():`thread from ${e.id.slice(0,8)}`);return t.length>80?t.slice(0,77)+"...":t}async function Ul(e){if(!e.rescore.enabled)return{proposals:e.proposals,ran:!1,considered:0,promoted:0,demoted:0,unsure:0,failed:0,capped:!1};let t=e.rescore.band??Ae,s=e.rescore.cap??pt,n=e.rescore.model??ut,r=new Map(e.scannables.map(b=>[b.id,b])),o=Il(e.proposals,r,t);if(o.length===0)return{proposals:e.proposals,ran:!0,considered:0,promoted:0,demoted:0,unsure:0,failed:0,capped:!1};if(o.length>s)return{proposals:e.proposals,ran:!1,considered:o.length,promoted:0,demoted:0,unsure:0,failed:0,capped:!0};let a=new Map,c=0,d=0,u=0,g=0;for(let b=0;b<o.length&&!e.signal?.aborted;b++){let S=o[b],y=await jl(S,{model:n,signal:e.signal});y?(a.set(Dl(S.step1),y),y.verdict==="same_workflow"?c++:y.verdict==="unrelated"?d++:u++):g++,e.onProgress?.({phase:"rescoring",current:b+1,total:o.length,verdict:y?.verdict??"failed"})}return{proposals:Ml({proposals:e.proposals,rescored:a,applyThreshold:e.applyThreshold}),ran:!0,considered:o.length,promoted:c,demoted:d,unsure:u,failed:g,capped:!1}}async function $l(e){let t=f(),s=new Map(e.rows.map(u=>[u.id,u])),n=Qi(e.edges,e.scannables),r=new Date().toISOString(),o=[],a=new Map,c=0;for(let u of n){if(c++,e.signal?.aborted)break;let g=s.get(u.rootId),h=Fl(g);if(!e.llmNames){a.set(u.rootId,h),e.onProgress?.({phase:"naming",current:c,total:n.length,thread_name:h});continue}let S=await eE({rootRow:g,sessionIds:u.sessionIds,rowById:s,signal:e.signal,model:e.model})??h;a.set(u.rootId,S),e.onProgress?.({phase:"naming",current:c,total:n.length,thread_name:S})}return t.transaction(()=>{for(let u of n){if(!a.has(u.rootId))continue;let g=s.get(u.rootId),h=`auto-scan-${Qh()}`,b=a.get(u.rootId)??Fl(g),S=`Auto-detected workflow chain (${u.sessionIds.length} sessions). Source: auto-scan-v1.`;t.prepare("INSERT INTO threads (id, name, summary, created_at) VALUES (?, ?, ?, ?)").run(h,b,S,r),t.prepare(`INSERT INTO thread_edges
1341
1341
  (thread_id, session_id, parent_session_id, role, confidence, source, added_at)
1342
1342
  VALUES (?, ?, NULL, 'origin', 1.0, 'auto-scan-v1', ?)`).run(h,u.rootId,r);let y=new Map;for(let k of e.edges)u.sessionIds.includes(k.child_id)&&y.set(k.child_id,k);for(let k of u.sessionIds){if(k===u.rootId)continue;let w=y.get(k);w&&t.prepare(`INSERT INTO thread_edges
1343
1343
  (thread_id, session_id, parent_session_id, role, confidence, source, added_at)
1344
- VALUES (?, ?, ?, 'child', ?, 'auto-scan-v1', ?)`).run(h,k,w.parent_id,w.confidence,r)}o.push({thread_id:h,name:b,session_count:u.sessionIds.length})}})(),{project:e.project,threads:o}}var gt=new Map,Yt=new Map,sE=300*1e3;function mt(e,t,s){e.events.push({id:e.events.length+1,kind:t,data:s});for(let n of e.waiters)n();e.waiters.clear()}function nE(e){e.cleanupTimer||(e.cleanupTimer=setTimeout(()=>{gt.delete(e.jobId),Yt.get(e.project)===e.jobId&&Yt.delete(e.project)},sE),e.cleanupTimer.unref?.())}function Xs(e){return{jobId:e.jobId,project:e.project,threshold:e.threshold,llm_names:e.llmNames,status:e.status,startedAt:e.startedAt,endedAt:e.endedAt,total_threads:e.totalThreads,threads_named:e.threadsNamed,edges_written:e.edgesWritten,threads_created:e.threadsCreated,current_thread_name:e.currentThreadName,error:e.error,rescore:e.rescore}}var rE=500,oE=30,$r="claude-haiku-4-5-20251001",Bl={"claude-haiku-4-5-20251001":{in:1,out:5,label:"Haiku 4.5"},"claude-sonnet-4-6":{in:3,out:15,label:"Sonnet 4.6"},"claude-opus-4-7":{in:15,out:75,label:"Opus 4.7"}};function Hl(e){return Bl[e]??Bl[$r]}function Wl(e){let t=typeof e.threshold=="number"?e.threshold:Ss;if(!Number.isFinite(t)||t<0||t>1)return{error:"threshold must be a number in [0, 1]"};let s=e.model??$r,n="",r=!!e.llm_rescore?.enabled,o={lo:e.llm_rescore?.band_lo??Ae.lo,hi:e.llm_rescore?.band_hi??Ae.hi};if(r&&(!Number.isFinite(o.lo)||!Number.isFinite(o.hi)||o.lo<0||o.hi>1||o.lo>o.hi))return{error:"rescore band must satisfy 0 \u2264 lo \u2264 hi \u2264 1"};let a=e.llm_rescore?.model??ut,c=Pr({project:e.project});if(c.length===0)return{eligible_sessions:0,proposed_edges:0,estimated_threads:0,estimated_llm_calls:0,estimated_input_tokens_max:0,estimated_output_tokens_max:0,estimated_cost_usd_max:0,existing_auto_scan_threads:0,plan_window_estimate:Ce(0,s),accuracy_caveat:n,model:s,llm_rescore:r?{enabled:!0,band:o,cap:pt,estimated_borderline_pairs:0,estimated_input_tokens_max:0,estimated_output_tokens_max:0,estimated_cost_usd_max:0,plan_window_estimate:Ce(0,a),exceeds_cap:!1,model:a}:null};let{byProject:d,scannablesByProject:u}=Ur(c),g=d.get(e.project)??[],h=u.get(e.project)??[],b=r?Math.min(t,o.lo):t,S=ze(h,b),y=r?S.filter(p=>p.confidence>=t):S,k=ql(y),w=k*rE,D=k*oE,L=Hl(s),X=w/1e6*L.in,M=D/1e6*L.out,B=X+M,se=Ce(k,s),i=Pl(e.project),l=null;if(r){let p=vl(S,o),m=Hl(a),_=p*Ll,E=p*Cl,T=_/1e6*m.in+E/1e6*m.out;l={enabled:!0,band:o,cap:pt,estimated_borderline_pairs:p,estimated_input_tokens_max:_,estimated_output_tokens_max:E,estimated_cost_usd_max:Math.round(T*1e4)/1e4,plan_window_estimate:Ce(p,a),exceeds_cap:p>pt,model:a}}return{eligible_sessions:g.length,proposed_edges:y.length,estimated_threads:k,estimated_llm_calls:k,estimated_input_tokens_max:w,estimated_output_tokens_max:D,estimated_cost_usd_max:Math.round(B*1e4)/1e4,existing_auto_scan_threads:i,plan_window_estimate:se,accuracy_caveat:n,model:s,llm_rescore:l}}function ql(e){let t=new Map,s=o=>{let a=o;for(;t.get(a)!==a;)a=t.get(a);return a},n=(o,a)=>{let c=s(o),d=s(a);c!==d&&t.set(c,d)};for(let o of e)t.has(o.parent_id)||t.set(o.parent_id,o.parent_id),t.has(o.child_id)||t.set(o.child_id,o.child_id),n(o.parent_id,o.child_id);let r=new Set;for(let o of t.keys())r.add(s(o));return r.size}function Jl(e){let t=typeof e.threshold=="number"?e.threshold:Ss;if(!Number.isFinite(t)||t<0||t>1)return{error:"threshold must be a number in [0, 1]"};let s=e.llm_names??!0,n=e.model??$r,r=!!e.llm_rescore?.enabled,o={lo:e.llm_rescore?.band_lo??Ae.lo,hi:e.llm_rescore?.band_hi??Ae.hi};if(r&&(!Number.isFinite(o.lo)||!Number.isFinite(o.hi)||o.lo<0||o.hi>1||o.lo>o.hi))return{error:"rescore band must satisfy 0 \u2264 lo \u2264 hi \u2264 1"};let a=e.llm_rescore?.model??ut,c=Yt.get(e.project);if(c){let B=gt.get(c);if(B&&B.status==="running")return{jobId:c,reused:!0};Yt.delete(e.project)}let d=Pr({project:e.project});if(d.length===0)return{error:`no eligible sessions in project "${e.project}"`};let{byProject:u,scannablesByProject:g}=Ur(d),h=u.get(e.project),b=g.get(e.project);if(!h||!b)return{error:`project "${e.project}" not found`};let S=r?Math.min(t,o.lo):t,y=ze(b,S),k=r?y.filter(B=>B.confidence>=t):y;if(y.length===0||k.length===0&&!r)return{error:"no edges above threshold; nothing to apply"};let w=tE(),D=new AbortController,L=ql(k),X=new Date().toISOString(),M={jobId:w,project:e.project,threshold:t,llmNames:s,status:"running",startedAt:X,endedAt:null,events:[],waiters:new Set,controller:D,totalThreads:L,threadsNamed:0,edgesWritten:0,threadsCreated:0,currentThreadName:null,error:null,cleanupTimer:null,rescore:r?{enabled:!0,considered:0,promoted:0,demoted:0,unsure:0,failed:0,capped:!1}:null};return gt.set(w,M),Yt.set(e.project,w),(async()=>{await Promise.resolve();try{mt(M,"progress",{phase:"linking",edges_proposed:y.length,estimated_threads:L});let B=y;if(r){let i=await Ul({proposals:y,scannables:b,applyThreshold:t,rescore:{enabled:!0,band:o,model:a},signal:D.signal,onProgress:l=>{l.phase==="rescoring"&&mt(M,"progress",{phase:"rescoring",current:l.current,total:l.total,verdict:l.verdict})}});B=i.proposals,M.rescore={enabled:!0,considered:i.considered,promoted:i.promoted,demoted:i.demoted,unsure:i.unsure,failed:i.failed,capped:i.capped}}else B=y.filter(i=>i.confidence>=t);if(B.length===0){M.status=D.signal.aborted?"cancelled":"done",M.endedAt=new Date().toISOString(),mt(M,"done",{...Xs(M),threads:[]});return}let se=await $l({project:e.project,rows:h,edges:B,scannables:b,llmNames:s,model:n,signal:D.signal,onProgress:i=>{i.phase==="naming"&&(M.threadsNamed=i.current,M.currentThreadName=i.thread_name??null,mt(M,"progress",{phase:"naming",current:i.current,total:i.total,thread_name:i.thread_name}))}});M.threadsCreated=se.threads.length,M.edgesWritten=B.length+se.threads.length,M.status=D.signal.aborted?"cancelled":"done",M.endedAt=new Date().toISOString(),mt(M,"done",{...Xs(M),threads:se.threads})}catch(B){M.status="failed",M.endedAt=new Date().toISOString(),M.error=B instanceof Error?B.message:String(B??"unknown error"),mt(M,"done",Xs(M))}finally{nE(M)}})(),{jobId:w,reused:!1}}async function*Xl(e,t=0){let s=gt.get(e);if(!s)return;let n=t;for(;;){for(;n<s.events.length;){let r=s.events[n];if(!r)break;if(n+=1,yield r,r.kind==="done")return}if(s.status!=="running")return;await new Promise(r=>s.waiters.add(r))}}function Gl(e){let t=gt.get(e);return!t||t.status!=="running"?!1:(t.controller.abort(),!0)}function Br(e){let t=gt.get(e);return t?Xs(t):null}rs();import{randomUUID as iE}from"node:crypto";var Gs=new Map;function Yl(e){let t={id:iE(),status:"pending",createdAt:new Date().toISOString(),finishedAt:null,total:e,completed:0,results:[],error:null,controller:new AbortController,listeners:new Set};return Gs.set(t.id,t),t}function Ys(e){return Gs.get(e)}function _t(e,t){for(let s of e.listeners)s(t)}function Kl(e,t){return e.listeners.add(t),()=>{e.listeners.delete(t)}}function zl(e){let t=Gs.get(e);return t?(t.controller.abort(),t.status="cancelled",t.finishedAt=new Date().toISOString(),_t(t,{type:"status",status:"cancelled"}),!0):!1}function Vl(e){return Gs.delete(e)}Ge();function Ks(e){let{session:t,knownTags:s,minTags:n,maxTags:r}=e,o=s.slice(0,50).map(c=>c.tag).join(", "),a=t.current_tags.length>0?`already applied, do not repeat: [${t.current_tags.join(", ")}]`:"currently has no tags";return[`You are tagging a software engineering session. Produce ${n}-${r} concise, lowercase, hyphen-separated tags that describe:`," - the domain or subsystem touched (auth, db, frontend, ...)"," - the kind of work (bugfix, feature, refactor, research, ...)"," - any specific tool, library, or product if prominent","","Prefer tags from the known-tags list below when applicable \u2014 consistency over creativity. Never invent marketing-sounding labels. Never tag based on speculation; only on observed work.","",`known tags (most used first, up to 50): ${o||"(none yet)"}`,"","Session:",` project: ${t.project}`,t.alias?` alias: ${JSON.stringify(t.alias)}`:" alias: (none)",t.git_branch?` git_branch: ${t.git_branch}`:"",` ${a}`," first_user_message:",Zl(t.first_user_message," ")," message_sample:",Zl(t.message_sample," "),"","Return a single JSON object matching this schema exactly, with no prose before or after:",`{"tags": string[] length ${n}-${r}, "confidence": number 0-1, "rationale": string one short sentence}`].filter(Boolean).join(`
1344
+ VALUES (?, ?, ?, 'child', ?, 'auto-scan-v1', ?)`).run(h,k,w.parent_id,w.confidence,r)}o.push({thread_id:h,name:b,session_count:u.sessionIds.length})}})(),{project:e.project,threads:o}}var gt=new Map,Yt=new Map,rE=300*1e3;function mt(e,t,s){e.events.push({id:e.events.length+1,kind:t,data:s});for(let n of e.waiters)n();e.waiters.clear()}function oE(e){e.cleanupTimer||(e.cleanupTimer=setTimeout(()=>{gt.delete(e.jobId),Yt.get(e.project)===e.jobId&&Yt.delete(e.project)},rE),e.cleanupTimer.unref?.())}function Xs(e){return{jobId:e.jobId,project:e.project,threshold:e.threshold,llm_names:e.llmNames,status:e.status,startedAt:e.startedAt,endedAt:e.endedAt,total_threads:e.totalThreads,threads_named:e.threadsNamed,edges_written:e.edgesWritten,threads_created:e.threadsCreated,current_thread_name:e.currentThreadName,error:e.error,rescore:e.rescore}}var iE=500,aE=30,$r="claude-haiku-4-5-20251001",Bl={"claude-haiku-4-5-20251001":{in:1,out:5,label:"Haiku 4.5"},"claude-sonnet-4-6":{in:3,out:15,label:"Sonnet 4.6"},"claude-opus-4-7":{in:15,out:75,label:"Opus 4.7"}};function Hl(e){return Bl[e]??Bl[$r]}function Wl(e){let t=typeof e.threshold=="number"?e.threshold:Ss;if(!Number.isFinite(t)||t<0||t>1)return{error:"threshold must be a number in [0, 1]"};let s=e.model??$r,n="",r=!!e.llm_rescore?.enabled,o={lo:e.llm_rescore?.band_lo??Ae.lo,hi:e.llm_rescore?.band_hi??Ae.hi};if(r&&(!Number.isFinite(o.lo)||!Number.isFinite(o.hi)||o.lo<0||o.hi>1||o.lo>o.hi))return{error:"rescore band must satisfy 0 \u2264 lo \u2264 hi \u2264 1"};let a=e.llm_rescore?.model??ut,c=Pr({project:e.project});if(c.length===0)return{eligible_sessions:0,proposed_edges:0,estimated_threads:0,estimated_llm_calls:0,estimated_input_tokens_max:0,estimated_output_tokens_max:0,estimated_cost_usd_max:0,existing_auto_scan_threads:0,plan_window_estimate:Ce(0,s),accuracy_caveat:n,model:s,llm_rescore:r?{enabled:!0,band:o,cap:pt,estimated_borderline_pairs:0,estimated_input_tokens_max:0,estimated_output_tokens_max:0,estimated_cost_usd_max:0,plan_window_estimate:Ce(0,a),exceeds_cap:!1,model:a}:null};let{byProject:d,scannablesByProject:u}=Ur(c),g=d.get(e.project)??[],h=u.get(e.project)??[],b=r?Math.min(t,o.lo):t,S=ze(h,b),y=r?S.filter(p=>p.confidence>=t):S,k=ql(y),w=k*iE,D=k*aE,L=Hl(s),X=w/1e6*L.in,M=D/1e6*L.out,B=X+M,se=Ce(k,s),i=Pl(e.project),l=null;if(r){let p=vl(S,o),m=Hl(a),_=p*Ll,E=p*Cl,T=_/1e6*m.in+E/1e6*m.out;l={enabled:!0,band:o,cap:pt,estimated_borderline_pairs:p,estimated_input_tokens_max:_,estimated_output_tokens_max:E,estimated_cost_usd_max:Math.round(T*1e4)/1e4,plan_window_estimate:Ce(p,a),exceeds_cap:p>pt,model:a}}return{eligible_sessions:g.length,proposed_edges:y.length,estimated_threads:k,estimated_llm_calls:k,estimated_input_tokens_max:w,estimated_output_tokens_max:D,estimated_cost_usd_max:Math.round(B*1e4)/1e4,existing_auto_scan_threads:i,plan_window_estimate:se,accuracy_caveat:n,model:s,llm_rescore:l}}function ql(e){let t=new Map,s=o=>{let a=o;for(;t.get(a)!==a;)a=t.get(a);return a},n=(o,a)=>{let c=s(o),d=s(a);c!==d&&t.set(c,d)};for(let o of e)t.has(o.parent_id)||t.set(o.parent_id,o.parent_id),t.has(o.child_id)||t.set(o.child_id,o.child_id),n(o.parent_id,o.child_id);let r=new Set;for(let o of t.keys())r.add(s(o));return r.size}function Jl(e){let t=typeof e.threshold=="number"?e.threshold:Ss;if(!Number.isFinite(t)||t<0||t>1)return{error:"threshold must be a number in [0, 1]"};let s=e.llm_names??!0,n=e.model??$r,r=!!e.llm_rescore?.enabled,o={lo:e.llm_rescore?.band_lo??Ae.lo,hi:e.llm_rescore?.band_hi??Ae.hi};if(r&&(!Number.isFinite(o.lo)||!Number.isFinite(o.hi)||o.lo<0||o.hi>1||o.lo>o.hi))return{error:"rescore band must satisfy 0 \u2264 lo \u2264 hi \u2264 1"};let a=e.llm_rescore?.model??ut,c=Yt.get(e.project);if(c){let B=gt.get(c);if(B&&B.status==="running")return{jobId:c,reused:!0};Yt.delete(e.project)}let d=Pr({project:e.project});if(d.length===0)return{error:`no eligible sessions in project "${e.project}"`};let{byProject:u,scannablesByProject:g}=Ur(d),h=u.get(e.project),b=g.get(e.project);if(!h||!b)return{error:`project "${e.project}" not found`};let S=r?Math.min(t,o.lo):t,y=ze(b,S),k=r?y.filter(B=>B.confidence>=t):y;if(y.length===0||k.length===0&&!r)return{error:"no edges above threshold; nothing to apply"};let w=nE(),D=new AbortController,L=ql(k),X=new Date().toISOString(),M={jobId:w,project:e.project,threshold:t,llmNames:s,status:"running",startedAt:X,endedAt:null,events:[],waiters:new Set,controller:D,totalThreads:L,threadsNamed:0,edgesWritten:0,threadsCreated:0,currentThreadName:null,error:null,cleanupTimer:null,rescore:r?{enabled:!0,considered:0,promoted:0,demoted:0,unsure:0,failed:0,capped:!1}:null};return gt.set(w,M),Yt.set(e.project,w),(async()=>{await Promise.resolve();try{mt(M,"progress",{phase:"linking",edges_proposed:y.length,estimated_threads:L});let B=y;if(r){let i=await Ul({proposals:y,scannables:b,applyThreshold:t,rescore:{enabled:!0,band:o,model:a},signal:D.signal,onProgress:l=>{l.phase==="rescoring"&&mt(M,"progress",{phase:"rescoring",current:l.current,total:l.total,verdict:l.verdict})}});B=i.proposals,M.rescore={enabled:!0,considered:i.considered,promoted:i.promoted,demoted:i.demoted,unsure:i.unsure,failed:i.failed,capped:i.capped}}else B=y.filter(i=>i.confidence>=t);if(B.length===0){M.status=D.signal.aborted?"cancelled":"done",M.endedAt=new Date().toISOString(),mt(M,"done",{...Xs(M),threads:[]});return}let se=await $l({project:e.project,rows:h,edges:B,scannables:b,llmNames:s,model:n,signal:D.signal,onProgress:i=>{i.phase==="naming"&&(M.threadsNamed=i.current,M.currentThreadName=i.thread_name??null,mt(M,"progress",{phase:"naming",current:i.current,total:i.total,thread_name:i.thread_name}))}});M.threadsCreated=se.threads.length,M.edgesWritten=B.length+se.threads.length,M.status=D.signal.aborted?"cancelled":"done",M.endedAt=new Date().toISOString(),mt(M,"done",{...Xs(M),threads:se.threads})}catch(B){M.status="failed",M.endedAt=new Date().toISOString(),M.error=B instanceof Error?B.message:String(B??"unknown error"),mt(M,"done",Xs(M))}finally{oE(M)}})(),{jobId:w,reused:!1}}async function*Xl(e,t=0){let s=gt.get(e);if(!s)return;let n=t;for(;;){for(;n<s.events.length;){let r=s.events[n];if(!r)break;if(n+=1,yield r,r.kind==="done")return}if(s.status!=="running")return;await new Promise(r=>s.waiters.add(r))}}function Gl(e){let t=gt.get(e);return!t||t.status!=="running"?!1:(t.controller.abort(),!0)}function Br(e){let t=gt.get(e);return t?Xs(t):null}rs();import{randomUUID as cE}from"node:crypto";var Gs=new Map;function Yl(e){let t={id:cE(),status:"pending",createdAt:new Date().toISOString(),finishedAt:null,total:e,completed:0,results:[],error:null,controller:new AbortController,listeners:new Set};return Gs.set(t.id,t),t}function Ys(e){return Gs.get(e)}function _t(e,t){for(let s of e.listeners)s(t)}function Kl(e,t){return e.listeners.add(t),()=>{e.listeners.delete(t)}}function zl(e){let t=Gs.get(e);return t?(t.controller.abort(),t.status="cancelled",t.finishedAt=new Date().toISOString(),_t(t,{type:"status",status:"cancelled"}),!0):!1}function Vl(e){return Gs.delete(e)}Ge();function Ks(e){let{session:t,knownTags:s,minTags:n,maxTags:r}=e,o=s.slice(0,50).map(c=>c.tag).join(", "),a=t.current_tags.length>0?`already applied, do not repeat: [${t.current_tags.join(", ")}]`:"currently has no tags";return[`You are tagging a software engineering session. Produce ${n}-${r} concise, lowercase, hyphen-separated tags that describe:`," - the domain or subsystem touched (auth, db, frontend, ...)"," - the kind of work (bugfix, feature, refactor, research, ...)"," - any specific tool, library, or product if prominent","","Prefer tags from the known-tags list below when applicable \u2014 consistency over creativity. Never invent marketing-sounding labels. Never tag based on speculation; only on observed work.","",`known tags (most used first, up to 50): ${o||"(none yet)"}`,"","Session:",` project: ${t.project}`,t.alias?` alias: ${JSON.stringify(t.alias)}`:" alias: (none)",t.git_branch?` git_branch: ${t.git_branch}`:"",` ${a}`," first_user_message:",Zl(t.first_user_message," ")," message_sample:",Zl(t.message_sample," "),"","Return a single JSON object matching this schema exactly, with no prose before or after:",`{"tags": string[] length ${n}-${r}, "confidence": number 0-1, "rationale": string one short sentence}`].filter(Boolean).join(`
1345
1345
  `)}function Zl(e,t){return e.split(`
1346
1346
  `).map(s=>t+s).join(`
1347
- `)}Ge();import{z as Kt}from"zod";var aE=Kt.object({tags:Kt.array(Kt.string()).min(1),confidence:Kt.number().min(0).max(1),rationale:Kt.string().min(1).max(500)});function cE(e){let t=e.trim();return t.startsWith("```")?t.replace(/^```(?:json)?\s*/i,"").replace(/```$/i,"").trim():t}function zs(e,t={}){let s=t.maxTags??10,n;try{n=JSON.parse(cE(e))}catch{return{ok:!1,reason:"not valid JSON"}}let r=aE.safeParse(n);if(!r.success)return{ok:!1,reason:r.error.issues.map(c=>c.message).join("; ")};let o=r.data.tags.map(c=>De(c)).filter(c=>c.length>0),a=Array.from(new Set(o)).slice(0,s);return a.length===0?{ok:!1,reason:"no usable tags after normalization"}:{ok:!0,data:{tags:a,confidence:r.data.confidence,rationale:r.data.rationale}}}import lE from"@anthropic-ai/sdk";async function Vs(e){let n=(await new lE({apiKey:e.apiKey}).messages.create({model:e.model,max_tokens:512,temperature:.2,messages:[{role:"user",content:e.prompt}]},e.signal?{signal:e.signal}:void 0)).content.find(r=>r.type==="text");if(!n||n.type!=="text")throw new Error("Anthropic response contained no text block");return n.text}function dE(e){if(!(e instanceof Error))return!1;let t=e;return t.status===429||t.status===502||t.status===503||t.status===504}async function Zs(e,t={}){let s=t.maxAttempts??3,n=t.baseDelayMs??500,r;for(let o=0;o<s;o++)try{return await e()}catch(a){if(r=a,!dE(a)||o===s-1)throw a;await new Promise(c=>setTimeout(c,n*Math.pow(2,o)))}throw r}async function Ql(e,t){e.status="running",_t(e,{type:"status",status:"running"});let s=Xe();for(let n of t.sessions){if(e.controller.signal.aborted)break;let r=Ks({session:n,knownTags:s,minTags:t.minTags,maxTags:t.maxTags}),o={sessionId:n.id,project:n.project,alias:n.alias,first_user_message:n.first_user_message,current_tags:n.current_tags,suggestion:null,error:null,applied:!1};try{let a=await Zs(()=>Vs({apiKey:t.apiKey,model:t.model,prompt:r,signal:e.controller.signal})),c=zs(a,{maxTags:t.maxTags});c.ok?o.suggestion=c.data:o.error=c.reason}catch(a){o.error=a instanceof Error?a.message:String(a)}e.results.push(o),e.completed+=1,_t(e,{type:"result",result:o}),_t(e,{type:"progress",completed:e.completed,total:e.total})}if(!e.controller.signal.aborted){e.status="completed",e.finishedAt=new Date().toISOString();let n=e.results.filter(o=>o.suggestion&&!o.error).length,r=e.results.filter(o=>o.error).length;_t(e,{type:"done",summary:{ok:n,failed:r}})}}function ed(e,t){let s=0,n=0;for(let r of t){let o=e.results.find(a=>a.sessionId===r.sessionId);if(o){for(let a of r.tags)try{let{added:c}=Je(r.sessionId,a);c&&(s+=1)}catch(c){console.error("[scanner] apply failed:",r.sessionId,a,c),n+=1}o.applied=!0}}return{applied:s,failed:n}}Ge();rs();var Y={running:!1,status:"idle",processed:0,total:0,currentSessionId:null,lastError:null,lastRunAt:null,controller:null},Hr=new Set;function Vt(){return{status:Y.status,processed:Y.processed,total:Y.total,currentSessionId:Y.currentSessionId,lastError:Y.lastError,lastRunAt:Y.lastRunAt}}function td(e){return Hr.add(e),()=>{Hr.delete(e)}}function zt(){let e=Vt();for(let t of Hr)t(e)}async function Qs(){let e=Re();if(!(!e.enabled||!e.autopilot)&&!(e.backend!=="api"||!e.apiKey)&&!Y.running){Y.running=!0,Y.status="scanning",Y.processed=0,Y.total=0,Y.currentSessionId=null,Y.lastError=null,Y.controller=new AbortController,zt();try{let t=Ye({untaggedOnly:!0,limit:200});if(Y.total=t.length,zt(),t.length===0){Y.status="idle",Y.lastRunAt=new Date().toISOString();return}let s=Xe();for(let n of t){if(Y.controller.signal.aborted)break;let r=Re();if(!r.autopilot||!r.enabled||r.backend!=="api"||!r.apiKey)break;Y.currentSessionId=n.id,zt();let o=Ks({session:n,knownTags:s,minTags:r.minTagsPerSession,maxTags:r.maxTagsPerSession});try{let a=await Zs(()=>Vs({apiKey:r.apiKey,model:r.model,prompt:o,signal:Y.controller.signal})),c=zs(a,{maxTags:r.maxTagsPerSession});if(c.ok)for(let d of c.data.tags)try{Je(n.id,d)}catch(u){console.error("[autopilot] addTag failed:",n.id,d,u)}}catch(a){console.error("[autopilot] scan failed for",n.id,a)}Y.processed+=1,zt(),await new Promise(a=>setTimeout(a,1500))}Y.status="idle",Y.lastRunAt=new Date().toISOString()}catch(t){Y.status="error",Y.lastError=t instanceof Error?t.message:String(t),console.error("[autopilot] fatal:",t)}finally{Y.running=!1,Y.currentSessionId=null,Y.controller=null,zt()}}}import{execFileSync as uE}from"node:child_process";import{existsSync as sd,readFileSync as pE,writeFileSync as nd}from"node:fs";import{homedir as mE}from"node:os";import{dirname as gE,join as _E,resolve as fE}from"node:path";import{fileURLToPath as hE}from"node:url";var ft=_E(mE(),".claude.json"),EE=gE(hE(import.meta.url)),bE=fE(EE,"..","mcp","server.js");function qr(){if(!sd(ft))return{};try{let e=pE(ft,"utf8"),t=JSON.parse(e);return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}catch(e){return console.error("[mcp-installer] failed to parse ~/.claude.json:",e),{}}}var Wr=new Map;function SE(e){let t=Wr.get(e);if(t!==void 0)return t;try{return uE("command",["-v",e],{stdio:"ignore"}),Wr.set(e,!0),!0}catch{return Wr.set(e,!1),!1}}function TE(){return SE("claude-recall-mcp")?{command:"claude-recall-mcp",args:[]}:{command:process.execPath,args:[bE]}}function Ie(){let t=qr().mcpServers?.recall;return{configPath:ft,configExists:sd(ft),installed:!!(t&&typeof t.command=="string"),command:t?.command??null,args:t?.args??null}}function rd(){let e=qr(),t=e.mcpServers??{},s=TE(),n=t.recall;if(n?.command===s.command&&JSON.stringify(n?.args??[])===JSON.stringify(s.args))return Ie();let o={command:s.command};s.args.length>0&&(o.args=s.args);let a={...e,mcpServers:{...t,recall:o}};return nd(ft,JSON.stringify(a,null,2)),Ie()}function od(){let e=qr(),t=e.mcpServers??{};if(!t.recall)return Ie();let{recall:s,...n}=t,r={...e,mcpServers:n};return nd(ft,JSON.stringify(r,null,2)),Ie()}import{existsSync as id,mkdirSync as yE,readFileSync as wE,writeFileSync as ad}from"node:fs";import{homedir as RE}from"node:os";import{join as cd}from"node:path";import{z as ve}from"zod";function ld(){return process.env.RECALL_HOME??cd(RE(),".recall")}function dd(){let e=ld();id(e)||yE(e,{recursive:!0})}function Xr(){return cd(ld(),"onboarding.json")}var en=ve.object({version:ve.literal(1).default(1),completed:ve.boolean().default(!1),skipped:ve.boolean().default(!1),finishedAt:ve.string().nullable().default(null),completedSteps:ve.array(ve.string().max(100)).max(50).default([]),threadsIntroSeen:ve.boolean().default(!1)}),Jr={version:1,completed:!1,skipped:!1,finishedAt:null,completedSteps:[],threadsIntroSeen:!1};function tn(){let e=Xr();if(!id(e))return{...Jr};try{let t=JSON.parse(wE(e,"utf8")),s=en.safeParse(t);return s.success?s.data:{...Jr}}catch(t){return console.error("[onboarding-state] failed to parse onboarding.json, using defaults:",t),{...Jr}}}function ud(e){dd();let t=tn(),s=en.parse({...t,...e,completedSteps:kE([...t.completedSteps??[],...e.completedSteps??[]]),version:1});return ad(Xr(),JSON.stringify(s,null,2)),s}function pd(){dd();let e=tn(),t={version:1,completed:!1,skipped:!1,finishedAt:null,completedSteps:e.completedSteps,threadsIntroSeen:e.threadsIntroSeen};return ad(Xr(),JSON.stringify(t,null,2)),t}function kE(e){let t=new Set,s=[];for(let n of e)t.has(n)||(t.add(n),s.push(n));return s}ge();In();Cn();import{existsSync as md,mkdirSync as AE,readFileSync as xE,writeFileSync as NE}from"node:fs";import{homedir as OE}from"node:os";import{join as gd}from"node:path";import{z as xe}from"zod";function _d(){return process.env.RECALL_HOME??gd(OE(),".recall")}function LE(){let e=_d();md(e)||AE(e,{recursive:!0})}function fd(){return gd(_d(),"config.json")}var nn=xe.object({enabled:xe.boolean().default(!1),model:xe.string().optional(),ratePerMinute:xe.number().int().min(1).max(600).default(30),lastProcessedSessionId:xe.string().nullable().default(null),backfillPaused:xe.boolean().default(!1),autoExtractEnabled:xe.boolean().default(!1),autoExtractIntervalMinutes:xe.number().int().min(5).max(720).default(60),autoExtractBatchSize:xe.number().int().min(1).max(20).default(1)}),sn={enabled:!1,ratePerMinute:30,lastProcessedSessionId:null,backfillPaused:!1,autoExtractEnabled:!1,autoExtractIntervalMinutes:60,autoExtractBatchSize:1};function hd(){let e=fd();if(!md(e))return{};try{return JSON.parse(xE(e,"utf8"))}catch(t){return console.error("[semantic-config] failed to parse config.json, using defaults:",t),{}}}function ce(){let e=hd().semantic;if(!e)return{...sn};let t=nn.safeParse({...sn,...e});return t.success?t.data:{...sn}}function rn(e){LE();let t=hd(),s=nn.parse({...sn,...t.semantic??{},...e}),n={...t,semantic:s};return NE(fd(),JSON.stringify(n,null,2)),s}H();ge();import{existsSync as CE,mkdirSync as IE,writeFileSync as vE}from"node:fs";import{homedir as jE}from"node:os";import{join as Gr}from"node:path";var ME=1,DE=12e3,Ed=3,FE=[];function PE(){return process.env.RECALL_HOME??Gr(jE(),".recall")}function bd(){return Gr(PE(),"semantic")}function UE(){let e=bd();CE(e)||IE(e,{recursive:!0})}function $E(e){let t=f(),s=t.prepare(`SELECT s.id, s.message_count, s.first_user_message,
1347
+ `)}Ge();import{z as Kt}from"zod";var lE=Kt.object({tags:Kt.array(Kt.string()).min(1),confidence:Kt.number().min(0).max(1),rationale:Kt.string().min(1).max(500)});function dE(e){let t=e.trim();return t.startsWith("```")?t.replace(/^```(?:json)?\s*/i,"").replace(/```$/i,"").trim():t}function zs(e,t={}){let s=t.maxTags??10,n;try{n=JSON.parse(dE(e))}catch{return{ok:!1,reason:"not valid JSON"}}let r=lE.safeParse(n);if(!r.success)return{ok:!1,reason:r.error.issues.map(c=>c.message).join("; ")};let o=r.data.tags.map(c=>De(c)).filter(c=>c.length>0),a=Array.from(new Set(o)).slice(0,s);return a.length===0?{ok:!1,reason:"no usable tags after normalization"}:{ok:!0,data:{tags:a,confidence:r.data.confidence,rationale:r.data.rationale}}}import uE from"@anthropic-ai/sdk";async function Vs(e){let n=(await new uE({apiKey:e.apiKey}).messages.create({model:e.model,max_tokens:512,temperature:.2,messages:[{role:"user",content:e.prompt}]},e.signal?{signal:e.signal}:void 0)).content.find(r=>r.type==="text");if(!n||n.type!=="text")throw new Error("Anthropic response contained no text block");return n.text}function pE(e){if(!(e instanceof Error))return!1;let t=e;return t.status===429||t.status===502||t.status===503||t.status===504}async function Zs(e,t={}){let s=t.maxAttempts??3,n=t.baseDelayMs??500,r;for(let o=0;o<s;o++)try{return await e()}catch(a){if(r=a,!pE(a)||o===s-1)throw a;await new Promise(c=>setTimeout(c,n*Math.pow(2,o)))}throw r}async function Ql(e,t){e.status="running",_t(e,{type:"status",status:"running"});let s=Xe();for(let n of t.sessions){if(e.controller.signal.aborted)break;let r=Ks({session:n,knownTags:s,minTags:t.minTags,maxTags:t.maxTags}),o={sessionId:n.id,project:n.project,alias:n.alias,first_user_message:n.first_user_message,current_tags:n.current_tags,suggestion:null,error:null,applied:!1};try{let a=await Zs(()=>Vs({apiKey:t.apiKey,model:t.model,prompt:r,signal:e.controller.signal})),c=zs(a,{maxTags:t.maxTags});c.ok?o.suggestion=c.data:o.error=c.reason}catch(a){o.error=a instanceof Error?a.message:String(a)}e.results.push(o),e.completed+=1,_t(e,{type:"result",result:o}),_t(e,{type:"progress",completed:e.completed,total:e.total})}if(!e.controller.signal.aborted){e.status="completed",e.finishedAt=new Date().toISOString();let n=e.results.filter(o=>o.suggestion&&!o.error).length,r=e.results.filter(o=>o.error).length;_t(e,{type:"done",summary:{ok:n,failed:r}})}}function ed(e,t){let s=0,n=0;for(let r of t){let o=e.results.find(a=>a.sessionId===r.sessionId);if(o){for(let a of r.tags)try{let{added:c}=Je(r.sessionId,a);c&&(s+=1)}catch(c){console.error("[scanner] apply failed:",r.sessionId,a,c),n+=1}o.applied=!0}}return{applied:s,failed:n}}Ge();rs();var Y={running:!1,status:"idle",processed:0,total:0,currentSessionId:null,lastError:null,lastRunAt:null,controller:null},Hr=new Set;function Vt(){return{status:Y.status,processed:Y.processed,total:Y.total,currentSessionId:Y.currentSessionId,lastError:Y.lastError,lastRunAt:Y.lastRunAt}}function td(e){return Hr.add(e),()=>{Hr.delete(e)}}function zt(){let e=Vt();for(let t of Hr)t(e)}async function Qs(){let e=Re();if(!(!e.enabled||!e.autopilot)&&!(e.backend!=="api"||!e.apiKey)&&!Y.running){Y.running=!0,Y.status="scanning",Y.processed=0,Y.total=0,Y.currentSessionId=null,Y.lastError=null,Y.controller=new AbortController,zt();try{let t=Ye({untaggedOnly:!0,limit:200});if(Y.total=t.length,zt(),t.length===0){Y.status="idle",Y.lastRunAt=new Date().toISOString();return}let s=Xe();for(let n of t){if(Y.controller.signal.aborted)break;let r=Re();if(!r.autopilot||!r.enabled||r.backend!=="api"||!r.apiKey)break;Y.currentSessionId=n.id,zt();let o=Ks({session:n,knownTags:s,minTags:r.minTagsPerSession,maxTags:r.maxTagsPerSession});try{let a=await Zs(()=>Vs({apiKey:r.apiKey,model:r.model,prompt:o,signal:Y.controller.signal})),c=zs(a,{maxTags:r.maxTagsPerSession});if(c.ok)for(let d of c.data.tags)try{Je(n.id,d)}catch(u){console.error("[autopilot] addTag failed:",n.id,d,u)}}catch(a){console.error("[autopilot] scan failed for",n.id,a)}Y.processed+=1,zt(),await new Promise(a=>setTimeout(a,1500))}Y.status="idle",Y.lastRunAt=new Date().toISOString()}catch(t){Y.status="error",Y.lastError=t instanceof Error?t.message:String(t),console.error("[autopilot] fatal:",t)}finally{Y.running=!1,Y.currentSessionId=null,Y.controller=null,zt()}}}import{execFileSync as mE}from"node:child_process";import{existsSync as sd,readFileSync as gE,writeFileSync as nd}from"node:fs";import{homedir as _E}from"node:os";import{dirname as fE,join as hE,resolve as EE}from"node:path";import{fileURLToPath as bE}from"node:url";var ft=hE(_E(),".claude.json"),SE=fE(bE(import.meta.url)),TE=EE(SE,"..","mcp","server.js");function qr(){if(!sd(ft))return{};try{let e=gE(ft,"utf8"),t=JSON.parse(e);return t&&typeof t=="object"&&!Array.isArray(t)?t:{}}catch(e){return console.error("[mcp-installer] failed to parse ~/.claude.json:",e),{}}}var Wr=new Map;function yE(e){let t=Wr.get(e);if(t!==void 0)return t;try{return mE("command",["-v",e],{stdio:"ignore"}),Wr.set(e,!0),!0}catch{return Wr.set(e,!1),!1}}function wE(){return yE("claude-recall-mcp")?{command:"claude-recall-mcp",args:[]}:{command:process.execPath,args:[TE]}}function Ie(){let t=qr().mcpServers?.recall;return{configPath:ft,configExists:sd(ft),installed:!!(t&&typeof t.command=="string"),command:t?.command??null,args:t?.args??null}}function rd(){let e=qr(),t=e.mcpServers??{},s=wE(),n=t.recall;if(n?.command===s.command&&JSON.stringify(n?.args??[])===JSON.stringify(s.args))return Ie();let o={command:s.command};s.args.length>0&&(o.args=s.args);let a={...e,mcpServers:{...t,recall:o}};return nd(ft,JSON.stringify(a,null,2)),Ie()}function od(){let e=qr(),t=e.mcpServers??{};if(!t.recall)return Ie();let{recall:s,...n}=t,r={...e,mcpServers:n};return nd(ft,JSON.stringify(r,null,2)),Ie()}import{existsSync as id,mkdirSync as RE,readFileSync as kE,writeFileSync as ad}from"node:fs";import{homedir as AE}from"node:os";import{join as cd}from"node:path";import{z as ve}from"zod";function ld(){return process.env.RECALL_HOME??cd(AE(),".recall")}function dd(){let e=ld();id(e)||RE(e,{recursive:!0})}function Xr(){return cd(ld(),"onboarding.json")}var en=ve.object({version:ve.literal(1).default(1),completed:ve.boolean().default(!1),skipped:ve.boolean().default(!1),finishedAt:ve.string().nullable().default(null),completedSteps:ve.array(ve.string().max(100)).max(50).default([]),threadsIntroSeen:ve.boolean().default(!1)}),Jr={version:1,completed:!1,skipped:!1,finishedAt:null,completedSteps:[],threadsIntroSeen:!1};function tn(){let e=Xr();if(!id(e))return{...Jr};try{let t=JSON.parse(kE(e,"utf8")),s=en.safeParse(t);return s.success?s.data:{...Jr}}catch(t){return console.error("[onboarding-state] failed to parse onboarding.json, using defaults:",t),{...Jr}}}function ud(e){dd();let t=tn(),s=en.parse({...t,...e,completedSteps:xE([...t.completedSteps??[],...e.completedSteps??[]]),version:1});return ad(Xr(),JSON.stringify(s,null,2)),s}function pd(){dd();let e=tn(),t={version:1,completed:!1,skipped:!1,finishedAt:null,completedSteps:e.completedSteps,threadsIntroSeen:e.threadsIntroSeen};return ad(Xr(),JSON.stringify(t,null,2)),t}function xE(e){let t=new Set,s=[];for(let n of e)t.has(n)||(t.add(n),s.push(n));return s}ge();In();Cn();import{existsSync as md,mkdirSync as NE,readFileSync as OE,writeFileSync as LE}from"node:fs";import{homedir as CE}from"node:os";import{join as gd}from"node:path";import{z as xe}from"zod";function _d(){return process.env.RECALL_HOME??gd(CE(),".recall")}function IE(){let e=_d();md(e)||NE(e,{recursive:!0})}function fd(){return gd(_d(),"config.json")}var nn=xe.object({enabled:xe.boolean().default(!1),model:xe.string().optional(),ratePerMinute:xe.number().int().min(1).max(600).default(30),lastProcessedSessionId:xe.string().nullable().default(null),backfillPaused:xe.boolean().default(!1),autoExtractEnabled:xe.boolean().default(!1),autoExtractIntervalMinutes:xe.number().int().min(5).max(720).default(60),autoExtractBatchSize:xe.number().int().min(1).max(20).default(1)}),sn={enabled:!1,ratePerMinute:30,lastProcessedSessionId:null,backfillPaused:!1,autoExtractEnabled:!1,autoExtractIntervalMinutes:60,autoExtractBatchSize:1};function hd(){let e=fd();if(!md(e))return{};try{return JSON.parse(OE(e,"utf8"))}catch(t){return console.error("[semantic-config] failed to parse config.json, using defaults:",t),{}}}function ce(){let e=hd().semantic;if(!e)return{...sn};let t=nn.safeParse({...sn,...e});return t.success?t.data:{...sn}}function rn(e){IE();let t=hd(),s=nn.parse({...sn,...t.semantic??{},...e}),n={...t,semantic:s};return LE(fd(),JSON.stringify(n,null,2)),s}H();ge();import{existsSync as vE,mkdirSync as jE,writeFileSync as ME}from"node:fs";import{homedir as DE}from"node:os";import{join as Gr}from"node:path";var FE=1,PE=12e3,Ed=3,UE=[];function $E(){return process.env.RECALL_HOME??Gr(DE(),".recall")}function bd(){return Gr($E(),"semantic")}function BE(){let e=bd();vE(e)||jE(e,{recursive:!0})}function HE(e){let t=f(),s=t.prepare(`SELECT s.id, s.message_count, s.first_user_message,
1348
1348
  p.name AS project,
1349
1349
  NULLIF(sa.alias, '') AS alias
1350
1350
  FROM sessions s
@@ -1353,10 +1353,10 @@ Return ONLY the workflow name on a single line.`;try{let o=t(r,[],e.model?{model
1353
1353
  WHERE s.id = ?`).get(e);if(!s)return null;let n=t.prepare(`SELECT role, content_text
1354
1354
  FROM messages
1355
1355
  WHERE session_id = ? AND is_sidechain = 0
1356
- ORDER BY COALESCE(timestamp, ''), rowid`).all(e),r=[],o=0;for(let a of n){if(!a.content_text)continue;let c=a.role??"system",d=a.content_text.replace(/```[\s\S]*?```/g,"[code]").replace(/<[^>]+>[\s\S]*?<\/[^>]+>/g,"").trim();if(!d)continue;let u=d.length>1500?d.slice(0,1500)+"\u2026":d,g=`${c}: ${u}`;if(o+g.length>DE)break;r.push(g),o+=g.length}return{id:s.id,alias:s.alias,project:s.project,firstUserMessage:s.first_user_message,excerpt:r.join(`
1356
+ ORDER BY COALESCE(timestamp, ''), rowid`).all(e),r=[],o=0;for(let a of n){if(!a.content_text)continue;let c=a.role??"system",d=a.content_text.replace(/```[\s\S]*?```/g,"[code]").replace(/<[^>]+>[\s\S]*?<\/[^>]+>/g,"").trim();if(!d)continue;let u=d.length>1500?d.slice(0,1500)+"\u2026":d,g=`${c}: ${u}`;if(o+g.length>PE)break;r.push(g),o+=g.length}return{id:s.id,alias:s.alias,project:s.project,firstUserMessage:s.first_user_message,excerpt:r.join(`
1357
1357
 
1358
- `),messageCount:s.message_count}}function BE(e){return["You are summarizing a Claude Code session for a local semantic-search index. The summary will be stored as plain text and matched against future natural-language queries.","",`Session: ${e.alias??e.id}`,`Project: ${e.project}`,e.firstUserMessage?`Opening prompt: ${e.firstUserMessage}`:"","","Transcript excerpt (truncated):","---",e.excerpt,"---","","Output a single JSON object on one line, with no Markdown fences and no commentary:",'{"summary": "<3 sentences describing what the user was trying to do, what was built or debugged, and the outcome>", "keywords": ["<concept>", "<technology>", "<problem>", ...]}',"","Constraints:","- summary: 3 sentences, plain prose, no bullet points",'- keywords: 10\u201315 lowercase tokens, multi-word entries hyphenated (e.g. "memory-leak"); no duplicates; no generic words like "code" or "session"',"- Output JSON only. Do not echo this prompt."].filter(Boolean).join(`
1359
- `)}function HE(e){let t=e.trim();try{let o=JSON.parse(t);typeof o.result=="string"&&(t=o.result.trim())}catch{}t=t.replace(/^```(?:json)?\s*/i,"").replace(/```\s*$/i,"").trim();let s=t.indexOf("{"),n=t.lastIndexOf("}");if(s===-1||n===-1||n<=s)return null;let r=t.slice(s,n+1);try{let o=JSON.parse(r),a=typeof o.summary=="string"?o.summary.trim():"",d=(Array.isArray(o.keywords)?o.keywords:[]).filter(u=>typeof u=="string").map(u=>u.trim().toLowerCase()).filter(u=>u.length>0&&u.length<64);return!a||d.length===0?null:{summary:a,keywords:Array.from(new Set(d)).slice(0,20)}}catch{return null}}function WE(e){let t=f(),s=e.keywords.join(",");t.prepare(`INSERT INTO session_semantic
1358
+ `),messageCount:s.message_count}}function WE(e){return["You are summarizing a Claude Code session for a local semantic-search index. The summary will be stored as plain text and matched against future natural-language queries.","",`Session: ${e.alias??e.id}`,`Project: ${e.project}`,e.firstUserMessage?`Opening prompt: ${e.firstUserMessage}`:"","","Transcript excerpt (truncated):","---",e.excerpt,"---","","Output a single JSON object on one line, with no Markdown fences and no commentary:",'{"summary": "<3 sentences describing what the user was trying to do, what was built or debugged, and the outcome>", "keywords": ["<concept>", "<technology>", "<problem>", ...]}',"","Constraints:","- summary: 3 sentences, plain prose, no bullet points",'- keywords: 10\u201315 lowercase tokens, multi-word entries hyphenated (e.g. "memory-leak"); no duplicates; no generic words like "code" or "session"',"- Output JSON only. Do not echo this prompt."].filter(Boolean).join(`
1359
+ `)}function qE(e){let t=e.trim();try{let o=JSON.parse(t);typeof o.result=="string"&&(t=o.result.trim())}catch{}t=t.replace(/^```(?:json)?\s*/i,"").replace(/```\s*$/i,"").trim();let s=t.indexOf("{"),n=t.lastIndexOf("}");if(s===-1||n===-1||n<=s)return null;let r=t.slice(s,n+1);try{let o=JSON.parse(r),a=typeof o.summary=="string"?o.summary.trim():"",d=(Array.isArray(o.keywords)?o.keywords:[]).filter(u=>typeof u=="string").map(u=>u.trim().toLowerCase()).filter(u=>u.length>0&&u.length<64);return!a||d.length===0?null:{summary:a,keywords:Array.from(new Set(d)).slice(0,20)}}catch{return null}}function JE(e){let t=f(),s=e.keywords.join(",");t.prepare(`INSERT INTO session_semantic
1360
1360
  (session_id, summary, keywords, model, source_message_count, generated_at)
1361
1361
  VALUES (@session_id, @summary, @keywords, @model, @source_message_count, @generated_at)
1362
1362
  ON CONFLICT(session_id) DO UPDATE SET
@@ -1364,7 +1364,7 @@ Return ONLY the workflow name on a single line.`;try{let o=t(r,[],e.model?{model
1364
1364
  keywords = excluded.keywords,
1365
1365
  model = excluded.model,
1366
1366
  source_message_count = excluded.source_message_count,
1367
- generated_at = excluded.generated_at`).run({session_id:e.sessionId,summary:e.summary,keywords:s,model:e.model,source_message_count:e.sourceMessageCount,generated_at:e.generatedAt}),UE();let n=Gr(bd(),`${e.sessionId}.json`);vE(n,JSON.stringify({version:ME,session_id:e.sessionId,summary:e.summary,keywords:e.keywords,model:e.model,source_message_count:e.sourceMessageCount,generated_at:e.generatedAt},null,2))}var on=null;function qE(){let t=ce().ratePerMinute,s=t/6e4;return(!on||on.capacity!==t)&&(on={tokens:t,capacity:t,refillPerMs:s,lastRefill:Date.now()}),on}function JE(e){let t=Date.now(),s=t-e.lastRefill;s>0&&(e.tokens=Math.min(e.capacity,e.tokens+s*e.refillPerMs),e.lastRefill=t)}async function XE(e){for(;;){if(e?.aborted)throw new Error("aborted");let t=qE();if(JE(t),t.tokens>=1){t.tokens-=1;return}let s=1-t.tokens,n=Math.max(50,Math.ceil(s/t.refillPerMs));await new Promise(r=>setTimeout(r,Math.min(n,5e3)))}}async function an(e,t={}){let s=ce();if(!s.enabled)return{sessionId:e,ok:!1,reason:"disabled"};if(!oe())return{sessionId:e,ok:!1,reason:"claude-cli-missing"};let n=$E(e);if(!n)return{sessionId:e,ok:!1,reason:"session-not-found"};if(n.messageCount<Ed)return{sessionId:e,ok:!1,reason:"too-short"};if(!n.excerpt.trim())return{sessionId:e,ok:!1,reason:"empty-excerpt"};await XE(t.signal);let r=BE(n),o=await Fe(r,FE,{model:s.model});if(!o.success)return{sessionId:e,ok:!1,reason:`claude-cli-exit-${o.exitCode??"null"}`,model:s.model??null};let a=HE(o.stdout);return a?(WE({sessionId:n.id,summary:a.summary,keywords:a.keywords,model:s.model??null,sourceMessageCount:n.messageCount,generatedAt:new Date().toISOString()}),{sessionId:e,ok:!0,model:s.model??null}):{sessionId:e,ok:!1,reason:"parse-failed",model:s.model??null}}async function cn(e={}){let t=ce();if(!t.enabled)return{total:0,processed:0,ok:0,failed:0,currentSessionId:null};let s=f(),r={limit:e.limit??1e3},o="s.message_count >= 3";e.force||(o+=" AND ss.session_id IS NULL"),typeof e.projectId=="number"&&(o+=" AND s.project_id = @projectId",r.projectId=e.projectId),t.lastProcessedSessionId&&e.force;let a=s.prepare(`SELECT s.id
1367
+ generated_at = excluded.generated_at`).run({session_id:e.sessionId,summary:e.summary,keywords:s,model:e.model,source_message_count:e.sourceMessageCount,generated_at:e.generatedAt}),BE();let n=Gr(bd(),`${e.sessionId}.json`);ME(n,JSON.stringify({version:FE,session_id:e.sessionId,summary:e.summary,keywords:e.keywords,model:e.model,source_message_count:e.sourceMessageCount,generated_at:e.generatedAt},null,2))}var on=null;function XE(){let t=ce().ratePerMinute,s=t/6e4;return(!on||on.capacity!==t)&&(on={tokens:t,capacity:t,refillPerMs:s,lastRefill:Date.now()}),on}function GE(e){let t=Date.now(),s=t-e.lastRefill;s>0&&(e.tokens=Math.min(e.capacity,e.tokens+s*e.refillPerMs),e.lastRefill=t)}async function YE(e){for(;;){if(e?.aborted)throw new Error("aborted");let t=XE();if(GE(t),t.tokens>=1){t.tokens-=1;return}let s=1-t.tokens,n=Math.max(50,Math.ceil(s/t.refillPerMs));await new Promise(r=>setTimeout(r,Math.min(n,5e3)))}}async function an(e,t={}){let s=ce();if(!s.enabled)return{sessionId:e,ok:!1,reason:"disabled"};if(!oe())return{sessionId:e,ok:!1,reason:"claude-cli-missing"};let n=HE(e);if(!n)return{sessionId:e,ok:!1,reason:"session-not-found"};if(n.messageCount<Ed)return{sessionId:e,ok:!1,reason:"too-short"};if(!n.excerpt.trim())return{sessionId:e,ok:!1,reason:"empty-excerpt"};await YE(t.signal);let r=WE(n),o=await Fe(r,UE,{model:s.model});if(!o.success)return{sessionId:e,ok:!1,reason:`claude-cli-exit-${o.exitCode??"null"}`,model:s.model??null};let a=qE(o.stdout);return a?(JE({sessionId:n.id,summary:a.summary,keywords:a.keywords,model:s.model??null,sourceMessageCount:n.messageCount,generatedAt:new Date().toISOString()}),{sessionId:e,ok:!0,model:s.model??null}):{sessionId:e,ok:!1,reason:"parse-failed",model:s.model??null}}async function cn(e={}){let t=ce();if(!t.enabled)return{total:0,processed:0,ok:0,failed:0,currentSessionId:null};let s=f(),r={limit:e.limit??1e3},o="s.message_count >= 3";e.force||(o+=" AND ss.session_id IS NULL"),typeof e.projectId=="number"&&(o+=" AND s.project_id = @projectId",r.projectId=e.projectId),t.lastProcessedSessionId&&e.force;let a=s.prepare(`SELECT s.id
1368
1368
  FROM sessions s
1369
1369
  LEFT JOIN session_semantic ss ON ss.session_id = s.id
1370
1370
  WHERE ${o}
@@ -1373,20 +1373,20 @@ Return ONLY the workflow name on a single line.`;try{let o=t(r,[],e.model?{model
1373
1373
  ss.generated_at, ss.source_message_count
1374
1374
  FROM sessions s
1375
1375
  LEFT JOIN session_semantic ss ON ss.session_id = s.id
1376
- WHERE s.id = ?`).get(e);if(n&&!(n.message_count<Ed)&&!(n.generated_at&&n.source_message_count!=null&&n.source_message_count>=n.message_count))try{await an(e)}catch(r){console.error("[semantic] processSession error for",e,r)}}function Yr(){let e=ce(),t=f(),s=t.prepare("SELECT COUNT(*) AS n FROM sessions WHERE message_count >= 3").get().n,n=t.prepare("SELECT COUNT(*) AS n FROM session_semantic").get().n;return{enabled:e.enabled,claudeCliAvailable:oe(),ratePerMinute:e.ratePerMinute,model:e.model??null,totalSessions:s,processedSessions:n,pendingSessions:Math.max(0,s-n),lastProcessedSessionId:e.lastProcessedSessionId,backfillPaused:e.backfillPaused}}H();H();import{createReadStream as GE}from"node:fs";import{createInterface as YE}from"node:readline";function ln(e){return typeof e=="number"&&Number.isFinite(e)?e:0}function Vr(e){let t=e?.usage;if(!t||typeof t!="object")return null;let s={inputTokens:ln(t.input_tokens),outputTokens:ln(t.output_tokens),cacheCreateTokens:ln(t.cache_creation_input_tokens),cacheReadTokens:ln(t.cache_read_input_tokens)};return s.inputTokens===0&&s.outputTokens===0&&s.cacheCreateTokens===0&&s.cacheReadTokens===0?null:s}var KE=/\x1B\[[0-9;]*[a-zA-Z]/g;function Kr(e){return e.replace(KE,"")}var zr=12e3;function Td(e,t){if(e.length<=zr)return e;let s=e.slice(0,zr),n=e.length-zr;return`${s}
1376
+ WHERE s.id = ?`).get(e);if(n&&!(n.message_count<Ed)&&!(n.generated_at&&n.source_message_count!=null&&n.source_message_count>=n.message_count))try{await an(e)}catch(r){console.error("[semantic] processSession error for",e,r)}}function Yr(){let e=ce(),t=f(),s=t.prepare("SELECT COUNT(*) AS n FROM sessions WHERE message_count >= 3").get().n,n=t.prepare("SELECT COUNT(*) AS n FROM session_semantic").get().n;return{enabled:e.enabled,claudeCliAvailable:oe(),ratePerMinute:e.ratePerMinute,model:e.model??null,totalSessions:s,processedSessions:n,pendingSessions:Math.max(0,s-n),lastProcessedSessionId:e.lastProcessedSessionId,backfillPaused:e.backfillPaused}}H();H();import{createReadStream as KE}from"node:fs";import{createInterface as zE}from"node:readline";function ln(e){return typeof e=="number"&&Number.isFinite(e)?e:0}function Vr(e){let t=e?.usage;if(!t||typeof t!="object")return null;let s={inputTokens:ln(t.input_tokens),outputTokens:ln(t.output_tokens),cacheCreateTokens:ln(t.cache_creation_input_tokens),cacheReadTokens:ln(t.cache_read_input_tokens)};return s.inputTokens===0&&s.outputTokens===0&&s.cacheCreateTokens===0&&s.cacheReadTokens===0?null:s}var VE=/\x1B\[[0-9;]*[a-zA-Z]/g;function Kr(e){return e.replace(VE,"")}var zr=12e3;function Td(e,t){if(e.length<=zr)return e;let s=e.slice(0,zr),n=e.length-zr;return`${s}
1377
1377
 
1378
- \u27E8\u2026 ${n.toLocaleString()} more chars in ${t}; see raw JSONL for full content \u27E9`}function zE(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function VE(e){if(typeof e.content=="string")return e.content;if(Array.isArray(e.content)){let t=[];for(let s of e.content)if(s&&typeof s=="object"){let n=s;n.type==="text"&&typeof n.text=="string"?t.push(n.text):n.type==="image"&&t.push("[image]")}return t.join(`
1379
- `)}return""}function ZE(e){if(!e)return{text:"",toolNames:[]};if(typeof e.content=="string")return{text:Kr(e.content),toolNames:[]};if(!Array.isArray(e.content))return{text:"",toolNames:[]};let t=[],s=[];for(let n of e.content)if(!(!n||typeof n!="object")){if(n.type==="text"&&typeof n.text=="string"){t.push(Kr(n.text));continue}if(n.type==="tool_use"&&typeof n.name=="string"){s.push(n.name);let r=n.input!=null?zE(n.input):"",o=Td(r,"tool input");t.push(`\u26A1 **Tool call \xB7 \`${n.name}\`**
1378
+ \u27E8\u2026 ${n.toLocaleString()} more chars in ${t}; see raw JSONL for full content \u27E9`}function ZE(e){try{return JSON.stringify(e,null,2)}catch{return String(e)}}function QE(e){if(typeof e.content=="string")return e.content;if(Array.isArray(e.content)){let t=[];for(let s of e.content)if(s&&typeof s=="object"){let n=s;n.type==="text"&&typeof n.text=="string"?t.push(n.text):n.type==="image"&&t.push("[image]")}return t.join(`
1379
+ `)}return""}function eb(e){if(!e)return{text:"",toolNames:[]};if(typeof e.content=="string")return{text:Kr(e.content),toolNames:[]};if(!Array.isArray(e.content))return{text:"",toolNames:[]};let t=[],s=[];for(let n of e.content)if(!(!n||typeof n!="object")){if(n.type==="text"&&typeof n.text=="string"){t.push(Kr(n.text));continue}if(n.type==="tool_use"&&typeof n.name=="string"){s.push(n.name);let r=n.input!=null?ZE(n.input):"",o=Td(r,"tool input");t.push(`\u26A1 **Tool call \xB7 \`${n.name}\`**
1380
1380
 
1381
1381
  \`\`\`json
1382
1382
  ${o}
1383
- \`\`\``);continue}if(n.type==="tool_result"){let r=Kr(VE(n));if(r){let o=Td(r,"tool result");t.push(`**Tool result**
1383
+ \`\`\``);continue}if(n.type==="tool_result"){let r=Kr(QE(n));if(r){let o=Td(r,"tool result");t.push(`**Tool result**
1384
1384
 
1385
1385
  \`\`\`
1386
1386
  ${o}
1387
1387
  \`\`\``)}else t.push("_(tool result was empty or image-only)_");continue}if(n.type==="image"){t.push("_(image)_");continue}t.push(`_(unknown block: ${n.type})_`)}return{text:t.join(`
1388
1388
 
1389
- `),toolNames:s}}async function*yd(e){let t=GE(e,{encoding:"utf8"}),s=YE({input:t,crlfDelay:1/0});for await(let n of s){if(!n.trim())continue;let r;try{r=JSON.parse(n)}catch{continue}if(!r.uuid||!r.sessionId)continue;let{text:o,toolNames:a}=ZE(r.message);yield{uuid:r.uuid,parentUuid:r.parentUuid??null,sessionId:r.sessionId,type:r.type??"unknown",role:r.message?.role??null,timestamp:r.timestamp??null,isSidechain:r.isSidechain===!0,cwd:r.cwd??null,gitBranch:r.gitBranch??null,version:r.version??null,contentText:o,toolNames:a,raw:n,usage:Vr(r.message),model:r.message?.model??null}}}function wd(e,t,s){e.prepare("DELETE FROM message_usage WHERE session_id = ?").run(t);let n=e.prepare(`
1389
+ `),toolNames:s}}async function*yd(e){let t=KE(e,{encoding:"utf8"}),s=zE({input:t,crlfDelay:1/0});for await(let n of s){if(!n.trim())continue;let r;try{r=JSON.parse(n)}catch{continue}if(!r.uuid||!r.sessionId)continue;let{text:o,toolNames:a}=eb(r.message);yield{uuid:r.uuid,parentUuid:r.parentUuid??null,sessionId:r.sessionId,type:r.type??"unknown",role:r.message?.role??null,timestamp:r.timestamp??null,isSidechain:r.isSidechain===!0,cwd:r.cwd??null,gitBranch:r.gitBranch??null,version:r.version??null,contentText:o,toolNames:a,raw:n,usage:Vr(r.message),model:r.message?.model??null}}}function wd(e,t,s){e.prepare("DELETE FROM message_usage WHERE session_id = ?").run(t);let n=e.prepare(`
1390
1390
  INSERT INTO message_usage (
1391
1391
  message_uuid, session_id, model,
1392
1392
  input_tokens, output_tokens, cache_create_tokens, cache_read_tokens,
@@ -1418,14 +1418,14 @@ ${o}
1418
1418
  total_cache_create_tokens = @cc,
1419
1419
  total_cache_read_tokens = @cr,
1420
1420
  primary_model = @model
1421
- WHERE id = @id`).run({id:t,input:s.input_tokens,output:s.output_tokens,cc:s.cache_create_tokens,cr:s.cache_read_tokens,model:n?.model??null})}var QE=500,un=new Set,Rd=null,pn=!1;function kd(){return un.size}function eb(){return`
1421
+ WHERE id = @id`).run({id:t,input:s.input_tokens,output:s.output_tokens,cc:s.cache_create_tokens,cr:s.cache_read_tokens,model:n?.model??null})}var tb=500,un=new Set,Rd=null,pn=!1;function kd(){return un.size}function sb(){return`
1422
1422
  SELECT m.uuid, m.session_id, m.timestamp, m.raw_json
1423
1423
  FROM messages m
1424
1424
  LEFT JOIN message_usage mu ON mu.message_uuid = m.uuid
1425
1425
  WHERE m.role = 'assistant' AND mu.message_uuid IS NULL
1426
1426
  AND m.uuid NOT IN (SELECT value FROM json_each(?))
1427
1427
  LIMIT ?
1428
- `}function Ad(e,t){let s=t.limit??Number.MAX_SAFE_INTEGER,n=Math.max(1,t.chunkSize??QE),r=e.prepare(eb()),o=e.prepare(`
1428
+ `}function Ad(e,t){let s=t.limit??Number.MAX_SAFE_INTEGER,n=Math.max(1,t.chunkSize??tb),r=e.prepare(sb()),o=e.prepare(`
1429
1429
  INSERT INTO message_usage (
1430
1430
  message_uuid, session_id, model,
1431
1431
  input_tokens, output_tokens, cache_create_tokens, cache_read_tokens,
@@ -1435,7 +1435,7 @@ ${o}
1435
1435
  @input, @output, @cc, @cr, @ts
1436
1436
  )
1437
1437
  ON CONFLICT(message_uuid) DO NOTHING
1438
- `),a=0,c=0,d=new Set;for(;a<s;){let u=Math.min(n,s-a),g=JSON.stringify([...un]),h=r.all(g,u);if(h.length===0)break;let b=new Set;if(e.transaction(()=>{for(let y of h){let k;try{k=JSON.parse(y.raw_json)}catch{un.add(y.uuid);continue}let w=Vr(k.message);if(!w){un.add(y.uuid);continue}o.run({uuid:y.uuid,session_id:y.session_id,model:k.message?.model??null,input:w.inputTokens,output:w.outputTokens,cc:w.cacheCreateTokens,cr:w.cacheReadTokens,ts:y.timestamp}),c+=1,b.add(y.session_id)}for(let y of b)dn(e,y),d.add(y)})(),a+=h.length,t.onProgress?.({scanned:a,inserted:c,sessionsTouched:d.size,done:h.length<u}),h.length<u)break}return{scanned:a,inserted:c,sessionsTouched:d.size,done:!0}}function xd(e={}){return Ad(f(),e)}function Nd(e={}){return pn?!1:(pn=!0,queueMicrotask(()=>{try{let t=Ad(f(),e);Rd={scanned:t.scanned,inserted:t.inserted,sessionsTouched:t.sessionsTouched,finishedAt:new Date().toISOString()}}catch(t){console.error("[stats.backfill] failed:",t)}finally{pn=!1}}),!0)}function Od(){return pn}function Zr(){return Rd}var tb=[[/opus[-_ ]?4[-_. ]?7/i,{label:"Opus 4.7",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/opus[-_ ]?4[-_. ]?6/i,{label:"Opus 4.6",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/sonnet[-_ ]?4[-_. ]?6/i,{label:"Sonnet 4.6",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/sonnet[-_ ]?4[-_. ]?5/i,{label:"Sonnet 4.5",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/haiku[-_ ]?4[-_. ]?5/i,{label:"Haiku 4.5",inputCentsPerMtok:100,outputCentsPerMtok:500,cacheCreateCentsPerMtok:125,cacheReadCentsPerMtok:10}],[/opus[-_ ]?4(?!.*[5-9])/i,{label:"Opus 4",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/sonnet[-_ ]?4(?!.*[5-9])/i,{label:"Sonnet 4",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/3[-_. ]?7[-_ ]?sonnet|sonnet[-_ ]?3[-_. ]?7/i,{label:"Sonnet 3.7",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/3[-_. ]?5[-_ ]?sonnet|sonnet[-_ ]?3[-_. ]?5/i,{label:"Sonnet 3.5",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/3[-_. ]?5[-_ ]?haiku|haiku[-_ ]?3[-_. ]?5/i,{label:"Haiku 3.5",inputCentsPerMtok:80,outputCentsPerMtok:400,cacheCreateCentsPerMtok:100,cacheReadCentsPerMtok:8}],[/3[-_ ]?opus|opus[-_ ]?3/i,{label:"Opus 3",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/3[-_ ]?haiku|haiku(?!.*3[-_. ]?5)/i,{label:"Haiku 3",inputCentsPerMtok:25,outputCentsPerMtok:125,cacheCreateCentsPerMtok:30,cacheReadCentsPerMtok:3}],[/opus/i,{label:"Opus",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/sonnet/i,{label:"Sonnet",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/haiku/i,{label:"Haiku",inputCentsPerMtok:100,outputCentsPerMtok:500,cacheCreateCentsPerMtok:125,cacheReadCentsPerMtok:10}]],Ld={label:"unknown",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30};function je(e){if(!e)return Ld;for(let[t,s]of tb)if(t.test(e))return s;return Ld}function he(e,t){if(e.byModel&&Object.keys(e.byModel).length>0){let a={input:0,output:0,cacheCreate:0,cacheRead:0},c=0;for(let[u,g]of Object.entries(e.byModel)){let h=je(u);a.input+=g.inputTokens/1e6*h.inputCentsPerMtok,a.output+=g.outputTokens/1e6*h.outputCentsPerMtok,a.cacheCreate+=g.cacheCreateTokens/1e6*h.cacheCreateCentsPerMtok,a.cacheRead+=g.cacheReadTokens/1e6*h.cacheReadCentsPerMtok,c+=g.inputTokens+g.outputTokens+g.cacheCreateTokens+g.cacheReadTokens}let d=a.input+a.output+a.cacheCreate+a.cacheRead;return{cents:d,dollars:d/100,totalTokens:c,parts:a}}let s=je(t),n={input:e.inputTokens/1e6*s.inputCentsPerMtok,output:e.outputTokens/1e6*s.outputCentsPerMtok,cacheCreate:e.cacheCreateTokens/1e6*s.cacheCreateCentsPerMtok,cacheRead:e.cacheReadTokens/1e6*s.cacheReadCentsPerMtok},r=n.input+n.output+n.cacheCreate+n.cacheRead,o=e.inputTokens+e.outputTokens+e.cacheCreateTokens+e.cacheReadTokens;return{cents:r,dollars:r/100,totalTokens:o,parts:n}}function ht(e){let t=e/100;return t===0?"$0.00":t<.01?"<$0.01":t<1?`$${t.toFixed(2)}`:t<100?`$${t.toFixed(2)}`:t<1e4?`$${t.toFixed(0)}`:`$${(t/1e3).toFixed(1)}k`}function Et(e){return!Number.isFinite(e)||e<0?"0":e<1e3?String(Math.round(e)):e<1e6?`${(e/1e3).toFixed(1)}k`:e<1e9?`${(e/1e6).toFixed(2)}M`:e<1e12?`${(e/1e9).toFixed(2)}B`:`${(e/1e12).toFixed(2)}T`}function Qr(e){let t=new Map;for(let n of e){let r=n.model??null,o=t.get(r)??{inputTokens:0,outputTokens:0,cacheCreateTokens:0,cacheReadTokens:0,messageCount:0};o.inputTokens+=n.input_tokens,o.outputTokens+=n.output_tokens,o.cacheCreateTokens+=n.cache_create_tokens,o.cacheReadTokens+=n.cache_read_tokens,o.messageCount+=n.n,t.set(r,o)}let s=[];for(let[n,r]of t.entries()){let o=he({inputTokens:r.inputTokens,outputTokens:r.outputTokens,cacheCreateTokens:r.cacheCreateTokens,cacheReadTokens:r.cacheReadTokens},n);s.push({model:n,modelLabel:je(n).label,inputTokens:r.inputTokens,outputTokens:r.outputTokens,cacheCreateTokens:r.cacheCreateTokens,cacheReadTokens:r.cacheReadTokens,messageCount:r.messageCount,cost:o})}return s.sort((n,r)=>r.cost.cents-n.cost.cents)}function eo(e){let t={};for(let s of e)t[s.model??"__unknown__"]={inputTokens:s.inputTokens,outputTokens:s.outputTokens,cacheCreateTokens:s.cacheCreateTokens,cacheReadTokens:s.cacheReadTokens};return{byModel:t}}function Cd(e){let t=f(),s=t.prepare(`SELECT s.id, p.name AS project, s.started_at, s.ended_at,
1438
+ `),a=0,c=0,d=new Set;for(;a<s;){let u=Math.min(n,s-a),g=JSON.stringify([...un]),h=r.all(g,u);if(h.length===0)break;let b=new Set;if(e.transaction(()=>{for(let y of h){let k;try{k=JSON.parse(y.raw_json)}catch{un.add(y.uuid);continue}let w=Vr(k.message);if(!w){un.add(y.uuid);continue}o.run({uuid:y.uuid,session_id:y.session_id,model:k.message?.model??null,input:w.inputTokens,output:w.outputTokens,cc:w.cacheCreateTokens,cr:w.cacheReadTokens,ts:y.timestamp}),c+=1,b.add(y.session_id)}for(let y of b)dn(e,y),d.add(y)})(),a+=h.length,t.onProgress?.({scanned:a,inserted:c,sessionsTouched:d.size,done:h.length<u}),h.length<u)break}return{scanned:a,inserted:c,sessionsTouched:d.size,done:!0}}function xd(e={}){return Ad(f(),e)}function Nd(e={}){return pn?!1:(pn=!0,queueMicrotask(()=>{try{let t=Ad(f(),e);Rd={scanned:t.scanned,inserted:t.inserted,sessionsTouched:t.sessionsTouched,finishedAt:new Date().toISOString()}}catch(t){console.error("[stats.backfill] failed:",t)}finally{pn=!1}}),!0)}function Od(){return pn}function Zr(){return Rd}var nb=[[/opus[-_ ]?4[-_. ]?7/i,{label:"Opus 4.7",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/opus[-_ ]?4[-_. ]?6/i,{label:"Opus 4.6",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/sonnet[-_ ]?4[-_. ]?6/i,{label:"Sonnet 4.6",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/sonnet[-_ ]?4[-_. ]?5/i,{label:"Sonnet 4.5",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/haiku[-_ ]?4[-_. ]?5/i,{label:"Haiku 4.5",inputCentsPerMtok:100,outputCentsPerMtok:500,cacheCreateCentsPerMtok:125,cacheReadCentsPerMtok:10}],[/opus[-_ ]?4(?!.*[5-9])/i,{label:"Opus 4",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/sonnet[-_ ]?4(?!.*[5-9])/i,{label:"Sonnet 4",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/3[-_. ]?7[-_ ]?sonnet|sonnet[-_ ]?3[-_. ]?7/i,{label:"Sonnet 3.7",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/3[-_. ]?5[-_ ]?sonnet|sonnet[-_ ]?3[-_. ]?5/i,{label:"Sonnet 3.5",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/3[-_. ]?5[-_ ]?haiku|haiku[-_ ]?3[-_. ]?5/i,{label:"Haiku 3.5",inputCentsPerMtok:80,outputCentsPerMtok:400,cacheCreateCentsPerMtok:100,cacheReadCentsPerMtok:8}],[/3[-_ ]?opus|opus[-_ ]?3/i,{label:"Opus 3",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/3[-_ ]?haiku|haiku(?!.*3[-_. ]?5)/i,{label:"Haiku 3",inputCentsPerMtok:25,outputCentsPerMtok:125,cacheCreateCentsPerMtok:30,cacheReadCentsPerMtok:3}],[/opus/i,{label:"Opus",inputCentsPerMtok:1500,outputCentsPerMtok:7500,cacheCreateCentsPerMtok:1875,cacheReadCentsPerMtok:150}],[/sonnet/i,{label:"Sonnet",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30}],[/haiku/i,{label:"Haiku",inputCentsPerMtok:100,outputCentsPerMtok:500,cacheCreateCentsPerMtok:125,cacheReadCentsPerMtok:10}]],Ld={label:"unknown",inputCentsPerMtok:300,outputCentsPerMtok:1500,cacheCreateCentsPerMtok:375,cacheReadCentsPerMtok:30};function je(e){if(!e)return Ld;for(let[t,s]of nb)if(t.test(e))return s;return Ld}function he(e,t){if(e.byModel&&Object.keys(e.byModel).length>0){let a={input:0,output:0,cacheCreate:0,cacheRead:0},c=0;for(let[u,g]of Object.entries(e.byModel)){let h=je(u);a.input+=g.inputTokens/1e6*h.inputCentsPerMtok,a.output+=g.outputTokens/1e6*h.outputCentsPerMtok,a.cacheCreate+=g.cacheCreateTokens/1e6*h.cacheCreateCentsPerMtok,a.cacheRead+=g.cacheReadTokens/1e6*h.cacheReadCentsPerMtok,c+=g.inputTokens+g.outputTokens+g.cacheCreateTokens+g.cacheReadTokens}let d=a.input+a.output+a.cacheCreate+a.cacheRead;return{cents:d,dollars:d/100,totalTokens:c,parts:a}}let s=je(t),n={input:e.inputTokens/1e6*s.inputCentsPerMtok,output:e.outputTokens/1e6*s.outputCentsPerMtok,cacheCreate:e.cacheCreateTokens/1e6*s.cacheCreateCentsPerMtok,cacheRead:e.cacheReadTokens/1e6*s.cacheReadCentsPerMtok},r=n.input+n.output+n.cacheCreate+n.cacheRead,o=e.inputTokens+e.outputTokens+e.cacheCreateTokens+e.cacheReadTokens;return{cents:r,dollars:r/100,totalTokens:o,parts:n}}function ht(e){let t=e/100;return t===0?"$0.00":t<.01?"<$0.01":t<1?`$${t.toFixed(2)}`:t<100?`$${t.toFixed(2)}`:t<1e4?`$${t.toFixed(0)}`:`$${(t/1e3).toFixed(1)}k`}function Et(e){return!Number.isFinite(e)||e<0?"0":e<1e3?String(Math.round(e)):e<1e6?`${(e/1e3).toFixed(1)}k`:e<1e9?`${(e/1e6).toFixed(2)}M`:e<1e12?`${(e/1e9).toFixed(2)}B`:`${(e/1e12).toFixed(2)}T`}function Qr(e){let t=new Map;for(let n of e){let r=n.model??null,o=t.get(r)??{inputTokens:0,outputTokens:0,cacheCreateTokens:0,cacheReadTokens:0,messageCount:0};o.inputTokens+=n.input_tokens,o.outputTokens+=n.output_tokens,o.cacheCreateTokens+=n.cache_create_tokens,o.cacheReadTokens+=n.cache_read_tokens,o.messageCount+=n.n,t.set(r,o)}let s=[];for(let[n,r]of t.entries()){let o=he({inputTokens:r.inputTokens,outputTokens:r.outputTokens,cacheCreateTokens:r.cacheCreateTokens,cacheReadTokens:r.cacheReadTokens},n);s.push({model:n,modelLabel:je(n).label,inputTokens:r.inputTokens,outputTokens:r.outputTokens,cacheCreateTokens:r.cacheCreateTokens,cacheReadTokens:r.cacheReadTokens,messageCount:r.messageCount,cost:o})}return s.sort((n,r)=>r.cost.cents-n.cost.cents)}function eo(e){let t={};for(let s of e)t[s.model??"__unknown__"]={inputTokens:s.inputTokens,outputTokens:s.outputTokens,cacheCreateTokens:s.cacheCreateTokens,cacheReadTokens:s.cacheReadTokens};return{byModel:t}}function Cd(e){let t=f(),s=t.prepare(`SELECT s.id, p.name AS project, s.started_at, s.ended_at,
1439
1439
  s.message_count,
1440
1440
  s.total_input_tokens, s.total_output_tokens,
1441
1441
  s.total_cache_create_tokens, s.total_cache_read_tokens,
@@ -1549,11 +1549,11 @@ ${o}
1549
1549
  COUNT(DISTINCT st.session_id) AS tagged
1550
1550
  FROM sessions s
1551
1551
  LEFT JOIN session_tags st ON st.session_id = s.id
1552
- WHERE s.project_id = ?`).get(e),k=y.total>0?y.tagged/y.total:0,w=Zt(k),D=Math.round((o*.2+c*.25+g*.15+S*.2+w*.2)*100);return{projectId:e,projectName:s.name,score:D,breakdown:{sessionCount:{raw:r,score:o,weight:.2},recency:{daysSinceLastSession:Math.round(a),score:c,weight:.25},fragmentation:{avgMessages:Math.round(u*10)/10,score:g,weight:.15},searchCoverage:{ratio:Math.round(b*100)/100,score:S,weight:.2},tagCoverage:{ratio:Math.round(k*100)/100,score:w,weight:.2}}}}function jd(){let t=f().prepare("SELECT id FROM projects ORDER BY name").all(),s=[];for(let n of t){let r=to(n.id);r&&s.push(r)}return s}H();import{execFile as sb}from"node:child_process";import{promisify as nb}from"node:util";import{stat as rb}from"node:fs/promises";var Md=nb(sb),Dd=1e4,ob="%H%x09%aI%x09%s";async function ib(e){try{let{stdout:t}=await Md("git",["rev-parse","--is-inside-work-tree"],{cwd:e,timeout:Dd});return t.trim()==="true"}catch{return!1}}async function ab(e,t,s){let n=["--no-pager","log","--all","--no-color","--since",t,"--until",s,`--pretty=format:${ob}`],{stdout:r}=await Md("git",n,{cwd:e,timeout:Dd,maxBuffer:8*1024*1024}),o=[],a=new Set;for(let c of r.split(`
1553
- `)){if(!c)continue;let[d,u,...g]=c.split(" ");!d||a.has(d)||(a.add(d),o.push({commit_sha:d,committed_at:u??null,subject:g.join(" ")||null}))}return o}function cb(e){return f().prepare(`SELECT id, cwd, started_at, ended_at
1554
- FROM sessions WHERE id = ?`).get(e)??null}function lb(e,t,s){if(s.length===0)return 0;let n=f(),r=new Date().toISOString(),o=n.prepare(`INSERT OR IGNORE INTO session_commits
1552
+ WHERE s.project_id = ?`).get(e),k=y.total>0?y.tagged/y.total:0,w=Zt(k),D=Math.round((o*.2+c*.25+g*.15+S*.2+w*.2)*100);return{projectId:e,projectName:s.name,score:D,breakdown:{sessionCount:{raw:r,score:o,weight:.2},recency:{daysSinceLastSession:Math.round(a),score:c,weight:.25},fragmentation:{avgMessages:Math.round(u*10)/10,score:g,weight:.15},searchCoverage:{ratio:Math.round(b*100)/100,score:S,weight:.2},tagCoverage:{ratio:Math.round(k*100)/100,score:w,weight:.2}}}}function jd(){let t=f().prepare("SELECT id FROM projects ORDER BY name").all(),s=[];for(let n of t){let r=to(n.id);r&&s.push(r)}return s}H();import{execFile as rb}from"node:child_process";import{promisify as ob}from"node:util";import{stat as ib}from"node:fs/promises";var Md=ob(rb),Dd=1e4,ab="%H%x09%aI%x09%s";async function cb(e){try{let{stdout:t}=await Md("git",["rev-parse","--is-inside-work-tree"],{cwd:e,timeout:Dd});return t.trim()==="true"}catch{return!1}}async function lb(e,t,s){let n=["--no-pager","log","--all","--no-color","--since",t,"--until",s,`--pretty=format:${ab}`],{stdout:r}=await Md("git",n,{cwd:e,timeout:Dd,maxBuffer:8*1024*1024}),o=[],a=new Set;for(let c of r.split(`
1553
+ `)){if(!c)continue;let[d,u,...g]=c.split(" ");!d||a.has(d)||(a.add(d),o.push({commit_sha:d,committed_at:u??null,subject:g.join(" ")||null}))}return o}function db(e){return f().prepare(`SELECT id, cwd, started_at, ended_at
1554
+ FROM sessions WHERE id = ?`).get(e)??null}function ub(e,t,s){if(s.length===0)return 0;let n=f(),r=new Date().toISOString(),o=n.prepare(`INSERT OR IGNORE INTO session_commits
1555
1555
  (session_id, commit_sha, committed_at, subject, cwd_snapshot, correlated_at)
1556
- VALUES (?, ?, ?, ?, ?, ?)`),a=0;return n.transaction(d=>{for(let u of d)o.run(e,u.commit_sha,u.committed_at,u.subject,t,r).changes>0&&(a+=1)})(s),a}async function so(e){let t=cb(e);if(!t)return{sessionId:e,status:"error",commitsFound:0,commitsInserted:0,error:"session not found"};if(!t.cwd)return{sessionId:e,status:"no-cwd",commitsFound:0,commitsInserted:0};if(!t.started_at||!t.ended_at)return{sessionId:e,status:"no-window",commitsFound:0,commitsInserted:0};let s=t.started_at,n=t.ended_at===t.started_at?new Date(Date.parse(t.ended_at)+1e3).toISOString():t.ended_at;try{if(!(await rb(t.cwd)).isDirectory())return{sessionId:e,status:"cwd-missing",commitsFound:0,commitsInserted:0}}catch{return{sessionId:e,status:"cwd-missing",commitsFound:0,commitsInserted:0}}if(!await ib(t.cwd))return{sessionId:e,status:"not-a-repo",commitsFound:0,commitsInserted:0};try{let o=await ab(t.cwd,s,n),a=lb(e,t.cwd,o);return{sessionId:e,status:"ok",commitsFound:o.length,commitsInserted:a}}catch(o){return{sessionId:e,status:"error",commitsFound:0,commitsInserted:0,error:o.message}}}function mn(e){let t=f(),s=e.trim();if(!/^[0-9a-fA-F]{4,40}$/.test(s))return[];let n=`${s.toLowerCase()}%`;return t.prepare(`SELECT sc.session_id AS sessionId,
1556
+ VALUES (?, ?, ?, ?, ?, ?)`),a=0;return n.transaction(d=>{for(let u of d)o.run(e,u.commit_sha,u.committed_at,u.subject,t,r).changes>0&&(a+=1)})(s),a}async function so(e){let t=db(e);if(!t)return{sessionId:e,status:"error",commitsFound:0,commitsInserted:0,error:"session not found"};if(!t.cwd)return{sessionId:e,status:"no-cwd",commitsFound:0,commitsInserted:0};if(!t.started_at||!t.ended_at)return{sessionId:e,status:"no-window",commitsFound:0,commitsInserted:0};let s=t.started_at,n=t.ended_at===t.started_at?new Date(Date.parse(t.ended_at)+1e3).toISOString():t.ended_at;try{if(!(await ib(t.cwd)).isDirectory())return{sessionId:e,status:"cwd-missing",commitsFound:0,commitsInserted:0}}catch{return{sessionId:e,status:"cwd-missing",commitsFound:0,commitsInserted:0}}if(!await cb(t.cwd))return{sessionId:e,status:"not-a-repo",commitsFound:0,commitsInserted:0};try{let o=await lb(t.cwd,s,n),a=ub(e,t.cwd,o);return{sessionId:e,status:"ok",commitsFound:o.length,commitsInserted:a}}catch(o){return{sessionId:e,status:"error",commitsFound:0,commitsInserted:0,error:o.message}}}function mn(e){let t=f(),s=e.trim();if(!/^[0-9a-fA-F]{4,40}$/.test(s))return[];let n=`${s.toLowerCase()}%`;return t.prepare(`SELECT sc.session_id AS sessionId,
1557
1557
  NULLIF(sa.alias, '') AS alias,
1558
1558
  p.name AS project,
1559
1559
  s.started_at AS startedAt,
@@ -1570,17 +1570,17 @@ ${o}
1570
1570
  ORDER BY COALESCE(sc.committed_at, s.started_at, '') DESC`).all(s,n)}function no(e){return f().prepare(`SELECT commit_sha, committed_at, subject, correlated_at
1571
1571
  FROM session_commits
1572
1572
  WHERE session_id = ?
1573
- ORDER BY COALESCE(committed_at, correlated_at) ASC`).all(e)}var db=3e4;function Fd(e){try{let s=f().prepare(`SELECT MAX(correlated_at) AS last_at
1574
- FROM session_commits WHERE session_id = ?`).get(e),n=s?.last_at?Date.parse(s.last_at):0;if(n&&Date.now()-n<db)return}catch{}so(e).catch(t=>{console.error(`[git-correlator] ${e.slice(0,8)} failed:`,t)})}H();import{execFile as ub}from"node:child_process";import{promisify as pb}from"node:util";import{stat as mb}from"node:fs/promises";var gb=pb(ub),_b=60,fb=7,hb=7,Eb=5e3;function bb(){let e=f(),t=s=>{try{return!!e.prepare(s).get()}catch{return!1}};return{semantic:t("SELECT 1 FROM session_semantic LIMIT 1"),cost:t(`SELECT 1 FROM sessions
1573
+ ORDER BY COALESCE(committed_at, correlated_at) ASC`).all(e)}var pb=3e4;function Fd(e){try{let s=f().prepare(`SELECT MAX(correlated_at) AS last_at
1574
+ FROM session_commits WHERE session_id = ?`).get(e),n=s?.last_at?Date.parse(s.last_at):0;if(n&&Date.now()-n<pb)return}catch{}so(e).catch(t=>{console.error(`[git-correlator] ${e.slice(0,8)} failed:`,t)})}H();import{execFile as mb}from"node:child_process";import{promisify as gb}from"node:util";import{stat as _b}from"node:fs/promises";var fb=gb(mb),hb=60,Eb=7,bb=7,Sb=5e3;function Tb(){let e=f(),t=s=>{try{return!!e.prepare(s).get()}catch{return!1}};return{semantic:t("SELECT 1 FROM session_semantic LIMIT 1"),cost:t(`SELECT 1 FROM sessions
1575
1575
  WHERE (COALESCE(total_input_tokens,0)
1576
1576
  + COALESCE(total_output_tokens,0)
1577
1577
  + COALESCE(total_cache_create_tokens,0)
1578
1578
  + COALESCE(total_cache_read_tokens,0)) > 0
1579
- LIMIT 1`),git:t("SELECT 1 FROM session_commits LIMIT 1")}}function ro(e){if(!e)return[];let t=new Set,s=[];for(let n of e.split(",")){let r=n.trim().toLowerCase();!r||t.has(r)||(t.add(r),s.push(r))}return s}function Pd(e){return{sessionId:e.session_id,project:e.project,alias:e.alias,startedAt:e.started_at,endedAt:e.ended_at,firstUserMessage:e.first_user_message}}function Sb(){let e=f(),t=e.prepare(`SELECT ss.keywords
1579
+ LIMIT 1`),git:t("SELECT 1 FROM session_commits LIMIT 1")}}function ro(e){if(!e)return[];let t=new Set,s=[];for(let n of e.split(",")){let r=n.trim().toLowerCase();!r||t.has(r)||(t.add(r),s.push(r))}return s}function Pd(e){return{sessionId:e.session_id,project:e.project,alias:e.alias,startedAt:e.started_at,endedAt:e.ended_at,firstUserMessage:e.first_user_message}}function yb(){let e=f(),t=e.prepare(`SELECT ss.keywords
1580
1580
  FROM session_semantic ss
1581
1581
  JOIN sessions s ON s.id = ss.session_id
1582
1582
  WHERE s.started_at IS NOT NULL
1583
- AND julianday('now') - julianday(s.started_at) <= @windowDays`).all({windowDays:fb});if(t.length===0)return null;let s=new Set;for(let o of t)for(let a of ro(o.keywords))s.add(a);if(s.size===0)return null;let n=e.prepare(`SELECT ss.session_id AS session_id,
1583
+ AND julianday('now') - julianday(s.started_at) <= @windowDays`).all({windowDays:Eb});if(t.length===0)return null;let s=new Set;for(let o of t)for(let a of ro(o.keywords))s.add(a);if(s.size===0)return null;let n=e.prepare(`SELECT ss.session_id AS session_id,
1584
1584
  ss.summary AS summary,
1585
1585
  ss.keywords AS keywords,
1586
1586
  p.name AS project,
@@ -1596,7 +1596,7 @@ ${o}
1596
1596
  WHERE s.started_at IS NOT NULL
1597
1597
  AND s.message_count > 2
1598
1598
  AND julianday('now') - julianday(s.started_at) >= @ageDays
1599
- ORDER BY s.started_at ASC`).all({ageDays:_b});if(n.length===0)return null;let r=null;for(let o of n){let c=ro(o.keywords).filter(d=>s.has(d));c.length!==0&&(!r||c.length>r.overlap.length)&&(r={row:o,overlap:c})}return r?{...Pd(r.row),summary:r.row.summary,keywords:ro(r.row.keywords),matchedKeywords:r.overlap,daysAgo:Math.max(0,Math.round(r.row.days_old))}:null}function Tb(){let t=f().prepare(`SELECT s.id AS session_id,
1599
+ ORDER BY s.started_at ASC`).all({ageDays:hb});if(n.length===0)return null;let r=null;for(let o of n){let c=ro(o.keywords).filter(d=>s.has(d));c.length!==0&&(!r||c.length>r.overlap.length)&&(r={row:o,overlap:c})}return r?{...Pd(r.row),summary:r.row.summary,keywords:ro(r.row.keywords),matchedKeywords:r.overlap,daysAgo:Math.max(0,Math.round(r.row.days_old))}:null}function wb(){let t=f().prepare(`SELECT s.id AS session_id,
1600
1600
  p.name AS project,
1601
1601
  NULLIF(sa.alias, '') AS alias,
1602
1602
  s.started_at AS started_at,
@@ -1615,27 +1615,27 @@ ${o}
1615
1615
  AND (COALESCE(s.total_input_tokens, 0)
1616
1616
  + COALESCE(s.total_output_tokens, 0)
1617
1617
  + COALESCE(s.total_cache_create_tokens, 0)
1618
- + COALESCE(s.total_cache_read_tokens, 0)) > 0`).all({windowDays:hb});if(t.length===0)return null;let s=null;for(let n of t){let r=he({inputTokens:n.input_tokens,outputTokens:n.output_tokens,cacheCreateTokens:n.cache_create_tokens,cacheReadTokens:n.cache_read_tokens},n.primary_model);r.cents<=0||(!s||r.cents>s.cents)&&(s={row:n,cents:r.cents,totalTokens:r.totalTokens})}return s?{...Pd(s.row),totalTokens:s.totalTokens,costCents:s.cents,costDisplay:ht(s.cents),tokensDisplay:Et(s.totalTokens),primaryModel:s.row.primary_model,primaryModelLabel:je(s.row.primary_model).label}:null}async function yb(e){try{if(!(await mb(e)).isDirectory())return null}catch{return null}try{let{stdout:t}=await gb("git",["rev-parse","HEAD"],{cwd:e,timeout:Eb}),s=t.trim();return/^[0-9a-f]{40}$/.test(s)?s:null}catch{return null}}async function wb(){let e=f(),t=e.prepare(`SELECT s.id AS id, s.cwd AS cwd
1618
+ + COALESCE(s.total_cache_read_tokens, 0)) > 0`).all({windowDays:bb});if(t.length===0)return null;let s=null;for(let n of t){let r=he({inputTokens:n.input_tokens,outputTokens:n.output_tokens,cacheCreateTokens:n.cache_create_tokens,cacheReadTokens:n.cache_read_tokens},n.primary_model);r.cents<=0||(!s||r.cents>s.cents)&&(s={row:n,cents:r.cents,totalTokens:r.totalTokens})}return s?{...Pd(s.row),totalTokens:s.totalTokens,costCents:s.cents,costDisplay:ht(s.cents),tokensDisplay:Et(s.totalTokens),primaryModel:s.row.primary_model,primaryModelLabel:je(s.row.primary_model).label}:null}async function Rb(e){try{if(!(await _b(e)).isDirectory())return null}catch{return null}try{let{stdout:t}=await fb("git",["rev-parse","HEAD"],{cwd:e,timeout:Sb}),s=t.trim();return/^[0-9a-f]{40}$/.test(s)?s:null}catch{return null}}async function kb(){let e=f(),t=e.prepare(`SELECT s.id AS id, s.cwd AS cwd
1619
1619
  FROM sessions s
1620
1620
  WHERE s.cwd IS NOT NULL AND s.started_at IS NOT NULL
1621
1621
  ORDER BY COALESCE(s.ended_at, s.started_at, '') DESC
1622
- LIMIT 1`).get();if(!t?.cwd)return null;let s=await yb(t.cwd);if(!s)return null;let n=mn(s);if(n.length===0)return null;let r=n[0],o=e.prepare(`SELECT s.first_user_message AS first_user_message, s.ended_at AS ended_at
1622
+ LIMIT 1`).get();if(!t?.cwd)return null;let s=await Rb(t.cwd);if(!s)return null;let n=mn(s);if(n.length===0)return null;let r=n[0],o=e.prepare(`SELECT s.first_user_message AS first_user_message, s.ended_at AS ended_at
1623
1623
  FROM sessions s
1624
- WHERE s.id = ?`).get(r.sessionId);return{sessionId:r.sessionId,project:r.project,alias:r.alias,startedAt:r.startedAt,endedAt:o?.ended_at??r.endedAt,firstUserMessage:o?.first_user_message??null,commitSha:r.commitSha,shortSha:r.commitSha.slice(0,7),subject:r.subject,committedAt:r.committedAt,cwd:t.cwd}}async function Ud(){let e=bb(),t=e.semantic?Promise.resolve().then(()=>{try{return Sb()}catch(c){return console.error("[discover.rediscovered]",c),null}}):Promise.resolve(null),s=e.cost?Promise.resolve().then(()=>{try{return Tb()}catch(c){return console.error("[discover.expensive]",c),null}}):Promise.resolve(null),n=e.git?wb().catch(c=>(console.error("[discover.authored]",c),null)):Promise.resolve(null),[r,o,a]=await Promise.all([t,s,n]);return{rediscovered:r,expensive:o,authored:a,availability:e,generatedAt:new Date().toISOString()}}ot();H();ot();async function $d(e,t=50){let s=await Tr(e),n=f(),r=Buffer.from(s.buffer,s.byteOffset,s.byteLength);return n.prepare(`SELECT v.rowid, v.distance, cm.session_id, cm.text, cm.message_uuids
1624
+ WHERE s.id = ?`).get(r.sessionId);return{sessionId:r.sessionId,project:r.project,alias:r.alias,startedAt:r.startedAt,endedAt:o?.ended_at??r.endedAt,firstUserMessage:o?.first_user_message??null,commitSha:r.commitSha,shortSha:r.commitSha.slice(0,7),subject:r.subject,committedAt:r.committedAt,cwd:t.cwd}}async function Ud(){let e=Tb(),t=e.semantic?Promise.resolve().then(()=>{try{return yb()}catch(c){return console.error("[discover.rediscovered]",c),null}}):Promise.resolve(null),s=e.cost?Promise.resolve().then(()=>{try{return wb()}catch(c){return console.error("[discover.expensive]",c),null}}):Promise.resolve(null),n=e.git?kb().catch(c=>(console.error("[discover.authored]",c),null)):Promise.resolve(null),[r,o,a]=await Promise.all([t,s,n]);return{rediscovered:r,expensive:o,authored:a,availability:e,generatedAt:new Date().toISOString()}}ot();H();ot();async function $d(e,t=50){let s=await Tr(e),n=f(),r=Buffer.from(s.buffer,s.byteOffset,s.byteLength);return n.prepare(`SELECT v.rowid, v.distance, cm.session_id, cm.text, cm.message_uuids
1625
1625
  FROM vec_chunks v JOIN chunk_meta cm ON cm.rowid = v.rowid
1626
1626
  WHERE v.embedding MATCH ? AND k = ? ORDER BY v.distance`).all(r,t).map(a=>({sessionId:a.session_id,chunkRowid:a.rowid,distance:a.distance,text:a.text,messageUuids:JSON.parse(a.message_uuids)}))}async function Bd(e,t=10,s=.65){let n=f(),r=n.prepare("SELECT rowid FROM chunk_meta WHERE session_id = ? ORDER BY rowid LIMIT 1").get(e);if(!r)return[];let o=n.prepare("SELECT embedding FROM vec_chunks WHERE rowid = ?").get(r.rowid);if(!o)return[];let a=n.prepare(`SELECT v.rowid, v.distance, cm.session_id FROM vec_chunks v JOIN chunk_meta cm ON cm.rowid = v.rowid
1627
- WHERE v.embedding MATCH ? AND k = ? ORDER BY v.distance`).all(o.embedding,t*5),c=new Map;for(let u of a){if(u.session_id===e)continue;let g=c.get(u.session_id);(g===void 0||u.distance<g)&&c.set(u.session_id,u.distance)}let d=[];for(let[u,g]of c){let h=1-g;h>=s&&d.push({sessionId:u,similarity:h})}return d.sort((u,g)=>g.similarity-u.similarity),d.slice(0,t)}function Rb(){let e=process.env.RECALL_RRF_K;if(e){let t=parseInt(e,10);if(!isNaN(t)&&t>=1&&t<=1e3)return t}return 60}function Hd(e){let t=Rb(),s=new Map;for(let r of e)for(let o=0;o<r.length;o++){let a=r[o],c=1/(t+o+1),d=s.get(a.id);d?(d.score+=c,d.lanes.push(a.lane),o+1<d.bestRank&&(d.bestRank=o+1,d.bestData=a.data)):s.set(a.id,{score:c,lanes:[a.lane],bestRank:o+1,bestData:a.data})}let n=[];for(let[r,o]of s)n.push({id:r,score:o.score,lanes:o.lanes,data:o.bestData});return n.sort((r,o)=>o.score-r.score),n}H();ot();H();function Wd(e){return e.replace(/```json[\s\S]*?```/g,"[tool-call]").replace(/\{[\s\S]{200,}?\}/g,"[json-object]")}function kb(e){let t=[],o=0;for(;o<e.length;){let a=[],c=0;for(;a.length<5&&o<e.length;){let u=e[o],g=Wd(u.content_text??"");if(c+g.length>2e3&&a.length>=3)break;a.push(u),c+=g.length,o++}if(a.length===0)break;let d=a.map(u=>{let g=u.role??"system",h=Wd(u.content_text??"");return`[${g}] ${h}`}).join(`
1627
+ WHERE v.embedding MATCH ? AND k = ? ORDER BY v.distance`).all(o.embedding,t*5),c=new Map;for(let u of a){if(u.session_id===e)continue;let g=c.get(u.session_id);(g===void 0||u.distance<g)&&c.set(u.session_id,u.distance)}let d=[];for(let[u,g]of c){let h=1-g;h>=s&&d.push({sessionId:u,similarity:h})}return d.sort((u,g)=>g.similarity-u.similarity),d.slice(0,t)}function Ab(){let e=process.env.RECALL_RRF_K;if(e){let t=parseInt(e,10);if(!isNaN(t)&&t>=1&&t<=1e3)return t}return 60}function Hd(e){let t=Ab(),s=new Map;for(let r of e)for(let o=0;o<r.length;o++){let a=r[o],c=1/(t+o+1),d=s.get(a.id);d?(d.score+=c,d.lanes.push(a.lane),o+1<d.bestRank&&(d.bestRank=o+1,d.bestData=a.data)):s.set(a.id,{score:c,lanes:[a.lane],bestRank:o+1,bestData:a.data})}let n=[];for(let[r,o]of s)n.push({id:r,score:o.score,lanes:o.lanes,data:o.bestData});return n.sort((r,o)=>o.score-r.score),n}H();ot();H();function Wd(e){return e.replace(/```json[\s\S]*?```/g,"[tool-call]").replace(/\{[\s\S]{200,}?\}/g,"[json-object]")}function xb(e){let t=[],o=0;for(;o<e.length;){let a=[],c=0;for(;a.length<5&&o<e.length;){let u=e[o],g=Wd(u.content_text??"");if(c+g.length>2e3&&a.length>=3)break;a.push(u),c+=g.length,o++}if(a.length===0)break;let d=a.map(u=>{let g=u.role??"system",h=Wd(u.content_text??"");return`[${g}] ${h}`}).join(`
1628
1628
 
1629
- `);t.push({messageUuids:a.map(u=>u.uuid),text:d}),o<e.length&&a.length>=3&&(o=Math.max(o-1,o-1))}return t}function qd(e){let s=f().prepare("SELECT uuid, role, content_text FROM messages WHERE session_id = ? AND is_sidechain = 0 AND content_text IS NOT NULL ORDER BY rowid").all(e);return kb(s)}var Jd=2e3,Ab=1e4,gn=null,oo=!1,Xd=null;function xb(){return f().prepare("SELECT COUNT(*) AS n FROM chunk_queue").get().n}async function Nb(){let e=f(),t=e.prepare("SELECT DISTINCT session_id FROM chunk_queue ORDER BY id LIMIT 1").get();if(!t)return!1;let s=t.session_id;try{e.prepare("DELETE FROM vec_chunks WHERE rowid IN (SELECT rowid FROM chunk_meta WHERE session_id = ?)").run(s),e.prepare("DELETE FROM chunk_meta WHERE session_id = ?").run(s);let n=qd(s);if(n.length===0)return e.prepare("DELETE FROM chunk_queue WHERE session_id = ?").run(s),!0;let r=n.map(u=>u.text),o=await $t(r),a=e.prepare("INSERT INTO chunk_meta(session_id, message_uuids, text, embedding_model_id, embedding_dim, stale, generated_at) VALUES (?, ?, ?, 'bge-base-en-v1.5', 768, 0, datetime('now'))"),c=e.prepare("INSERT INTO vec_chunks(rowid, embedding) VALUES (?, ?)");e.transaction(()=>{for(let u=0;u<n.length;u++){let g=a.run(s,JSON.stringify(n[u].messageUuids),n[u].text),h=Buffer.from(o[u].buffer,o[u].byteOffset,o[u].byteLength);c.run(g.lastInsertRowid,h)}e.prepare("DELETE FROM chunk_queue WHERE session_id = ?").run(s)})(),Xd=new Date().toISOString()}catch(n){console.error("[vector-worker] failed for session",s,n),e.prepare("DELETE FROM chunk_queue WHERE session_id = ?").run(s)}return!0}async function Gd(){if(!ke().loaded)return;let e=await Nb();gn!==null&&clearTimeout(gn),gn=setTimeout(()=>{Gd()},e?Jd:Ab)}function Yd(){if(!oo){if(!ke().loaded){console.error("[vector-worker] cannot start: embedder not loaded");return}oo=!0,gn=setTimeout(()=>{Gd()},Jd)}}function Kd(){return{running:oo,queueDepth:xb(),lastProcessedAt:Xd}}Z();import{existsSync as Zd,mkdirSync as zd,rmSync as Vd,createWriteStream as Ob,statSync as Lb}from"node:fs";import{join as _n}from"node:path";import{createHash as Cb}from"node:crypto";import{readFile as Ib}from"node:fs/promises";var vb="https://huggingface.co/BAAI/bge-base-en-v1.5/resolve/main/",Qd=[{path:"config.json",sha256:"bc00af31a4a31b74040d73370aa83b62da34c90b75eb77bfa7db039d90abd591"},{path:"tokenizer.json",sha256:"d241a60d5e8f04cc1b2b3e9ef7a4921b27bf526d9f6050ab90f9267a1f9e5c66"},{path:"tokenizer_config.json",sha256:"9261e7d79b44c8195c1cada2b453e55b00aeb81e907a6664974b4d7776172ab3"},{path:"onnx/model.onnx",sha256:"9bc579acdba21c253c62a9bf866891355a63ffa3442b52c8a37d75b2ccb91848"}];function eu(){return _n($,"models","BAAI","bge-base-en-v1.5")}function io(){let e=eu();return Qd.every(t=>Zd(_n(e,t.path)))}async function tu(e){let t=eu();zd(t,{recursive:!0}),zd(_n(t,"onnx"),{recursive:!0});for(let s of Qd){let n=_n(t,s.path),r=vb+s.path,o=0;Zd(n)&&(o=Lb(n).size);let a={};o>0&&(a.Range=`bytes=${o}-`);let c=await fetch(r,{headers:a});if(!c.ok&&c.status!==206)throw new Error(`Failed to download ${s.path}: HTTP ${c.status}`);let d=c.headers.get("content-length"),u=d?o+Number(d):0,g=c.body;if(!g)throw new Error(`No response body for ${s.path}`);let h=Ob(n,{flags:o>0?"a":"w"}),b=g.getReader(),S=o;for(;;){let{done:w,value:D}=await b.read();if(w)break;h.write(Buffer.from(D)),S+=D.byteLength,e?.(s.path,S,u)}if(h.end(),await new Promise((w,D)=>{h.on("finish",w),h.on("error",D)}),s.sha256==="TODO_PLACEHOLDER")throw Vd(n),new Error(`Refusing to install: SHA-256 not pinned for ${s.path}. Update model-download.ts.`);let y=await Ib(n);if(Cb("sha256").update(y).digest("hex")!==s.sha256)throw Vd(n),new Error(`SHA-256 mismatch for ${s.path}`)}}H();var jb=[/\btask\s+complete/i,/\bdone\b/i,/\bfinished\b/i,/\bimplemented\b/i,/\bcompleted\b/i,/\bshipped\b/i,/\ball\s+(?:tests?\s+)?pass/i,/\bsuccessfully\b/i],Mb=1440*60*1e3;function Db(e){let t=f(),s=t.prepare(`SELECT content_text, tool_names FROM messages
1629
+ `);t.push({messageUuids:a.map(u=>u.uuid),text:d}),o<e.length&&a.length>=3&&(o=Math.max(o-1,o-1))}return t}function qd(e){let s=f().prepare("SELECT uuid, role, content_text FROM messages WHERE session_id = ? AND is_sidechain = 0 AND content_text IS NOT NULL ORDER BY rowid").all(e);return xb(s)}var Jd=2e3,Nb=1e4,gn=null,oo=!1,Xd=null;function Ob(){return f().prepare("SELECT COUNT(*) AS n FROM chunk_queue").get().n}async function Lb(){let e=f(),t=e.prepare("SELECT DISTINCT session_id FROM chunk_queue ORDER BY id LIMIT 1").get();if(!t)return!1;let s=t.session_id;try{e.prepare("DELETE FROM vec_chunks WHERE rowid IN (SELECT rowid FROM chunk_meta WHERE session_id = ?)").run(s),e.prepare("DELETE FROM chunk_meta WHERE session_id = ?").run(s);let n=qd(s);if(n.length===0)return e.prepare("DELETE FROM chunk_queue WHERE session_id = ?").run(s),!0;let r=n.map(u=>u.text),o=await $t(r),a=e.prepare("INSERT INTO chunk_meta(session_id, message_uuids, text, embedding_model_id, embedding_dim, stale, generated_at) VALUES (?, ?, ?, 'bge-base-en-v1.5', 768, 0, datetime('now'))"),c=e.prepare("INSERT INTO vec_chunks(rowid, embedding) VALUES (?, ?)");e.transaction(()=>{for(let u=0;u<n.length;u++){let g=a.run(s,JSON.stringify(n[u].messageUuids),n[u].text),h=Buffer.from(o[u].buffer,o[u].byteOffset,o[u].byteLength);c.run(g.lastInsertRowid,h)}e.prepare("DELETE FROM chunk_queue WHERE session_id = ?").run(s)})(),Xd=new Date().toISOString()}catch(n){console.error("[vector-worker] failed for session",s,n),e.prepare("DELETE FROM chunk_queue WHERE session_id = ?").run(s)}return!0}async function Gd(){if(!ke().loaded)return;let e=await Lb();gn!==null&&clearTimeout(gn),gn=setTimeout(()=>{Gd()},e?Jd:Nb)}function Yd(){if(!oo){if(!ke().loaded){console.error("[vector-worker] cannot start: embedder not loaded");return}oo=!0,gn=setTimeout(()=>{Gd()},Jd)}}function Kd(){return{running:oo,queueDepth:Ob(),lastProcessedAt:Xd}}Z();import{existsSync as Zd,mkdirSync as zd,rmSync as Vd,createWriteStream as Cb,statSync as Ib}from"node:fs";import{join as _n}from"node:path";import{createHash as vb}from"node:crypto";import{readFile as jb}from"node:fs/promises";var Mb="https://huggingface.co/BAAI/bge-base-en-v1.5/resolve/main/",Qd=[{path:"config.json",sha256:"bc00af31a4a31b74040d73370aa83b62da34c90b75eb77bfa7db039d90abd591"},{path:"tokenizer.json",sha256:"d241a60d5e8f04cc1b2b3e9ef7a4921b27bf526d9f6050ab90f9267a1f9e5c66"},{path:"tokenizer_config.json",sha256:"9261e7d79b44c8195c1cada2b453e55b00aeb81e907a6664974b4d7776172ab3"},{path:"onnx/model.onnx",sha256:"9bc579acdba21c253c62a9bf866891355a63ffa3442b52c8a37d75b2ccb91848"}];function eu(){return _n($,"models","BAAI","bge-base-en-v1.5")}function io(){let e=eu();return Qd.every(t=>Zd(_n(e,t.path)))}async function tu(e){let t=eu();zd(t,{recursive:!0}),zd(_n(t,"onnx"),{recursive:!0});for(let s of Qd){let n=_n(t,s.path),r=Mb+s.path,o=0;Zd(n)&&(o=Ib(n).size);let a={};o>0&&(a.Range=`bytes=${o}-`);let c=await fetch(r,{headers:a});if(!c.ok&&c.status!==206)throw new Error(`Failed to download ${s.path}: HTTP ${c.status}`);let d=c.headers.get("content-length"),u=d?o+Number(d):0,g=c.body;if(!g)throw new Error(`No response body for ${s.path}`);let h=Cb(n,{flags:o>0?"a":"w"}),b=g.getReader(),S=o;for(;;){let{done:w,value:D}=await b.read();if(w)break;h.write(Buffer.from(D)),S+=D.byteLength,e?.(s.path,S,u)}if(h.end(),await new Promise((w,D)=>{h.on("finish",w),h.on("error",D)}),s.sha256==="TODO_PLACEHOLDER")throw Vd(n),new Error(`Refusing to install: SHA-256 not pinned for ${s.path}. Update model-download.ts.`);let y=await jb(n);if(vb("sha256").update(y).digest("hex")!==s.sha256)throw Vd(n),new Error(`SHA-256 mismatch for ${s.path}`)}}H();var Db=[/\btask\s+complete/i,/\bdone\b/i,/\bfinished\b/i,/\bimplemented\b/i,/\bcompleted\b/i,/\bshipped\b/i,/\ball\s+(?:tests?\s+)?pass/i,/\bsuccessfully\b/i],Fb=1440*60*1e3;function Pb(e){let t=f(),s=t.prepare(`SELECT content_text, tool_names FROM messages
1630
1630
  WHERE session_id = ? AND role = 'assistant'
1631
- ORDER BY timestamp DESC LIMIT 5`).all(e),n=!1;for(let d of s)if(d.content_text&&jb.some(u=>u.test(d.content_text))){n=!0;break}let r=t.prepare(`SELECT content_text, tool_names FROM messages
1632
- WHERE session_id = ?`).all(e),o={fileWrites:!1,testRuns:!1,commits:!1,buildSuccess:!1};for(let d of r){let u=d.tool_names??"",g=d.content_text??"";/\bWrite\b|\bEdit\b/.test(u)&&(o.fileWrites=!0),/\b(?:jest|pytest|vitest|mocha|test|spec)\b/i.test(g)&&/pass|ok|✓/i.test(g)&&(o.testRuns=!0),/\bgit\s+commit\b/i.test(g)&&(o.commits=!0),(/\bbuild\s+(?:succeeded|success|passed)\b/i.test(g)||/tsc.*(?:0 errors|no errors)/i.test(g))&&(o.buildSuccess=!0)}return n?{status:[o.fileWrites,o.testRuns,o.commits,o.buildSuccess].filter(Boolean).length>=2?"verified":"unverified",evidence:o,claimFound:n}:{status:"neutral",evidence:o,claimFound:n}}function Fb(e){let t=Db(e);return f().prepare("UPDATE sessions SET verification_status = ?, verification_computed_at = ? WHERE id = ?").run(t.status,Date.now(),e),t}function su(e){let s=f().prepare("SELECT verification_status, verification_computed_at FROM sessions WHERE id = ?").get(e);if(s?.verification_status&&s.verification_computed_at&&Date.now()-s.verification_computed_at<Mb){let n={fileWrites:!1,testRuns:!1,commits:!1,buildSuccess:!1};return{status:s.verification_status,evidence:n,claimFound:s.verification_status!=="neutral"}}return Fb(e)}import{readFileSync as Pb,writeFileSync as Ub,mkdirSync as $b,chmodSync as Bb}from"node:fs";import{join as nu}from"node:path";import{homedir as ru}from"node:os";function ou(){return nu(ru(),".recall","config.json")}function iu(){try{return JSON.parse(Pb(ou(),"utf-8"))}catch{return{}}}function Hb(e){let t=ou();$b(nu(ru(),".recall"),{recursive:!0}),Ub(t,JSON.stringify(e,null,2)+`
1633
- `,"utf-8"),Bb(t,384)}function ao(){let t=iu().verification;return typeof t=="object"&&t!==null&&"enabled"in t?!!t.enabled:!1}function au(e){let t=iu();t.verification={...typeof t.verification=="object"&&t.verification!==null?t.verification:{},enabled:e},Hb(t)}var Wb=[{name:"Anthropic API key",regex:/sk-ant-[a-zA-Z0-9_\-]{40,}/g,severity:"high"},{name:"OpenAI API key",regex:/sk-(?:proj-)?[a-zA-Z0-9]{32,}/g,severity:"high"},{name:"AWS access key ID",regex:/AKIA[0-9A-Z]{16}/g,severity:"high"},{name:"GitHub PAT",regex:/gh[pousr]_[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Stripe live/test key",regex:/(?:sk|rk|pk)_(?:live|test)_[a-zA-Z0-9]{24,}/g,severity:"high"},{name:"Slack token",regex:/xox[abprs]-[A-Za-z0-9\-]{10,}/g,severity:"high"},{name:"Google API key",regex:/AIza[0-9A-Za-z_\-]{35}/g,severity:"high"},{name:"Private key block",regex:/-----BEGIN (?:RSA |DSA |EC |OPENSSH |ENCRYPTED )?PRIVATE KEY-----/g,severity:"high"},{name:"Apify token",regex:/apify_api_[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Notion integration",regex:/(?:secret_|ntn_)[A-Za-z0-9]{40,}/g,severity:"high"},{name:"Vercel token",regex:/vercel_[A-Za-z0-9]{24,}/g,severity:"high"},{name:"Supabase service key",regex:/sbp_[A-Za-z0-9]{40,}/g,severity:"high"},{name:"SendGrid key",regex:/SG\.[A-Za-z0-9_\-]{20,}\.[A-Za-z0-9_\-]{20,}/g,severity:"high"},{name:"Mailgun key",regex:/key-[a-f0-9]{32}/g,severity:"high"},{name:"Twilio SID",regex:/AC[a-f0-9]{32}/g,severity:"high"},{name:"Discord bot token",regex:/[MN][A-Za-z\d]{23}\.[\w-]{6}\.[\w-]{27,38}/g,severity:"high"},{name:"npm token",regex:/npm_[A-Za-z0-9]{36}/g,severity:"high"},{name:"HuggingFace token",regex:/hf_[A-Za-z0-9]{30,}/g,severity:"high"},{name:"Replicate token",regex:/r8_[A-Za-z0-9]{32,}/g,severity:"high"},{name:"Figma token",regex:/figd_[A-Za-z0-9_\-]{30,}/g,severity:"high"},{name:"Linear key",regex:/lin_api_[A-Za-z0-9]{30,}/g,severity:"high"},{name:"DigitalOcean token",regex:/dop_v1_[a-f0-9]{64}/g,severity:"high"},{name:"Generic provider token",regex:/\b[a-z][a-z0-9]{2,20}_(?:api|pat|token|sk|pk|key|auth)_(?=[A-Za-z0-9_\-]*\d)[A-Za-z0-9_\-]{20,}\b/g,severity:"high"},{name:"Bearer token",regex:/\b[Bb]earer\s+[A-Za-z0-9_\-\.=]{24,}\b/g,severity:"medium"},{name:"Slack webhook URL",regex:/https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Discord webhook URL",regex:/https:\/\/(?:ptb\.|canary\.)?discord(?:app)?\.com\/api\/webhooks\/\d+\/[A-Za-z0-9_\-]{40,}/g,severity:"high"},{name:"Teams webhook URL",regex:/https:\/\/[a-zA-Z0-9.\-]+\.webhook\.office\.com\/webhookb2\/[A-Za-z0-9@_\-\/]{30,}/g,severity:"high"},{name:"Secret near keyword",regex:/\b(?:webhook[_\s\-]?secret|signing[_\s\-]?secret|webhook[_\s\-]?signing[_\s\-]?secret|api[_\s\-]?secret|client[_\s\-]?secret|private[_\s\-]?key|access[_\s\-]?token|auth[_\s\-]?token|api[_\s\-]?key)\b[\s\S]{0,200}?\b(?:[a-fA-F0-9]{32,}|[A-Za-z0-9+/_\-]{20,}(?:\.[A-Za-z0-9+/_\-]{10,}){1,2}|[A-Za-z0-9+/_\-]{40,}={0,2})\b/gi,severity:"high"},{name:"JWT",regex:/eyJ[a-zA-Z0-9_\-]{10,}\.[a-zA-Z0-9_\-]{10,}\.[a-zA-Z0-9_\-]{10,}/g,severity:"medium"},{name:"URL with password",regex:/https?:\/\/[^:\s/@]+:[^@\s]{6,}@[^\s/]+/g,severity:"high"},{name:"Password assignment",regex:/(?<![A-Za-z])(?:password|passwd|pwd|secret|token|api[_\-]?key|access[_\-]?key|auth[_\-]?token|webhook[_\-]?secret|client[_\-]?secret|private[_\-]?key)\b\s*[:=]\s*["']?[A-Za-z0-9_\-+/=]{16,}/gi,severity:"high"}];function qb(e){if(e.length<=8)return e.slice(0,2)+"\u2022".repeat(Math.max(0,e.length-4))+e.slice(-2);let t=e.slice(0,Math.min(6,Math.floor(e.length/3))),s=e.slice(-Math.min(4,Math.floor(e.length/4)));return`${t}${"\u2022".repeat(Math.max(3,e.length-t.length-s.length))}${s}`}function Jb(e){let t=5381;for(let s=0;s<e.length;s++)t=(t<<5)+t+e.charCodeAt(s)|0;return(t>>>0).toString(36)}function qe(e){if(!e)return{redacted:e,count:0};let t=e,s=0,n=new Set;for(let r of Wb)r.regex.lastIndex=0,t=t.replace(r.regex,o=>{let a=`${r.name}::${Jb(o)}`;return n.has(a)||(n.add(a),s+=1),`[REDACTED ${r.name}: ${qb(o)}]`});return{redacted:t,count:s}}var eS=5e3,_o={scanned:0,linked:0,renamed:0,skipped_manual:0,ambiguous_cwd:0},co=0,lo=_o,uo=null;async function tS(){return Date.now()-co>=eS&&!uo&&(uo=Ds().then(s=>(lo=s,co=Date.now(),s)).catch(()=>(co=Date.now(),lo=_o,_o)).finally(()=>{uo=null})),lo}var sS=2e3,nS=6,En=new Map;function Qt(e){return e.replace(/[\\%_]/g,t=>"\\"+t)}function rS(e,t){let s=Date.now(),n=(En.get(e)??[]).filter(a=>s-a.ts<sS);return En.set(e,n),n.length<2||n[n.length-1].name===t?!1:n.slice(0,-1).some(a=>a.name===t)}function oS(e,t){let s=En.get(e)??[];for(s.push({name:t,ts:Date.now()});s.length>nS;)s.shift();En.set(e,s)}function lu(e,t){let s=t.trim();if(!s)return 0;if(ne(s)){let o=tt(s);if(!o)return 0;s=o}if(re(s))return 0;if(rS(e,s))return console.log(`[terminal] dropping rename of pid ${e} \u2192 "${s}", flap signature (competing editor sync sources)`),0;oS(e,s);let n=I.sessionsFor(e),r=0;for(let o of n)try{if(Te(o)===s)continue;me(o,s),r++}catch{}return r>0&&console.log(`[terminal] rename of pid ${e} \u2192 "${s}" propagated to ${r} session(s)`),r}var du=(()=>{try{let e=bn(Eo(bo(import.meta.url)),"..","..","package.json");return JSON.parse(hn(e,"utf8")).version??"0.0.0"}catch{return"0.0.0"}})(),po=!1,mo=!1,go=!1,aS=Eo(bo(import.meta.url)),fo=bn(aS,"..","web"),ho=bn(fo,"index.html"),cS=Yb(ho);function uu(){return f().prepare(`SELECT
1631
+ ORDER BY timestamp DESC LIMIT 5`).all(e),n=!1;for(let d of s)if(d.content_text&&Db.some(u=>u.test(d.content_text))){n=!0;break}let r=t.prepare(`SELECT content_text, tool_names FROM messages
1632
+ WHERE session_id = ?`).all(e),o={fileWrites:!1,testRuns:!1,commits:!1,buildSuccess:!1};for(let d of r){let u=d.tool_names??"",g=d.content_text??"";/\bWrite\b|\bEdit\b/.test(u)&&(o.fileWrites=!0),/\b(?:jest|pytest|vitest|mocha|test|spec)\b/i.test(g)&&/pass|ok|✓/i.test(g)&&(o.testRuns=!0),/\bgit\s+commit\b/i.test(g)&&(o.commits=!0),(/\bbuild\s+(?:succeeded|success|passed)\b/i.test(g)||/tsc.*(?:0 errors|no errors)/i.test(g))&&(o.buildSuccess=!0)}return n?{status:[o.fileWrites,o.testRuns,o.commits,o.buildSuccess].filter(Boolean).length>=2?"verified":"unverified",evidence:o,claimFound:n}:{status:"neutral",evidence:o,claimFound:n}}function Ub(e){let t=Pb(e);return f().prepare("UPDATE sessions SET verification_status = ?, verification_computed_at = ? WHERE id = ?").run(t.status,Date.now(),e),t}function su(e){let s=f().prepare("SELECT verification_status, verification_computed_at FROM sessions WHERE id = ?").get(e);if(s?.verification_status&&s.verification_computed_at&&Date.now()-s.verification_computed_at<Fb){let n={fileWrites:!1,testRuns:!1,commits:!1,buildSuccess:!1};return{status:s.verification_status,evidence:n,claimFound:s.verification_status!=="neutral"}}return Ub(e)}import{readFileSync as $b,writeFileSync as Bb,mkdirSync as Hb,chmodSync as Wb}from"node:fs";import{join as nu}from"node:path";import{homedir as ru}from"node:os";function ou(){return nu(ru(),".recall","config.json")}function iu(){try{return JSON.parse($b(ou(),"utf-8"))}catch{return{}}}function qb(e){let t=ou();Hb(nu(ru(),".recall"),{recursive:!0}),Bb(t,JSON.stringify(e,null,2)+`
1633
+ `,"utf-8"),Wb(t,384)}function ao(){let t=iu().verification;return typeof t=="object"&&t!==null&&"enabled"in t?!!t.enabled:!1}function au(e){let t=iu();t.verification={...typeof t.verification=="object"&&t.verification!==null?t.verification:{},enabled:e},qb(t)}var Jb=[{name:"Anthropic API key",regex:/sk-ant-[a-zA-Z0-9_\-]{40,}/g,severity:"high"},{name:"OpenAI API key",regex:/sk-(?:proj-)?[a-zA-Z0-9]{32,}/g,severity:"high"},{name:"AWS access key ID",regex:/AKIA[0-9A-Z]{16}/g,severity:"high"},{name:"GitHub PAT",regex:/gh[pousr]_[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Stripe live/test key",regex:/(?:sk|rk|pk)_(?:live|test)_[a-zA-Z0-9]{24,}/g,severity:"high"},{name:"Slack token",regex:/xox[abprs]-[A-Za-z0-9\-]{10,}/g,severity:"high"},{name:"Google API key",regex:/AIza[0-9A-Za-z_\-]{35}/g,severity:"high"},{name:"Private key block",regex:/-----BEGIN (?:RSA |DSA |EC |OPENSSH |ENCRYPTED )?PRIVATE KEY-----/g,severity:"high"},{name:"Apify token",regex:/apify_api_[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Notion integration",regex:/(?:secret_|ntn_)[A-Za-z0-9]{40,}/g,severity:"high"},{name:"Vercel token",regex:/vercel_[A-Za-z0-9]{24,}/g,severity:"high"},{name:"Supabase service key",regex:/sbp_[A-Za-z0-9]{40,}/g,severity:"high"},{name:"SendGrid key",regex:/SG\.[A-Za-z0-9_\-]{20,}\.[A-Za-z0-9_\-]{20,}/g,severity:"high"},{name:"Mailgun key",regex:/key-[a-f0-9]{32}/g,severity:"high"},{name:"Twilio SID",regex:/AC[a-f0-9]{32}/g,severity:"high"},{name:"Discord bot token",regex:/[MN][A-Za-z\d]{23}\.[\w-]{6}\.[\w-]{27,38}/g,severity:"high"},{name:"npm token",regex:/npm_[A-Za-z0-9]{36}/g,severity:"high"},{name:"HuggingFace token",regex:/hf_[A-Za-z0-9]{30,}/g,severity:"high"},{name:"Replicate token",regex:/r8_[A-Za-z0-9]{32,}/g,severity:"high"},{name:"Figma token",regex:/figd_[A-Za-z0-9_\-]{30,}/g,severity:"high"},{name:"Linear key",regex:/lin_api_[A-Za-z0-9]{30,}/g,severity:"high"},{name:"DigitalOcean token",regex:/dop_v1_[a-f0-9]{64}/g,severity:"high"},{name:"Generic provider token",regex:/\b[a-z][a-z0-9]{2,20}_(?:api|pat|token|sk|pk|key|auth)_(?=[A-Za-z0-9_\-]*\d)[A-Za-z0-9_\-]{20,}\b/g,severity:"high"},{name:"Bearer token",regex:/\b[Bb]earer\s+[A-Za-z0-9_\-\.=]{24,}\b/g,severity:"medium"},{name:"Slack webhook URL",regex:/https:\/\/hooks\.slack\.com\/services\/T[A-Z0-9]+\/B[A-Z0-9]+\/[A-Za-z0-9]{20,}/g,severity:"high"},{name:"Discord webhook URL",regex:/https:\/\/(?:ptb\.|canary\.)?discord(?:app)?\.com\/api\/webhooks\/\d+\/[A-Za-z0-9_\-]{40,}/g,severity:"high"},{name:"Teams webhook URL",regex:/https:\/\/[a-zA-Z0-9.\-]+\.webhook\.office\.com\/webhookb2\/[A-Za-z0-9@_\-\/]{30,}/g,severity:"high"},{name:"Secret near keyword",regex:/\b(?:webhook[_\s\-]?secret|signing[_\s\-]?secret|webhook[_\s\-]?signing[_\s\-]?secret|api[_\s\-]?secret|client[_\s\-]?secret|private[_\s\-]?key|access[_\s\-]?token|auth[_\s\-]?token|api[_\s\-]?key)\b[\s\S]{0,200}?\b(?:[a-fA-F0-9]{32,}|[A-Za-z0-9+/_\-]{20,}(?:\.[A-Za-z0-9+/_\-]{10,}){1,2}|[A-Za-z0-9+/_\-]{40,}={0,2})\b/gi,severity:"high"},{name:"JWT",regex:/eyJ[a-zA-Z0-9_\-]{10,}\.[a-zA-Z0-9_\-]{10,}\.[a-zA-Z0-9_\-]{10,}/g,severity:"medium"},{name:"URL with password",regex:/https?:\/\/[^:\s/@]+:[^@\s]{6,}@[^\s/]+/g,severity:"high"},{name:"Password assignment",regex:/(?<![A-Za-z])(?:password|passwd|pwd|secret|token|api[_\-]?key|access[_\-]?key|auth[_\-]?token|webhook[_\-]?secret|client[_\-]?secret|private[_\-]?key)\b\s*[:=]\s*["']?[A-Za-z0-9_\-+/=]{16,}/gi,severity:"high"}];function Xb(e){if(e.length<=8)return e.slice(0,2)+"\u2022".repeat(Math.max(0,e.length-4))+e.slice(-2);let t=e.slice(0,Math.min(6,Math.floor(e.length/3))),s=e.slice(-Math.min(4,Math.floor(e.length/4)));return`${t}${"\u2022".repeat(Math.max(3,e.length-t.length-s.length))}${s}`}function Gb(e){let t=5381;for(let s=0;s<e.length;s++)t=(t<<5)+t+e.charCodeAt(s)|0;return(t>>>0).toString(36)}function qe(e){if(!e)return{redacted:e,count:0};let t=e,s=0,n=new Set;for(let r of Jb)r.regex.lastIndex=0,t=t.replace(r.regex,o=>{let a=`${r.name}::${Gb(o)}`;return n.has(a)||(n.add(a),s+=1),`[REDACTED ${r.name}: ${Xb(o)}]`});return{redacted:t,count:s}}var sS=5e3,_o={scanned:0,linked:0,renamed:0,skipped_manual:0,ambiguous_cwd:0},co=0,lo=_o,uo=null;async function nS(){return Date.now()-co>=sS&&!uo&&(uo=Ds().then(s=>(lo=s,co=Date.now(),s)).catch(()=>(co=Date.now(),lo=_o,_o)).finally(()=>{uo=null})),lo}var rS=2e3,oS=6,En=new Map;function Qt(e){return e.replace(/[\\%_]/g,t=>"\\"+t)}function iS(e,t){let s=Date.now(),n=(En.get(e)??[]).filter(a=>s-a.ts<rS);return En.set(e,n),n.length<2||n[n.length-1].name===t?!1:n.slice(0,-1).some(a=>a.name===t)}function aS(e,t){let s=En.get(e)??[];for(s.push({name:t,ts:Date.now()});s.length>oS;)s.shift();En.set(e,s)}function lu(e,t){let s=t.trim();if(!s)return 0;if(ne(s)){let o=tt(s);if(!o)return 0;s=o}if(re(s))return 0;if(iS(e,s))return console.log(`[terminal] dropping rename of pid ${e} \u2192 "${s}", flap signature (competing editor sync sources)`),0;aS(e,s);let n=I.sessionsFor(e),r=0;for(let o of n)try{if(Te(o)===s)continue;me(o,s),r++}catch{}return r>0&&console.log(`[terminal] rename of pid ${e} \u2192 "${s}" propagated to ${r} session(s)`),r}var du=(()=>{try{let e=bn(Eo(bo(import.meta.url)),"..","..","package.json");return JSON.parse(hn(e,"utf8")).version??"0.0.0"}catch{return"0.0.0"}})(),po=!1,mo=!1,go=!1,lS=Eo(bo(import.meta.url)),fo=bn(lS,"..","web"),ho=bn(fo,"index.html"),dS=zb(ho);function uu(){return f().prepare(`SELECT
1634
1634
  (SELECT COUNT(*) FROM projects) AS projects,
1635
1635
  (SELECT COUNT(*) FROM sessions) AS sessions,
1636
1636
  (SELECT COUNT(*) FROM messages) AS messages,
1637
1637
  (SELECT MIN(started_at) FROM sessions WHERE started_at IS NOT NULL) AS earliest,
1638
- (SELECT MAX(started_at) FROM sessions WHERE started_at IS NOT NULL) AS latest`).get()}var lS=/^(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i,dS=/^https?:\/\/(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i;async function es(e,t){if((await Tt()).tier!=="pro")return e.json({error:"pro_required",message:"This feature requires a Claude Recall Pro license.",upgrade_url:"https://clauderecall.com/pricing",activate_command:"recall activate <license-key>"},402);await t()}var fn=new Map,mu=0,pu=0,gu=null,uS=6e4;function pS(){mu+=1;let e=Date.now();e-pu<uS||(pu=e,console.warn("[auth] /api/terminal/* request rejected without a valid X-Recall-Token. The VS Code / Cursor extension is likely outdated relative to the daemon \u2014 tab names will not flow through, and session titles will fall back to the heuristic first-message snippet. Reinstall: `code --install-extension extensions/vscode/clauderecall-vscode-*.vsix` and restart the extension host. Run `recall doctor` for a full pipeline view."))}function mS(){gu=new Date().toISOString()}function gS(){return{silentTerminalRejections:mu,lastTerminalSyncAt:gu}}function _S(e){let t=new Xb;if(t.use("*",iS({maxSize:1*1024*1024})),t.use("*",async(i,l)=>{let p=i.req.raw.headers.get("host")??"";if(!lS.test(p))return i.text("Forbidden: invalid Host header",403);let m=i.req.raw.headers.get("origin");if(m&&!dS.test(m))return i.text("Forbidden: cross-origin request rejected",403);await l()}),e){let i=Buffer.from(e,"utf8");t.use("/api/*",async(l,p)=>{if(l.req.method==="GET"&&l.req.path==="/api/health")return p();let m=l.req.raw.headers.get("x-recall-token")??"",_=!1;if(m.length===e.length)try{_=Zb(Buffer.from(m,"utf8"),i)}catch{_=!1}return _?p():(l.req.path.startsWith("/api/terminal/")&&pS(),l.json({error:"unauthorized"},401))})}t.use("*",async(i,l)=>{await l(),i.res.headers.set("Content-Security-Policy","default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https://clauderecall.com; font-src 'self' data:; connect-src 'self' data: https://clauderecall.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"),i.res.headers.set("X-Content-Type-Options","nosniff"),i.res.headers.set("X-Frame-Options","DENY"),i.res.headers.set("Referrer-Policy","no-referrer"),i.res.headers.set("Cross-Origin-Resource-Policy","same-origin")}),t.get("/api/health",i=>i.json({status:"ok",version:du,uptimeSeconds:Math.round(process.uptime()),pipeline:gS()})),t.get("/api/stats",i=>i.json(uu())),t.get("/api/stats/session/:id",i=>{let l=Cd(i.req.param("id"));return l?i.json(l):i.json({error:"session not found"},404)}),t.get("/api/stats/project/:name",i=>{let l=Id(i.req.param("name"));return l?i.json(l):i.json({error:"project not found"},404)}),t.get("/api/stats/overview",i=>{let l=i.req.query("range"),p=l==="7d"?"7d":l==="30d"?"30d":"all";return i.json(vd(p))}),t.post("/api/stats/backfill",async i=>{let l=await i.req.json().catch(()=>({})),p=l.limit?Math.max(1,Math.min(1e5,Number(l.limit))):5e3;if(p>5e3){let _=Nd({limit:p});return i.json({mode:"background",started:_,alreadyRunning:!_&&Od(),limit:p,lastRun:Zr()})}let m=xd({limit:p});return i.json({mode:"sync",started:!1,alreadyRunning:!1,limit:p,result:m,lastRun:Zr()})}),t.get("/api/stats/health",i=>i.json(jd())),t.get("/api/stats/health/:projectId",i=>{let l=Number(i.req.param("projectId")),p=to(l);return p?i.json(p):i.json({error:"project not found"},404)}),t.get("/api/config/verification",i=>i.json({enabled:ao()})),t.put("/api/config/verification",async i=>{let l=await i.req.json();return typeof l.enabled=="boolean"&&au(l.enabled),i.json({enabled:ao()})}),t.get("/api/sessions/:id/verification",i=>{let l=i.req.param("id"),p=su(l);return i.json(p)}),t.get("/api/sessions/:id/share-stats",i=>{let l=i.req.param("id"),m=f().prepare(`SELECT tool_names, raw_json FROM messages
1638
+ (SELECT MAX(started_at) FROM sessions WHERE started_at IS NOT NULL) AS latest`).get()}var uS=/^(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i,pS=/^https?:\/\/(127\.0\.0\.1|localhost|\[::1\])(:\d+)?$/i;async function es(e,t){if((await Tt()).tier!=="pro")return e.json({error:"pro_required",message:"This feature requires a Claude Recall Pro license.",upgrade_url:"https://clauderecall.com/pricing",activate_command:"recall activate <license-key>"},402);await t()}var fn=new Map,mu=0,pu=0,gu=null,mS=6e4;function gS(){mu+=1;let e=Date.now();e-pu<mS||(pu=e,console.warn("[auth] /api/terminal/* request rejected without a valid X-Recall-Token. The VS Code / Cursor extension is likely outdated relative to the daemon \u2014 tab names will not flow through, and session titles will fall back to the heuristic first-message snippet. Reinstall: `code --install-extension extensions/vscode/clauderecall-vscode-*.vsix` and restart the extension host. Run `recall doctor` for a full pipeline view."))}function _S(){gu=new Date().toISOString()}function fS(){return{silentTerminalRejections:mu,lastTerminalSyncAt:gu}}function hS(e){let t=new Yb;if(t.use("*",cS({maxSize:1*1024*1024})),t.use("*",async(i,l)=>{let p=i.req.raw.headers.get("host")??"";if(!uS.test(p))return i.text("Forbidden: invalid Host header",403);let m=i.req.raw.headers.get("origin");if(m&&!pS.test(m))return i.text("Forbidden: cross-origin request rejected",403);await l()}),e){let i=Buffer.from(e,"utf8");t.use("/api/*",async(l,p)=>{if(l.req.method==="GET"&&l.req.path==="/api/health")return p();let m=l.req.raw.headers.get("x-recall-token")??"",_=!1;if(m.length===e.length)try{_=eS(Buffer.from(m,"utf8"),i)}catch{_=!1}return _?p():(l.req.path.startsWith("/api/terminal/")&&gS(),l.json({error:"unauthorized"},401))})}t.use("*",async(i,l)=>{await l(),i.res.headers.set("Content-Security-Policy","default-src 'self'; script-src 'self' 'wasm-unsafe-eval'; style-src 'self' 'unsafe-inline'; img-src 'self' data: blob: https://clauderecall.com; font-src 'self' data:; connect-src 'self' data: https://clauderecall.com; frame-ancestors 'none'; base-uri 'self'; form-action 'self'"),i.res.headers.set("X-Content-Type-Options","nosniff"),i.res.headers.set("X-Frame-Options","DENY"),i.res.headers.set("Referrer-Policy","no-referrer"),i.res.headers.set("Cross-Origin-Resource-Policy","same-origin")}),t.get("/api/health",i=>i.json({status:"ok",version:du,uptimeSeconds:Math.round(process.uptime()),pipeline:fS()})),t.get("/api/stats",i=>i.json(uu())),t.get("/api/stats/session/:id",i=>{let l=Cd(i.req.param("id"));return l?i.json(l):i.json({error:"session not found"},404)}),t.get("/api/stats/project/:name",i=>{let l=Id(i.req.param("name"));return l?i.json(l):i.json({error:"project not found"},404)}),t.get("/api/stats/overview",i=>{let l=i.req.query("range"),p=l==="7d"?"7d":l==="30d"?"30d":"all";return i.json(vd(p))}),t.post("/api/stats/backfill",async i=>{let l=await i.req.json().catch(()=>({})),p=l.limit?Math.max(1,Math.min(1e5,Number(l.limit))):5e3;if(p>5e3){let _=Nd({limit:p});return i.json({mode:"background",started:_,alreadyRunning:!_&&Od(),limit:p,lastRun:Zr()})}let m=xd({limit:p});return i.json({mode:"sync",started:!1,alreadyRunning:!1,limit:p,result:m,lastRun:Zr()})}),t.get("/api/stats/health",i=>i.json(jd())),t.get("/api/stats/health/:projectId",i=>{let l=Number(i.req.param("projectId")),p=to(l);return p?i.json(p):i.json({error:"project not found"},404)}),t.get("/api/config/verification",i=>i.json({enabled:ao()})),t.put("/api/config/verification",async i=>{let l=await i.req.json();return typeof l.enabled=="boolean"&&au(l.enabled),i.json({enabled:ao()})}),t.get("/api/sessions/:id/verification",i=>{let l=i.req.param("id"),p=su(l);return i.json(p)}),t.get("/api/sessions/:id/share-stats",i=>{let l=i.req.param("id"),m=f().prepare(`SELECT tool_names, raw_json FROM messages
1639
1639
  WHERE session_id = ? AND tool_names IS NOT NULL AND tool_names != ''`).all(l),_=m.length,E=new Set;for(let T of m){if(!/Read|Write|Edit/.test(T.tool_names))continue;let R=T.raw_json.match(/"(?:file_path|path)":\s*"([^"]+)"/g);if(R)for(let A of R){let x=A.match(/":\s*"([^"]+)"/);x&&E.add(x[1])}}return i.json({filesReferenced:E.size,toolCallCount:_})}),t.get("/api/sessions/:id/commits",async i=>{let l=i.req.param("id"),p=no(l);if(p.length>0||i.req.query("refresh")!=="1")return i.json({commits:p});let m=await so(l);return i.json({commits:no(l),status:m.status})}),t.get("/api/commits/:sha/session",i=>{let l=i.req.param("sha");return/^[0-9a-fA-F]{4,40}$/.test(l)?i.json({sessions:mn(l)}):i.json({error:"invalid sha format"},400)}),t.get("/api/license/status",async i=>{let l=await Tt();return i.json(l)}),t.post("/api/feedback",async i=>{let l;try{l=await i.req.json()}catch{return i.json({error:"invalid json"},400)}if(!l||typeof l!="object")return i.json({error:"invalid body"},400);let p=process.env.RECALL_FEEDBACK_API??"https://clauderecall.com/api/feedback",m=p==="https://clauderecall.com/api/feedback",_=await Tt(),E=St(),T=m&&_.tier==="pro"&&E?E.license_jwt:null,R=(()=>{try{let N=bn(Eo(bo(import.meta.url)),"..","..","package.json");return JSON.parse(hn(N,"utf8")).version}catch{return"unknown"}})(),A=l,x={score:A.score,comment:A.comment??null,surface:"web",version:typeof A.version=="string"?A.version:R,os:typeof A.os=="string"?A.os:process.platform,trigger_kind:typeof A.trigger_kind=="string"?A.trigger_kind:"manual",license_jwt:T};try{let N=await fetch(p,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(x)}),v=await N.json().catch(()=>({}));return i.json(v,N.status)}catch(N){let v=N instanceof Error?N.message:"network error";return i.json({error:"upstream_unreachable",detail:v},502)}}),t.get("/api/discover/today",es,async i=>{try{return i.json(await Ud())}catch(l){return console.error("[discover.today]",l),i.json({rediscovered:null,expensive:null,authored:null,availability:{semantic:!1,cost:!1,git:!1},generatedAt:new Date().toISOString(),error:l.message},500)}}),t.get("/api/macro-repos",i=>i.json({macro_repos:Rr(),orphan_projects:Kc()})),t.get("/api/bug-synthesis",i=>{let l=i.req.query("scope"),p=i.req.query("target_id"),m=i.req.query("limit"),_=l==="cluster"||l==="project"?l:void 0,E=m?Math.max(1,Number(m)):50,T=nl({scope:_,target_id:p??void 0,limit:E});return i.json({results:T})}),t.get("/api/bug-synthesis/counts",i=>{let l=i.req.query("scope");if(l!=="cluster"&&l!=="project")return i.json({error:'scope must be "cluster" or "project"'},400);let p=rl(l);return i.json({counts:Array.from(p.entries()).map(([m,_])=>({target_id:m,count:_}))})}),t.get("/api/bug-synthesis/:id",i=>{let l=Number(i.req.param("id"));if(!Number.isFinite(l))return i.json({error:"invalid id"},400);let p=kr(l);return p?i.json({result:p}):i.json({error:"not found"},404)}),t.delete("/api/bug-synthesis/:id",i=>{let l=Number(i.req.param("id"));return Number.isFinite(l)?(ol(l),i.json({ok:!0})):i.json({error:"invalid id"},400)});let s=j.object({name:j.string().min(1).max(100),description:j.string().max(500).nullable().optional()});t.post("/api/macro-repos",async i=>{let l=await i.req.json().catch(()=>null),p=s.safeParse(l);if(!p.success)return i.json({error:"invalid request body",details:p.error.format()},400);try{let m=zc({name:p.data.name,description:p.data.description??null});return i.json({macro_repo:m},201)}catch(m){let _=m instanceof Error?m.message:String(m);return _.includes("UNIQUE constraint")?i.json({error:`a macro repo named "${p.data.name}" already exists`},409):i.json({error:_},400)}});let n=j.object({name:j.string().min(1).max(100).optional(),description:j.string().max(500).nullable().optional()});t.patch("/api/macro-repos/:id",async i=>{let l=Number(i.req.param("id"));if(!Number.isFinite(l))return i.json({error:"invalid id"},400);let p=await i.req.json().catch(()=>null),m=n.safeParse(p);if(!m.success)return i.json({error:"invalid request body"},400);try{let _=Vc(l,m.data);return i.json({macro_repo:_})}catch(_){let E=_ instanceof Error?_.message:String(_);return E.includes("not found")?i.json({error:E},404):E.includes("UNIQUE constraint")?i.json({error:"another macro repo already has that name"},409):i.json({error:E},400)}}),t.delete("/api/macro-repos/:id",i=>{let l=Number(i.req.param("id"));return Number.isFinite(l)?(Zc(l),i.json({ok:!0})):i.json({error:"invalid id"},400)});let r=j.object({project_id:j.number().int().positive()});t.post("/api/macro-repos/:id/members",async i=>{let l=Number(i.req.param("id"));if(!Number.isFinite(l))return i.json({error:"invalid id"},400);let p=await i.req.json().catch(()=>null),m=r.safeParse(p);if(!m.success)return i.json({error:"invalid request body"},400);try{return Qc(l,m.data.project_id),i.json({macro_repo:it(l)})}catch(_){let E=_ instanceof Error?_.message:String(_);return i.json({error:E},E.includes("not found")?404:400)}}),t.delete("/api/macro-repos/:id/members/:projectId",i=>{let l=Number(i.req.param("id")),p=Number(i.req.param("projectId"));return!Number.isFinite(l)||!Number.isFinite(p)?i.json({error:"invalid id"},400):(el(l,p),i.json({macro_repo:it(l)}))}),t.get("/api/projects",i=>{let l=f(),m=i.req.query("system")==="1"||i.req.query("system")==="true"?"":" AND COALESCE(s.auto_title, '') NOT LIKE '[meta]%' AND COALESCE(s.auto_title, '') NOT LIKE '[output-index]%' AND COALESCE(s.auto_title, '') NOT LIKE '[skill]%'",_=l.prepare(`SELECT p.id, p.name, p.decoded_path,
1640
1640
  COUNT(CASE WHEN s.id IS NOT NULL${m} THEN 1 END) AS session_count,
1641
1641
  COALESCE(SUM(CASE WHEN s.id IS NOT NULL${m} THEN s.message_count ELSE 0 END), 0) AS message_count,
@@ -1795,9 +1795,9 @@ ${o}
1795
1795
  WHERE s.id = ?`).get(p);if(!T)return i.json({error:"not found"},404);let R=l.prepare(`SELECT uuid, type, role, timestamp, is_sidechain, content_text, tool_names
1796
1796
  FROM messages
1797
1797
  WHERE session_id = ?
1798
- ORDER BY COALESCE(timestamp, ''), rowid`).all(p),A=si(T,R,{mode:m,includeSidechain:_,prelude:E});return i.text(A)}),t.get("/api/collections",i=>{let l=i.req.query("archived")==="1";return i.json({collections:Ei(l)})}),t.get("/api/collections/:id",i=>{let l=i.req.param("id"),p=Ne(l);if(!p)return i.json({error:"not found"},404);let m=bi(l,!0);return i.json({collection:p,members:m})}),t.post("/api/collections",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.name!="string")return i.json({error:"name required"},400);try{let p=At({name:l.name,description:l.description??null,icon:l.icon??null,color:l.color??null,parent_id:l.parent_id??null,sort_key:l.sort_key});return i.json(p,201)}catch(p){return i.json({error:p.message},400)}}),t.patch("/api/collections/:id",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>null);if(!p)return i.json({error:"body required"},400);try{let m=Ti(l,p);return i.json(m)}catch(m){return i.json({error:m.message},400)}}),t.post("/api/collections/:id/archive",i=>{let l=i.req.param("id");try{let p=yi(l);return i.json(p)}catch(p){return i.json({error:p.message},404)}}),t.post("/api/collections/:id/restore",i=>{let l=i.req.param("id");try{let p=wi(l);return i.json(p)}catch(p){return i.json({error:p.message},404)}}),t.post("/api/collections/:id/members",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>null);if(!p||typeof p.session_id!="string")return i.json({error:"session_id required"},400);try{let m=xt(l,p.session_id,p.note??null);return i.json(m)}catch(m){return i.json({error:m.message},400)}}),t.delete("/api/collections/:id/members/:sid",i=>{let l=i.req.param("id"),p=i.req.param("sid");try{let m=Ri(l,p);return i.json(m)}catch(m){return i.json({error:m.message},400)}}),t.get("/api/sessions/:id/collections",i=>{let l=i.req.param("id");return i.json({collections:Si(l)})});let w=["cwd-prefix","project-id","tag","plan-file","git-branch-prefix"];t.get("/api/auto-collections/rules",i=>i.json({rules:Oi()})),t.post("/api/auto-collections/rules",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.name!="string"||typeof l.pattern!="string"||!l.type||!w.includes(l.type))return i.json({error:"name, type, pattern required (type must be a known matcher)"},400);try{let p=Bn({name:l.name,type:l.type,pattern:l.pattern,collection_id:l.collection_id,parent_collection_id:l.parent_collection_id,priority:l.priority,enabled:l.enabled});return i.json(p,201)}catch(p){return i.json({error:p.message},400)}}),t.patch("/api/auto-collections/rules/:id",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>null);if(!p)return i.json({error:"body required"},400);try{let m=Li(l,p);return i.json(m)}catch(m){return i.json({error:m.message},400)}}),t.delete("/api/auto-collections/rules/:id",i=>{let l=i.req.param("id");try{let p=Ci(l);return i.json(p)}catch(p){return i.json({error:p.message},400)}}),t.get("/api/auto-collections/suggestions",i=>{let l=i.req.query("dismissed")==="1";return i.json({suggestions:gs({includeDismissed:l})})}),t.post("/api/auto-collections/suggestions/:id/accept",i=>{let l=i.req.param("id");try{let p=vi(l);return i.json({rule:p})}catch(p){return i.json({error:p.message},400)}}),t.post("/api/auto-collections/suggestions/:id/dismiss",i=>{let l=i.req.param("id");try{return Ii(l),i.json({ok:!0})}catch(p){return i.json({error:p.message},400)}}),t.post("/api/auto-collections/detect",i=>{let l=_s();return i.json({suggestions:l})}),t.get("/api/auto-collections/suggestions/:id/preview",i=>{let l=i.req.param("id"),p=Math.max(1,Math.min(20,Number(i.req.query("limit"))||3)),_=gs({includeDismissed:!1}).find(T=>T.id===l);if(!_)return i.json({error:"suggestion not found"},404);let E=xi(_.type,_.pattern,p);return i.json({sessions:E})}),t.get("/api/auto-collections/parents",i=>{let l=Array.from(ji());return i.json({auto_collection_ids:l})}),t.get("/api/threads",i=>{let l=i.req.query("archived")==="1";return i.json({threads:Jn({includeArchived:l})})}),t.get("/api/threads/:id",i=>{let l=i.req.param("id"),p=te(l);if(!p)return i.json({error:"thread not found"},404);let m=p.edges.map(_=>({..._,alias_source:_.alias==null?null:I.isSessionAutoLinked(_.session_id)?"auto":"manual"}));return i.json({thread:{...p,edges:m}})}),t.post("/api/threads",async i=>{let l=await i.req.json().catch(()=>({}));if(!l.name)return i.json({error:"name required"},400);try{let p=hs({name:l.name,summary:l.summary??null,originSessionId:l.originSessionId});return i.json({thread:p})}catch(p){return i.json({error:p.message},400)}}),t.patch("/api/threads/:id",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({}));try{p.name&&qi(l,p.name),p.close&&Ji(l),p.reopen&&Xi(l),p.archive&&Gi(l),"folder_id"in p&&ma(l,p.folder_id??null);let m=te(l);return m?i.json({thread:m}):i.json({error:"thread not found"},404)}catch(m){return i.json({error:m.message},400)}}),t.get("/api/thread-folders",i=>i.json({folders:Kn()})),t.post("/api/thread-folders",async i=>{let l=await i.req.json().catch(()=>({}));if(!l.name||typeof l.name!="string")return i.json({error:"name required"},400);try{let p=aa({name:l.name,parentFolderId:l.parent_folder_id??null,projectScope:l.project_scope??null});return i.json({folder:p})}catch(p){return i.json({error:p.message},400)}}),t.patch("/api/thread-folders/:id",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({}));try{let m;return p.name&&(m=la(l,p.name)),"parent_folder_id"in p&&(m=da(l,p.parent_folder_id??null)),m?i.json({folder:m}):i.json({error:"no patch fields"},400)}catch(m){return i.json({error:m.message},400)}}),t.delete("/api/thread-folders/:id",i=>{let l=i.req.param("id");try{return pa(l),i.json({ok:!0})}catch(p){return i.json({error:p.message},400)}}),t.post("/api/thread-folders/reorder",async i=>{let l=await i.req.json().catch(()=>({})),p=l.ordered_ids;if(!Array.isArray(p))return i.json({error:"ordered_ids must be an array"},400);try{return ua(l.parent_folder_id??null,l.project_scope??null,p),i.json({ok:!0})}catch(m){return i.json({error:m.message},400)}}),t.post("/api/threads/:id/sessions",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({}));if(!p.sessionId)return i.json({error:"sessionId required"},400);try{let m=Es({threadId:l,sessionId:p.sessionId,parentSessionId:p.parentSessionId??null,role:p.role});return i.json({edge:m})}catch(m){return i.json({error:m.message},400)}}),t.delete("/api/threads/:id/sessions/:sessionId",i=>{let l=i.req.param("id"),p=i.req.param("sessionId"),m=Wi(l,p);return i.json(m)}),t.patch("/api/threads/:id/sessions/:sessionId",async i=>{let l=i.req.param("id"),p=i.req.param("sessionId"),m=await i.req.json().catch(()=>({}));try{let _=Nt(l,p,m.parentSessionId??null);return i.json({edge:_})}catch(_){return i.json({error:_.message},400)}}),t.post("/api/threads/:id/merge",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({}));if(!p.sourceId)return i.json({error:"sourceId required"},400);try{let m=Yi(p.sourceId,l);return i.json({thread:m})}catch(m){return i.json({error:m.message},400)}}),t.post("/api/threads/:id/split",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({}));if(!p.sessionIds?.length||!p.newThreadName)return i.json({error:"sessionIds and newThreadName required"},400);try{let m=Ki({threadId:l,sessionIds:p.sessionIds,newThreadName:p.newThreadName});return i.json({thread:m})}catch(m){return i.json({error:m.message},400)}}),t.get("/api/sessions/:id/threads",i=>{let l=i.req.param("id");return i.json({threads:Hi(l)})});let D=j.object({enabled:j.boolean(),band_lo:j.number().min(0).max(1).optional(),band_hi:j.number().min(0).max(1).optional(),model:j.string().regex(/^[a-zA-Z0-9._-]{1,100}$/).optional()}).optional(),L=j.object({project:j.string().min(1),threshold:j.number().min(0).max(1).optional(),model:j.string().regex(/^[a-zA-Z0-9._-]{1,100}$/).optional(),llm_rescore:D});t.post("/api/threads/scan/preflight",async i=>{let l=we(i);if(l)return l;let p=await i.req.json().catch(()=>null),m=L.safeParse(p);if(!m.success)return i.json({error:"invalid request body",details:m.error.format()},400);let _=Wl({project:m.data.project,threshold:m.data.threshold,model:m.data.model,llm_rescore:m.data.llm_rescore});return"error"in _?i.json({error:_.error},400):i.json(_)});let X=j.object({project:j.string().min(1),threshold:j.number().min(0).max(1).optional(),llm_names:j.boolean().optional(),model:j.string().regex(/^[a-zA-Z0-9._-]{1,100}$/).optional(),llm_rescore:D});t.post("/api/threads/scan/apply",async i=>{let l=we(i);if(l)return l;let p=await i.req.json().catch(()=>null),m=X.safeParse(p);if(!m.success)return i.json({error:"invalid request body",details:m.error.format()},400);let _=Jl({project:m.data.project,threshold:m.data.threshold,llm_names:m.data.llm_names,model:m.data.model,llm_rescore:m.data.llm_rescore});return"error"in _?i.json({error:_.error},400):i.json({jobId:_.jobId,reused:_.reused},_.reused?409:200)}),t.get("/api/threads/scan/jobs/:jobId/stream",i=>{let l=i.req.param("jobId");if(!Br(l))return i.json({error:"job not found"},404);let m=Number(i.req.header("Last-Event-ID")??0);return Me(i,async _=>{let E=!1,T=setInterval(()=>{E||_.writeSSE({event:"heartbeat",data:""}).catch(()=>{E=!0})},15e3);try{for await(let R of Xl(l,m))if(E||(await _.writeSSE({id:String(R.id),event:R.kind,data:JSON.stringify(R.data)}),R.kind==="done"))break}finally{E=!0,clearInterval(T)}})}),t.get("/api/threads/scan/jobs/:jobId",i=>{let l=Br(i.req.param("jobId"));return l?i.json(l):i.json({error:"job not found"},404)}),t.delete("/api/threads/scan/jobs/:jobId",i=>{let l=we(i);return l||(Gl(i.req.param("jobId"))?i.json({ok:!0}):i.json({error:"job not found or already done"},404))});let M=j.object({project_id:j.number().int().positive(),mode:j.enum(["preflight","apply"]),window_hours:j.number().min(.5).max(168).optional(),score_threshold:j.number().min(0).max(1).optional(),use_live_pids:j.boolean().optional()});t.post("/api/threads/sync-active",async i=>{let l=await i.req.json().catch(()=>null),p=M.safeParse(l);if(!p.success)return i.json({error:"invalid request body",details:p.error.format()},400);try{let m=await ra(p.data.project_id,{windowHours:p.data.window_hours,scoreThreshold:p.data.score_threshold,useLivePids:p.data.use_live_pids});if(p.data.mode==="preflight")return i.json({plan:m});let _=oa(m);return i.json({plan:m,result:_})}catch(m){return i.json({error:m.message},400)}}),t.get("/api/threads/:id/titles/preflight",i=>{let l=i.req.param("id"),p=te(l);if(!p)return i.json({error:"thread not found"},404);let m=f(),_=0;for(let E of p.edges)m.prepare("SELECT auto_title_source FROM sessions WHERE id = ?").get(E.session_id)?.auto_title_source==="agent"&&(_+=1);return i.json({total:p.edges.length,alreadyTitled:_,untitled:p.edges.length-_})}),t.post("/api/threads/:id/titles/generate",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({})),m=te(l);if(!m)return i.json({error:"thread not found"},404);if(m.edges.length===0)return i.json({error:"thread has no sessions"},400);let _=Re(),E=p.model??_.model,T=mc({threadId:l,force:p.force??!1,model:E});return i.json({jobId:T})}),t.get("/api/jobs/:jobId/stream",i=>{let l=i.req.param("jobId");if(!dr(l))return i.json({error:"job not found"},404);let m=Number(i.req.header("Last-Event-ID")??0);return Me(i,async _=>{let E=!1,T=setInterval(()=>{E||_.writeSSE({event:"heartbeat",data:""}).catch(()=>{E=!0})},15e3);try{for await(let R of gc(l,m))if(E||(await _.writeSSE({id:String(R.id),event:R.kind,data:JSON.stringify(R.data)}),R.kind==="done"))break}finally{E=!0,clearInterval(T)}})}),t.get("/api/jobs/:jobId",i=>{let l=dr(i.req.param("jobId"));return l?i.json(l):i.json({error:"job not found"},404)}),t.delete("/api/jobs/:jobId",i=>_c(i.req.param("jobId"))?i.json({ok:!0}):i.json({error:"job not found or already done"},404)),t.post("/api/terminal/opened",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.shell_pid!="number"||typeof l.tab_name!="string")return i.json({error:"shell_pid and tab_name required"},400);let p=I.claimPidOwnership(l.shell_pid,l.extension_instance_id??null);if(p==="rejected")return i.json({ok:!0,rejected:!0,reason:"pid-owned-by-other-extension-instance",count:I.size()});let m=I.upsert({shell_pid:l.shell_pid,tab_name:l.tab_name,cwd:l.cwd??null,opened_at:l.opened_at??new Date().toISOString()});return i.json({ok:!0,ownership:p,count:I.size(),entry:m})}),t.post("/api/terminal/renamed",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.shell_pid!="number"||typeof l.tab_name!="string")return i.json({error:"shell_pid and tab_name required"},400);let p=I.claimPidOwnership(l.shell_pid,l.extension_instance_id??null);if(p==="rejected")return i.json({ok:!0,rejected:!0,reason:"pid-owned-by-other-extension-instance"});let m=I.rename(l.shell_pid,l.tab_name);if(!m)return i.json({error:"unknown shell_pid"},404);let _=lu(l.shell_pid,l.tab_name);return i.json({ok:!0,ownership:p,entry:m,propagated:_})}),t.post("/api/terminal/closed",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.shell_pid!="number")return i.json({error:"shell_pid required"},400);let p=I.remove(l.shell_pid);return i.json({ok:!0,removed:p,count:I.size()})}),t.post("/api/terminal/claude-started",async i=>{let l=await i.req.json().catch(()=>null);return!l||typeof l.shell_pid!="number"?i.json({error:"shell_pid required"},400):(I.pushPending({shell_pid:l.shell_pid,tab_name:typeof l.tab_name=="string"?l.tab_name:"",cwd:typeof l.cwd=="string"?l.cwd:null,started_at:typeof l.started_at=="string"?l.started_at:new Date().toISOString()}),i.json({ok:!0,pending:I.pendingSize()}))}),t.post("/api/terminal/output",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.shell_pid!="number"||typeof l.text!="string")return i.json({error:"shell_pid and text required"},400);let p=l.text.length>8192?l.text.slice(-8192):l.text,m=typeof l.captured_at=="string"?l.captured_at:new Date().toISOString();return I.setOutputTail(l.shell_pid,p,m),i.json({ok:!0})}),t.post("/api/terminal/sync",async i=>{let l=await i.req.json().catch(()=>null);if(!l||!Array.isArray(l.terminals))return i.json({error:"terminals array required"},400);let p=new Map;for(let O of I.all())p.set(O.shell_pid,O.tab_name);let m=l.terminals.filter(O=>!!O&&typeof O.shell_pid=="number"&&typeof O.tab_name=="string").map(O=>({shell_pid:O.shell_pid,tab_name:O.tab_name,cwd:O.cwd??null,opened_at:O.opened_at??new Date().toISOString()})),_=l.extension_instance_id??null,E=[],T=m.filter(O=>{let F=I.claimPidOwnership(O.shell_pid,_);return E.push({shell_pid:O.shell_pid,ownership:F}),F!=="rejected"}),R=I.sync(T),A=0;for(let O of T){let F=p.get(O.shell_pid),U=I.get(O.shell_pid)?.tab_name??O.tab_name,V=!!U&&!re(U)&&!ne(U)?U:O.tab_name;F!==void 0&&F!==V&&(A+=lu(O.shell_pid,V))}let x=E.filter(O=>O.ownership==="rejected").length;x>0&&console.log(`[terminal/sync] dropped ${x} tab_name update(s), pid(s) owned by a different extension instance`);let N=await tS(),v={resolved:0,expired:0};try{v=Rc()}catch{}let C={rebound:0,ghosts:0,ambiguous:0};try{C=wc()}catch{}return mS(),i.json({ok:!0,count:I.size(),diff:R,propagated:A,live_sweep:N,deferred_resolved:v,rebound:C})}),t.get("/api/terminal/registry",i=>i.json({terminals:I.all(),count:I.size()})),t.get("/api/terminal/sessions/:shellPid",i=>{let l=i.req.param("shellPid"),p=Number(l);if(!Number.isInteger(p)||p<=0)return i.json({error:"shellPid must be a positive integer"},400);let m=I.sessionsFor(p);return i.json({shell_pid:p,sessions:m})}),t.get("/api/sessions/:id/linked-terminal",i=>{let l=i.req.param("id"),p=I.all().find(_=>I.sessionsFor(_.shell_pid).includes(l)),m=[];if(!p){let _=f().prepare("SELECT cwd, started_at FROM sessions WHERE id = ?").get(l);if(_?.cwd&&_.started_at){let E=Date.parse(_.started_at);if(Number.isFinite(E)){let T=_.cwd.replace(/\/+$/,""),R=300*1e3;for(let A of I.all()){if(!A.cwd||A.cwd.replace(/\/+$/,"")!==T||re(A.tab_name))continue;let x=Date.parse(A.opened_at),N=Date.parse(A.last_seen_at);!Number.isFinite(x)||!Number.isFinite(N)||x>E||N+R<E||m.push({shell_pid:A.shell_pid,tab_name:A.tab_name,cwd:A.cwd,opened_at:A.opened_at,last_seen_at:A.last_seen_at,reason:"time-overlap"})}m.sort((A,x)=>Date.parse(x.last_seen_at)-Date.parse(A.last_seen_at))}}}return p?i.json({linked:{shell_pid:p.shell_pid,tab_name:p.tab_name,cwd:p.cwd},suggested:[]}):i.json({linked:null,suggested:m})}),t.post("/api/sessions/:id/auto-relink",async i=>{let l=i.req.param("id");if(Te(l))return i.json({applied:!1,reason:"has-alias"});if(I.all().some(T=>I.sessionsFor(T.shell_pid).includes(l)))return i.json({applied:!1,reason:"already-linked"});let m=f().prepare("SELECT cwd, git_branch, started_at FROM sessions WHERE id = ?").get(l);if(!m?.cwd)return i.json({applied:!1,reason:"no-cwd"});let _=m.cwd.replace(/\/+$/,""),E=I.all().filter(T=>T.cwd&&T.cwd.replace(/\/+$/,"")===_&&!re(T.tab_name));if(E.length===1){let T=E[0],R=yt({sessionStartedAt:m.started_at??null,terminalOpenedAt:T.opened_at??null});if(!R.allowed)return i.json({applied:!1,reason:"temporal-guard",guard_reason:R.reason});let A=I.getOrigin(l),x=st({tabName:T.tab_name,origin:A??null,cwd:m.cwd??null,gitBranch:m.git_branch??null});return x?(me(l,x),I.linkSession(l,T.shell_pid),i.json({applied:!0,alias:x,linked_pid:T.shell_pid,linked_tab_name:T.tab_name,method:"cwd-singleton"})):i.json({applied:!1,reason:"no-usable-name"})}if(E.length>1){let T=await yc(l);if(T){let A=I.get(T.shell_pid),x=yt({sessionStartedAt:m.started_at??null,terminalOpenedAt:A?.opened_at??null});if(!x.allowed)return i.json({applied:!1,reason:"temporal-guard",guard_reason:x.reason});let N=I.getOrigin(l),v=st({tabName:T.tab_name,origin:N??null,cwd:m.cwd??null,gitBranch:m.git_branch??null});if(v)return me(l,v),I.linkSession(l,T.shell_pid),i.json({applied:!0,alias:v,linked_pid:T.shell_pid,linked_tab_name:T.tab_name,matched_fingerprints:T.matched_fingerprints,method:"content-match"})}let R=6e4;if(m.started_at){let A=Date.parse(m.started_at);if(Number.isFinite(A)){let x=E.filter(v=>yt({sessionStartedAt:m.started_at,terminalOpenedAt:v.opened_at??null}).allowed).map(v=>({t:v,gap:A-Date.parse(v.opened_at??"")})).filter(v=>Number.isFinite(v.gap)&&v.gap>=0&&v.gap<=R);if(x.length>=2)return i.json({applied:!1,reason:"ambiguous-temporal",candidate_count:x.length});let N=x[0];if(N){let v=I.getOrigin(l),C=st({tabName:N.t.tab_name,origin:v??null,cwd:m.cwd??null,gitBranch:m.git_branch??null});if(C)return me(l,C),I.linkSession(l,N.t.shell_pid),i.json({applied:!0,alias:C,linked_pid:N.t.shell_pid,linked_tab_name:N.t.tab_name,method:"closest-before-temporal",gap_ms:N.gap})}}}return i.json({applied:!1,reason:"ambiguous",candidate_count:E.length})}return i.json({applied:!1,reason:"no-candidates"})}),t.post("/api/sessions/:id/relink",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>null);if(p?.clear)return I.unlinkSession(l),ns(l),i.json({ok:!0,alias:null,linked_pid:null});if(!p||typeof p.shell_pid!="number")return i.json({error:"shell_pid required"},400);let m=I.get(p.shell_pid);if(!m)return i.json({error:"terminal not registered"},404);let _=I.getOrigin(l),E=f().prepare("SELECT cwd, git_branch FROM sessions WHERE id = ?").get(l),T=null,R=m.tab_name?.trim()??"";if(R&&!re(R)&&!ne(R))T=R;else if(R&&ne(R)){let A=tt(R);A&&!re(A)&&(T=A)}return T?(I.unlinkSession(l),me(l,T),i.json({ok:!0,alias:T,linked_pid:p.shell_pid,linked_tab_name:m.tab_name})):i.json({error:"terminal has no usable name, name the tab in your editor first, then retry the relink"},422)}),t.post("/api/sessions/:id/recorrelate",async i=>{let l=i.req.param("id"),p=f().prepare("SELECT file_path FROM sessions WHERE id = ?").get(l);if(!p?.file_path)return i.json({error:"session not found"},404);I.unlinkSession(l),ns(l),await Ms(p.file_path);let m=Te(l);return i.json({ok:!0,alias:m,linked_pid:I.all().find(_=>I.sessionsFor(_.shell_pid).includes(l))?.shell_pid??null})}),t.get("/api/paste-expand",async i=>{let l=i.req.query("session"),p=i.req.query("message"),m=i.req.query("path");if(!l||!p||!m)return i.json({error:"session, message and path are required"},400);let _=f(),E=_.prepare("SELECT rowid, content_text FROM messages WHERE uuid = ? AND session_id = ?").get(p,l);if(!E)return i.json({error:"message not found in session"},404);let T=m.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");if(!new RegExp(`\\[Pasted text #\\d+ \\+\\d+ lines\\]\\s*${T}`).test(E.content_text??""))return i.json({error:"path not referenced by this message"},403);let A=_.prepare(`SELECT content_text FROM messages
1798
+ ORDER BY COALESCE(timestamp, ''), rowid`).all(p),A=si(T,R,{mode:m,includeSidechain:_,prelude:E});return i.text(A)}),t.get("/api/collections",i=>{let l=i.req.query("archived")==="1";return i.json({collections:Ei(l)})}),t.get("/api/collections/:id",i=>{let l=i.req.param("id"),p=Ne(l);if(!p)return i.json({error:"not found"},404);let m=bi(l,!0);return i.json({collection:p,members:m})}),t.post("/api/collections",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.name!="string")return i.json({error:"name required"},400);try{let p=At({name:l.name,description:l.description??null,icon:l.icon??null,color:l.color??null,parent_id:l.parent_id??null,sort_key:l.sort_key});return i.json(p,201)}catch(p){return i.json({error:p.message},400)}}),t.patch("/api/collections/:id",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>null);if(!p)return i.json({error:"body required"},400);try{let m=Ti(l,p);return i.json(m)}catch(m){return i.json({error:m.message},400)}}),t.post("/api/collections/:id/archive",i=>{let l=i.req.param("id");try{let p=yi(l);return i.json(p)}catch(p){return i.json({error:p.message},404)}}),t.post("/api/collections/:id/restore",i=>{let l=i.req.param("id");try{let p=wi(l);return i.json(p)}catch(p){return i.json({error:p.message},404)}}),t.post("/api/collections/:id/members",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>null);if(!p||typeof p.session_id!="string")return i.json({error:"session_id required"},400);try{let m=xt(l,p.session_id,p.note??null);return i.json(m)}catch(m){return i.json({error:m.message},400)}}),t.delete("/api/collections/:id/members/:sid",i=>{let l=i.req.param("id"),p=i.req.param("sid");try{let m=Ri(l,p);return i.json(m)}catch(m){return i.json({error:m.message},400)}}),t.get("/api/sessions/:id/collections",i=>{let l=i.req.param("id");return i.json({collections:Si(l)})});let w=["cwd-prefix","project-id","tag","plan-file","git-branch-prefix"];t.get("/api/auto-collections/rules",i=>i.json({rules:Oi()})),t.post("/api/auto-collections/rules",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.name!="string"||typeof l.pattern!="string"||!l.type||!w.includes(l.type))return i.json({error:"name, type, pattern required (type must be a known matcher)"},400);try{let p=Bn({name:l.name,type:l.type,pattern:l.pattern,collection_id:l.collection_id,parent_collection_id:l.parent_collection_id,priority:l.priority,enabled:l.enabled});return i.json(p,201)}catch(p){return i.json({error:p.message},400)}}),t.patch("/api/auto-collections/rules/:id",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>null);if(!p)return i.json({error:"body required"},400);try{let m=Li(l,p);return i.json(m)}catch(m){return i.json({error:m.message},400)}}),t.delete("/api/auto-collections/rules/:id",i=>{let l=i.req.param("id");try{let p=Ci(l);return i.json(p)}catch(p){return i.json({error:p.message},400)}}),t.get("/api/auto-collections/suggestions",i=>{let l=i.req.query("dismissed")==="1";return i.json({suggestions:gs({includeDismissed:l})})}),t.post("/api/auto-collections/suggestions/:id/accept",i=>{let l=i.req.param("id");try{let p=vi(l);return i.json({rule:p})}catch(p){return i.json({error:p.message},400)}}),t.post("/api/auto-collections/suggestions/:id/dismiss",i=>{let l=i.req.param("id");try{return Ii(l),i.json({ok:!0})}catch(p){return i.json({error:p.message},400)}}),t.post("/api/auto-collections/detect",i=>{let l=_s();return i.json({suggestions:l})}),t.get("/api/auto-collections/suggestions/:id/preview",i=>{let l=i.req.param("id"),p=Math.max(1,Math.min(20,Number(i.req.query("limit"))||3)),_=gs({includeDismissed:!1}).find(T=>T.id===l);if(!_)return i.json({error:"suggestion not found"},404);let E=xi(_.type,_.pattern,p);return i.json({sessions:E})}),t.get("/api/auto-collections/parents",i=>{let l=Array.from(ji());return i.json({auto_collection_ids:l})}),t.get("/api/threads",i=>{let l=i.req.query("archived")==="1";return i.json({threads:Jn({includeArchived:l})})}),t.get("/api/threads/:id",i=>{let l=i.req.param("id"),p=te(l);if(!p)return i.json({error:"thread not found"},404);let m=p.edges.map(_=>({..._,alias_source:_.alias==null?null:I.isSessionAutoLinked(_.session_id)?"auto":"manual"}));return i.json({thread:{...p,edges:m}})}),t.post("/api/threads",async i=>{let l=await i.req.json().catch(()=>({}));if(!l.name)return i.json({error:"name required"},400);try{let p=hs({name:l.name,summary:l.summary??null,originSessionId:l.originSessionId});return i.json({thread:p})}catch(p){return i.json({error:p.message},400)}}),t.patch("/api/threads/:id",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({}));try{p.name&&qi(l,p.name),p.close&&Ji(l),p.reopen&&Xi(l),p.archive&&Gi(l),"folder_id"in p&&ma(l,p.folder_id??null);let m=te(l);return m?i.json({thread:m}):i.json({error:"thread not found"},404)}catch(m){return i.json({error:m.message},400)}}),t.get("/api/thread-folders",i=>i.json({folders:Kn()})),t.post("/api/thread-folders",async i=>{let l=await i.req.json().catch(()=>({}));if(!l.name||typeof l.name!="string")return i.json({error:"name required"},400);try{let p=aa({name:l.name,parentFolderId:l.parent_folder_id??null,projectScope:l.project_scope??null});return i.json({folder:p})}catch(p){return i.json({error:p.message},400)}}),t.patch("/api/thread-folders/:id",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({}));try{let m;return p.name&&(m=la(l,p.name)),"parent_folder_id"in p&&(m=da(l,p.parent_folder_id??null)),m?i.json({folder:m}):i.json({error:"no patch fields"},400)}catch(m){return i.json({error:m.message},400)}}),t.delete("/api/thread-folders/:id",i=>{let l=i.req.param("id");try{return pa(l),i.json({ok:!0})}catch(p){return i.json({error:p.message},400)}}),t.post("/api/thread-folders/reorder",async i=>{let l=await i.req.json().catch(()=>({})),p=l.ordered_ids;if(!Array.isArray(p))return i.json({error:"ordered_ids must be an array"},400);try{return ua(l.parent_folder_id??null,l.project_scope??null,p),i.json({ok:!0})}catch(m){return i.json({error:m.message},400)}}),t.post("/api/threads/:id/sessions",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({}));if(!p.sessionId)return i.json({error:"sessionId required"},400);try{let m=Es({threadId:l,sessionId:p.sessionId,parentSessionId:p.parentSessionId??null,role:p.role});return i.json({edge:m})}catch(m){return i.json({error:m.message},400)}}),t.delete("/api/threads/:id/sessions/:sessionId",i=>{let l=i.req.param("id"),p=i.req.param("sessionId"),m=Wi(l,p);return i.json(m)}),t.patch("/api/threads/:id/sessions/:sessionId",async i=>{let l=i.req.param("id"),p=i.req.param("sessionId"),m=await i.req.json().catch(()=>({}));try{let _=Nt(l,p,m.parentSessionId??null);return i.json({edge:_})}catch(_){return i.json({error:_.message},400)}}),t.post("/api/threads/:id/merge",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({}));if(!p.sourceId)return i.json({error:"sourceId required"},400);try{let m=Yi(p.sourceId,l);return i.json({thread:m})}catch(m){return i.json({error:m.message},400)}}),t.post("/api/threads/:id/split",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({}));if(!p.sessionIds?.length||!p.newThreadName)return i.json({error:"sessionIds and newThreadName required"},400);try{let m=Ki({threadId:l,sessionIds:p.sessionIds,newThreadName:p.newThreadName});return i.json({thread:m})}catch(m){return i.json({error:m.message},400)}}),t.get("/api/sessions/:id/threads",i=>{let l=i.req.param("id");return i.json({threads:Hi(l)})});let D=j.object({enabled:j.boolean(),band_lo:j.number().min(0).max(1).optional(),band_hi:j.number().min(0).max(1).optional(),model:j.string().regex(/^[a-zA-Z0-9._-]{1,100}$/).optional()}).optional(),L=j.object({project:j.string().min(1),threshold:j.number().min(0).max(1).optional(),model:j.string().regex(/^[a-zA-Z0-9._-]{1,100}$/).optional(),llm_rescore:D});t.post("/api/threads/scan/preflight",async i=>{let l=we(i);if(l)return l;let p=await i.req.json().catch(()=>null),m=L.safeParse(p);if(!m.success)return i.json({error:"invalid request body",details:m.error.format()},400);let _=Wl({project:m.data.project,threshold:m.data.threshold,model:m.data.model,llm_rescore:m.data.llm_rescore});return"error"in _?i.json({error:_.error},400):i.json(_)});let X=j.object({project:j.string().min(1),threshold:j.number().min(0).max(1).optional(),llm_names:j.boolean().optional(),model:j.string().regex(/^[a-zA-Z0-9._-]{1,100}$/).optional(),llm_rescore:D});t.post("/api/threads/scan/apply",async i=>{let l=we(i);if(l)return l;let p=await i.req.json().catch(()=>null),m=X.safeParse(p);if(!m.success)return i.json({error:"invalid request body",details:m.error.format()},400);let _=Jl({project:m.data.project,threshold:m.data.threshold,llm_names:m.data.llm_names,model:m.data.model,llm_rescore:m.data.llm_rescore});return"error"in _?i.json({error:_.error},400):i.json({jobId:_.jobId,reused:_.reused},_.reused?409:200)}),t.get("/api/threads/scan/jobs/:jobId/stream",i=>{let l=i.req.param("jobId");if(!Br(l))return i.json({error:"job not found"},404);let m=Number(i.req.header("Last-Event-ID")??0);return Me(i,async _=>{let E=!1,T=setInterval(()=>{E||_.writeSSE({event:"heartbeat",data:""}).catch(()=>{E=!0})},15e3);try{for await(let R of Xl(l,m))if(E||(await _.writeSSE({id:String(R.id),event:R.kind,data:JSON.stringify(R.data)}),R.kind==="done"))break}finally{E=!0,clearInterval(T)}})}),t.get("/api/threads/scan/jobs/:jobId",i=>{let l=Br(i.req.param("jobId"));return l?i.json(l):i.json({error:"job not found"},404)}),t.delete("/api/threads/scan/jobs/:jobId",i=>{let l=we(i);return l||(Gl(i.req.param("jobId"))?i.json({ok:!0}):i.json({error:"job not found or already done"},404))});let M=j.object({project_id:j.number().int().positive(),mode:j.enum(["preflight","apply"]),window_hours:j.number().min(.5).max(168).optional(),score_threshold:j.number().min(0).max(1).optional(),use_live_pids:j.boolean().optional()});t.post("/api/threads/sync-active",async i=>{let l=await i.req.json().catch(()=>null),p=M.safeParse(l);if(!p.success)return i.json({error:"invalid request body",details:p.error.format()},400);try{let m=await ra(p.data.project_id,{windowHours:p.data.window_hours,scoreThreshold:p.data.score_threshold,useLivePids:p.data.use_live_pids});if(p.data.mode==="preflight")return i.json({plan:m});let _=oa(m);return i.json({plan:m,result:_})}catch(m){return i.json({error:m.message},400)}}),t.get("/api/threads/:id/titles/preflight",i=>{let l=i.req.param("id"),p=te(l);if(!p)return i.json({error:"thread not found"},404);let m=f(),_=0;for(let E of p.edges)m.prepare("SELECT auto_title_source FROM sessions WHERE id = ?").get(E.session_id)?.auto_title_source==="agent"&&(_+=1);return i.json({total:p.edges.length,alreadyTitled:_,untitled:p.edges.length-_})}),t.post("/api/threads/:id/titles/generate",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>({})),m=te(l);if(!m)return i.json({error:"thread not found"},404);if(m.edges.length===0)return i.json({error:"thread has no sessions"},400);let _=Re(),E=p.model??_.model,T=mc({threadId:l,force:p.force??!1,model:E});return i.json({jobId:T})}),t.get("/api/jobs/:jobId/stream",i=>{let l=i.req.param("jobId");if(!dr(l))return i.json({error:"job not found"},404);let m=Number(i.req.header("Last-Event-ID")??0);return Me(i,async _=>{let E=!1,T=setInterval(()=>{E||_.writeSSE({event:"heartbeat",data:""}).catch(()=>{E=!0})},15e3);try{for await(let R of gc(l,m))if(E||(await _.writeSSE({id:String(R.id),event:R.kind,data:JSON.stringify(R.data)}),R.kind==="done"))break}finally{E=!0,clearInterval(T)}})}),t.get("/api/jobs/:jobId",i=>{let l=dr(i.req.param("jobId"));return l?i.json(l):i.json({error:"job not found"},404)}),t.delete("/api/jobs/:jobId",i=>_c(i.req.param("jobId"))?i.json({ok:!0}):i.json({error:"job not found or already done"},404)),t.post("/api/terminal/opened",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.shell_pid!="number"||typeof l.tab_name!="string")return i.json({error:"shell_pid and tab_name required"},400);let p=I.claimPidOwnership(l.shell_pid,l.extension_instance_id??null);if(p==="rejected")return i.json({ok:!0,rejected:!0,reason:"pid-owned-by-other-extension-instance",count:I.size()});let m=I.upsert({shell_pid:l.shell_pid,tab_name:l.tab_name,cwd:l.cwd??null,opened_at:l.opened_at??new Date().toISOString()});return i.json({ok:!0,ownership:p,count:I.size(),entry:m})}),t.post("/api/terminal/renamed",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.shell_pid!="number"||typeof l.tab_name!="string")return i.json({error:"shell_pid and tab_name required"},400);let p=I.claimPidOwnership(l.shell_pid,l.extension_instance_id??null);if(p==="rejected")return i.json({ok:!0,rejected:!0,reason:"pid-owned-by-other-extension-instance"});let m=I.rename(l.shell_pid,l.tab_name);if(!m)return i.json({error:"unknown shell_pid"},404);let _=lu(l.shell_pid,l.tab_name);return i.json({ok:!0,ownership:p,entry:m,propagated:_})}),t.post("/api/terminal/closed",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.shell_pid!="number")return i.json({error:"shell_pid required"},400);let p=I.remove(l.shell_pid);return i.json({ok:!0,removed:p,count:I.size()})}),t.post("/api/terminal/claude-started",async i=>{let l=await i.req.json().catch(()=>null);return!l||typeof l.shell_pid!="number"?i.json({error:"shell_pid required"},400):(I.pushPending({shell_pid:l.shell_pid,tab_name:typeof l.tab_name=="string"?l.tab_name:"",cwd:typeof l.cwd=="string"?l.cwd:null,started_at:typeof l.started_at=="string"?l.started_at:new Date().toISOString()}),i.json({ok:!0,pending:I.pendingSize()}))}),t.post("/api/terminal/output",async i=>{let l=await i.req.json().catch(()=>null);if(!l||typeof l.shell_pid!="number"||typeof l.text!="string")return i.json({error:"shell_pid and text required"},400);let p=l.text.length>8192?l.text.slice(-8192):l.text,m=typeof l.captured_at=="string"?l.captured_at:new Date().toISOString();return I.setOutputTail(l.shell_pid,p,m),i.json({ok:!0})}),t.post("/api/terminal/sync",async i=>{let l=await i.req.json().catch(()=>null);if(!l||!Array.isArray(l.terminals))return i.json({error:"terminals array required"},400);let p=new Map;for(let O of I.all())p.set(O.shell_pid,O.tab_name);let m=l.terminals.filter(O=>!!O&&typeof O.shell_pid=="number"&&typeof O.tab_name=="string").map(O=>({shell_pid:O.shell_pid,tab_name:O.tab_name,cwd:O.cwd??null,opened_at:O.opened_at??new Date().toISOString()})),_=l.extension_instance_id??null,E=[],T=m.filter(O=>{let F=I.claimPidOwnership(O.shell_pid,_);return E.push({shell_pid:O.shell_pid,ownership:F}),F!=="rejected"}),R=I.sync(T),A=0;for(let O of T){let F=p.get(O.shell_pid),U=I.get(O.shell_pid)?.tab_name??O.tab_name,V=!!U&&!re(U)&&!ne(U)?U:O.tab_name;F!==void 0&&F!==V&&(A+=lu(O.shell_pid,V))}let x=E.filter(O=>O.ownership==="rejected").length;x>0&&console.log(`[terminal/sync] dropped ${x} tab_name update(s), pid(s) owned by a different extension instance`);let N=await nS(),v={resolved:0,expired:0};try{v=Rc()}catch{}let C={rebound:0,ghosts:0,ambiguous:0};try{C=wc()}catch{}return _S(),i.json({ok:!0,count:I.size(),diff:R,propagated:A,live_sweep:N,deferred_resolved:v,rebound:C})}),t.get("/api/terminal/registry",i=>i.json({terminals:I.all(),count:I.size()})),t.get("/api/terminal/sessions/:shellPid",i=>{let l=i.req.param("shellPid"),p=Number(l);if(!Number.isInteger(p)||p<=0)return i.json({error:"shellPid must be a positive integer"},400);let m=I.sessionsFor(p);return i.json({shell_pid:p,sessions:m})}),t.get("/api/sessions/:id/linked-terminal",i=>{let l=i.req.param("id"),p=I.all().find(_=>I.sessionsFor(_.shell_pid).includes(l)),m=[];if(!p){let _=f().prepare("SELECT cwd, started_at FROM sessions WHERE id = ?").get(l);if(_?.cwd&&_.started_at){let E=Date.parse(_.started_at);if(Number.isFinite(E)){let T=_.cwd.replace(/\/+$/,""),R=300*1e3;for(let A of I.all()){if(!A.cwd||A.cwd.replace(/\/+$/,"")!==T||re(A.tab_name))continue;let x=Date.parse(A.opened_at),N=Date.parse(A.last_seen_at);!Number.isFinite(x)||!Number.isFinite(N)||x>E||N+R<E||m.push({shell_pid:A.shell_pid,tab_name:A.tab_name,cwd:A.cwd,opened_at:A.opened_at,last_seen_at:A.last_seen_at,reason:"time-overlap"})}m.sort((A,x)=>Date.parse(x.last_seen_at)-Date.parse(A.last_seen_at))}}}return p?i.json({linked:{shell_pid:p.shell_pid,tab_name:p.tab_name,cwd:p.cwd},suggested:[]}):i.json({linked:null,suggested:m})}),t.post("/api/sessions/:id/auto-relink",async i=>{let l=i.req.param("id");if(Te(l))return i.json({applied:!1,reason:"has-alias"});if(I.all().some(T=>I.sessionsFor(T.shell_pid).includes(l)))return i.json({applied:!1,reason:"already-linked"});let m=f().prepare("SELECT cwd, git_branch, started_at FROM sessions WHERE id = ?").get(l);if(!m?.cwd)return i.json({applied:!1,reason:"no-cwd"});let _=m.cwd.replace(/\/+$/,""),E=I.all().filter(T=>T.cwd&&T.cwd.replace(/\/+$/,"")===_&&!re(T.tab_name));if(E.length===1){let T=E[0],R=yt({sessionStartedAt:m.started_at??null,terminalOpenedAt:T.opened_at??null});if(!R.allowed)return i.json({applied:!1,reason:"temporal-guard",guard_reason:R.reason});let A=I.getOrigin(l),x=st({tabName:T.tab_name,origin:A??null,cwd:m.cwd??null,gitBranch:m.git_branch??null});return x?(me(l,x),I.linkSession(l,T.shell_pid),i.json({applied:!0,alias:x,linked_pid:T.shell_pid,linked_tab_name:T.tab_name,method:"cwd-singleton"})):i.json({applied:!1,reason:"no-usable-name"})}if(E.length>1){let T=await yc(l);if(T){let A=I.get(T.shell_pid),x=yt({sessionStartedAt:m.started_at??null,terminalOpenedAt:A?.opened_at??null});if(!x.allowed)return i.json({applied:!1,reason:"temporal-guard",guard_reason:x.reason});let N=I.getOrigin(l),v=st({tabName:T.tab_name,origin:N??null,cwd:m.cwd??null,gitBranch:m.git_branch??null});if(v)return me(l,v),I.linkSession(l,T.shell_pid),i.json({applied:!0,alias:v,linked_pid:T.shell_pid,linked_tab_name:T.tab_name,matched_fingerprints:T.matched_fingerprints,method:"content-match"})}let R=6e4;if(m.started_at){let A=Date.parse(m.started_at);if(Number.isFinite(A)){let x=E.filter(v=>yt({sessionStartedAt:m.started_at,terminalOpenedAt:v.opened_at??null}).allowed).map(v=>({t:v,gap:A-Date.parse(v.opened_at??"")})).filter(v=>Number.isFinite(v.gap)&&v.gap>=0&&v.gap<=R);if(x.length>=2)return i.json({applied:!1,reason:"ambiguous-temporal",candidate_count:x.length});let N=x[0];if(N){let v=I.getOrigin(l),C=st({tabName:N.t.tab_name,origin:v??null,cwd:m.cwd??null,gitBranch:m.git_branch??null});if(C)return me(l,C),I.linkSession(l,N.t.shell_pid),i.json({applied:!0,alias:C,linked_pid:N.t.shell_pid,linked_tab_name:N.t.tab_name,method:"closest-before-temporal",gap_ms:N.gap})}}}return i.json({applied:!1,reason:"ambiguous",candidate_count:E.length})}return i.json({applied:!1,reason:"no-candidates"})}),t.post("/api/sessions/:id/relink",async i=>{let l=i.req.param("id"),p=await i.req.json().catch(()=>null);if(p?.clear)return I.unlinkSession(l),ns(l),i.json({ok:!0,alias:null,linked_pid:null});if(!p||typeof p.shell_pid!="number")return i.json({error:"shell_pid required"},400);let m=I.get(p.shell_pid);if(!m)return i.json({error:"terminal not registered"},404);let _=I.getOrigin(l),E=f().prepare("SELECT cwd, git_branch FROM sessions WHERE id = ?").get(l),T=null,R=m.tab_name?.trim()??"";if(R&&!re(R)&&!ne(R))T=R;else if(R&&ne(R)){let A=tt(R);A&&!re(A)&&(T=A)}return T?(I.unlinkSession(l),me(l,T),i.json({ok:!0,alias:T,linked_pid:p.shell_pid,linked_tab_name:m.tab_name})):i.json({error:"terminal has no usable name, name the tab in your editor first, then retry the relink"},422)}),t.post("/api/sessions/:id/recorrelate",async i=>{let l=i.req.param("id"),p=f().prepare("SELECT file_path FROM sessions WHERE id = ?").get(l);if(!p?.file_path)return i.json({error:"session not found"},404);I.unlinkSession(l),ns(l),await Ms(p.file_path);let m=Te(l);return i.json({ok:!0,alias:m,linked_pid:I.all().find(_=>I.sessionsFor(_.shell_pid).includes(l))?.shell_pid??null})}),t.get("/api/paste-expand",async i=>{let l=i.req.query("session"),p=i.req.query("message"),m=i.req.query("path");if(!l||!p||!m)return i.json({error:"session, message and path are required"},400);let _=f(),E=_.prepare("SELECT rowid, content_text FROM messages WHERE uuid = ? AND session_id = ?").get(p,l);if(!E)return i.json({error:"message not found in session"},404);let T=m.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");if(!new RegExp(`\\[Pasted text #\\d+ \\+\\d+ lines\\]\\s*${T}`).test(E.content_text??""))return i.json({error:"path not referenced by this message"},403);let A=_.prepare(`SELECT content_text FROM messages
1799
1799
  WHERE session_id = ? AND rowid > ?
1800
- ORDER BY rowid ASC LIMIT 10`).all(l,E.rowid);for(let x of A){let N=x.content_text??"";if(N.includes("**Tool result**")&&N.includes(m))return i.json({source:"tool-result",content:N});if(/^\s*1\t/.test(N)&&N.length>200)return i.json({source:"tool-result",content:N})}try{let x=await Vb(m),N=Qb();if(!x.startsWith(N+"/")&&!x.startsWith(N+"\\"))return i.json({error:"path outside allowed root"},403);let v=[".ssh",".gnupg",".gpg",".aws",".kube",".docker",".password-store"],O=x.slice(N.length+1).split("/")[0].split("\\")[0];if(v.includes(O))return i.json({error:"path inside sensitive directory"},403);let F=await Kb(x),U=2*1024*1024;if(F.size>U)return i.json({error:"file too large",size:F.size,max:U},413);let Q=await zb(x,"utf8");return i.json({source:"disk",content:Q})}catch(x){return i.json({source:"missing",error:x.message})}}),t.get("/api/projects/:name/stats",i=>{let l=f(),p=i.req.param("name"),m=l.prepare(`SELECT
1800
+ ORDER BY rowid ASC LIMIT 10`).all(l,E.rowid);for(let x of A){let N=x.content_text??"";if(N.includes("**Tool result**")&&N.includes(m))return i.json({source:"tool-result",content:N});if(/^\s*1\t/.test(N)&&N.length>200)return i.json({source:"tool-result",content:N})}try{let x=await Qb(m),N=tS();if(!x.startsWith(N+"/")&&!x.startsWith(N+"\\"))return i.json({error:"path outside allowed root"},403);let v=[".ssh",".gnupg",".gpg",".aws",".kube",".docker",".password-store"],O=x.slice(N.length+1).split("/")[0].split("\\")[0];if(v.includes(O))return i.json({error:"path inside sensitive directory"},403);let F=await Vb(x),U=2*1024*1024;if(F.size>U)return i.json({error:"file too large",size:F.size,max:U},413);let Q=await Zb(x,"utf8");return i.json({source:"disk",content:Q})}catch(x){return i.json({source:"missing",error:x.message})}}),t.get("/api/projects/:name/stats",i=>{let l=f(),p=i.req.param("name"),m=l.prepare(`SELECT
1801
1801
  (SELECT COUNT(*) FROM sessions s JOIN projects p ON p.id=s.project_id WHERE p.name=? AND s.message_count > 2) AS sessions,
1802
1802
  (SELECT COALESCE(SUM(s.message_count), 0) FROM sessions s JOIN projects p ON p.id=s.project_id WHERE p.name=?) AS messages,
1803
1803
  (SELECT MIN(s.started_at) FROM sessions s JOIN projects p ON p.id=s.project_id WHERE p.name=? AND s.started_at IS NOT NULL) AS earliest,
@@ -1805,7 +1805,7 @@ ${o}
1805
1805
  JOIN projects p ON p.id = s.project_id
1806
1806
  WHERE p.name = ? AND s.git_branch IS NOT NULL
1807
1807
  ORDER BY s.git_branch
1808
- LIMIT 20`).all(p).map(E=>E.git_branch);return i.json({...m,branches:_})});function B(i){return i.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function se(i){if(!e)return i;let l=`<meta name="recall-token" content="${B(e)}" />`,p=i.indexOf("</head>");return p!==-1?i.slice(0,p)+l+i.slice(p):l+i}return cS?(t.use("/assets/*",cu({root:fo})),t.get("/favicon.svg",cu({root:fo})),t.get("/",i=>(i.header("cache-control","no-cache, no-store, must-revalidate"),i.header("pragma","no-cache"),i.header("expires","0"),i.html(se(hn(ho,"utf8"))))),t.get("*",i=>i.req.path.startsWith("/api/")?i.notFound():(i.header("cache-control","no-cache, no-store, must-revalidate"),i.header("pragma","no-cache"),i.header("expires","0"),i.html(se(hn(ho,"utf8")))))):t.get("/",i=>{let l=uu();return i.html(ti({projects:l.projects,sessions:l.sessions,messages:l.messages,port:Number(i.req.raw.headers.get("host")?.split(":")[1]??0),version:du}))}),t}function fS(){if(Qs(),!!He().heuristicEnabled){try{let{updated:e}=ic();e>0&&console.log(`[auto-title] backfilled heuristic title on ${e} sessions`)}catch(e){console.error("[auto-title] backfill failed:",e)}try{let{scanned:e,updated:t}=ac();t>0&&console.log(`[auto-title] refreshed templated heuristic title on ${t}/${e} sessions`)}catch(e){console.error("[auto-title] templated-title refresh failed:",e)}try{let{scanned:e,updated:t}=cc();t>0&&console.log(`[auto-title] refreshed recursive_meta title on ${t}/${e} sessions`)}catch(e){console.error("[auto-title] recursive_meta refresh failed:",e)}try{let{scanned:e,updated:t}=lc();t>0&&console.log(`[auto-title] canonicalized brand on ${t}/${e} session titles`)}catch(e){console.error("[auto-title] brand canonicalization failed:",e)}}}async function _u(e,t){let s=_S(t);return new Promise((n,r)=>{try{let o=Gb({fetch:s.fetch,port:e,hostname:"127.0.0.1"},()=>{n(o),setImmediate(()=>{try{fS()}catch(a){console.error("[daemon] startup maintenance crashed:",a)}})})}catch(o){r(o)}})}Z();H();import{watch as hS}from"chokidar";import{statSync as hu}from"node:fs";import{basename as ES}from"node:path";var bS=1500,So=new Map;function SS(e){let t=e.split("/"),s=t.findIndex(n=>n==="projects");return s===-1||s+1>=t.length?null:t[s+1]??null}async function TS(e){let t=0;try{t=hu(e).mtimeMs}catch{return}let s=SS(e);if(!s)return;let n=f(),r=n.prepare("SELECT id, file_mtime FROM sessions WHERE file_path = ? LIMIT 1").get(e);if(r&&r.file_mtime>=t)return;let o=new Map,a=null;for await(let k of yd(e)){let w=o.get(k.sessionId);if(w||(w={sessionId:k.sessionId,entries:[],earliest:null,latest:null,firstUser:null,users:0,assistants:0,cwd:null,branch:null,version:null},o.set(k.sessionId,w)),w.entries.push(k),k.timestamp&&((!w.earliest||k.timestamp<w.earliest)&&(w.earliest=k.timestamp),(!w.latest||k.timestamp>w.latest)&&(w.latest=k.timestamp)),k.role==="user"&&!k.isSidechain){if(w.users+=1,!w.firstUser&&k.contentText){let D=k.contentText.replace(/^(?:<[^>]+>[\s\S]*?<\/[^>]+>\s*)+/,"").trim();D&&!/^<local-command-caveat>/.test(D)&&(w.firstUser=qe(D).redacted.slice(0,2e3))}}else k.role==="assistant"&&!k.isSidechain&&(w.assistants+=1);!w.cwd&&k.cwd&&(w.cwd=k.cwd),!w.branch&&k.gitBranch&&(w.branch=k.gitBranch),!w.version&&k.version&&(w.version=k.version),!a&&k.cwd&&(a=k.cwd)}let c=a?ES(a)||a:s,d=a??s.replace(/^-/,"/").replace(/-/g,"/"),u=n.prepare(`INSERT INTO projects (encoded_path, decoded_path, name)
1808
+ LIMIT 20`).all(p).map(E=>E.git_branch);return i.json({...m,branches:_})});function B(i){return i.replace(/&/g,"&amp;").replace(/"/g,"&quot;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function se(i){if(!e)return i;let l=`<meta name="recall-token" content="${B(e)}" />`,p=i.indexOf("</head>");return p!==-1?i.slice(0,p)+l+i.slice(p):l+i}return dS?(t.use("/assets/*",cu({root:fo})),t.get("/favicon.svg",cu({root:fo})),t.get("/",i=>(i.header("cache-control","no-cache, no-store, must-revalidate"),i.header("pragma","no-cache"),i.header("expires","0"),i.html(se(hn(ho,"utf8"))))),t.get("*",i=>i.req.path.startsWith("/api/")?i.notFound():(i.header("cache-control","no-cache, no-store, must-revalidate"),i.header("pragma","no-cache"),i.header("expires","0"),i.html(se(hn(ho,"utf8")))))):t.get("/",i=>{let l=uu();return i.html(ti({projects:l.projects,sessions:l.sessions,messages:l.messages,port:Number(i.req.raw.headers.get("host")?.split(":")[1]??0),version:du}))}),t}function ES(){if(Qs(),!!He().heuristicEnabled){try{let{updated:e}=ic();e>0&&console.log(`[auto-title] backfilled heuristic title on ${e} sessions`)}catch(e){console.error("[auto-title] backfill failed:",e)}try{let{scanned:e,updated:t}=ac();t>0&&console.log(`[auto-title] refreshed templated heuristic title on ${t}/${e} sessions`)}catch(e){console.error("[auto-title] templated-title refresh failed:",e)}try{let{scanned:e,updated:t}=cc();t>0&&console.log(`[auto-title] refreshed recursive_meta title on ${t}/${e} sessions`)}catch(e){console.error("[auto-title] recursive_meta refresh failed:",e)}try{let{scanned:e,updated:t}=lc();t>0&&console.log(`[auto-title] canonicalized brand on ${t}/${e} session titles`)}catch(e){console.error("[auto-title] brand canonicalization failed:",e)}}}async function _u(e,t){let s=hS(t);return new Promise((n,r)=>{try{let o=Kb({fetch:s.fetch,port:e,hostname:"127.0.0.1"},()=>{n(o),setImmediate(()=>{try{ES()}catch(a){console.error("[daemon] startup maintenance crashed:",a)}})})}catch(o){r(o)}})}Z();H();import{watch as bS}from"chokidar";import{statSync as hu}from"node:fs";import{basename as SS}from"node:path";var TS=1500,So=new Map;function yS(e){let t=e.split("/"),s=t.findIndex(n=>n==="projects");return s===-1||s+1>=t.length?null:t[s+1]??null}async function wS(e){let t=0;try{t=hu(e).mtimeMs}catch{return}let s=yS(e);if(!s)return;let n=f(),r=n.prepare("SELECT id, file_mtime FROM sessions WHERE file_path = ? LIMIT 1").get(e);if(r&&r.file_mtime>=t)return;let o=new Map,a=null;for await(let k of yd(e)){let w=o.get(k.sessionId);if(w||(w={sessionId:k.sessionId,entries:[],earliest:null,latest:null,firstUser:null,users:0,assistants:0,cwd:null,branch:null,version:null},o.set(k.sessionId,w)),w.entries.push(k),k.timestamp&&((!w.earliest||k.timestamp<w.earliest)&&(w.earliest=k.timestamp),(!w.latest||k.timestamp>w.latest)&&(w.latest=k.timestamp)),k.role==="user"&&!k.isSidechain){if(w.users+=1,!w.firstUser&&k.contentText){let D=k.contentText.replace(/^(?:<[^>]+>[\s\S]*?<\/[^>]+>\s*)+/,"").trim();D&&!/^<local-command-caveat>/.test(D)&&(w.firstUser=qe(D).redacted.slice(0,2e3))}}else k.role==="assistant"&&!k.isSidechain&&(w.assistants+=1);!w.cwd&&k.cwd&&(w.cwd=k.cwd),!w.branch&&k.gitBranch&&(w.branch=k.gitBranch),!w.version&&k.version&&(w.version=k.version),!a&&k.cwd&&(a=k.cwd)}let c=a?SS(a)||a:s,d=a??s.replace(/^-/,"/").replace(/-/g,"/"),u=n.prepare(`INSERT INTO projects (encoded_path, decoded_path, name)
1809
1809
  VALUES (?, ?, ?)
1810
1810
  ON CONFLICT(encoded_path) DO UPDATE SET decoded_path = excluded.decoded_path, name = excluded.name
1811
1811
  RETURNING id`),g=n.prepare(`
@@ -1836,23 +1836,23 @@ ${o}
1836
1836
  VALUES (@uuid, @session_id, @parent_uuid, @type, @role, @timestamp,
1837
1837
  @is_sidechain, @content_text, @tool_names, @raw_json)
1838
1838
  ON CONFLICT(uuid) DO NOTHING
1839
- `),b=n.prepare("DELETE FROM messages WHERE session_id = ?"),S=new Date().toISOString();if(n.transaction(()=>{let{id:k}=u.get(s,d,c);for(let w of o.values()){g.run({id:w.sessionId,project_id:k,file_path:e,file_mtime:t,started_at:w.earliest,ended_at:w.latest,message_count:w.entries.length,user_message_count:w.users,assistant_message_count:w.assistants,first_user_message:w.firstUser,cwd:w.cwd,git_branch:w.branch,version:w.version,indexed_at:S}),b.run(w.sessionId);for(let D of w.entries)h.run(yS(D));wd(n,w.sessionId,w.entries),dn(n,w.sessionId)}})(),He().heuristicEnabled)for(let k of o.values()){let w=et(k.firstUser);w&&de(k.sessionId,w,"heuristic")}}function yS(e){let t=qe(e.contentText).redacted,s=qe(e.raw).redacted;return{uuid:e.uuid,session_id:e.sessionId,parent_uuid:e.parentUuid,type:e.type,role:e.role,timestamp:e.timestamp,is_sidechain:e.isSidechain?1:0,content_text:t,tool_names:e.toolNames.join(","),raw_json:s}}function fu(e){let t=So.get(e);t?.timer&&clearTimeout(t.timer);let s={timer:null};s.timer=setTimeout(()=>{So.delete(e),TS(e).then(async()=>{Ms(e);try{let r=f().prepare("SELECT id FROM sessions WHERE file_path = ?").all(e);for(let o of r){Sd(o.id),Fd(o.id);try{Ni(o.id)}catch(a){console.error("[watcher] auto-collections apply failed:",a)}}}catch(n){console.error("[watcher] semantic dispatch failed:",n)}}).catch(n=>{console.error(`[watcher] reindex failed for ${e}:`,n)})},bS),So.set(e,s)}function Eu(){let e=hS(Mo,{depth:4,ignoreInitial:!0,persistent:!0,awaitWriteFinish:{stabilityThreshold:500,pollInterval:200},ignored:t=>{if(t.endsWith(".jsonl"))return!1;try{if(hu(t).isDirectory())return!1}catch{}return!0}});return e.on("add",t=>t.endsWith(".jsonl")&&fu(t)),e.on("change",t=>t.endsWith(".jsonl")&&fu(t)),e}import{createServer as Su}from"node:net";function bu(e){return new Promise(t=>{let s=Su();s.once("error",()=>t(!1)),s.once("listening",()=>{s.close(()=>t(!0))}),s.listen(e,"127.0.0.1")})}async function Tu(){let e=new Set([3e3,3001,4200,5e3,5173,8e3,8080,8888,9e3]),t=51370;if(!e.has(t)&&await bu(t))return t;for(let s=0;s<50;s++){let n=49152+Math.floor(Math.random()*16383);if(!e.has(n)&&await bu(n))return n}return new Promise((s,n)=>{let r=Su();r.once("error",n),r.listen(0,"127.0.0.1",()=>{let o=r.address();if(o&&typeof o=="object"){let a=o.port;r.close(()=>s(a))}else r.close(),n(new Error("could not determine a free port"))})})}Z();import{existsSync as AS,readFileSync as iO,writeFileSync as wu,unlinkSync as xS}from"node:fs";import{join as yo}from"node:path";Z();import{randomBytes as wS}from"node:crypto";import{writeFileSync as RS,readFileSync as eO,existsSync as tO}from"node:fs";import{join as kS}from"node:path";var To=kS($,"daemon.token");function yu(){J();let e=wS(32).toString("hex");return RS(To,e,{encoding:"utf8",mode:384}),e}var Ru=yo($,"daemon.pid"),ku=yo($,"daemon.port"),dO=yo($,"daemon.log");function Au(e){J(),wu(Ru,JSON.stringify(e),{encoding:"utf8",mode:384}),wu(ku,String(e.port),{encoding:"utf8",mode:384})}function wo(){for(let e of[Ru,ku,To])if(AS(e))try{xS(e)}catch{}}H();H();import{createHash as NS}from"node:crypto";var OS=/\b0x[0-9a-fA-F]+\b/g,LS=/\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b/g,CS=/\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?\b/g,IS=/:\d+:\d+/g,vS=/\bline\s+\d+\b/gi,jS=/\bcolumn\s+\d+\b/gi,MS=/\b(?:pid|PID|process(?:\s+id)?)\s*[:=]?\s*\d+\b/gi,DS=/\b(?:port|:)\s*[:=]?\s*\d{2,5}\b/gi,FS=/\b\d{4,}\b/g,PS=/(['"`])[^'"`\n]{1,128}\1/g;function US(e){if(!e)return"";let t=String(e);return t=t.replace(OS,"<hex>"),t=t.replace(LS,"<uuid>"),t=t.replace(CS,"<ts>"),t=t.replace(IS,":<line>:<col>"),t=t.replace(vS,"line <n>"),t=t.replace(jS,"column <n>"),t=t.replace(MS,"pid <n>"),t=t.replace(DS,"port <n>"),t=t.replace(FS,"<num>"),t=t.replace(PS,"<arg>"),t=t.replace(/\s+/g," ").trim(),t.toLowerCase()}function $S(e){let t=(e.error_type??"unknown").toLowerCase().trim(),s=US(e.snippet??e.message_hash??""),n=`${t}|${s}`;return NS("sha256").update(n).digest("hex").slice(0,16)}function BS(e){let t=f(),s=["oi.bug_signatures IS NOT NULL"],n=[];e&&(s.push("p.name = ?"),n.push(e));let r=`WHERE ${s.join(" AND ")}`,o=t.prepare(`SELECT oi.session_id AS session_id,
1839
+ `),b=n.prepare("DELETE FROM messages WHERE session_id = ?"),S=new Date().toISOString();if(n.transaction(()=>{let{id:k}=u.get(s,d,c);for(let w of o.values()){g.run({id:w.sessionId,project_id:k,file_path:e,file_mtime:t,started_at:w.earliest,ended_at:w.latest,message_count:w.entries.length,user_message_count:w.users,assistant_message_count:w.assistants,first_user_message:w.firstUser,cwd:w.cwd,git_branch:w.branch,version:w.version,indexed_at:S}),b.run(w.sessionId);for(let D of w.entries)h.run(RS(D));wd(n,w.sessionId,w.entries),dn(n,w.sessionId)}})(),He().heuristicEnabled)for(let k of o.values()){let w=et(k.firstUser);w&&de(k.sessionId,w,"heuristic")}}function RS(e){let t=qe(e.contentText).redacted,s=qe(e.raw).redacted;return{uuid:e.uuid,session_id:e.sessionId,parent_uuid:e.parentUuid,type:e.type,role:e.role,timestamp:e.timestamp,is_sidechain:e.isSidechain?1:0,content_text:t,tool_names:e.toolNames.join(","),raw_json:s}}function fu(e){let t=So.get(e);t?.timer&&clearTimeout(t.timer);let s={timer:null};s.timer=setTimeout(()=>{So.delete(e),wS(e).then(async()=>{Ms(e);try{let r=f().prepare("SELECT id FROM sessions WHERE file_path = ?").all(e);for(let o of r){Sd(o.id),Fd(o.id);try{Ni(o.id)}catch(a){console.error("[watcher] auto-collections apply failed:",a)}}}catch(n){console.error("[watcher] semantic dispatch failed:",n)}}).catch(n=>{console.error(`[watcher] reindex failed for ${e}:`,n)})},TS),So.set(e,s)}function Eu(){let e=bS(Mo,{depth:4,ignoreInitial:!0,persistent:!0,awaitWriteFinish:{stabilityThreshold:500,pollInterval:200},ignored:t=>{if(t.endsWith(".jsonl"))return!1;try{if(hu(t).isDirectory())return!1}catch{}return!0}});return e.on("add",t=>t.endsWith(".jsonl")&&fu(t)),e.on("change",t=>t.endsWith(".jsonl")&&fu(t)),e}import{createServer as Su}from"node:net";function bu(e){return new Promise(t=>{let s=Su();s.once("error",()=>t(!1)),s.once("listening",()=>{s.close(()=>t(!0))}),s.listen(e,"127.0.0.1")})}async function Tu(){let e=new Set([3e3,3001,4200,5e3,5173,8e3,8080,8888,9e3]),t=51370;if(!e.has(t)&&await bu(t))return t;for(let s=0;s<50;s++){let n=49152+Math.floor(Math.random()*16383);if(!e.has(n)&&await bu(n))return n}return new Promise((s,n)=>{let r=Su();r.once("error",n),r.listen(0,"127.0.0.1",()=>{let o=r.address();if(o&&typeof o=="object"){let a=o.port;r.close(()=>s(a))}else r.close(),n(new Error("could not determine a free port"))})})}Z();import{existsSync as NS,readFileSync as cO,writeFileSync as wu,unlinkSync as OS}from"node:fs";import{join as yo}from"node:path";Z();import{randomBytes as kS}from"node:crypto";import{writeFileSync as AS,readFileSync as sO,existsSync as nO}from"node:fs";import{join as xS}from"node:path";var To=xS($,"daemon.token");function yu(){J();let e=kS(32).toString("hex");return AS(To,e,{encoding:"utf8",mode:384}),e}var Ru=yo($,"daemon.pid"),ku=yo($,"daemon.port"),pO=yo($,"daemon.log");function Au(e){J(),wu(Ru,JSON.stringify(e),{encoding:"utf8",mode:384}),wu(ku,String(e.port),{encoding:"utf8",mode:384})}function wo(){for(let e of[Ru,ku,To])if(NS(e))try{OS(e)}catch{}}H();H();import{createHash as LS}from"node:crypto";var CS=/\b0x[0-9a-fA-F]+\b/g,IS=/\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b/g,vS=/\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z?\b/g,jS=/:\d+:\d+/g,MS=/\bline\s+\d+\b/gi,DS=/\bcolumn\s+\d+\b/gi,FS=/\b(?:pid|PID|process(?:\s+id)?)\s*[:=]?\s*\d+\b/gi,PS=/\b(?:port|:)\s*[:=]?\s*\d{2,5}\b/gi,US=/\b\d{4,}\b/g,$S=/(['"`])[^'"`\n]{1,128}\1/g;function BS(e){if(!e)return"";let t=String(e);return t=t.replace(CS,"<hex>"),t=t.replace(IS,"<uuid>"),t=t.replace(vS,"<ts>"),t=t.replace(jS,":<line>:<col>"),t=t.replace(MS,"line <n>"),t=t.replace(DS,"column <n>"),t=t.replace(FS,"pid <n>"),t=t.replace(PS,"port <n>"),t=t.replace(US,"<num>"),t=t.replace($S,"<arg>"),t=t.replace(/\s+/g," ").trim(),t.toLowerCase()}function HS(e){let t=(e.error_type??"unknown").toLowerCase().trim(),s=BS(e.snippet??e.message_hash??""),n=`${t}|${s}`;return LS("sha256").update(n).digest("hex").slice(0,16)}function WS(e){let t=f(),s=["oi.bug_signatures IS NOT NULL"],n=[];e&&(s.push("p.name = ?"),n.push(e));let r=`WHERE ${s.join(" AND ")}`,o=t.prepare(`SELECT oi.session_id AS session_id,
1840
1840
  p.name AS project,
1841
1841
  s.started_at AS started_at,
1842
1842
  oi.bug_signatures AS bug_signatures
1843
1843
  FROM session_output_index oi
1844
1844
  LEFT JOIN sessions s ON s.id = oi.session_id
1845
1845
  LEFT JOIN projects p ON p.id = s.project_id
1846
- ${r}`).all(...n),a=[];for(let c of o){if(!c.bug_signatures)continue;let d=[];try{let u=JSON.parse(c.bug_signatures);Array.isArray(u)&&(d=u)}catch{continue}for(let u of d){if(!u||typeof u!="object"||!(u.snippet??"").trim())continue;let h=$S(u);a.push({session_id:c.session_id,project:c.project,started_at:c.started_at,signature:u,fingerprint:h})}}return a}function HS(e){let t=new Map;for(let n of e){let r=t.get(n.fingerprint);r||(r=[],t.set(n.fingerprint,r)),r.push(n)}let s=[];for(let[n,r]of t){let o=new Set,a=[];for(let g of r)o.has(g.session_id)||(o.add(g.session_id),a.push(g));let c=[...a].sort((g,h)=>{let b=g.started_at??"",S=h.started_at??"";return b&&S?b<S?-1:b>S?1:0:b?-1:S?1:0}),d=c.find(g=>g.started_at),u=[...c].reverse().find(g=>g.started_at);s.push({fingerprint:n,example_message:a[0].signature.snippet??a[0].signature.message_hash??"",members:a,first_seen_at:d?.started_at??new Date().toISOString(),last_seen_at:u?.started_at??new Date().toISOString()})}return s}function WS(e,t){if(e.length!==t.length)return 0;let s=0,n=0,r=0;for(let a=0;a<e.length;a++)s+=e[a]*t[a],n+=e[a]*e[a],r+=t[a]*t[a];let o=Math.sqrt(n)*Math.sqrt(r);return o>0?s/o:0}function qS(e){let{records:t,vectors:s,epsilon:n,minPts:r}=e,o=t.length;if(o===0)return[];let a=[];for(let g=0;g<o;g++){let h=[];for(let b=0;b<o;b++){if(g===b)continue;1-WS(s[g],s[b])<=n&&h.push(b)}a.push(h)}let c=new Array(o).fill(!1),d=new Array(o).fill(-1),u=[];for(let g=0;g<o;g++){if(c[g])continue;c[g]=!0;let h=a[g];if(h.length<r)continue;let b=u.length;u.push({members:[t[g]]}),d[g]=b;let S=[...h];for(;S.length>0;){let y=S.shift();if(!c[y]&&(c[y]=!0,a[y].length>=r))for(let k of a[y])(!c[k]||d[k]===-1)&&S.push(k);d[y]===-1&&(d[y]=b,u[b].members.push(t[y]))}}return u}async function JS(e,t,s,n){if(e.length===0)return[];let r=e.map(d=>{let u=d.signature.snippet??d.signature.message_hash??"";return`${d.signature.error_type??""}: ${u}`.trim()}),o=await t(r);if(o.length!==e.length)throw new Error(`embedder returned ${o.length} vectors for ${e.length} inputs`);let a=qS({records:e,vectors:o,epsilon:s,minPts:n}),c=[];for(let d of a){if(d.members.length===0)continue;let u=new Set,g=[];for(let w of d.members)u.has(w.session_id)||(u.add(w.session_id),g.push(w));if(g.length===0)continue;let b=`sem:${[...g.map(w=>w.fingerprint)].sort()[0]}`,S=[...g].sort((w,D)=>{let L=w.started_at??"",X=D.started_at??"";return L<X?-1:L>X?1:0}),y=S.find(w=>w.started_at),k=[...S].reverse().find(w=>w.started_at);c.push({fingerprint:b,example_message:g[0].signature.snippet??g[0].signature.message_hash??"",members:g,first_seen_at:y?.started_at??new Date().toISOString(),last_seen_at:k?.started_at??new Date().toISOString()})}return c}function xu(e,t){let s={clusters_created:0,clusters_merged:0,members_added:0,cluster_ids:[]};for(let n of e){if(n.members.length<t)continue;let r=Ga(n.fingerprint),o=Ya(n.fingerprint),a=n.members.map(u=>u.session_id).filter(u=>!o.has(u));if(r.length===0){let u=$a({signature_hash:n.fingerprint,example_message:n.example_message.slice(0,256),member_session_ids:n.members.map(g=>g.session_id),first_seen_at:n.first_seen_at,last_seen_at:n.last_seen_at});s.clusters_created+=1,s.members_added+=u.members.length,s.cluster_ids.push(u.cluster.id);continue}if(a.length===0){s.cluster_ids.push(r[0].id);continue}let c=r[0],d=Ha(c.id,a);d.added>0&&(s.clusters_merged+=1,s.members_added+=d.added),s.cluster_ids.push(c.id)}return s}async function Nu(e={}){let t=Math.max(2,Math.floor(e.minClusterSize??3)),s=Math.max(1,Math.min(5e3,Math.floor(e.limit??1e3))),n=e.semanticEpsilon??.15,r=Math.max(1,Math.floor(e.semanticMinPts??1)),o=BS(e.project),a=new Set(o.map(L=>L.session_id)),c=HS(o),d=[],u=!1;if(e.semantic){let L=e.embedder??null;if(!L)try{L=await YS()}catch(X){let B=(X instanceof Error?X.message:String(X)).split(`
1846
+ ${r}`).all(...n),a=[];for(let c of o){if(!c.bug_signatures)continue;let d=[];try{let u=JSON.parse(c.bug_signatures);Array.isArray(u)&&(d=u)}catch{continue}for(let u of d){if(!u||typeof u!="object"||!(u.snippet??"").trim())continue;let h=HS(u);a.push({session_id:c.session_id,project:c.project,started_at:c.started_at,signature:u,fingerprint:h})}}return a}function qS(e){let t=new Map;for(let n of e){let r=t.get(n.fingerprint);r||(r=[],t.set(n.fingerprint,r)),r.push(n)}let s=[];for(let[n,r]of t){let o=new Set,a=[];for(let g of r)o.has(g.session_id)||(o.add(g.session_id),a.push(g));let c=[...a].sort((g,h)=>{let b=g.started_at??"",S=h.started_at??"";return b&&S?b<S?-1:b>S?1:0:b?-1:S?1:0}),d=c.find(g=>g.started_at),u=[...c].reverse().find(g=>g.started_at);s.push({fingerprint:n,example_message:a[0].signature.snippet??a[0].signature.message_hash??"",members:a,first_seen_at:d?.started_at??new Date().toISOString(),last_seen_at:u?.started_at??new Date().toISOString()})}return s}function JS(e,t){if(e.length!==t.length)return 0;let s=0,n=0,r=0;for(let a=0;a<e.length;a++)s+=e[a]*t[a],n+=e[a]*e[a],r+=t[a]*t[a];let o=Math.sqrt(n)*Math.sqrt(r);return o>0?s/o:0}function XS(e){let{records:t,vectors:s,epsilon:n,minPts:r}=e,o=t.length;if(o===0)return[];let a=[];for(let g=0;g<o;g++){let h=[];for(let b=0;b<o;b++){if(g===b)continue;1-JS(s[g],s[b])<=n&&h.push(b)}a.push(h)}let c=new Array(o).fill(!1),d=new Array(o).fill(-1),u=[];for(let g=0;g<o;g++){if(c[g])continue;c[g]=!0;let h=a[g];if(h.length<r)continue;let b=u.length;u.push({members:[t[g]]}),d[g]=b;let S=[...h];for(;S.length>0;){let y=S.shift();if(!c[y]&&(c[y]=!0,a[y].length>=r))for(let k of a[y])(!c[k]||d[k]===-1)&&S.push(k);d[y]===-1&&(d[y]=b,u[b].members.push(t[y]))}}return u}async function GS(e,t,s,n){if(e.length===0)return[];let r=e.map(d=>{let u=d.signature.snippet??d.signature.message_hash??"";return`${d.signature.error_type??""}: ${u}`.trim()}),o=await t(r);if(o.length!==e.length)throw new Error(`embedder returned ${o.length} vectors for ${e.length} inputs`);let a=XS({records:e,vectors:o,epsilon:s,minPts:n}),c=[];for(let d of a){if(d.members.length===0)continue;let u=new Set,g=[];for(let w of d.members)u.has(w.session_id)||(u.add(w.session_id),g.push(w));if(g.length===0)continue;let b=`sem:${[...g.map(w=>w.fingerprint)].sort()[0]}`,S=[...g].sort((w,D)=>{let L=w.started_at??"",X=D.started_at??"";return L<X?-1:L>X?1:0}),y=S.find(w=>w.started_at),k=[...S].reverse().find(w=>w.started_at);c.push({fingerprint:b,example_message:g[0].signature.snippet??g[0].signature.message_hash??"",members:g,first_seen_at:y?.started_at??new Date().toISOString(),last_seen_at:k?.started_at??new Date().toISOString()})}return c}function xu(e,t){let s={clusters_created:0,clusters_merged:0,members_added:0,cluster_ids:[]};for(let n of e){if(n.members.length<t)continue;let r=Ga(n.fingerprint),o=Ya(n.fingerprint),a=n.members.map(u=>u.session_id).filter(u=>!o.has(u));if(r.length===0){let u=$a({signature_hash:n.fingerprint,example_message:n.example_message.slice(0,256),member_session_ids:n.members.map(g=>g.session_id),first_seen_at:n.first_seen_at,last_seen_at:n.last_seen_at});s.clusters_created+=1,s.members_added+=u.members.length,s.cluster_ids.push(u.cluster.id);continue}if(a.length===0){s.cluster_ids.push(r[0].id);continue}let c=r[0],d=Ha(c.id,a);d.added>0&&(s.clusters_merged+=1,s.members_added+=d.added),s.cluster_ids.push(c.id)}return s}async function Nu(e={}){let t=Math.max(2,Math.floor(e.minClusterSize??3)),s=Math.max(1,Math.min(5e3,Math.floor(e.limit??1e3))),n=e.semanticEpsilon??.15,r=Math.max(1,Math.floor(e.semanticMinPts??1)),o=WS(e.project),a=new Set(o.map(L=>L.session_id)),c=qS(o),d=[],u=!1;if(e.semantic){let L=e.embedder??null;if(!L)try{L=await zS()}catch(X){let B=(X instanceof Error?X.message:String(X)).split(`
1847
1847
  `)[0];console.warn(`[bug-pattern] --semantic requested but the embedder is unavailable: ${B}
1848
- Falling back to exact-match-only clustering. Run \`recall semantic install\` to enable the semantic pass.`),u=!0}if(L){let X=[];for(let M of c)M.members.length===1&&X.push(M.members[0]);X.length>=2&&(d=await JS(X,L,n,r))}}let g=c.filter(L=>L.members.length>=t),h=d.filter(L=>L.members.length>=t),b=xu(g,t),S=xu(h,t),y=[...b.cluster_ids,...S.cluster_ids],k=Array.from(new Set(y)),w=[];if(k.length>0){let L=f(),X=k.map(()=>"?").join(","),M=L.prepare(`SELECT * FROM bug_pattern_clusters
1848
+ Falling back to exact-match-only clustering. Run \`recall semantic install\` to enable the semantic pass.`),u=!0}if(L){let X=[];for(let M of c)M.members.length===1&&X.push(M.members[0]);X.length>=2&&(d=await GS(X,L,n,r))}}let g=c.filter(L=>L.members.length>=t),h=d.filter(L=>L.members.length>=t),b=xu(g,t),S=xu(h,t),y=[...b.cluster_ids,...S.cluster_ids],k=Array.from(new Set(y)),w=[];if(k.length>0){let L=f(),X=k.map(()=>"?").join(","),M=L.prepare(`SELECT * FROM bug_pattern_clusters
1849
1849
  WHERE id IN (${X})
1850
1850
  ORDER BY occurrence_count DESC, last_seen_at DESC
1851
- LIMIT ?`).all(...k,s);for(let B of M)w.push({id:B.id,signature_hash:B.signature_hash,example_message:B.example_message,occurrence_count:B.occurrence_count,first_seen_at:B.first_seen_at,last_seen_at:B.last_seen_at,resolved_in_session_id:B.resolved_in_session_id,fix_summary:B.fix_summary})}return{progress:{total_sessions:a.size,total_signatures:o.length,exact_match_groups:g.length,semantic_groups:h.length,clusters_created:b.clusters_created+S.clusters_created,clusters_merged:b.clusters_merged+S.clusters_merged,members_added:b.members_added+S.members_added,semantic_skipped:u},clusters:w}}var XS=async()=>{let{embed:e,loadEmbedder:t,getEmbedderStatus:s}=await Promise.resolve().then(()=>(ot(),Xc));return s().loaded||await t(),e},GS=XS;async function YS(){return GS()}H();var Ro={citation:"same-project",similar:"same-project",skill_track:"same-project",bug_pattern:"cross-project",wiki_link:"cross-project",temporal_proximity:"same-project"},KS=2,zS=.25,VS=5,ZS=60,QS=25;function Sn(e){return e.trim().toLowerCase()}function eT(e){let t=new Set;for(let s of e.files_written)t.add(`file:${Sn(s)}`);for(let s of e.brands_mentioned)t.add(`brand:${Sn(s)}`);for(let s of e.terms_introduced)t.add(`term:${Sn(s)}`);for(let s of e.plan_ids_referenced)t.add(`plan:${Sn(s)}`);return t}function tT(e){if(!Number.isFinite(e)||e<0)return 1;let t=Math.exp(-e/ZS);return Math.max(.2,t)}function sT(e,t){if(!e||!t)return 0;let s=Date.parse(e),n=Date.parse(t);return!Number.isFinite(s)||!Number.isFinite(n)?0:Math.abs(n-s)/(1e3*60*60*24)}function nT(e){let t=Be(e);return t?{session_id:t.session_id,files_written:t.files_written,brands_mentioned:t.brands_mentioned,terms_introduced:t.terms_introduced.map(s=>s.term),plan_ids_referenced:t.plan_ids_referenced}:null}function rT(e){return f().prepare(`SELECT s.id AS id, s.project_id AS project_id, s.started_at AS started_at
1851
+ LIMIT ?`).all(...k,s);for(let B of M)w.push({id:B.id,signature_hash:B.signature_hash,example_message:B.example_message,occurrence_count:B.occurrence_count,first_seen_at:B.first_seen_at,last_seen_at:B.last_seen_at,resolved_in_session_id:B.resolved_in_session_id,fix_summary:B.fix_summary})}return{progress:{total_sessions:a.size,total_signatures:o.length,exact_match_groups:g.length,semantic_groups:h.length,clusters_created:b.clusters_created+S.clusters_created,clusters_merged:b.clusters_merged+S.clusters_merged,members_added:b.members_added+S.members_added,semantic_skipped:u},clusters:w}}var YS=async()=>{let{embed:e,loadEmbedder:t,getEmbedderStatus:s}=await Promise.resolve().then(()=>(ot(),Xc));return s().loaded||await t(),e},KS=YS;async function zS(){return KS()}H();var Ro={citation:"same-project",similar:"same-project",skill_track:"same-project",bug_pattern:"cross-project",wiki_link:"cross-project",temporal_proximity:"same-project"},VS=2,ZS=.25,QS=5,eT=60,tT=25;function Sn(e){return e.trim().toLowerCase()}function sT(e){let t=new Set;for(let s of e.files_written)t.add(`file:${Sn(s)}`);for(let s of e.brands_mentioned)t.add(`brand:${Sn(s)}`);for(let s of e.terms_introduced)t.add(`term:${Sn(s)}`);for(let s of e.plan_ids_referenced)t.add(`plan:${Sn(s)}`);return t}function nT(e){if(!Number.isFinite(e)||e<0)return 1;let t=Math.exp(-e/eT);return Math.max(.2,t)}function rT(e,t){if(!e||!t)return 0;let s=Date.parse(e),n=Date.parse(t);return!Number.isFinite(s)||!Number.isFinite(n)?0:Math.abs(n-s)/(1e3*60*60*24)}function oT(e){let t=Be(e);return t?{session_id:t.session_id,files_written:t.files_written,brands_mentioned:t.brands_mentioned,terms_introduced:t.terms_introduced.map(s=>s.term),plan_ids_referenced:t.plan_ids_referenced}:null}function iT(e){return f().prepare(`SELECT s.id AS id, s.project_id AS project_id, s.started_at AS started_at
1852
1852
  FROM sessions s
1853
1853
  JOIN session_output_index oi ON oi.session_id = s.id
1854
1854
  WHERE s.project_id = ?
1855
- ORDER BY COALESCE(s.started_at, ''), s.id`).all(e)}function oT(e,t){let s=new Map,n=new Map,r=new Map;for(let o of e){r.set(o.id,o.started_at);let a=t.get(o.id);if(!a)continue;let c=eT(a);if(c.size!==0){n.set(o.id,c);for(let d of c){let u=s.get(d);u?u.push(o.id):s.set(d,[o.id])}}}return{posting:s,vocab:n,startedAt:r}}function iT(e,t){let s=t.vocab.get(e),n=t.startedAt.get(e)??null;if(!s||!n)return[];let r=new Map;for(let a of s){let c=t.posting.get(a);if(c)for(let d of c){if(d===e)continue;let u=t.startedAt.get(d);if(!u||u>=n)continue;let g=r.get(d);g?g.push(a):r.set(d,[a])}}let o=[];for(let[a,c]of r){let d=c.length;if(d<KS)continue;let u=t.startedAt.get(a)??null,g=sT(n,u),h=tT(g),b=Math.min(1,d/VS*h);if(b<zS)continue;let S=c.slice(0,12);o.push({target_session_id:a,matched_terms:S,overlap:d,days_apart:Math.round(g*10)/10,recency:Math.round(h*1e3)/1e3,confidence:Math.round(b*1e3)/1e3})}return o.sort((a,c)=>c.confidence-a.confidence),o.slice(0,QS)}async function Ou(e){if(Ro.citation!=="same-project")throw new Error("citation policy unexpectedly not same-project \u2014 refusing to run inference");let t=rT(e.projectId),s=new Map;for(let a of t){let c=nT(a.id);c&&s.set(a.id,c)}let n=oT(t,s),r={total_sessions:t.length,processed_sessions:0,suggestions_created:0,suggestions_skipped_existing:0,current_session_id:null};e.onProgress?.({...r});let o=[];for(let a of t){if(e.signal?.aborted)break;r.current_session_id=a.id,e.onProgress?.({...r});let c=iT(a.id,n);for(let d of c)try{let u=Ct({source_session_id:a.id,target_session_id:d.target_session_id,link_type:"citation",confidence:d.confidence,evidence:{matched_terms:d.matched_terms,overlap_count:d.overlap,recency:d.recency,days_apart:d.days_apart},inferred_by:"L2"});o.push(u.id),r.suggestions_created+=1}catch(u){console.error("[citation-inference] createSuggestion failed:",u)}r.processed_sessions+=1,e.onProgress?.({...r})}return r.current_session_id=null,e.onProgress?.({...r}),{progress:r,suggestion_ids:o}}H();var aT=/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/gi,cT=[/\bv\d+\.\d+(?:\.[A-Za-z]+)?\b/g,/\bPhase\s+[A-Ha-h]\b/g,/\bL\d+\b/g,/MASTER-PLAN-[A-Za-z-]+/g],lT=.95,dT=.85;var ko=50;function uT(e){if(!e)return[];let t=new Set,s=[],n=e.match(aT);if(!n)return s;for(let r of n){let o=r.toLowerCase();if(!t.has(o)&&(t.add(o),s.push(o),s.length>=ko))break}return s}function pT(e){if(!e)return[];let t=new Set,s=[];for(let n of cT){n.lastIndex=0;let r=e.match(n);if(r){for(let o of r){let a=o.trim().toLowerCase().replace(/\s+/g," ");if(!(!a||a.length>64)&&!t.has(a)&&(t.add(a),s.push(a),s.length>=ko))break}if(s.length>=ko)break}}return s}function Lu(e){let t=f();return typeof e=="number"?t.prepare("SELECT id, project_id FROM sessions WHERE project_id = ?").all(e):t.prepare("SELECT id, project_id FROM sessions").all()}function Cu(e){let t=f();return typeof e=="number"?t.prepare(`SELECT m.uuid AS message_uuid, m.session_id, m.content_text,
1855
+ ORDER BY COALESCE(s.started_at, ''), s.id`).all(e)}function aT(e,t){let s=new Map,n=new Map,r=new Map;for(let o of e){r.set(o.id,o.started_at);let a=t.get(o.id);if(!a)continue;let c=sT(a);if(c.size!==0){n.set(o.id,c);for(let d of c){let u=s.get(d);u?u.push(o.id):s.set(d,[o.id])}}}return{posting:s,vocab:n,startedAt:r}}function cT(e,t){let s=t.vocab.get(e),n=t.startedAt.get(e)??null;if(!s||!n)return[];let r=new Map;for(let a of s){let c=t.posting.get(a);if(c)for(let d of c){if(d===e)continue;let u=t.startedAt.get(d);if(!u||u>=n)continue;let g=r.get(d);g?g.push(a):r.set(d,[a])}}let o=[];for(let[a,c]of r){let d=c.length;if(d<VS)continue;let u=t.startedAt.get(a)??null,g=rT(n,u),h=nT(g),b=Math.min(1,d/QS*h);if(b<ZS)continue;let S=c.slice(0,12);o.push({target_session_id:a,matched_terms:S,overlap:d,days_apart:Math.round(g*10)/10,recency:Math.round(h*1e3)/1e3,confidence:Math.round(b*1e3)/1e3})}return o.sort((a,c)=>c.confidence-a.confidence),o.slice(0,tT)}async function Ou(e){if(Ro.citation!=="same-project")throw new Error("citation policy unexpectedly not same-project \u2014 refusing to run inference");let t=iT(e.projectId),s=new Map;for(let a of t){let c=oT(a.id);c&&s.set(a.id,c)}let n=aT(t,s),r={total_sessions:t.length,processed_sessions:0,suggestions_created:0,suggestions_skipped_existing:0,current_session_id:null};e.onProgress?.({...r});let o=[];for(let a of t){if(e.signal?.aborted)break;r.current_session_id=a.id,e.onProgress?.({...r});let c=cT(a.id,n);for(let d of c)try{let u=Ct({source_session_id:a.id,target_session_id:d.target_session_id,link_type:"citation",confidence:d.confidence,evidence:{matched_terms:d.matched_terms,overlap_count:d.overlap,recency:d.recency,days_apart:d.days_apart},inferred_by:"L2"});o.push(u.id),r.suggestions_created+=1}catch(u){console.error("[citation-inference] createSuggestion failed:",u)}r.processed_sessions+=1,e.onProgress?.({...r})}return r.current_session_id=null,e.onProgress?.({...r}),{progress:r,suggestion_ids:o}}H();var lT=/[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}/gi,dT=[/\bv\d+\.\d+(?:\.[A-Za-z]+)?\b/g,/\bPhase\s+[A-Ha-h]\b/g,/\bL\d+\b/g,/MASTER-PLAN-[A-Za-z-]+/g],uT=.95,pT=.85;var ko=50;function mT(e){if(!e)return[];let t=new Set,s=[],n=e.match(lT);if(!n)return s;for(let r of n){let o=r.toLowerCase();if(!t.has(o)&&(t.add(o),s.push(o),s.length>=ko))break}return s}function gT(e){if(!e)return[];let t=new Set,s=[];for(let n of dT){n.lastIndex=0;let r=e.match(n);if(r){for(let o of r){let a=o.trim().toLowerCase().replace(/\s+/g," ");if(!(!a||a.length>64)&&!t.has(a)&&(t.add(a),s.push(a),s.length>=ko))break}if(s.length>=ko)break}}return s}function Lu(e){let t=f();return typeof e=="number"?t.prepare("SELECT id, project_id FROM sessions WHERE project_id = ?").all(e):t.prepare("SELECT id, project_id FROM sessions").all()}function Cu(e){let t=f();return typeof e=="number"?t.prepare(`SELECT m.uuid AS message_uuid, m.session_id, m.content_text,
1856
1856
  s.project_id
1857
1857
  FROM messages m
1858
1858
  JOIN sessions s ON s.id = m.session_id
@@ -1865,9 +1865,9 @@ ${o}
1865
1865
  JOIN sessions s ON s.id = m.session_id
1866
1866
  WHERE m.is_sidechain = 0
1867
1867
  AND m.content_text IS NOT NULL
1868
- AND length(m.content_text) > 0`).all()}function mT(e){let t=f(),s=typeof e=="number"?"WHERE s.project_id = ?":"",n=typeof e=="number"?[e]:[];return t.prepare(`SELECT oi.session_id AS session_id,
1868
+ AND length(m.content_text) > 0`).all()}function _T(e){let t=f(),s=typeof e=="number"?"WHERE s.project_id = ?":"",n=typeof e=="number"?[e]:[];return t.prepare(`SELECT oi.session_id AS session_id,
1869
1869
  s.project_id AS project_id,
1870
1870
  oi.plan_ids_referenced AS plan_ids_json
1871
1871
  FROM session_output_index oi
1872
1872
  JOIN sessions s ON s.id = oi.session_id
1873
- ${s}`).all(...n)}function gT(e){if(!e)return[];try{let t=JSON.parse(e);if(Array.isArray(t))return t.filter(s=>typeof s=="string")}catch{}return[]}function Iu(e={}){if(Ro.citation!=="same-project")throw new Error("citation policy unexpectedly not same-project");let t=Lu(e.projectId),s=new Set(t.map(o=>o.id)),n=new Map;for(let o of t)n.set(o.id,o.project_id);let r=0;for(let o of Cu(e.projectId)){if(e.signal?.aborted)break;let a=uT(o.content_text);if(a.length===0)continue;let c=n.get(o.session_id);if(c!==void 0)for(let d of a){if(d===o.session_id)continue;let u=n.get(d);if(!(u===void 0&&!s.has(d))&&!(u!==void 0&&c!==void 0&&u!==c))try{Ct({source_session_id:o.session_id,target_session_id:d,link_type:"citation",confidence:lT,evidence:{matched_uuid:d,source_message_uuid:o.message_uuid,scanner:"uuid-ref"},inferred_by:"L1"}),r+=1}catch{}}}return{created:r}}function vu(e={}){let t=mT(e.projectId);if(t.length===0)return{created:0};let s=new Map;for(let c of t){let d=gT(c.plan_ids_json);for(let u of d){let g=u.trim().toLowerCase();if(!g)continue;let h=s.get(g);h?h.push({id:c.session_id,project_id:c.project_id}):s.set(g,[{id:c.session_id,project_id:c.project_id}])}}if(s.size===0)return{created:0};let n=Lu(e.projectId),r=new Map;for(let c of n)r.set(c.id,c.project_id);let o=0,a=new Map;for(let c of Cu(e.projectId)){if(e.signal?.aborted)break;let d=pT(c.content_text);if(d.length===0)continue;let u=r.get(c.session_id);if(u!==void 0)for(let g of d){let h=s.get(g);if(h)for(let b of h){if(b.id===c.session_id||b.project_id!==u)continue;let S=a.get(c.session_id);S||(S=new Map,a.set(c.session_id,S));let y=S.get(b.id);y||(y=new Set,S.set(b.id,y)),y.add(g)}}}for(let[c,d]of a)for(let[u,g]of d)try{Ct({source_session_id:c,target_session_id:u,link_type:"citation",confidence:dT,evidence:{matched_plan_ids:Array.from(g).slice(0,12),scanner:"plan-ref"},inferred_by:"L1"}),o+=1}catch{}return{created:o}}ge();var le="[daemon:inference]",Ao=!1,xo=!1,No=!1,Oo=!1,Lo=!1,ju=0,Co=!1,Io=!1;function _T(){return f().prepare("SELECT id, name FROM projects").all()}async function Mu(){if(Ao)return;Ao=!0;let e=Date.now();try{let s=(await Nu({minClusterSize:2})).progress;(s.clusters_created||s.clusters_merged||s.members_added)&&console.log(`${le} bug-patterns: created=${s.clusters_created} merged=${s.clusters_merged} members_added=${s.members_added} (${Date.now()-e}ms)`)}catch(t){console.error(`${le} bug-patterns failed:`,t)}finally{Ao=!1}}async function Du(){if(xo)return;xo=!0;let e=Date.now();try{let t=0,s=0;for(let n of _T())try{let r=await Ou({projectId:n.id});t+=r.progress.suggestions_created,s+=1}catch(r){console.error(`${le} citations failed for project "${n.name}":`,r)}t>0&&console.log(`${le} citations: ${t} suggestion(s) across ${s} project(s) (${Date.now()-e}ms)`)}catch(t){console.error(`${le} citations failed:`,t)}finally{xo=!1}}function Fu(){if(No)return;No=!0;let e=Date.now();try{let t=Iu({}),s=vu({});t.created+s.created>0&&console.log(`${le} l1: uuid=${t.created} plan=${s.created} (${Date.now()-e}ms)`)}catch(t){console.error(`${le} l1 failed:`,t)}finally{No=!1}}async function Pu(){if(Oo)return;let e=ce();if(!e.enabled||e.backfillPaused)return;Oo=!0;let t=Date.now();try{let s=await cn({limit:25});s.processed>0&&console.log(`${le} backfill: processed=${s.processed} ok=${s.ok} failed=${s.failed} (${Date.now()-t}ms)`)}catch(s){console.error(`${le} backfill failed:`,s)}finally{Oo=!1}}async function Uu(){if(Lo)return;let e=ce();if(!e.autoExtractEnabled)return;let t=e.autoExtractIntervalMinutes*60*1e3;if(Date.now()-ju<t)return;if(!oe()){Co||(console.log(`${le} auto-extract: claude CLI not on PATH \u2014 pausing nibbler (will retry; install Claude Code or run \`recall semantic auto-extract off\` to silence)`),Co=!0);return}if(Co=!1,!await Go().catch(()=>!1)){Io||(console.log(`${le} auto-extract: Pro license required \u2014 pausing nibbler (run \`recall semantic auto-extract off\` to silence; upgrade unlocks)`),Io=!0);return}Io=!1,Lo=!0,ju=Date.now();let n=Date.now();try{let r=e.autoExtractBatchSize,{eligible:o}=rt({limit:r});if(o.length===0)return;let a=0,c=0,d=0,u=0;for(let g of o){let h=await Sr(g.id,{model:We});h.ok?a+=1:h.skipped||(c+=1),h.usage?.input_tokens&&(d+=h.usage.input_tokens),h.usage?.output_tokens&&(u+=h.usage.output_tokens)}console.log(`${le} auto-extract: processed=${o.length} ok=${a} failed=${c} tokens=${d}+${u} (${Date.now()-n}ms)`)}catch(r){console.error(`${le} auto-extract failed:`,r)}finally{Lo=!1}}function $u(){let g=[],h=[];return g.push(setTimeout(()=>{Mu()},9e4)),h.push(setInterval(()=>{Mu()},18e5)),g.push(setTimeout(()=>{Du()},18e4)),h.push(setInterval(()=>{Du()},36e5)),g.push(setTimeout(()=>Fu(),12e4)),h.push(setInterval(()=>Fu(),18e5)),g.push(setTimeout(()=>{Pu()},24e4)),h.push(setInterval(()=>{Pu()},9e5)),g.push(setTimeout(()=>{Uu()},3e5)),h.push(setInterval(()=>{Uu()},9e5)),console.log(`${le} scheduled: bug-patterns (30m), citations (60m), l1 (30m), backfill (15m, when enabled), auto-extract (60m, when enabled)`),{startupTimers:g,intervalTimers:h,stop:()=>{for(let b of g)clearTimeout(b);for(let b of h)clearInterval(b)}}}var fT=360*60*1e3,hT=60*1e3,ET=1440*60*1e3,bT=300*1e3,ST=300*1e3,TT=10*1e3,yT=1440*60*1e3,wT=30*1e3,RT=500;async function kT(){let e=await Tu(),t=yu(),s=await _u(e,t);Au({pid:process.pid,port:e,startedAt:new Date().toISOString()});let n=Eu(),r=()=>{try{_s()}catch(L){console.error("[daemon] suggestion scan failed:",L)}},o=setTimeout(r,hT),a=setInterval(r,fT),c=()=>{try{let L=I.reapStaleLinks();(L.pruned_pids||L.pruned_sessions)&&console.log(`[daemon] reaper: pruned ${L.pruned_pids} pid${L.pruned_pids===1?"":"s"}, ${L.pruned_sessions} session link${L.pruned_sessions===1?"":"s"}`)}catch(L){console.error("[daemon] stale-link reaper failed:",L)}},d=setTimeout(c,bT),u=setInterval(c,ET),g=()=>{try{let L=I.gcDeadPids();(L.pruned_pids||L.pruned_sessions)&&console.log(`[daemon] dead-pid gc: pruned ${L.pruned_pids} pid${L.pruned_pids===1?"":"s"}, ${L.pruned_sessions} session link${L.pruned_sessions===1?"":"s"}`)}catch(L){console.error("[daemon] dead-pid gc failed:",L)}},h=setTimeout(g,TT),b=setInterval(g,ST),S=()=>{Xo().then(L=>{L.ran&&L.revoked&&console.log(`[daemon] license check: REVOKED${L.reason?` (${L.reason})`:""}`)}).catch(L=>{console.error("[daemon] license check failed:",L)})},y=setTimeout(S,wT),k=setInterval(S,yT),w=$u(),D=L=>{console.log(`[daemon] received ${L}, shutting down`),clearTimeout(o),clearInterval(a),clearTimeout(d),clearInterval(u),clearTimeout(h),clearInterval(b),clearTimeout(y),clearInterval(k),w.stop(),n.close(),s.close(),wo(),process.exit(0)};process.on("SIGTERM",()=>D("SIGTERM")),process.on("SIGINT",()=>D("SIGINT")),process.on("SIGHUP",()=>D("SIGHUP")),console.log(`[daemon] ready on http://127.0.0.1:${e} pid=${process.pid}`),setTimeout(()=>{Ds().then(L=>{console.log(`[daemon] boot sweep: scanned ${L.scanned} live claude(s), linked ${L.linked}, renamed ${L.renamed}, ambiguous_cwd ${L.ambiguous_cwd}`)}).catch(L=>{console.error("[daemon] boot sweep failed:",L)})},RT)}kT().catch(e=>{console.error("[daemon] fatal:",e),wo(),process.exit(1)});
1873
+ ${s}`).all(...n)}function fT(e){if(!e)return[];try{let t=JSON.parse(e);if(Array.isArray(t))return t.filter(s=>typeof s=="string")}catch{}return[]}function Iu(e={}){if(Ro.citation!=="same-project")throw new Error("citation policy unexpectedly not same-project");let t=Lu(e.projectId),s=new Set(t.map(o=>o.id)),n=new Map;for(let o of t)n.set(o.id,o.project_id);let r=0;for(let o of Cu(e.projectId)){if(e.signal?.aborted)break;let a=mT(o.content_text);if(a.length===0)continue;let c=n.get(o.session_id);if(c!==void 0)for(let d of a){if(d===o.session_id)continue;let u=n.get(d);if(!(u===void 0&&!s.has(d))&&!(u!==void 0&&c!==void 0&&u!==c))try{Ct({source_session_id:o.session_id,target_session_id:d,link_type:"citation",confidence:uT,evidence:{matched_uuid:d,source_message_uuid:o.message_uuid,scanner:"uuid-ref"},inferred_by:"L1"}),r+=1}catch{}}}return{created:r}}function vu(e={}){let t=_T(e.projectId);if(t.length===0)return{created:0};let s=new Map;for(let c of t){let d=fT(c.plan_ids_json);for(let u of d){let g=u.trim().toLowerCase();if(!g)continue;let h=s.get(g);h?h.push({id:c.session_id,project_id:c.project_id}):s.set(g,[{id:c.session_id,project_id:c.project_id}])}}if(s.size===0)return{created:0};let n=Lu(e.projectId),r=new Map;for(let c of n)r.set(c.id,c.project_id);let o=0,a=new Map;for(let c of Cu(e.projectId)){if(e.signal?.aborted)break;let d=gT(c.content_text);if(d.length===0)continue;let u=r.get(c.session_id);if(u!==void 0)for(let g of d){let h=s.get(g);if(h)for(let b of h){if(b.id===c.session_id||b.project_id!==u)continue;let S=a.get(c.session_id);S||(S=new Map,a.set(c.session_id,S));let y=S.get(b.id);y||(y=new Set,S.set(b.id,y)),y.add(g)}}}for(let[c,d]of a)for(let[u,g]of d)try{Ct({source_session_id:c,target_session_id:u,link_type:"citation",confidence:pT,evidence:{matched_plan_ids:Array.from(g).slice(0,12),scanner:"plan-ref"},inferred_by:"L1"}),o+=1}catch{}return{created:o}}ge();var le="[daemon:inference]",Ao=!1,xo=!1,No=!1,Oo=!1,Lo=!1,ju=0,Co=!1,Io=!1;function hT(){return f().prepare("SELECT id, name FROM projects").all()}async function Mu(){if(Ao)return;Ao=!0;let e=Date.now();try{let s=(await Nu({minClusterSize:2})).progress;(s.clusters_created||s.clusters_merged||s.members_added)&&console.log(`${le} bug-patterns: created=${s.clusters_created} merged=${s.clusters_merged} members_added=${s.members_added} (${Date.now()-e}ms)`)}catch(t){console.error(`${le} bug-patterns failed:`,t)}finally{Ao=!1}}async function Du(){if(xo)return;xo=!0;let e=Date.now();try{let t=0,s=0;for(let n of hT())try{let r=await Ou({projectId:n.id});t+=r.progress.suggestions_created,s+=1}catch(r){console.error(`${le} citations failed for project "${n.name}":`,r)}t>0&&console.log(`${le} citations: ${t} suggestion(s) across ${s} project(s) (${Date.now()-e}ms)`)}catch(t){console.error(`${le} citations failed:`,t)}finally{xo=!1}}function Fu(){if(No)return;No=!0;let e=Date.now();try{let t=Iu({}),s=vu({});t.created+s.created>0&&console.log(`${le} l1: uuid=${t.created} plan=${s.created} (${Date.now()-e}ms)`)}catch(t){console.error(`${le} l1 failed:`,t)}finally{No=!1}}async function Pu(){if(Oo)return;let e=ce();if(!e.enabled||e.backfillPaused)return;Oo=!0;let t=Date.now();try{let s=await cn({limit:25});s.processed>0&&console.log(`${le} backfill: processed=${s.processed} ok=${s.ok} failed=${s.failed} (${Date.now()-t}ms)`)}catch(s){console.error(`${le} backfill failed:`,s)}finally{Oo=!1}}async function Uu(){if(Lo)return;let e=ce();if(!e.autoExtractEnabled)return;let t=e.autoExtractIntervalMinutes*60*1e3;if(Date.now()-ju<t)return;if(!oe()){Co||(console.log(`${le} auto-extract: claude CLI not on PATH \u2014 pausing nibbler (will retry; install Claude Code or run \`recall semantic auto-extract off\` to silence)`),Co=!0);return}if(Co=!1,!await Go().catch(()=>!1)){Io||(console.log(`${le} auto-extract: Pro license required \u2014 pausing nibbler (run \`recall semantic auto-extract off\` to silence; upgrade unlocks)`),Io=!0);return}Io=!1,Lo=!0,ju=Date.now();let n=Date.now();try{let r=e.autoExtractBatchSize,{eligible:o}=rt({limit:r});if(o.length===0)return;let a=0,c=0,d=0,u=0;for(let g of o){let h=await Sr(g.id,{model:We});h.ok?a+=1:h.skipped||(c+=1),h.usage?.input_tokens&&(d+=h.usage.input_tokens),h.usage?.output_tokens&&(u+=h.usage.output_tokens)}console.log(`${le} auto-extract: processed=${o.length} ok=${a} failed=${c} tokens=${d}+${u} (${Date.now()-n}ms)`)}catch(r){console.error(`${le} auto-extract failed:`,r)}finally{Lo=!1}}function $u(){let g=[],h=[];return g.push(setTimeout(()=>{Mu()},9e4)),h.push(setInterval(()=>{Mu()},18e5)),g.push(setTimeout(()=>{Du()},18e4)),h.push(setInterval(()=>{Du()},36e5)),g.push(setTimeout(()=>Fu(),12e4)),h.push(setInterval(()=>Fu(),18e5)),g.push(setTimeout(()=>{Pu()},24e4)),h.push(setInterval(()=>{Pu()},9e5)),g.push(setTimeout(()=>{Uu()},3e5)),h.push(setInterval(()=>{Uu()},9e5)),console.log(`${le} scheduled: bug-patterns (30m), citations (60m), l1 (30m), backfill (15m, when enabled), auto-extract (60m, when enabled)`),{startupTimers:g,intervalTimers:h,stop:()=>{for(let b of g)clearTimeout(b);for(let b of h)clearInterval(b)}}}var ET=360*60*1e3,bT=60*1e3,ST=1440*60*1e3,TT=300*1e3,yT=300*1e3,wT=10*1e3,RT=1440*60*1e3,kT=30*1e3,AT=500;async function xT(){let e=await Tu(),t=yu(),s=await _u(e,t);Au({pid:process.pid,port:e,startedAt:new Date().toISOString()});let n=Eu(),r=()=>{try{_s()}catch(L){console.error("[daemon] suggestion scan failed:",L)}},o=setTimeout(r,bT),a=setInterval(r,ET),c=()=>{try{let L=I.reapStaleLinks();(L.pruned_pids||L.pruned_sessions)&&console.log(`[daemon] reaper: pruned ${L.pruned_pids} pid${L.pruned_pids===1?"":"s"}, ${L.pruned_sessions} session link${L.pruned_sessions===1?"":"s"}`)}catch(L){console.error("[daemon] stale-link reaper failed:",L)}},d=setTimeout(c,TT),u=setInterval(c,ST),g=()=>{try{let L=I.gcDeadPids();(L.pruned_pids||L.pruned_sessions)&&console.log(`[daemon] dead-pid gc: pruned ${L.pruned_pids} pid${L.pruned_pids===1?"":"s"}, ${L.pruned_sessions} session link${L.pruned_sessions===1?"":"s"}`)}catch(L){console.error("[daemon] dead-pid gc failed:",L)}},h=setTimeout(g,wT),b=setInterval(g,yT),S=()=>{Xo().then(L=>{L.ran&&L.revoked&&console.log(`[daemon] license check: REVOKED${L.reason?` (${L.reason})`:""}`)}).catch(L=>{console.error("[daemon] license check failed:",L)})},y=setTimeout(S,kT),k=setInterval(S,RT),w=$u(),D=L=>{console.log(`[daemon] received ${L}, shutting down`),clearTimeout(o),clearInterval(a),clearTimeout(d),clearInterval(u),clearTimeout(h),clearInterval(b),clearTimeout(y),clearInterval(k),w.stop(),n.close(),s.close(),wo(),process.exit(0)};process.on("SIGTERM",()=>D("SIGTERM")),process.on("SIGINT",()=>D("SIGINT")),process.on("SIGHUP",()=>D("SIGHUP")),console.log(`[daemon] ready on http://127.0.0.1:${e} pid=${process.pid}`),setTimeout(()=>{Ds().then(L=>{console.log(`[daemon] boot sweep: scanned ${L.scanned} live claude(s), linked ${L.linked}, renamed ${L.renamed}, ambiguous_cwd ${L.ambiguous_cwd}`)}).catch(L=>{console.error("[daemon] boot sweep failed:",L)})},AT)}xT().catch(e=>{console.error("[daemon] fatal:",e),wo(),process.exit(1)});