@chatpanel/events 0.226.0 → 0.290.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.
Files changed (69) hide show
  1. package/agent-kinds.js +1 -0
  2. package/agent-run-hint.js +1 -0
  3. package/browser-relay.js +1 -0
  4. package/bug-report.js +11 -0
  5. package/citations.js +5 -5
  6. package/client-prefs.js +1 -1
  7. package/context-attachments.js +9 -9
  8. package/decide-by-model.js +2 -0
  9. package/default-skills.js +1 -1
  10. package/drive-backup.js +1 -0
  11. package/feature-map.js +1 -1
  12. package/fetched.js +2 -2
  13. package/history-search.js +8 -0
  14. package/index.js +1 -1
  15. package/kokoro-text.js +1 -0
  16. package/library.js +10 -10
  17. package/link-connect.js +1 -0
  18. package/link-noise.js +1 -0
  19. package/link-protocol.js +1 -0
  20. package/mcp-manager.js +1 -1
  21. package/memory-capture.js +1 -0
  22. package/memory.js +2 -2
  23. package/message-links.js +3 -0
  24. package/model-entries.js +1 -1
  25. package/model-list.js +1 -0
  26. package/monitor-profile.js +1 -1
  27. package/monitor-turn.js +12 -0
  28. package/note-merge.js +13 -0
  29. package/notes-grounding.js +6 -0
  30. package/offers.js +3 -0
  31. package/package.json +81 -1
  32. package/page-guard.js +4 -0
  33. package/prefetch.js +2 -2
  34. package/prompted-tools.js +18 -0
  35. package/provider-presets.js +1 -0
  36. package/qr.js +1 -0
  37. package/recall.js +7 -0
  38. package/record-entities.js +2 -0
  39. package/reply-focus.js +1 -0
  40. package/request-options.js +1 -0
  41. package/research.js +16 -0
  42. package/sandbox-policy.js +1 -1
  43. package/search-modes.js +9 -0
  44. package/settings-registry.js +1 -1
  45. package/sideline.js +13 -11
  46. package/site-pages.js +1 -0
  47. package/skill-creator.js +8 -0
  48. package/skill-scan.js +3 -3
  49. package/slash-commands.js +1 -1
  50. package/sources-retrieval.js +3 -3
  51. package/speak-stream.js +1 -1
  52. package/speaker-cluster.js +1 -0
  53. package/stitch.js +24 -0
  54. package/stream-reveal.cases.json +348 -0
  55. package/stream-reveal.js +1 -0
  56. package/text-index.js +1 -0
  57. package/titles.js +4 -4
  58. package/voice-barge-in.cases.json +1 -0
  59. package/voice-brain.js +1 -0
  60. package/voice-channel-gate.cases.json +1 -0
  61. package/voice-channel-gate.js +1 -0
  62. package/voice-intents.js +2 -2
  63. package/voice-loop.js +1 -1
  64. package/voice-speaker.js +1 -1
  65. package/voice-vad.js +1 -1
  66. package/weather-tool.js +1 -1
  67. package/weather.js +2 -2
  68. package/web-research.js +7 -0
  69. package/web-search-tool.js +3 -3
@@ -0,0 +1 @@
1
+ const s=new Set(["model","messages","stream","tools","tool_choice","system"]),i=new Set(["authorization","content-type","anthropic-version","anthropic-dangerous-direct-browser-access","x-api-key"]);function a(t,r="JSON"){const n=String(t||"").trim();if(!n)return{};let e;try{e=JSON.parse(n)}catch(o){throw new Error(`${r} is not valid JSON: ${o.message}`)}if(!e||typeof e!="object"||Array.isArray(e))throw new Error(`${r} must be a JSON object.`);return e}function c(t={}){const r={};for(const[n,e]of Object.entries(t||{}))!n||s.has(n)||(r[n]=e);return r}function f(t={},r={}){return{...c(r),...t}}function y(t={}){const r={};for(const[n,e]of Object.entries(t||{})){const o=String(n||"").trim();!o||i.has(o.toLowerCase())||e==null||e===""||(r[o]=String(e))}return r}function u(t){return!t||typeof t!="object"||Array.isArray(t)||Object.keys(t).length===0?"":JSON.stringify(t,null,2)}export{f as mergeExtraBody,a as parseJsonObject,u as prettyJson,c as sanitizeExtraBody,y as sanitizeExtraHeaders};
package/research.js ADDED
@@ -0,0 +1,16 @@
1
+ import{lexicalPlan as te}from"./recall.js";import{namesIn as ne}from"./search-modes.js";import{recall as se}from"./memory.js";import{splitForWindow as oe,partChars as O,partPrompt as ie,mapParts as re,reduceNotes as ae}from"./stitch.js";import{normalizeCorrections as le}from"./search-modes.js";import{defineSchema as U,describeSchema as z,parseStructured as B}from"./structured.js";const R=Object.freeze({rounds:2,records:3,chunks:10,chunkChars:2800,parts:16,ms:6e4}),q=[["meeting",/\b(meetings?|calls?|standups?|syncs?|1:1s?|one[- ]on[- ]ones?)\b/i],["note",/\bnotes?\b/i],["chat",/\b(chats?|conversations?)\b/i]],G=/\b(last|latest|most recent|recent|newest)\b/i,H=/\b(first|earliest|oldest)\b/i,ce=/\b(how many|how often|number of|count)\b/i,de=/\b(list|which|all (?:my|the)|every)\b/i,W=/\b(summari[sz]e|summary|what (?:was|is) it about|what was (?:discussed|said)|details?|in detail|tell me more|go deeper|deeper|explain|what did (?:we|they|he|she|i) (?:say|discuss|decide|talk about))\b/i,K=/^(?:meet|meets|met|meeting|talk|talked|speak|spoke|chat|chatted|most|often|frequent|frequently|common|top|people|attendees?|participants?|contacts?|shows?|attends?|joins?|busiest|months?|weeks?|days?|monthly|weekly|daily|per|each|every|count|many|much)$/i,Q=/\b(?:who (?:do|did|have) i (?:meet|met|talk(?:ed)?|speak|spoke|chat(?:ted)?)(?: with| to)?(?: the)? most(?: often)?|most (?:frequent|common|met) (?:people|attendees|participants|contacts)|top (?:people|attendees|participants|contacts)|who (?:shows up|attends|joins) (?:the )?most)\b/i,J=/\b(?:per|by|each|every|a) (month|week|day)\b|\b(monthly|weekly|daily)\b|\bwhich (month|week|day)\b|\bbusiest (month|week|day)\b/i,he=/\b(who (?:else )?(?:was|were) (?:in|at|on|there)|who (?:joined|attended|spoke|was there)|attendees?|participants?|who (?:else )?(?:is|are) in)\b/i,ue=/\b(even later|later than that|more recent|after that|newer)\b/i,me=/\b(even earlier|earlier than that|before that|older)\b/i,pe=/^\s*(?:no\b|nope\b|not that\b|it\b|that\b|this\b|and\b|also\b|what about\b|how about\b|what was it\b|summari[sz]e\b|more\b|even\b)/i,fe=/\b(\d{4}-\d{2}-\d{2}|(?:jan|feb|mar|apr|may|jun|jul|aug|sep|sept|oct|nov|dec)[a-z]*\.? \d{1,2}(?:st|nd|rd|th)?,? \d{4}|\d{1,2}(?:st|nd|rd|th)? (?:jan|feb|mar|apr|may|jun|jul|aug|sep|sept|oct|nov|dec)[a-z]* \d{4})\b/i;function we(n){const s=fe.exec(String(n||""));if(!s)return 0;const h=Date.parse(s[1].replace(/(\d)(st|nd|rd|th)/i,"$1").replace(/\bsept\b/i,"sep"));return Number.isFinite(h)?h:0}function ge(n,{previous:s=null,knownNames:h=[],now:a=Date.now()}={}){const i=String(n||""),c=i.toLowerCase(),o=te(i,{now:a}),p=h.filter(m=>m&&new RegExp(`\\b${String(m).toLowerCase().replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\b`).test(c)),k=[...new Set([...ne(i),...p])],u=q.find(([,m])=>m.test(i))?.[0]||"",E=new Set(k.flatMap(m=>m.toLowerCase().split(/\s+/))),e={intent:Q.test(i)||J.test(i)?"group":he.test(i)?"people":ce.test(i)?"count":G.test(i)?"latest":H.test(i)?"earliest":de.test(i)?"list":W.test(i)?"detail":"find",kind:u,names:k,terms:o.terms.filter(m=>!E.has(m)&&!q.some(([,v])=>v.test(m))&&!G.test(m)&&!H.test(m)),sort:"relevance",limit:8,since:o.sinceAt||0,after:0,before:0,readFull:W.test(i),followUp:!1,target:null,group:""};if(e.intent==="group"){const m=J.exec(i),v=m?(m[1]||m[2]||m[3]||m[4]||"").toLowerCase().replace(/ly$/,"").replace(/^dai$/,"day"):"";e.group=Q.test(i)?"person":v,e.group==="person"&&(e.kind=e.kind||"meeting"),e.terms=e.terms.filter($=>!K.test($)),e.limit=5}e.intent==="latest"&&(e.sort="newest",e.limit=5),e.intent==="earliest"&&(e.sort="oldest",e.limit=5),e.intent==="list"&&(e.limit=12),e.intent==="people"&&(e.sort="newest",e.limit=3,e.readFull=!0,e.kind=e.kind||"meeting");const w=s?.plan;if(w&&(pe.test(i)||/\b(?:the|that|this) (?:meeting|call|chat|note)\b/i.test(i)||!k.length&&!u&&i.trim().split(/\s+/).length<=6)){e.followUp=!0,e.kind=e.kind||w.kind,e.names=e.names.length?e.names:w.names,e.terms=e.terms.length?e.terms:w.terms;const m=we(s.answer);ue.test(i)?(e.intent="latest",e.sort="newest",e.after=m?m+864e5:w.after,e.limit=5):me.test(i)?(e.intent="earliest",e.sort="newest",e.before=m||w.before,e.limit=5):e.intent==="people"?e.target=s.top||null:e.readFull||/\b(it|that|this)\b/i.test(i)?(e.intent="detail",e.readFull=!0,e.target=s.top||null,e.sort=w.sort):(e.intent=w.intent,e.sort=w.sort)}return(e.intent==="latest"||e.intent==="earliest")&&(e.readFull=e.readFull||!1),e}function be(n,s,h){if(n.length<=h)return n;const a=[...s.names||[],...s.terms||[]].map(c=>String(c).toLowerCase()).filter(c=>c.length>2),i=n.filter(c=>a.some(o=>c.text.toLowerCase().includes(o)));return[...i,...n.filter(c=>!i.includes(c))].slice(0,h).sort((c,o)=>c.at-o.at)}function ye(n,s,{chunkChars:h=R.chunkChars,max:a=R.chunks}={}){const i=String(n||""),c=[];for(let u=0;u<i.length;u+=h)c.push({at:u,text:i.slice(u,u+h)});const o=[...s.names||[],...s.terms||[]].map(u=>String(u).toLowerCase()).filter(u=>u.length>2);if(!o.length||c.length<=a)return c.slice(0,a);const p=c.filter(u=>o.some(E=>u.text.toLowerCase().includes(E))),k=c.filter(u=>!p.includes(u));return[...p,...k].slice(0,a).sort((u,E)=>u.at-E.at)}const L=n=>n?new Date(n).toISOString().slice(0,10):"",ke=new RegExp("^\\s*(?:\\[\\s*\\d{1,2}:\\d{2}(?::\\d{2})?(?:\\s*[AaPp]\\.?[Mm]\\.?)?\\s*\\]\\s*|\\(?\\d{1,2}:\\d{2}(?::\\d{2})?(?:\\s*[AaPp]\\.?[Mm]\\.?)?\\)?\\s+)?(?:\\*\\*)?(\\p{Lu}[\\p{L}\\p{N}'. -]{0,48}?(?:\\s*[([][^()[\\]\\n]{1,40}[)\\]])?)(?:\\*\\*)?\\s*(?:_?\\(\\d{1,2}:\\d{2}(?::\\d{2})?\\)_?)?\\s*:\\s+\\S","gmu"),$e=/^(https?|note|notes|summary|topics|action items|key moments|decisions?|risks?|questions?|meeting|transcript|date|time|duration|title|subject|agenda|location|attendees|participants|speakers?|recording|source|link|url|tags?|status|owner|next steps)$/i;function Se(n){const s=new Map;for(const h of String(n||"").matchAll(ke)){const a=h[1].replace(/\s*[([]\d{1,2}:\d{2}(?::\d{2})?[)\]]$/,"").trim(),i=a.replace(/\s*[([][^()[\]]*[)\]]$/,"").trim();if(!i||$e.test(i))continue;const c=i.toLowerCase(),o=s.get(c);o?o.lines++:s.set(c,{name:a,lines:1})}return[...s.values()].sort((h,a)=>a.lines-h.lines)}function xe(n,s=""){if(!Array.isArray(n))return null;const h=o=>String(o||"").replace(/\s*[([][^()[\]]*[)\]]$/,"").trim().toLowerCase(),a=String(s||"").trim().toLowerCase(),i=o=>!!a&&(o===a||!a.includes(" ")&&o.split(/\s+/)[0]===a),c=new Map;for(const o of n){const p=h(o?.key);if(!p||i(p))continue;const k=c.get(p);k?k.count+=Number(o.count)||0:c.set(p,{key:String(o.key).trim(),count:Number(o.count)||0})}return[...c.values()].sort((o,p)=>p.count-o.count||o.key.localeCompare(p.key))}const V=U({name:"frame",purpose:"what kind of question about the person's own records this is",fields:{intent:{type:"enum",values:["find","latest","earliest","count","group","people","list","detail"],required:!0,describe:"latest/earliest: the most recent or first one; count: how many; group: counts per person or per month/week/day; people: who was there; list: several items; detail: what one said or was about; find: anything else"},kind:{type:"enum",values:["","meeting","note","chat"],describe:"the kind of record asked about, or empty"},names:{type:"string[]",max:3,describe:"people named in the question, exactly as written; empty when none"},group:{type:"enum",values:["","person","month","week","day"],describe:"for group: what to count by; else empty"}}});function Ce(n){return`Classify this question about the person's own chats, notes and meetings.
2
+
3
+ ${z(V)}
4
+
5
+ Question: ${String(n).slice(0,400)}`}const Y=U({name:"evidence",purpose:"whether what was found answers the question",fields:{answered:{type:"enum",values:["yes","partly","no"],required:!0,describe:"yes when the found text answers the question, partly when it answers some of it, no when it does not"},missing:{type:"string",max:120,describe:"when not yes: a few search words (names, topics, dates) for what is missing; else empty"}}});function Ee(n,s,{maxChars:h=6e3}={}){const a=String(s||"");return`Does the text found below answer the question? Judge only from the text.
6
+
7
+ ${z(Y)}
8
+
9
+ Question: ${String(n).slice(0,400)}
10
+
11
+ ---
12
+ ${a.length>h?`${a.slice(0,h)}
13
+ …`:a}`}function Ae(n){const s={meeting:"meetings",note:"notes",chat:"chats"}[n.kind]||"records",h=n.names.length?` naming ${n.names.join(" and ")}`:"",a=n.terms.length?` about ${n.terms.slice(0,6).join(", ")}`:"",i=[n.after?`after ${L(n.after-864e5)}`:"",n.before?`before ${L(n.before)}`:"",n.since?`since ${L(n.since)}`:""].filter(Boolean).join(", "),c=n.sort==="newest"?", newest first":n.sort==="oldest"?", oldest first":", most relevant first";return`${s}${h}${a}${i?` ${i}`:""}${c}`}async function Pe(n,{query:s,readText:h,searchModes:a=null,complete:i=null,memories:c=[],previous:o=null,knownNames:p=[],limits:k=R,now:u=()=>Date.now(),mapWindow:E=0,answerWindow:e=0,parallel:w=1,corrections:m=null,self:v=""}={}){const $=u(),y={...R,...k},_=le(m),F=new Set(_.notNames),T=new Set(_.hidden),t=ge(n,{previous:o,knownNames:p.filter(l=>!F.has(String(l).toLowerCase())),now:$}),X=String(n||""),I={framedBy:"rules"};if(t.names=t.names.filter(l=>!F.has(String(l).toLowerCase())),t.target&&T.has(t.target)&&(t.target=null),i&&y.modelFrame!==!1&&t.intent==="find"&&!t.followUp&&!t.target){const l=await i(Ce(n),{maxTokens:90}).catch(()=>""),d=B(l,V);if(d){I.framedBy="model",d.intent&&d.intent!=="find"&&(t.intent=d.intent),!t.kind&&d.kind&&(t.kind=d.kind);const f=(d.names||[]).map(g=>String(g).trim()).filter(g=>g&&X.toLowerCase().includes(g.toLowerCase())&&!F.has(g.toLowerCase()));!t.names.length&&f.length&&(t.names=f.slice(0,3)),t.intent==="group"&&(t.group=d.group||(t.kind==="meeting"?"person":"month"),t.terms=t.terms.filter(g=>!K.test(g)),t.limit=5),t.intent==="latest"&&(t.sort="newest",t.limit=5),t.intent==="earliest"&&(t.sort="oldest",t.limit=5),t.intent==="list"&&(t.limit=12),t.intent==="detail"&&(t.readFull=!0),t.intent==="people"&&(t.sort="newest",t.limit=3,t.readFull=!0,t.kind=t.kind||"meeting")}}const r={plan:t,rows:[],count:null,read:[],rounds:0,ms:0,attachment:null,how:Ae(t),...I};r.memory=se(c,{text:`${n} ${t.names.join(" ")}`,includeAmbient:!1,limit:5}).map(l=>l.text);const A=()=>u()-$>y.ms;try{r.rounds=1;const l=await s(t)||{};r.rows=(l.rows||[]).filter(d=>!T.has(d.id)),r.count=Number.isFinite(l.count)?Math.max(0,l.count-((l.rows||[]).length-r.rows.length)):r.rows.length,r.groups=t.group==="person"?xe(l.groups,v):l.groups||null}catch{r.rows=[]}if(!r.rows.length&&!r.groups?.length&&a&&r.rounds<y.rounds&&!A()){r.rounds=2;try{const l=await a(n);r.rows=(l?.modes?.hybrid||[]).filter(d=>!d.echo&&!T.has(d.id)).slice(0,t.limit),r.how=`${r.how}; nothing matched that exactly, so a wider search of everything`}catch{}}if(!r.rows.length&&!t.target&&!r.groups?.length)return r.ms=u()-$,r.memory.length&&(r.attachment=P(n,r,{now:$})),r;const Z=["count","group"].includes(t.intent)?0:["latest","earliest","detail","people"].includes(t.intent)?1:y.records,ee=t.target?[{id:t.target}]:r.rows.filter(l=>!String(l.id).startsWith("memory:")).slice(0,Z),j=O({windowTokens:E,reserveTokens:450}),N=async l=>{const d=await h(l.id).catch(()=>null);if(!d?.text)return;const f=Se(d.text),g=i&&t.readFull&&j>0,x=g?be(oe(d.text,{maxChars:j}),t,y.parts):ye(d.text,t,{chunkChars:y.chunkChars,max:t.readFull?y.chunks:2}).map(b=>({...b,index:Math.floor(b.at/y.chunkChars)+1,of:Math.ceil(d.text.length/y.chunkChars)}));let C=[];i&&t.readFull&&t.intent!=="people"&&(C=(await re(x,S=>i(ie({question:n,title:d.title||l.title,date:L(d.date||l.date),speakers:f,part:S}),{maxTokens:g?400:220}),{concurrency:w,late:A})).map((S,M)=>S&&x.length>1?`[part ${x[M].index}/${x[M].of}] ${S}`:S).filter(Boolean)),C.length||(C=x.map(b=>b.text.replace(/\s+/g," ").trim()).filter(Boolean)),r.read.push({id:d.id||l.id,title:d.title||l.title,date:d.date||l.date,notes:C,chunks:x.length,of:x[0]?.of||1,speakers:f})};for(const l of ee){if(A())break;await N(l)}if(i&&y.check!==!1&&a&&r.rounds<y.rounds&&!A()&&!["count","group","people","latest","earliest"].includes(t.intent)&&(r.read.length||r.rows.length)){const l=P(n,r,{now:$}),d=l?await i(Ee(n,l.text),{maxTokens:80}).catch(()=>""):"",f=B(d,Y);if(r.verdict=f?.answered||null,f?.answered==="no"){r.rounds+=1;const g=[n,f.missing].filter(Boolean).join(" ").slice(0,600);try{const C=((await a(g))?.modes?.hybrid||[]).filter(b=>!b.echo&&!T.has(b.id)&&!r.rows.some(S=>S.id===b.id));if(C.length){r.rows.push(...C.slice(0,5)),r.how=`${r.how}; what that found did not answer it, so a wider search${f.missing?` for "${String(f.missing).slice(0,80)}"`:""}`;const b=C.find(S=>!String(S.id).startsWith("memory:"));b&&!A()&&await N(b)}}catch{}}}const D=O({windowTokens:e,reserveTokens:1024,frameTokens:900});if(D>0&&r.read.length){r.fitted=!0;const l=Math.floor(D/r.read.length);for(const d of r.read)d.notes=await ae(d.notes,{question:n,budgetChars:l,batchChars:j||l,complete:i?f=>i(f,{maxTokens:500}):null,concurrency:w,late:A})}return r.ms=u()-$,r.attachment=P(n,r,{now:$}),r}function P(n,s,{now:h=Date.now()}={}){const a=[];s.memory?.length&&a.push("Kept by the person (memory):",...s.memory.map(o=>`- [memory] ${o}`),""),a.push(`Searched ${s.how}${s.count!=null&&s.plan.intent!=="detail"?` — ${s.count} found`:""}.`),s.groups?.length&&a.push("","Grouped:",...s.groups.slice(0,24).map(o=>`- ${o.key}: ${o.count}`)),s.rows.length&&(a.push("","Found:"),s.rows.slice(0,12).forEach((o,p)=>a.push(`${p+1}. [${o.id}] ${o.title||""}${o.date?` — ${L(o.date)}`:""}${o.snippet?` — ${String(o.snippet).replace(/\s+/g," ").slice(0,160)}`:""}`)));for(const o of s.read)a.push("",`Read [${o.id}] "${o.title}"${o.date?` (${L(o.date)})`:""} — ${o.chunks} of ${o.of} part${o.of===1?"":"s"}:`),(s.plan.intent==="people"||o.speakers?.length>1)&&a.push(` Speakers (lines spoken): ${(o.speakers||[]).map(p=>`${p.name} (${p.lines})`).join(", ")||"none recorded"}`),s.plan.intent!=="people"&&a.push(...o.notes.map(p=>` ${s.fitted?p:p.slice(0,1600)}`));if(!s.rows.length&&!s.read.length&&!s.memory?.length&&!s.groups?.length)return null;const c=`(ALREADY RESEARCHED the person's own data for the question below — the whole store, not a guess. ${s.plan.intent==="latest"?"The FIRST found item is the most recent; answer with its date.":s.plan.intent==="earliest"?"The FIRST found item is the earliest; answer with its date.":s.plan.intent==="count"?"Answer with the count found.":s.plan.intent==="group"?s.groups?.length?"Answer from the grouped counts; they cover the whole store.":"The store could not group this; say so, and answer from what was found.":s.plan.intent==="people"?"Answer with the speakers listed for the meeting read.":"Answer from what was read."} Cite the [id] you use. If the answer is not here, say it was not found in their data; never guess and never say you have no access.)
14
+
15
+ ${a.join(`
16
+ `)}`;return{id:`prefetch_research_${h}`,kind:"prefetch",prefetch:"personal",title:"Researched your own data",text:c,chars:c.length}}export{Y as EVIDENCE_SCHEMA,V as FRAME_SCHEMA,R as RESEARCH_LIMITS,ye as chunksFor,we as dateIn,Ae as describePlan,Ee as evidencePrompt,Ce as framePrompt,ge as frameQuestion,xe as peopleGroups,Pe as research,P as researchAttachment,Se as speakersIn};
package/sandbox-policy.js CHANGED
@@ -1 +1 @@
1
- import{EventError as L}from"./event.js";import{normalizeGrant as x}from"./sandbox-grant.js";import{SECRET_DIR_NAMES as P,SECRET_DIR_PAIRS as N}from"./secret-names.js";const R=Object.freeze(["none","process","container","kubernetes"]),S=Object.freeze(["open","allowlist","none","gateway"]),E=Object.freeze(["~/.chatpanel","~/.ssh","~/.gnupg","~/.aws","~/.azure","~/.config/gcloud","~/.kube","~/.netrc","~/.docker/config.json","~/.npmrc","~/.pypirc"]),g=e=>{let t=String(e||"").trim();for(;t.length>1&&(t.endsWith("/")||t.endsWith("\\"));)t=t.slice(0,-1);return t},_=(e,t)=>t&&(e==="~"||e.startsWith("~/")||e.startsWith("~\\"))?t+e.slice(1):e,m=e=>String(e||"").replace(/\\/g,"/"),b=(e,t)=>{const n=m(g(e)),r=m(g(t));return!!n&&!!r&&(n===r||n.startsWith(`${r}/`))},v=E.map(e=>m(g(e)).replace(/^~\//,"").split("/").filter(Boolean));function I(e,t=""){const n=m(g(_(g(e),t)));if(!n)return!1;for(const o of E)if(b(n,o)||t&&b(n,_(o,t)))return!0;const r=n.split("/").filter(Boolean).map(o=>o.toLowerCase());return v.some(o=>{for(let s=0;s+o.length<=r.length;s+=1)if(o.every((c,l)=>c.toLowerCase()===r[s+l]))return!0;return!1})}const $=Object.freeze([...[...P].map(e=>`~/**/${e}`),...N.map(([e,t])=>`~/**/${e}/${t}`),...[".env",".netrc","_netrc",".git-credentials",".pgpass",".my.cnf",".npmrc",".pypirc",".htpasswd",".terraformrc",".vault-token","credentials","credentials.toml","id_rsa","id_dsa","id_ecdsa","id_ed25519","*.pem","*.p12","*.pfx","*.jks","*.keystore","*.kdbx","*.ppk"].map(e=>`~/**/${e}`)]);function Z(e,{home:t="",globs:n=[...E,...$]}={}){const r=m(g(_(g(e),t)));if(!r)return null;const o=r.split("/").filter(Boolean),s=m(g(t));for(const c of n){const l=m(g(c));if(l){if(l.startsWith("~/**/")){if(s&&!b(r,s))continue;const a=l.slice(5).split("/").filter(Boolean).map(z);for(let i=0;i+a.length<=o.length;i+=1)if(a.every((f,p)=>f.test(o[i+p])))return c;continue}if(b(r,_(l,t)))return c}}return null}function z(e){return new RegExp(`^${e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*")}$`,"i")}const W=".cache/chatpanel/ca-bundle.crt",J=".cache/chatpanel/ca-bundle.pem";function ee(e=""){const t=m(g(e));return t?`${t}/${W}`:`~/${W}`}const H=Object.freeze(["~/.npm","~/.cache","~/.local","~/Library/Caches","~/.nvm","~/.volta","~/.asdf","~/.nodenv","~/.bun","~/.deno","~/.pyenv","~/.rye","~/.pdm","~/.cargo","~/.rustup","~/go","~/.goenv","~/.m2","~/.gradle","~/.sdkman","~/.jenv","~/.gem","~/.rbenv","~/.bundle","~/.composer","~/.nuget","~/.dotnet","~/.stack","~/.ghcup","~/.opam","~/.pub-cache","~/.gitconfig","~/.config/git"]),D=Object.freeze(["/tmp","/private/tmp","~/.cache","~/.npm","~/.local/share/uv","~/.local/state"]),C=Object.freeze({codex:Object.freeze({hosts:["api.openai.com","chatgpt.com","auth.openai.com","*.openai.com"],write:["~/.codex"]}),claude:Object.freeze({hosts:["api.anthropic.com","*.anthropic.com","claude.ai","statsig.anthropic.com"],write:["~/.claude","~/.claude.json"],keychain:!0}),antigravity:Object.freeze({hosts:["*.googleapis.com","*.google.com","oauth2.googleapis.com"],write:["~/.gemini","~/.antigravity","~/.config/antigravity"]}),custom:Object.freeze({hosts:[],write:[]}),mcp:Object.freeze({hosts:[],write:[]}),extract:Object.freeze({hosts:[],write:[]}),"model-server":Object.freeze({hosts:["huggingface.co","*.huggingface.co","*.hf.co","cdn-lfs.huggingface.co","cas-bridge.xethub.hf.co","dl.chatpanel.net"],write:[]})}),T="~/Library/Keychains",K=/(^|\/)Keychains\/?$/,k=Object.freeze(["github.com","*.github.com","*.githubusercontent.com","gitlab.com","bitbucket.org","registry.npmjs.org","pypi.org","files.pythonhosted.org","crates.io","static.crates.io","proxy.golang.org","sum.golang.org","huggingface.co","*.huggingface.co"]),h=e=>!!e&&typeof e=="object"&&!Array.isArray(e),O=e=>Array.isArray(e)&&e.every(t=>typeof t=="string"&&t.length>0),d=(e,t)=>{if(!e)throw new L("SHAPE",t)},u=e=>[...new Set(e)];function j(e){d(h(e),"kit: must be an object"),d(typeof e.id=="string"&&e.id.length>0,"kit: id required"),d(h(e.network)&&S.includes(e.network.mode),`kit ${e.id}: network.mode must be one of ${S.join(", ")}`),d(O(e.network.allowedDomains||[]),`kit ${e.id}: network.allowedDomains must be string[]`),d(O(e.network.deniedDomains||[]),`kit ${e.id}: network.deniedDomains must be string[]`),d(h(e.filesystem),`kit ${e.id}: filesystem required`);for(const t of["allowWrite","denyWrite","allowRead","denyRead"])d(O(e.filesystem[t]||[]),`kit ${e.id}: filesystem.${t} must be string[]`);return d(O(e.filesystem.allowWrite)&&e.filesystem.allowWrite.length>0,`kit ${e.id}: filesystem.allowWrite must name at least the working directory`),e.image!=null&&d(typeof e.image=="string",`kit ${e.id}: image must be a string`),e.credentials!=null&&d(Array.isArray(e.credentials)&&e.credentials.every(t=>h(t)&&typeof t.name=="string"&&typeof t.forHost=="string"),`kit ${e.id}: credentials must be [{ name, forHost }]`),{id:e.id,kind:e.kind||"process",image:e.image||null,network:{mode:e.network.mode,allowedDomains:u(e.network.allowedDomains||[]),deniedDomains:u(e.network.deniedDomains||[])},filesystem:{allowWrite:u(e.filesystem.allowWrite),denyWrite:u(e.filesystem.denyWrite||[]),allowRead:u(e.filesystem.allowRead||[]),denyRead:u(e.filesystem.denyRead||[])},credentials:e.credentials||[],limits:h(e.limits)?{...e.limits}:{}}}import{normalizeGrant as ue,mergeGrants as pe,parseHostList as ge}from"./sandbox-grant.js";function te({engine:e="custom",cwd:t,mode:n="open",extraHosts:r=[],extraWrite:o=[],extraDenyRead:s=[],grant:c=null,home:l="",reads:a="enumerated",readOnly:i=!1}={}){const f=C[e]||C.custom;d(typeof t=="string"&&t.length>0,"kit: cwd required");const p=x(c);return j({id:`${e}:${n}`,kind:"process",network:{mode:n,allowedDomains:n==="open"?["*"]:n==="none"?[]:u([...f.hosts,...k,...r,...p.hosts]),deniedDomains:[]},filesystem:{allowWrite:u(i?[...D,...f.write]:[t,...D,...f.write,...[...o,...p.write].filter(A=>!I(A,l))]),denyWrite:[],allowRead:a==="inverted"?u([t,...H,...f.write,...f.keychain?[T]:[],...U({grant:p,extraWrite:o,cwd:t,home:l})]):[t],denyRead:u([...a==="inverted"?["~",...l?[l]:[]]:[],...[...E,...$].filter(A=>!(f.keychain&&K.test(A))),...s])}})}function Y(e){if(!/[*?[{]/.test(e))return e;const t=e.split(/[\\/]/),n=t.findIndex(s=>/[*?[{]/.test(s)),r=e.includes("\\")&&!e.includes("/")?"\\":"/",o=t.slice(0,n).join(r);return o&&o!=="~"?o:""}function U({grant:e=null,extraWrite:t=[],cwd:n="",home:r=""}={}){const o=i=>r&&(i==="~"||i.startsWith("~/")||i.startsWith("~\\"))?r+i.slice(1):i,s=i=>{let f=String(i||"").trim();for(;f.length>1&&(f.endsWith("/")||f.endsWith("\\"));)f=f.slice(0,-1);return f},c=(i,f)=>i===f||i.startsWith(`${f}/`)||i.startsWith(`${f}\\`),l=s(o(n)),a=[];for(const i of[...x(e).write,...Array.isArray(t)?t:[]]){const f=Y(s(o(s(i))));if(f&&!I(f,r)&&!(l&&c(f,l))&&!a.some(p=>c(f,p))){for(let p=a.length-1;p>=0;p--)c(a[p],f)&&a.splice(p,1);a.push(f)}}return a}function ne(e,{loopback:t=[],home:n="",platform:r="darwin"}={}){const o=j(e),s=l=>n&&l.startsWith("~")?n+l.slice(1):l,c=o.network.mode==="none"?[]:t.map(l=>`127.0.0.1:${l}`);return{network:{allowedDomains:u([...o.network.allowedDomains,...c]),deniedDomains:o.network.deniedDomains,allowLocalBinding:r==="darwin"&&c.length>0},filesystem:{denyRead:o.filesystem.denyRead.map(s),allowRead:o.filesystem.allowRead.map(s),allowWrite:o.filesystem.allowWrite.map(s),denyWrite:o.filesystem.denyWrite.map(s)}}}function oe({layer:e="none",runtime:t=null,kitId:n=null,mode:r=null,reason:o=null,hosts:s=null}={}){return d(R.includes(e),`sandbox record: layer must be one of ${R.join(", ")}`),{layer:e,runtime:t,kit:n,mode:r,...e==="none"&&o?{reason:o}:{},...Array.isArray(s)&&s.length?{hosts:u(s)}:{}}}function B(e,{platform:t="darwin"}={}){const n=String(e);if(t==="win32"){d(!/[\r\n]/.test(n),"win32 command line: an argument holds a newline, which cmd.exe cannot carry");let r=n;if(n===""||/[ \t\v"]/.test(n)){r='"';for(let o=0;o<n.length;o++){let s=0;for(;o<n.length&&n[o]==="\\";)s++,o++;if(o===n.length){r+="\\".repeat(s*2);break}n[o]==='"'?r+="\\".repeat(s*2+1)+'"':r+="\\".repeat(s)+n[o]}r+='"'}return r.replace(/[()%!^"<>&|]/g,"^$&")}return n===""?"''":/^[A-Za-z0-9_\-./=:@%+,]+$/.test(n)?n:`'${n.replace(/'/g,"'\\''")}'`}const G=Object.freeze(["SSL_CERT_FILE","REQUESTS_CA_BUNDLE","CURL_CA_BUNDLE","GIT_SSL_CAINFO"]);function re(e={},{platform:t="darwin",caBundle:n=""}={}){const r={NODE_USE_ENV_PROXY:"1"};if(n)for(const o of G)e[o]||(r[o]=n);if(t==="linux")for(const o of["no_proxy","NO_PROXY"])typeof e[o]=="string"&&(r[o]=e[o].split(",").map(s=>s.trim()).filter(s=>s&&!/^(localhost|127\.0\.0\.1|::1|\[::1\])$/i.test(s)).join(","));return r}function se(e,t=[],{platform:n="darwin"}={}){return[e,...t].map(r=>B(r,{platform:n})).join(" ")}const ie=/[\\/]+/,w=e=>String(e||"").replace(/\//g,"\\").replace(/\\+$/,"").toLowerCase(),M=e=>/^[a-z]:$/i.test(w(e))||w(e)==="";function y(e,t){const n=w(e),r=w(t);return!!r&&n!==r&&n.startsWith(r+"\\")}function q(e){const t=String(e||"").replace(/\//g,"\\").split("\\");if(t.length<2)return"";const n=t.findIndex(r=>r.toLowerCase()==="node_modules");return(n>0?t.slice(0,n):t.slice(0,-1)).join("\\")}function ae({kit:e,files:t=[],home:n}){d(typeof n=="string"&&n.length>0,"windows grants: home required");const r=a=>(a.startsWith("~")?n+a.slice(1):a).replace(/\//g,"\\"),o=[];for(const a of e?.filesystem?.allowWrite||[]){const i=r(a);!/^[a-z]:\\/i.test(i)&&!i.startsWith("\\\\")||(d(!M(i)&&w(i)!==w(n),`windows grants: a write on ${i} would hand the sandbox account the whole profile`),y(i,n)&&o.push(i))}const s=(a,i)=>i.some(f=>w(a)===w(f)||y(a,f)),c=[];for(const a of t){const i=q(a);i&&y(i,n)&&c.push(i)}for(const a of e?.filesystem?.allowRead||[]){const i=r(a);y(i,n)&&c.push(i)}const l=u(c).filter(a=>!s(a,o));return{read:l.filter(a=>!l.some(i=>i!==a&&y(a,i))),write:u(o)}}const F=Object.freeze(["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","CLAUDE_CONFIG_DIR","OPENAI_API_KEY","OPENAI_BASE_URL","OPENAI_API_BASE","CODEX_HOME","GEMINI_API_KEY","GOOGLE_API_KEY","DEEPSEEK_API_KEY","DSH_HOME","OPENROUTER_API_KEY","GROQ_API_KEY","XAI_API_KEY","MISTRAL_API_KEY"]);function ce({engine:e="custom",home:t,env:n={},base:r={},carry:o=F}={}){d(typeof t=="string"&&t.length>0,"windows env: home required");const s=t.replace(/\//g,"\\"),c=/^[a-z]:/i.test(s)?s.slice(0,2):"",l={USERPROFILE:s,...c?{HOMEDRIVE:c,HOMEPATH:s.slice(2)}:{}};for(const[a,i]of Object.entries(n))typeof i=="string"&&(r[a]!==i||o.includes(a))&&(l[a]=i);return e==="codex"&&!l.CODEX_HOME&&(l.CODEX_HOME=s+"\\.codex"),l}function le(e,t){d(Array.isArray(e),"srt-win argv: must be an array");const n=e.indexOf("exec"),r=n>=0?e.indexOf("--",n+1):-1;d(n>=0&&r>n,"srt-win argv: expected `exec … -- <shell> <command>`");const o=new Set;for(let c=n+1;c<r;c++)e[c]==="--env"&&typeof e[c+1]=="string"&&o.add(e[c+1].split("=")[0].toUpperCase());const s=[];for(const[c,l]of Object.entries(t||{}))d(/^[A-Za-z_][A-Za-z0-9_]*$/.test(c),`srt-win env: bad key ${c}`),d(!/[\r\n]/.test(l),`srt-win env: ${c} holds a newline`),o.has(c.toUpperCase())||s.push("--env",`${c}=${l}`);return[...e.slice(0,r),...s,...e.slice(r)]}export{W as CA_BUNDLE_RELPATH,J as CA_BUNDLE_RELPATH_LEGACY,D as COMMON_WRITE,k as DEVELOPER_HOSTS,C as ENGINE_KITS,S as NETWORK_MODES,R as SANDBOX_LAYERS,E as SECRET_PATHS,$ as SECRET_READ_GLOBS,H as TOOLCHAIN_READ,F as WINDOWS_CARRY_KEYS,ee as caBundlePath,I as isSecretWritePath,te as kitFor,pe as mergeGrants,ue as normalizeGrant,ge as parseHostList,Z as readDenialFor,re as sandboxEnvOverlay,oe as sandboxRecord,se as shellJoin,B as shellQuote,ne as toSrtSettings,y as underWindowsHome,j as validateKit,ae as windowsGrantsFor,q as windowsInstallRoot,ce as windowsSandboxEnv,le as withSrtWinEnv,U as writableRoots};
1
+ import{EventError as L}from"./event.js";import{normalizeGrant as x}from"./sandbox-grant.js";import{SECRET_DIR_NAMES as P,SECRET_DIR_PAIRS as N}from"./secret-names.js";const R=Object.freeze(["none","process","container","kubernetes"]),S=Object.freeze(["open","allowlist","none","gateway"]),E=Object.freeze(["~/.chatpanel","~/.ssh","~/.gnupg","~/.aws","~/.azure","~/.config/gcloud","~/.kube","~/.netrc","~/.docker/config.json","~/.npmrc","~/.pypirc"]),g=e=>{let t=String(e||"").trim();for(;t.length>1&&(t.endsWith("/")||t.endsWith("\\"));)t=t.slice(0,-1);return t},_=(e,t)=>t&&(e==="~"||e.startsWith("~/")||e.startsWith("~\\"))?t+e.slice(1):e,m=e=>String(e||"").replace(/\\/g,"/"),b=(e,t)=>{const n=m(g(e)),r=m(g(t));return!!n&&!!r&&(n===r||n.startsWith(`${r}/`))},v=E.map(e=>m(g(e)).replace(/^~\//,"").split("/").filter(Boolean));function I(e,t=""){const n=m(g(_(g(e),t)));if(!n)return!1;for(const o of E)if(b(n,o)||t&&b(n,_(o,t)))return!0;const r=n.split("/").filter(Boolean).map(o=>o.toLowerCase());return v.some(o=>{for(let s=0;s+o.length<=r.length;s+=1)if(o.every((c,l)=>c.toLowerCase()===r[s+l]))return!0;return!1})}const $=Object.freeze([...[...P].map(e=>`~/**/${e}`),...N.map(([e,t])=>`~/**/${e}/${t}`),...[".env",".netrc","_netrc",".git-credentials",".pgpass",".my.cnf",".npmrc",".pypirc",".htpasswd",".terraformrc",".vault-token","credentials","credentials.toml","id_rsa","id_dsa","id_ecdsa","id_ed25519","*.pem","*.p12","*.pfx","*.jks","*.keystore","*.kdbx","*.ppk"].map(e=>`~/**/${e}`)]);function J(e,{home:t="",globs:n=[...E,...$]}={}){const r=m(g(_(g(e),t)));if(!r)return null;const o=r.split("/").filter(Boolean),s=m(g(t));for(const c of n){const l=m(g(c));if(l){if(l.startsWith("~/**/")){if(s&&!b(r,s))continue;const a=l.slice(5).split("/").filter(Boolean).map(z);for(let i=0;i+a.length<=o.length;i+=1)if(a.every((f,p)=>f.test(o[i+p])))return c;continue}if(b(r,_(l,t)))return c}}return null}function z(e){return new RegExp(`^${e.replace(/[.+^${}()|[\]\\]/g,"\\$&").replace(/\*/g,"[^/]*")}$`,"i")}const W=".cache/chatpanel/ca-bundle.crt",ee=".cache/chatpanel/ca-bundle.pem";function te(e=""){const t=m(g(e));return t?`${t}/${W}`:`~/${W}`}const H=Object.freeze(["~/.npm","~/.cache","~/.local","~/Library/Caches","~/.nvm","~/.volta","~/.asdf","~/.nodenv","~/.bun","~/.deno","~/.pyenv","~/.rye","~/.pdm","~/.cargo","~/.rustup","~/go","~/.goenv","~/.m2","~/.gradle","~/.sdkman","~/.jenv","~/.gem","~/.rbenv","~/.bundle","~/.composer","~/.nuget","~/.dotnet","~/.stack","~/.ghcup","~/.opam","~/.pub-cache","~/.gitconfig","~/.config/git"]),D=Object.freeze(["/tmp","/private/tmp","~/.cache","~/.npm","~/.local/share/uv","~/.local/state"]),C=Object.freeze({codex:Object.freeze({hosts:["api.openai.com","chatgpt.com","auth.openai.com","*.openai.com"],write:["~/.codex"]}),claude:Object.freeze({hosts:["api.anthropic.com","*.anthropic.com","claude.ai","statsig.anthropic.com"],write:["~/.claude","~/.claude.json"],keychain:!0}),antigravity:Object.freeze({hosts:["*.googleapis.com","*.google.com","oauth2.googleapis.com"],write:["~/.gemini","~/.antigravity","~/.config/antigravity"]}),custom:Object.freeze({hosts:[],write:[]}),mcp:Object.freeze({hosts:[],write:[]}),extract:Object.freeze({hosts:[],write:[]}),"model-server":Object.freeze({hosts:["huggingface.co","*.huggingface.co","*.hf.co","cdn-lfs.huggingface.co","cas-bridge.xethub.hf.co","dl.chatpanel.net"],write:[]})}),T="~/Library/Keychains",K=/(^|\/)Keychains\/?$/,k=Object.freeze(["github.com","*.github.com","*.githubusercontent.com","gitlab.com","bitbucket.org","registry.npmjs.org","pypi.org","files.pythonhosted.org","crates.io","static.crates.io","proxy.golang.org","sum.golang.org","huggingface.co","*.huggingface.co"]),h=e=>!!e&&typeof e=="object"&&!Array.isArray(e),O=e=>Array.isArray(e)&&e.every(t=>typeof t=="string"&&t.length>0),d=(e,t)=>{if(!e)throw new L("SHAPE",t)},u=e=>[...new Set(e)];function j(e){d(h(e),"kit: must be an object"),d(typeof e.id=="string"&&e.id.length>0,"kit: id required"),d(h(e.network)&&S.includes(e.network.mode),`kit ${e.id}: network.mode must be one of ${S.join(", ")}`),d(O(e.network.allowedDomains||[]),`kit ${e.id}: network.allowedDomains must be string[]`),d(O(e.network.deniedDomains||[]),`kit ${e.id}: network.deniedDomains must be string[]`),d(h(e.filesystem),`kit ${e.id}: filesystem required`);for(const t of["allowWrite","denyWrite","allowRead","denyRead"])d(O(e.filesystem[t]||[]),`kit ${e.id}: filesystem.${t} must be string[]`);return d(O(e.filesystem.allowWrite)&&e.filesystem.allowWrite.length>0,`kit ${e.id}: filesystem.allowWrite must name at least the working directory`),e.image!=null&&d(typeof e.image=="string",`kit ${e.id}: image must be a string`),e.credentials!=null&&d(Array.isArray(e.credentials)&&e.credentials.every(t=>h(t)&&typeof t.name=="string"&&typeof t.forHost=="string"),`kit ${e.id}: credentials must be [{ name, forHost }]`),{id:e.id,kind:e.kind||"process",image:e.image||null,network:{mode:e.network.mode,allowedDomains:u(e.network.allowedDomains||[]),deniedDomains:u(e.network.deniedDomains||[])},filesystem:{allowWrite:u(e.filesystem.allowWrite),denyWrite:u(e.filesystem.denyWrite||[]),allowRead:u(e.filesystem.allowRead||[]),denyRead:u(e.filesystem.denyRead||[])},credentials:e.credentials||[],limits:h(e.limits)?{...e.limits}:{}}}import{normalizeGrant as pe,mergeGrants as ge,parseHostList as me}from"./sandbox-grant.js";const Y=e=>String(e).replace(/([\\/])\*$/,"$1**");function ne({engine:e="custom",cwd:t,mode:n="open",extraHosts:r=[],extraWrite:o=[],extraDenyRead:s=[],grant:c=null,home:l="",reads:a="enumerated",readOnly:i=!1}={}){const f=C[e]||C.custom;d(typeof t=="string"&&t.length>0,"kit: cwd required");const p=x(c);return j({id:`${e}:${n}`,kind:"process",network:{mode:n,allowedDomains:n==="open"?["*"]:n==="none"?[]:u([...f.hosts,...k,...r,...p.hosts]),deniedDomains:[]},filesystem:{allowWrite:u(i?[...D,...f.write]:[t,...D,...f.write,...[...o,...p.write].filter(A=>!I(A,l)).map(Y)]),denyWrite:[],allowRead:a==="inverted"?u([t,...H,...f.write,...f.keychain?[T]:[],...B({grant:p,extraWrite:o,cwd:t,home:l})]):[t],denyRead:u([...a==="inverted"?["~",...l?[l]:[]]:[],...[...E,...$].filter(A=>!(f.keychain&&K.test(A))),...s])}})}function U(e){if(!/[*?[{]/.test(e))return e;const t=e.split(/[\\/]/),n=t.findIndex(s=>/[*?[{]/.test(s)),r=e.includes("\\")&&!e.includes("/")?"\\":"/",o=t.slice(0,n).join(r);return o&&o!=="~"?o:""}function B({grant:e=null,extraWrite:t=[],cwd:n="",home:r=""}={}){const o=i=>r&&(i==="~"||i.startsWith("~/")||i.startsWith("~\\"))?r+i.slice(1):i,s=i=>{let f=String(i||"").trim();for(;f.length>1&&(f.endsWith("/")||f.endsWith("\\"));)f=f.slice(0,-1);return f},c=(i,f)=>i===f||i.startsWith(`${f}/`)||i.startsWith(`${f}\\`),l=s(o(n)),a=[];for(const i of[...x(e).write,...Array.isArray(t)?t:[]]){const f=U(s(o(s(i))));if(f&&!I(f,r)&&!(l&&c(f,l))&&!a.some(p=>c(f,p))){for(let p=a.length-1;p>=0;p--)c(a[p],f)&&a.splice(p,1);a.push(f)}}return a}function oe(e,{loopback:t=[],home:n="",platform:r="darwin"}={}){const o=j(e),s=l=>n&&l.startsWith("~")?n+l.slice(1):l,c=o.network.mode==="none"?[]:t.map(l=>`127.0.0.1:${l}`);return{network:{allowedDomains:u([...o.network.allowedDomains,...c]),deniedDomains:o.network.deniedDomains,allowLocalBinding:r==="darwin"&&c.length>0},filesystem:{denyRead:o.filesystem.denyRead.map(s),allowRead:o.filesystem.allowRead.map(s),allowWrite:o.filesystem.allowWrite.map(s),denyWrite:o.filesystem.denyWrite.map(s)}}}function re({layer:e="none",runtime:t=null,kitId:n=null,mode:r=null,reason:o=null,hosts:s=null}={}){return d(R.includes(e),`sandbox record: layer must be one of ${R.join(", ")}`),{layer:e,runtime:t,kit:n,mode:r,...e==="none"&&o?{reason:o}:{},...Array.isArray(s)&&s.length?{hosts:u(s)}:{}}}function G(e,{platform:t="darwin"}={}){const n=String(e);if(t==="win32"){d(!/[\r\n]/.test(n),"win32 command line: an argument holds a newline, which cmd.exe cannot carry");let r=n;if(n===""||/[ \t\v"]/.test(n)){r='"';for(let o=0;o<n.length;o++){let s=0;for(;o<n.length&&n[o]==="\\";)s++,o++;if(o===n.length){r+="\\".repeat(s*2);break}n[o]==='"'?r+="\\".repeat(s*2+1)+'"':r+="\\".repeat(s)+n[o]}r+='"'}return r.replace(/[()%!^"<>&|]/g,"^$&")}return n===""?"''":/^[A-Za-z0-9_\-./=:@%+,]+$/.test(n)?n:`'${n.replace(/'/g,"'\\''")}'`}const M=Object.freeze(["SSL_CERT_FILE","REQUESTS_CA_BUNDLE","CURL_CA_BUNDLE","GIT_SSL_CAINFO"]);function se(e={},{platform:t="darwin",caBundle:n=""}={}){const r={NODE_USE_ENV_PROXY:"1"};if(n)for(const o of M)e[o]||(r[o]=n);if(t==="linux")for(const o of["no_proxy","NO_PROXY"])typeof e[o]=="string"&&(r[o]=e[o].split(",").map(s=>s.trim()).filter(s=>s&&!/^(localhost|127\.0\.0\.1|::1|\[::1\])$/i.test(s)).join(","));return r}function ie(e,t=[],{platform:n="darwin"}={}){return[e,...t].map(r=>G(r,{platform:n})).join(" ")}const ae=/[\\/]+/,w=e=>String(e||"").replace(/\//g,"\\").replace(/\\+$/,"").toLowerCase(),q=e=>/^[a-z]:$/i.test(w(e))||w(e)==="";function y(e,t){const n=w(e),r=w(t);return!!r&&n!==r&&n.startsWith(r+"\\")}function F(e){const t=String(e||"").replace(/\//g,"\\").split("\\");if(t.length<2)return"";const n=t.findIndex(r=>r.toLowerCase()==="node_modules");return(n>0?t.slice(0,n):t.slice(0,-1)).join("\\")}function ce({kit:e,files:t=[],home:n}){d(typeof n=="string"&&n.length>0,"windows grants: home required");const r=a=>(a.startsWith("~")?n+a.slice(1):a).replace(/\//g,"\\"),o=[];for(const a of e?.filesystem?.allowWrite||[]){const i=r(a);!/^[a-z]:\\/i.test(i)&&!i.startsWith("\\\\")||(d(!q(i)&&w(i)!==w(n),`windows grants: a write on ${i} would hand the sandbox account the whole profile`),y(i,n)&&o.push(i))}const s=(a,i)=>i.some(f=>w(a)===w(f)||y(a,f)),c=[];for(const a of t){const i=F(a);i&&y(i,n)&&c.push(i)}for(const a of e?.filesystem?.allowRead||[]){const i=r(a);y(i,n)&&c.push(i)}const l=u(c).filter(a=>!s(a,o));return{read:l.filter(a=>!l.some(i=>i!==a&&y(a,i))),write:u(o)}}const X=Object.freeze(["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","CLAUDE_CONFIG_DIR","OPENAI_API_KEY","OPENAI_BASE_URL","OPENAI_API_BASE","CODEX_HOME","GEMINI_API_KEY","GOOGLE_API_KEY","DEEPSEEK_API_KEY","DSH_HOME","OPENROUTER_API_KEY","GROQ_API_KEY","XAI_API_KEY","MISTRAL_API_KEY"]);function le({engine:e="custom",home:t,env:n={},base:r={},carry:o=X}={}){d(typeof t=="string"&&t.length>0,"windows env: home required");const s=t.replace(/\//g,"\\"),c=/^[a-z]:/i.test(s)?s.slice(0,2):"",l={USERPROFILE:s,...c?{HOMEDRIVE:c,HOMEPATH:s.slice(2)}:{}};for(const[a,i]of Object.entries(n))typeof i=="string"&&(r[a]!==i||o.includes(a))&&(l[a]=i);return e==="codex"&&!l.CODEX_HOME&&(l.CODEX_HOME=s+"\\.codex"),l}function fe(e,t){d(Array.isArray(e),"srt-win argv: must be an array");const n=e.indexOf("exec"),r=n>=0?e.indexOf("--",n+1):-1;d(n>=0&&r>n,"srt-win argv: expected `exec … -- <shell> <command>`");const o=new Set;for(let c=n+1;c<r;c++)e[c]==="--env"&&typeof e[c+1]=="string"&&o.add(e[c+1].split("=")[0].toUpperCase());const s=[];for(const[c,l]of Object.entries(t||{}))d(/^[A-Za-z_][A-Za-z0-9_]*$/.test(c),`srt-win env: bad key ${c}`),d(!/[\r\n]/.test(l),`srt-win env: ${c} holds a newline`),o.has(c.toUpperCase())||s.push("--env",`${c}=${l}`);return[...e.slice(0,r),...s,...e.slice(r)]}export{W as CA_BUNDLE_RELPATH,ee as CA_BUNDLE_RELPATH_LEGACY,D as COMMON_WRITE,k as DEVELOPER_HOSTS,C as ENGINE_KITS,S as NETWORK_MODES,R as SANDBOX_LAYERS,E as SECRET_PATHS,$ as SECRET_READ_GLOBS,H as TOOLCHAIN_READ,X as WINDOWS_CARRY_KEYS,te as caBundlePath,I as isSecretWritePath,ne as kitFor,ge as mergeGrants,pe as normalizeGrant,me as parseHostList,J as readDenialFor,se as sandboxEnvOverlay,re as sandboxRecord,ie as shellJoin,G as shellQuote,oe as toSrtSettings,y as underWindowsHome,j as validateKit,ce as windowsGrantsFor,F as windowsInstallRoot,le as windowsSandboxEnv,fe as withSrtWinEnv,B as writableRoots};
@@ -0,0 +1,9 @@
1
+ import{fuseRRF as F}from"./rrf.js";import{lexicalPlan as T}from"./recall.js";import{recall as Q}from"./memory.js";const Z=Object.freeze(["memory","keyword","graph","hybrid"]),W=new Set("i im ive id ill the a an this that these those what who whom whose which when where why how is are was were do does did can could will would should my your our their his her its we you he she they it me him them us yes no ok okay hi hello hey thanks please sure also and but or so if then monday tuesday wednesday thursday friday saturday sunday january february march april may june july august september october november december today tomorrow yesterday chap chapel chatpanel gemini nano claude codex speaker note notes chat chats meeting meetings summary topics action items met meet saw see called call asked ask told tell emailed email texted text messaged pinged ping spoke talked thanks thank dear cc per via with from here there now sorry great sure maybe perhaps still just only even also yet here's there's let please".split(/\s+/));function M(o,{max:a=12,midSentence:n=!1,exclude:r=[]}={}){const t=new Map,g=new Set(r.map(l=>String(l).toLowerCase()).filter(Boolean)),k=/\b([A-Z][a-z][A-Za-z'-]+(?:\s+[A-Z][a-z][A-Za-z'-]+){0,2})\b/g,d=String(o||"");for(const l of d.matchAll(k)){if(n&&/(^|[.!?:|\n"“]\s*)$/.test(d.slice(Math.max(0,l.index-3),l.index)))continue;const v=l[1].split(/\s+/).filter(i=>!W.has(i.toLowerCase().replace(/'s$/,"")));if(!v.length)continue;const S=v.join(" ").replace(/'s$/,"");if(S.length<3)continue;const b=S.toLowerCase();if(![...g].some(i=>b===i||b.split(" ").some(h=>i.split(" ").includes(h)))&&(t.set(b,t.get(b)||{name:S,count:0}),t.get(b).count+=1,t.size>=a*2))break}return[...t.values()].sort((l,v)=>v.count-l.count).slice(0,a).map(l=>l.name)}function I(o,{plan:a=null}={}){const n=(a?.terms?.length?a.terms:T(o).terms).map(t=>String(t).toLowerCase().replace(/[^a-z0-9]/g,"")).filter(t=>t.length>=2),r=new Set(n);for(const t of n)t.length>=7&&r.add(t.slice(0,5));return[...r].slice(0,12)}const q=o=>o?.sinceAt||0;function B(o,a){const n=I(o).filter(t=>t.length>=4);if(n.length<2)return!1;const r=String(a||"").toLowerCase();return n.filter(t=>r.includes(t)).length/n.length>=.8}const X=500;function N(o){const a=(n,r)=>[...new Set((Array.isArray(n)?n:[]).map(r).filter(Boolean))].slice(-X);return{notNames:a(o?.notNames,n=>String(n||"").replace(/\s+/g," ").trim().toLowerCase().slice(0,80)),hidden:a(o?.hidden,n=>String(n||"").trim().slice(0,200))}}function te(o,{op:a,value:n}){const r=N(o),t=String(n||"").trim();return t?a==="not-a-name"?N({...r,notNames:[...r.notNames,t]}):a==="undo-name"?{...r,notNames:r.notNames.filter(g=>g!==t.toLowerCase())}:a==="hide"?N({...r,hidden:[...r.hidden,t]}):a==="unhide"?{...r,hidden:r.hidden.filter(g=>g!==t)}:r:r}async function G(o,a,{decide:n,k:r=6}={}){const t=a.slice(0,r);if(!n||!t.length)return{reranked:a,decision:{verdict:"unknown"}};const g=[`Question: ${String(o).slice(0,400)}`,"",...t.map((i,h)=>`[${h+1}] ${i.title}: ${String(i.snippet||"").replace(/\s+/g," ").slice(0,280)}`)].join(`
2
+ `),k={};t.forEach((i,h)=>{k[`p${h+1}`]={type:"score",instructions:`How well does passage [${h+1}] answer the question? A passage that only repeats the question, or says it cannot tell, does NOT answer it.`,options:["no","partly","answers it"]}}),k.answer={type:"choice",instructions:'Which passage gives the answer itself (a name, a fact, a date)? "none" if none does.',options:[...t.map((i,h)=>String(h+1)),"none"]};let d=null;try{d=await n({state:g,questions:k})}catch{d=null}const l=d?.answers;if(!l)return{reranked:a,decision:{verdict:"unknown"}};const v=t.map((i,h)=>({...i,relevance:Number(l[`p${h+1}`]?.value??0),at:h})).sort((i,h)=>h.relevance-i.relevance||i.at-h.at).map(({at:i,...h})=>h),S=String(l.answer?.value??"none"),b=S==="none"?null:t[Number(S)-1];return{reranked:[...v,...a.slice(r)],decision:b?{verdict:"found",id:b.id,title:b.title,by:d.model||"model",calibrated:d.calibrated!==!1}:{verdict:"not-found",by:d.model||"model",calibrated:d.calibrated!==!1}}}async function se(o,{lexical:a,decide:n=null,corrections:r=null,memories:t=[],self:g="",excludeId:k=null,plan:d=null,limit:l=10,modes:v=Z,hops:S=5,now:b=()=>Date.now()}={}){const i=new Set(v),h=N(r),j=new Set(h.hidden),R=async s=>(await a(s)||[]).filter(m=>!j.has(m.id)),A=d||T(o),O={chats:"chat",notes:"note",meetings:"meeting"}[A.scope]||"",u={plan:{terms:I(o,{plan:A}),scope:A.scope,since:A.since||""},modes:{},ms:{},errors:{}},E=async(s,m)=>{const w=b();try{u.modes[s]=await m()}catch(x){u.modes[s]=[],u.errors[s]=String(x?.message||x)}return u.ms[s]=b()-w,u.modes[s]},P=await E("memory",async()=>i.has("memory")||i.has("graph")||i.has("hybrid")?Q(t,{text:o,includeAmbient:!1,limit:l}).map((s,m)=>({id:`memory:${s.id}`,kind:"memory",title:s.text,date:s.updatedAt||0,snippet:s.text,score:1/(1+m)})).filter(s=>!j.has(s.id)):[]),C=await E("keyword",async()=>i.has("keyword")||i.has("graph")||i.has("hybrid")?(await R({terms:u.plan.terms,kind:O,sinceAt:q(A),limit:Math.max(l,20)+5})||[]).filter(s=>s.id!==k).map((s,m)=>({...s,echo:B(o,`${s.title}
3
+ ${s.snippet||""}`),rank:m})).sort((s,m)=>Number(s.echo)-Number(m.echo)||s.rank-m.rank).map(({rank:s,...m},w)=>({...m,score:1/(1+w),...m.echo?{via:"an earlier time you asked"}:{}})):[]);await E("graph",async()=>{if(!i.has("graph")&&!i.has("hybrid"))return[];const s=new Map,m=(e,c,f)=>{const $=e.toLowerCase();if(x.has($))return;const H=s.get($)||{name:e,weight:0,from:f};H.weight+=c,s.set($,H)},w=g?[g]:[],x=new Set(h.notNames),p=new Set(C.filter(e=>e.echo).map(e=>e.id));for(const e of M(o,{exclude:w}))m(e,2,"question");P.slice(0,3).forEach((e,c)=>M(e.snippet,{exclude:w}).forEach(f=>m(f,1.5/(1+c),"memory"))),C.filter(e=>!e.echo).slice(0,8).forEach((e,c)=>[...e.names||[],...M(`${e.title}
4
+ ${e.snippet||""}`,{midSentence:!0,exclude:w})].forEach(f=>m(f,1/(2+c),e.id)));const y=e=>C.slice(0,8).filter(c=>`${c.title} ${c.snippet||""} ${(c.names||[]).join(" ")}`.toLowerCase().includes(e)).length,z=Math.min(8,C.length),Y=[...s.values()].some(e=>e.from==="question"||e.from==="memory"),_=[...s.entries()].filter(([e,c])=>c.from==="question"||c.from==="memory"||(!Y||y(e)>=2)&&(z<4||y(e)<=z/2)).map(([e,c])=>({...c,key:e,weight:c.weight/(1+Math.max(0,y(e)-2))})).sort((e,c)=>c.weight-e.weight).slice(0,S),L=new Map,D=(e,c,f)=>{const $=L.get(e.id)||{...e,score:0,via:[]};$.score+=c,f&&!$.via.includes(f)&&$.via.push(f),L.set(e.id,$)};C.forEach((e,c)=>D(e,(e.echo?.05:.5)/(1+c),null));for(const e of _)(await R({terms:[e.name.toLowerCase()],phrase:!0,kind:O,sinceAt:q(A),limit:10})||[]).filter(f=>f.id!==k&&!p.has(f.id)&&!B(o,`${f.title}
5
+ ${f.snippet||""}`)).forEach((f,$)=>D(f,e.weight/(1+$),e.name));return u.plan.names=_.map(e=>e.name),[...L.values()].sort((e,c)=>c.score-e.score).slice(0,l).map(e=>({...e,via:e.via.length?e.via.join(", "):void 0}))}),await E("hybrid",async()=>{if(!i.has("hybrid"))return[];const s=(u.modes.graph||[]).filter(p=>p.via),m=[u.modes.memory,u.modes.keyword,s].map(p=>(p||[]).map(y=>y.id)),w=new Map;for(const p of["graph","keyword","memory"])for(const y of u.modes[p]||[])w.has(y.id)||w.set(y.id,{...y,from:[]});for(const p of["memory","keyword","graph"])for(const y of u.modes[p]||[])w.get(y.id)?.from.push(p);const x=F(m,{limit:l+5}).map(({id:p,score:y})=>({...w.get(p),score:y,from:w.get(p).from.join("+")}));return[...x.filter(p=>!p.echo),...x.filter(p=>p.echo)].slice(0,l)}),n&&i.has("hybrid")&&await E("reranked",async()=>{const s=await G(o,u.modes.hybrid||[],{decide:n});return u.decision=s.decision,s.reranked});for(const s of Z)i.has(s)||delete u.modes[s];return i.has("keyword")&&(u.modes.keyword=C.slice(0,l)),u}const J=[/\bmy\s+(?:friends?|family|wife|husband|partner|mom|mum|dad|mother|father|son|daughter|kids?|brother|sister|boss|manager|colleagues?|team|doctor|neighbou?rs?|contacts?|notes?|meetings?|chats?|trip|plans?|tasks?|reminders?|flight|hotel|appointment|address|car|house|home)\b/i,/\b(?:did|have|had)\s+(?:i|we)\b/i,/\bwhat\s+did\s+(?:i|we|\w+)\s+(?:say|decide|agree|discuss|mention|write|note)\b/i,/\b(?:when|where|who|what)\s+(?:was|were|is|are)\s+(?:my|our)\b/i,/\b(?:i|we)\s+(?:told you|mentioned|said|talked about|discussed)\b/i,/\bremind me\b/i,/\bwho\s+(?:do|did|have)\s+i\s+(?:meet|met|talk|speak|spoke|chat)/i,/\b(?:meetings?|calls?|chats?|notes?)\s+(?:per|by|each|every|a)\s+(?:month|week|day)\b/i],K=/^\s*(?:(?:ok(?:ay)?|hey|so|and|also|please)[\s,]+)*(?:remember|note|keep in mind|don'?t forget|never forget|forget|call me|save (?:that|this))\b/i;function ne(o,{names:a=[]}={}){const n=String(o||"");if(n.trim().length<6||K.test(n))return!1;if(J.some(t=>t.test(n))||/\b(meetings?|calls?|chats?|notes?|conversations?)\b/i.test(n)&&M(n).length)return!0;const r=n.toLowerCase();return a.some(t=>t&&new RegExp(`\\b${String(t).toLowerCase().replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}\\b`).test(r))}function oe(o,{max:a=5,now:n=Date.now()}={}){const r=(o?.modes?.reranked||o?.modes?.hybrid||[]).filter(d=>!d.echo).slice(0,a);if(!r.length)return null;const t=r.map((d,l)=>{const v=d.kind==="memory"?"memory":`${d.id}${d.title?` “${String(d.title).slice(0,80)}”`:""}`,S=String(d.snippet||d.title||"").replace(/\s+/g," ").trim().slice(0,300);return`${l+1}. [${v}] ${S}`}),g=o?.decision?.verdict==="found"?`
6
+ Most likely answered by: ${o.decision.title}`:"",k=`(ALREADY SEARCHED the person's own chats, notes, meetings and memory for the question below. Answer from this; cite the [id] you used. If the answer is not here, say you could not find it in their data — never guess, and never say you have no access to their data.)
7
+
8
+ ${t.join(`
9
+ `)}${g}`;return{id:`prefetch_personal_${n}`,kind:"prefetch",prefetch:"personal",title:"Searched your own data",text:k,chars:k.length}}export{X as MAX_CORRECTIONS,Z as SEARCH_MODES,te as correct,oe as evidenceAttachment,B as isEcho,I as keywordTerms,M as namesIn,N as normalizeCorrections,ne as personalAsk,G as rerankAndDecide,se as runSearchModes};