@chatpanel/events 0.221.0 → 0.226.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.
@@ -0,0 +1 @@
1
+ const P=Object.freeze(["online","in-person","hybrid"]),O=Object.freeze(["off","standard","strong"]),k=Object.freeze(["app","system","tab","picker","device"]),p=Object.freeze({scenario:Object.freeze(["online","in-person","hybrid"]),noise:Object.freeze(["auto","off","standard","strong"]),echo:Object.freeze(["auto","on","off"]),gain:Object.freeze(["auto","on","off"]),playback:Object.freeze(["auto",...k])}),E=Object.freeze({scenario:"online",noise:"auto",echo:"auto",gain:"auto",playback:"auto",app:null}),R=Object.freeze({echoCancellation:!1,noiseSuppression:!1,autoGainControl:!1}),b=Object.freeze({echo:!0,noise:Object.freeze(["standard"]),gain:!0}),z=Object.freeze({macos:Object.freeze({playback:Object.freeze(["app","system","picker"]),mic:b,micMode:"user"}),windows:Object.freeze({playback:Object.freeze(["app","system"]),mic:b,micMode:null}),linux:Object.freeze({playback:Object.freeze(["app","system","device"]),mic:b,micMode:null}),ios:Object.freeze({playback:Object.freeze([]),mic:Object.freeze({echo:!0,noise:Object.freeze(["standard"]),gain:!0}),micMode:"user"}),android:Object.freeze({playback:Object.freeze([]),mic:Object.freeze({echo:!0,noise:Object.freeze(["standard"]),gain:!0}),micMode:null}),browser:Object.freeze({playback:Object.freeze(["tab","picker"]),mic:b,micMode:null}),terminal:Object.freeze({playback:Object.freeze(["device"]),mic:Object.freeze({echo:!1,noise:Object.freeze([]),gain:!1}),micMode:null})}),_=Object.freeze(Object.keys(z));function M(n,o={}){const a=z[n];if(!a)throw new Error(`unknown capture platform: ${n}`);const e=o&&typeof o=="object"?o:{};return{playback:Array.isArray(e.playback)?e.playback.filter(s=>k.includes(s)):[...a.playback],mic:{...a.mic,...e.mic&&typeof e.mic=="object"?e.mic:{}},micMode:e.micMode!==void 0?e.micMode:a.micMode}}const u=(n,o,a)=>o.includes(n)?n:a;function v(n){const o=n&&typeof n=="object"?n:{},a=E;return{scenario:u(o.scenario,p.scenario,a.scenario),noise:u(o.noise,p.noise,a.noise),echo:u(o.echo,p.echo,a.echo),gain:u(o.gain,p.gain,a.gain),playback:u(o.playback,p.playback,a.playback),app:typeof o.app=="string"&&o.app.trim()?o.app.trim().slice(0,80):null}}const g={"playback-unsupported":["info","That way of hearing the call is not available here, so another one is used."],"far-end-through-speakers":["warn","The call’s audio cannot be captured on its own here, so the microphone listens to the whole room — keep the call on speaker."],"far-end-unheard":["warn","The call’s audio cannot be captured on its own here, and with headphones only your side will be transcribed. Switch to the speaker to include everyone."],"strong-drops-room-voices":["info","Strong noise suppression keeps only the nearest voice, so standard is used for a room."],"noise-unsupported":["info","That level of noise suppression is not available here, so the nearest one is used."],"echo-unavailable":["warn","Echo cancellation is not available here — use headphones, or the call may be transcribed twice."],"echo-cancels-far-end":["warn","Echo cancellation is on while the call is heard through the room, so the other side may be cut out."],"mic-mode-isolation":["warn","The microphone is set to Voice Isolation, which removes everyone but the nearest voice. Switch it to Standard or Wide Spectrum for a room."]},c=n=>({code:n,level:g[n][0],text:g[n][1]});function x(n,o,a){const e=a.playback;return n!=="auto"?e.includes(n)?{source:n,fell:!1}:{source:w(o,e),fell:!0}:{source:w(o,e),fell:!1}}function w(n,o){return n&&o.includes("app")?"app":o.find(a=>a!=="app")||null}function T(n,o){if(n==="off")return"off";const a=O.indexOf(n);for(let e=a;e>0;e--)if(o.includes(O[e]))return O[e];return"off"}function I({prefs:n,caps:o,facts:a}={}){const e=v(n),s=o&&typeof o=="object"?o:M("browser"),f=s.mic||{echo:!1,noise:[],gain:!1},d=a?.headphones===!0?!0:a?.headphones===!1?!1:null,t=[];let r=null;if(e.scenario!=="in-person"){const{source:y,fell:S}=x(e.playback,e.app,{playback:Array.isArray(s.playback)?s.playback:[]});S&&t.push(c("playback-unsupported")),y&&(r={source:y,app:y==="app"?e.app:null})}let l=e.scenario==="online"?"self":"room",m=!r&&e.scenario==="hybrid";!r&&e.scenario==="online"&&(d===!0?t.push(c("far-end-unheard")):(l="room",m=!0,t.push(c("far-end-through-speakers"))));let i;e.echo!=="auto"?i=e.echo==="on":m||!r?i=!1:i=l==="room"||d!==!0,i&&m&&e.echo==="on"&&t.push(c("echo-cancels-far-end")),i&&!f.echo&&(i=!1,t.push(c("echo-unavailable")));let h=e.noise==="auto"?"standard":e.noise;h==="strong"&&l==="room"&&(h="standard",t.push(c("strong-drops-room-voices")));const j=T(h,Array.isArray(f.noise)?f.noise:[]);j!==h&&e.noise!=="auto"&&t.push(c("noise-unsupported"));const A=e.gain==="off"?!1:!!f.gain;l==="room"&&a?.micMode==="voice-isolation"&&t.push(c("mic-mode-isolation"));const C=!!r&&d!==!0;return{scenario:e.scenario,scribe:{mic:l,playback:!!r,echoGuard:C},mic:{echo:i,noise:j,gain:A},playback:r,notices:t}}function L(n){const o=n&&typeof n=="object"?n:{};return{channelCount:1,echoCancellation:!!o.echo,noiseSuppression:!!o.noise&&o.noise!=="off",autoGainControl:!!o.gain}}export{p as CAPTURE_PREFS,E as DEFAULT_CAPTURE_PREFS,O as NOISE_LEVELS,_ as PLATFORMS,R as PLAYBACK_AUDIO_CONSTRAINTS,k as PLAYBACK_SOURCES,P as SCENARIOS,M as captureCaps,L as micAudioConstraints,I as planCapture,v as readCapturePrefs};
package/citations.js CHANGED
@@ -1,6 +1,6 @@
1
- const g=/^\[(\d+)\]\s*\[([^\]]*)\]\(([^)\s]+)\)/gm;function k(n){const o=new Map;for(const e of String(n||"").matchAll(g)){const s=Number(e[1]);o.has(s)||o.set(s,{rank:s,title:e[2].trim(),url:e[3]})}return[...o.values()].sort((e,s)=>e.rank-s.rank)}const y=/\[(\d+(?:\s*,\s*\d+)*)\](?!\()/g;function d(n,o,{heading:e="Sources"}={}){const s=String(n??""),p=new Map((o||[]).filter(t=>t?.url).map(t=>[Number(t.rank),t]));if(!s.trim()||!p.size)return s;const r=new Set,c=s.split(/(```[\s\S]*?```|`[^`\n]*`)/g).map((t,a)=>a%2===1?t:t.replace(y,(h,m)=>{const f=m.split(",").map(u=>Number(u.trim()));return f.every(u=>p.has(u))?(f.forEach(u=>r.add(u)),f.map(u=>`([${u}](${p.get(u).url}))`).join(" ")):h})).join("");if(!r.size||new RegExp(`(^|\\n)\\s*(?:#{1,6}\\s*|\\*\\*)?${e}\\b`,"i").test(c))return c;const i=[...r].sort((t,a)=>t-a).map(t=>{const a=p.get(t);return`${t}. [${a.title||a.url}](${a.url})`}).join(`
1
+ import{effectiveToolName as g}from"./tool-traits.js";const k=/^\[(\d+)\]\s*\[([^\]]*)\]\(([^)\s]+)\)/gm;function y(s){const i=new Map;for(const n of String(s||"").matchAll(k)){const o=Number(n[1]);i.has(o)||i.set(o,{rank:o,title:n[2].trim(),url:n[3]})}return[...i.values()].sort((n,o)=>n.rank-o.rank)}const d=/\[(\d+(?:\s*,\s*\d+)*)\](?!\()/g;function x(s,i,{heading:n="Sources"}={}){const o=String(s??""),l=new Map((i||[]).filter(t=>t?.url).map(t=>[Number(t.rank),t]));if(!o.trim()||!l.size)return o;const e=new Set,c=o.split(/(```[\s\S]*?```|`[^`\n]*`)/g).map((t,r)=>r%2===1?t:t.replace(d,(m,h)=>{const p=h.split(",").map(a=>Number(a.trim()));return p.every(a=>l.has(a))?(p.forEach(a=>e.add(a)),p.map(a=>`([${a}](${l.get(a).url}))`).join(" ")):m})).join("");if(!e.size||new RegExp(`(^|\\n)\\s*(?:#{1,6}\\s*|\\*\\*)?${n}\\b`,"i").test(c))return c;const u=[...e].sort((t,r)=>t-r).map(t=>{const r=l.get(t);return`${t}. [${r.title||r.url}](${r.url})`}).join(`
2
2
  `);return`${c.trimEnd()}
3
3
 
4
- **${e}**
5
- ${i}
6
- `}const x=Object.freeze(new Set(["find","source","history_search","web_search","search","fetch","read_page"])),E=n=>String(n||"").replace(/^mcp[_-]/,"").split("__")[0];function _(n,{onRetrieved:o=null}={}){const e=new Map,s=(r,l)=>{const c=typeof l=="string"?l:l?.text||"";if(!c)return;const i=k(c);for(const t of i)e.has(t.rank)||e.set(t.rank,t);if(o)try{i.length?o({tool:r,count:i.length,chars:c.length,sources:i.slice(0,20).map(t=>({rank:t.rank,title:t.title||"",url:t.url||""}))}):x.has(E(r))&&o({tool:r,count:0,chars:c.length,sources:[]})}catch{}};return{tools:n&&typeof n.execute=="function"?{...n,execute:async(r,l,c)=>{const i=await n.execute(r,l,c);return s(r,i),i}}:n,list:()=>[...e.values()],apply(r){if(!e.size||!r||typeof r!="string")return r;try{return d(r,[...e.values()])}catch{return r}}}}export{x as RETRIEVAL_TOOLS,_ as createCitationCollector,d as linkifyCitations,k as sourcesFromToolText};
4
+ **${n}**
5
+ ${u}
6
+ `}const E=Object.freeze(new Set(["find","source","history_search","web_search","search","fetch","read_page"])),_=s=>String(s||"").replace(/^mcp[_-]/,"").split("__").pop();function b(s,{onRetrieved:i=null}={}){const n=new Map,o=(e,f,c)=>{const u=typeof c=="string"?c:c?.text||"";if(!u)return;const t=y(u);for(const r of t)n.has(r.rank)||n.set(r.rank,r);if(i)try{t.length?i({tool:e,count:t.length,chars:u.length,sources:t.slice(0,20).map(r=>({rank:r.rank,title:r.title||"",url:r.url||""}))}):E.has(_(g(e,f)))&&i({tool:e,count:0,chars:u.length,sources:[]})}catch{}};return{tools:s&&typeof s.execute=="function"?{...s,execute:async(e,f,c)=>{const u=await s.execute(e,f,c);return o(e,f,u),u}}:s,list:()=>[...n.values()],apply(e){if(!n.size||!e||typeof e!="string")return e;try{return x(e,[...n.values()])}catch{return e}}}}export{E as RETRIEVAL_TOOLS,b as createCitationCollector,x as linkifyCitations,y as sourcesFromToolText};
package/fetched.js CHANGED
@@ -1,3 +1,3 @@
1
- import{approxTokens as M,queryTerms as T}from"./sources-retrieval.js";import{effectiveToolName as w}from"./tool-traits.js";const k=Object.freeze({weather:10*6e4,web_search:30*6e4,history_search:10*6e4,history_get_source:30*6e4,history_related:10*6e4,history_list_meetings:10*6e4,history_get_meeting:30*6e4,meeting_live_transcript:6e4,read_page:5*6e4,read_transcript:30*6e4,mcp:10*6e4,default:5*6e4}),$=new Set(["source","get_result","describe","find_tool","team","sideline","thread","memory","note","skill_open","skill_file","screenshot","marked_screenshot","inspect_page","sense_canvas","probe_app_state","read_app_state","read_canvas"]);function q(t,e){return k[t]?k[t]:e==="mcp"||/^mcp[_:]/.test(String(e||""))?k.mcp:k.default}function b(t){if(t!=null){if(typeof t=="string")return t.trim().toLowerCase().replace(/\s+/g," ");if(Array.isArray(t))return t.map(b);if(typeof t=="object"){const e={};for(const o of Object.keys(t).sort()){const d=b(t[o]);d!==void 0&&d!==""&&(e[o]=d)}return e}return t}}function j(t,e){const o=typeof e=="string"?(()=>{try{return JSON.parse(e)}catch{return{text:e}}})():e||{},d=w(t,o),y=o&&typeof o=="object"&&("args"in o||"action"in o)?o.args??{}:o,p=b(y)||{};return{tool:String(t||""),action:d,args:p,key:`${d}|${JSON.stringify(p)}`}}function A(t){if(!t||typeof t!="object")return"";for(const e of["location","query","q","url","id","sourceId","name","text","path"])if(typeof t[e]=="string"&&t[e])return t[e];for(const e of Object.values(t))if(typeof e=="string"&&e)return e;return""}function J(t,e){const o=A(e);return o?`${t} — ${o.slice(0,60)}`:t}const D=t=>!t||/^(error\b|\w+ failed\b|\{"error"|could not answer)/i.test(String(t))||/now call web_search/i.test(String(t));function F({entries:t=[],now:e=()=>Date.now(),ttlFor:o=q,maxEntries:d=40,maxTokens:y=24e3,newId:p=null}={}){let c=(Array.isArray(t)?t:[]).filter(r=>r&&r.id&&r.key&&typeof r.text=="string").map(r=>({...r})),m=c.reduce((r,n)=>Math.max(r,Number(String(n.id).replace(/^f/,""))||0),0);const x=()=>p?p():`f${++m}`,g=(r,n=e())=>n-(r.at||0)<(r.ttl||o(r.action,r.tool)),a=()=>{const r=e();for(c=c.filter(i=>g(i,r));c.length>d;)c.shift();let n=c.reduce((i,u)=>i+u.tokens,0);for(;n>y&&c.length>1;)n-=c.shift().tokens};return{get entries(){return a(),[...c]},get tokens(){return a(),c.reduce((r,n)=>r+n.tokens,0)},remember({tool:r,input:n,text:i,title:u="",turn:l=null}={}){const f=typeof i=="string"?i:i&&typeof i=="object"&&typeof i.text=="string"?i.text:"";if(D(f))return null;const s=j(r,n);c=c.filter(h=>h.key!==s.key);const _={id:x(),tool:s.tool,action:s.action,key:s.key,args:s.args,title:u||J(s.action,s.args),text:f,tokens:M(f),at:e(),ttl:o(s.action,s.tool),uses:0,turn:l};return c.push(_),a(),_},lookup(r,n){const i=j(r,n),u=c.find(l=>l.key===i.key);return u&&g(u)?u:null},byId(r){const n=c.find(i=>i.id===String(r||"").trim());return n&&g(n)?n:null},relevant(r,{limit:n=4,previousTurn:i=null}={}){a();const u=T(String(r||"")),l=e();return c.map(s=>{const _=`${s.title} ${JSON.stringify(s.args)} ${s.text.slice(0,400)}`.toLowerCase();let h=0;for(const S of u)_.includes(S)&&(h+=Math.min(3,S.length/4));const O=(l-s.at)/6e4;return i!=null&&s.turn===i&&(h+=2),{e:s,s:h>0?h+Math.max(0,1-O/30):0}}).filter(s=>s.s>0).sort((s,_)=>_.s-s.s).slice(0,n).map(s=>s.e)},use(r){const n=c.find(i=>i.id===r);n&&(n.uses+=1)},toJSON(){return a(),c.map(r=>({...r}))},now:e}}function L(t=[]){return t.map(e=>({id:e.id,kind:"fetched",title:e.title,url:"",text:e.text}))}const N=t=>{const e=Math.floor(t/6e4);return e<1?"just now":`${e} min ago`};function z(t=[],{now:e=Date.now()}={}){return t.map(o=>({id:o.id,title:o.title,agoText:N(e-(o.at||e)),tokens:o.tokens}))}function I(t,e,{traitsOf:o=null,cacheable:d=null,now:y=null,turn:p=null}={}){if(!t||typeof t.execute!="function"||!e)return t;const c=y||e.now||(()=>Date.now()),m=o||(a=>t.traits?.get?.(a)||null),x=d||(a=>/^(history_|web_search$|weather$|read_page$|read_transcript$|list_|get_|search|fetch|read_|find_)/.test(a)),g=(a,r)=>{if($.has(a)||$.has(r))return!1;const n=m(a)||m(r);return n?!!n.readOnly&&!n.destructive:x(a,r)};return{...t,async execute(a,r,n){const i=typeof r=="string"?(()=>{try{return JSON.parse(r)}catch{return r}})():r,u=w(a,i);if(!g(u,a))return t.execute(a,r,n);const l=e.lookup(a,i);if(l)return e.use(l.id),{text:`${l.text}
1
+ import{approxTokens as O,queryTerms as T}from"./sources-retrieval.js";import{effectiveToolName as w}from"./tool-traits.js";const x=Object.freeze({weather:10*6e4,web_search:30*6e4,history_search:10*6e4,history_get_source:30*6e4,history_related:10*6e4,history_list_meetings:10*6e4,history_get_meeting:30*6e4,meeting_live_transcript:6e4,read_page:5*6e4,read_transcript:30*6e4,mcp:10*6e4,default:5*6e4}),j=new Set(["source","get_result","describe","find_tool","team","sideline","thread","memory","note","skill_open","skill_file","screenshot","marked_screenshot","inspect_page","sense_canvas","probe_app_state","read_app_state","read_canvas"]);function q(t,e){return x[t]?x[t]:e==="mcp"||/^mcp[_:]/.test(String(e||""))?x.mcp:x.default}function S(t){if(t!=null){if(typeof t=="string")return t.trim().toLowerCase().replace(/\s+/g," ");if(Array.isArray(t))return t.map(S);if(typeof t=="object"){const e={};for(const a of Object.keys(t).sort()){const f=S(t[a]);f!==void 0&&f!==""&&(e[a]=f)}return e}return t}}function M(t,e,{hiddenVia:a=null}={}){const f=typeof e=="string"?(()=>{try{return JSON.parse(e)}catch{return{text:e}}})():e||{},p=w(t,f);let _=f;if(f&&typeof f=="object"&&("args"in f||"action"in f)){const{action:g,args:s,...r}=f;_={...r,...s&&typeof s=="object"?s:{}}}const i=S(_)||{},k=p!==t&&a instanceof Map&&a.get(p)!==t?`${t}.${p}`:p;return{tool:String(t||""),action:p,args:i,key:`${k}|${JSON.stringify(i)}`}}function A(t){if(!t||typeof t!="object")return"";for(const e of["location","query","q","url","id","sourceId","name","text","path"])if(typeof t[e]=="string"&&t[e])return t[e];for(const e of Object.values(t))if(typeof e=="string"&&e)return e;return""}function J(t,e){const a=A(e);return a?`${t} — ${a.slice(0,60)}`:t}const D=t=>!t||/^(error\b|\w+ failed\b|\{"error"|could not answer)/i.test(String(t))||/now call web_search/i.test(String(t));function C({entries:t=[],now:e=()=>Date.now(),ttlFor:a=q,maxEntries:f=40,maxTokens:p=24e3,newId:_=null}={}){let i=(Array.isArray(t)?t:[]).filter(r=>r&&r.id&&r.key&&typeof r.text=="string").map(r=>({...r})),m=i.reduce((r,n)=>Math.max(r,Number(String(n.id).replace(/^f/,""))||0),0);const k=()=>_?_():`f${++m}`,g=(r,n=e())=>n-(r.at||0)<(r.ttl||a(r.action,r.tool)),s=()=>{const r=e();for(i=i.filter(o=>g(o,r));i.length>f;)i.shift();let n=i.reduce((o,h)=>o+h.tokens,0);for(;n>p&&i.length>1;)n-=i.shift().tokens};return{get entries(){return s(),[...i]},get tokens(){return s(),i.reduce((r,n)=>r+n.tokens,0)},remember({tool:r,input:n,text:o,title:h="",turn:u=null,hiddenVia:d=null}={}){const c=typeof o=="string"?o:o&&typeof o=="object"&&typeof o.text=="string"?o.text:"";if(D(c))return null;const l=M(r,n,{hiddenVia:d});i=i.filter(b=>b.key!==l.key);const y={id:k(),tool:l.tool,action:l.action,key:l.key,args:l.args,title:h||J(l.action,l.args),text:c,tokens:O(c),at:e(),ttl:a(l.action,l.tool),uses:0,turn:u};return i.push(y),s(),y},lookup(r,n,{hiddenVia:o=null}={}){const h=M(r,n,{hiddenVia:o}),u=i.find(d=>d.key===h.key);return u&&g(u)?u:null},byId(r){const n=i.find(o=>o.id===String(r||"").trim());return n&&g(n)?n:null},relevant(r,{limit:n=4,previousTurn:o=null}={}){s();const h=T(String(r||"")),u=e();return i.map(c=>{const l=`${c.title} ${JSON.stringify(c.args)} ${c.text.slice(0,400)}`.toLowerCase();let y=0;for(const $ of h)l.includes($)&&(y+=Math.min(3,$.length/4));const b=(u-c.at)/6e4;return o!=null&&c.turn===o&&(y+=2),{e:c,s:y>0?y+Math.max(0,1-b/30):0}}).filter(c=>c.s>0).sort((c,l)=>l.s-c.s).slice(0,n).map(c=>c.e)},use(r){const n=i.find(o=>o.id===r);n&&(n.uses+=1)},toJSON(){return s(),i.map(r=>({...r}))},now:e}}function F(t=[]){return t.map(e=>({id:e.id,kind:"fetched",title:e.title,url:"",text:e.text}))}const N=t=>{const e=Math.floor(t/6e4);return e<1?"just now":`${e} min ago`};function L(t=[],{now:e=Date.now()}={}){return t.map(a=>({id:a.id,title:a.title,agoText:N(e-(a.at||e)),tokens:a.tokens}))}function z(t,e,{traitsOf:a=null,cacheable:f=null,now:p=null,turn:_=null}={}){if(!t||typeof t.execute!="function"||!e)return t;const i=p||e.now||(()=>Date.now()),m=a||(s=>t.traits?.get?.(s)||null),k=f||(s=>/^(history_|web_search$|weather$|read_page$|read_transcript$|list_|get_|search|fetch|read_|find_)/.test(s)),g=(s,r)=>{if(j.has(s)||j.has(r))return!1;const n=m(s)||m(r);return n?!!n.readOnly&&!n.destructive:k(s,r)};return{...t,async execute(s,r,n){const o=typeof r=="string"?(()=>{try{return JSON.parse(r)}catch{return r}})():r,h=w(s,o);if(!g(h,s))return t.execute(s,r,n);const u=e.lookup(s,o,{hiddenVia:t.hiddenVia});if(u)return e.use(u.id),{text:`${u.text}
2
2
 
3
- (cached: the same request was answered ${N(c()-l.at)}; not fetched again)`,note:"cached",cached:!0,fetchedId:l.id};const f=await t.execute(a,r,n),s=typeof f=="string"?f:f&&typeof f=="object"&&typeof f.text=="string"?f.text:"";return s&&e.remember({tool:a,input:i,text:s,turn:p}),f}}}export{k as FETCHED_TTL_MS,F as createFetchedStore,q as defaultTtl,j as fetchKey,J as fetchTitle,L as fetchedAsSources,z as fetchedFacts,I as withFetchedMemo};
3
+ (cached: the same request was answered ${N(i()-u.at)}; not fetched again)`,note:"cached",cached:!0,fetchedId:u.id};const d=await t.execute(s,r,n),c=typeof d=="string"?d:d&&typeof d=="object"&&typeof d.text=="string"?d.text:"";return c&&e.remember({tool:s,input:o,text:c,turn:_,hiddenVia:t.hiddenVia}),d}}}export{x as FETCHED_TTL_MS,C as createFetchedStore,q as defaultTtl,M as fetchKey,J as fetchTitle,F as fetchedAsSources,L as fetchedFacts,z as withFetchedMemo};
@@ -0,0 +1 @@
1
+ const l=Object.freeze([{id:"zoom",label:"Zoom",macos:["us.zoom.xos"],windows:["Zoom.exe"]},{id:"teams",label:"Microsoft Teams",macos:["com.microsoft.teams2","com.microsoft.teams"],windows:["ms-teams.exe","Teams.exe"]},{id:"webex",label:"Webex",macos:["Cisco-Systems.Spark"],windows:["CiscoCollabHost.exe"]},{id:"slack",label:"Slack",macos:["com.tinyspeck.slackmacgap"],windows:["slack.exe"]},{id:"facetime",label:"FaceTime",macos:["com.apple.FaceTime"],windows:[]}].map(e=>Object.freeze({...e,macos:Object.freeze(e.macos),windows:Object.freeze(e.windows)})));function u(e,c="macos"){const a=String(e??"").trim(),t=l.find(o=>o.id===a);return t?c==="macos"?[...t.macos]:[...t.windows]:c==="macos"&&/^[A-Za-z0-9][\w.-]{0,119}$/.test(a)&&a.includes(".")?[a]:[]}const r=(e,c)=>!!e&&!!c&&(e===c||e.startsWith(`${c}.`)),f=e=>!e||/^com\.apple\./.test(e)&&!l.some(c=>c.macos.some(a=>r(e,a))),d=e=>String(e??"").replace(/[\u0000-\u001f]/g,"").trim().slice(0,80);function g(e,{platform:c="macos",self:a=null}={}){if(c!=="macos")return[];const t=new Map;for(const o of Array.isArray(e)?e:[]){const s=d(o?.bundleID);if(f(s)||a&&r(s,a))continue;const n=l.find(m=>m.macos.some(w=>r(s,w))),p=n?n.id:[...t.keys()].find(m=>!l.some(w=>w.id===m)&&r(s,m))||s,i=t.get(p)||{id:p,label:n?n.label:d(o?.name)||s,bundles:n?[...n.macos]:[s],meeting:!!n,playing:!1,mic:!1};i.playing=i.playing||!!o?.output,i.mic=i.mic||!!o?.input,t.set(p,i)}return[...t.values()].filter(o=>o.meeting||o.playing).sort((o,s)=>s.meeting-o.meeting||s.playing-o.playing||o.label.localeCompare(s.label))}export{l as MEETING_APPS,u as appBundles,r as bundleMatches,g as rankAudioApps};
@@ -1 +1 @@
1
- const m=Object.freeze({transcript:"The live transcript (the last few minutes)",summary:"The running meeting summary",findings:"What this monitor already found",web:"Web search",history:"Your past chats, meetings & notes",mcp:"Your connected MCP tools"}),i=Object.freeze({targetId:"",windowMin:5,maxFindings:6,maxMcpTools:2,sources:Object.freeze({transcript:!0,summary:!0,findings:!0,web:!1,history:!1,mcp:!1})}),u=(t,e,r,n)=>{if(t==null||t==="")return e;const s=Number(t);return Number.isFinite(s)?Math.min(n,Math.max(r,s)):e};function f(t){const e=t?.ui?.monitors||{},r=e.sources||{};return{targetId:String(e.targetId||""),windowMin:u(e.windowMin,i.windowMin,1,60),maxFindings:u(e.maxFindings,i.maxFindings,0,40),maxMcpTools:u(e.maxMcpTools,i.maxMcpTools,0,20),sources:Object.fromEntries(Object.keys(m).map(n=>[n,n==="transcript"?!0:r[n]===void 0?i.sources[n]:!!r[n]]))}}const p=t=>Math.max(1,t?.windowMin||5)*6e4,d=t=>!!(t?.sources?.web||t?.sources?.history||t?.sources?.mcp);function h(t,e){const r=t?.specs;if(!Array.isArray(r)||!r.length)return t;const n=e?.sources||{},s=a=>{const c=String(a||"");return c.startsWith("mcp_")?!!n.mcp:/^(web_search|search_web|fetch_url)$/.test(c)?!!n.web:/^(history_search|history_get|find_related|smart_search)$/.test(c)?!!n.history:!!/^meeting_live_transcript$/.test(c)},o=r.filter(a=>s(a?.name));return o.length===r.length?t:{...t,specs:o}}function l(t,e){if(!e?.sources?.findings)return[];const r=Array.isArray(t)?t:[],n=e?.maxFindings??i.maxFindings;return n>0?r.slice(-n):[]}function g(t){const e=Object.entries(t?.sources||{}).filter(([s,o])=>o&&s!=="transcript").map(([s])=>s),r=["last "+(t?.windowMin||5)+" min of transcript",...e],n=d(t);return`${r.join(" + ")} — ${n?"with tools, slower":"no tools, fastest"}`}export{i as DEFAULT_MONITOR_PROFILE,m as MONITOR_SOURCES,g as describeMonitorProfile,h as filterMonitorTools,d as monitorNeedsTools,f as monitorProfile,p as monitorWindowMs,l as recentFindings};
1
+ const x=Object.freeze({transcript:"The live transcript (the last few minutes)",summary:"The running meeting summary",findings:"What this monitor already found",web:"Web search",history:"Your past chats, meetings & notes",mcp:"Your connected MCP tools"}),a=Object.freeze({targetId:"",windowMin:5,maxFindings:6,maxMcpTools:2,sources:Object.freeze({transcript:!0,summary:!0,findings:!0,web:!1,history:!1,mcp:!1})}),f=(e,n,s,r)=>{if(e==null||e==="")return n;const i=Number(e);return Number.isFinite(i)?Math.min(r,Math.max(s,i)):n};function b(e){const n=e?.ui?.monitors||{},s=n.sources||{};return{targetId:String(n.targetId||""),windowMin:f(n.windowMin,a.windowMin,1,60),maxFindings:f(n.maxFindings,a.maxFindings,0,40),maxMcpTools:f(n.maxMcpTools,a.maxMcpTools,0,20),sources:Object.fromEntries(Object.keys(x).map(r=>[r,r==="transcript"?!0:s[r]===void 0?a.sources[r]:!!s[r]]))}}const y=e=>Math.max(1,e?.windowMin||5)*6e4,M=e=>!!(e?.sources?.web||e?.sources?.history||e?.sources?.mcp);function _(e,n){const s=e?.specs;if(!Array.isArray(s)||!s.length)return e;const r=n?.sources||{},i=t=>{const o=String(t||"");return o.startsWith("mcp_")?!!r.mcp:/^(web_search|search_web|fetch_url)$/.test(o)?!!r.web:/^(history_search|history_get|find_related|smart_search)$/.test(o)?!!r.history:!!/^meeting_live_transcript$/.test(o)},u=e.hiddenVia instanceof Map?e.hiddenVia:new Map,c=new Map([...u].filter(([t])=>i(t))),d=new Set(c.values()),h=s.filter(t=>i(t?.name)||d.has(t?.name)),g=(Array.isArray(e.reach)?e.reach:[]).filter(t=>c.has(t?.name));if(h.length===s.length&&c.size===u.size)return e;const l=e.execute,p=t=>JSON.stringify({error:`${t} is not available to this monitor.`});return{...e,specs:h,reach:g,hiddenVia:c,execute(t,o,w){if(d.has(t)){const m=o&&typeof o=="object"?String(o.action||""):"";if(m!=="describe"&&c.get(m)!==t)return p(m||t)}else if(!i(t))return p(t);return l(t,o,w)}}}function O(e,n){if(!n?.sources?.findings)return[];const s=Array.isArray(e)?e:[],r=n?.maxFindings??a.maxFindings;return r>0?s.slice(-r):[]}function T(e){const n=Object.entries(e?.sources||{}).filter(([i,u])=>u&&i!=="transcript").map(([i])=>i),s=["last "+(e?.windowMin||5)+" min of transcript",...n],r=M(e);return`${s.join(" + ")} — ${r?"with tools, slower":"no tools, fastest"}`}export{a as DEFAULT_MONITOR_PROFILE,x as MONITOR_SOURCES,T as describeMonitorProfile,_ as filterMonitorTools,M as monitorNeedsTools,b as monitorProfile,y as monitorWindowMs,O as recentFindings};
@@ -0,0 +1,10 @@
1
+ const g=n=>String(n||"Speaker").replace(/[*_[\]`\n\r]/g,"").trim().slice(0,60)||"Speaker";function x(n,r,s=null){const e=String(n?.text??""),t=Math.min(Math.max(Number(n?.end??n?.start??e.length)||0,0),e.length),d=Math.min(Math.max(Number(n?.start??t)||0,0),t),i=String(r?.text??"").replace(/\s+/g," ").trim();if(!i)return{text:e,caret:t,last:s};const l=!!s&&s.sid===r.sid&&s.at===t&&d===t;let a;if(l)a=` ${i}`;else{const o=e.slice(0,t);a=`${o.trim()?/\n\n$/.test(o)?"":/\n$/.test(o)?`
2
+ `:`
3
+
4
+ `:""}**${g(r.speaker)}:** ${i}`}const c=e.slice(t),h=l||!c||c.startsWith(`
5
+
6
+ `)?"":c.startsWith(`
7
+ `)?`
8
+ `:`
9
+
10
+ `,m=t+a.length;return{text:e.slice(0,t)+a+h+c,caret:m,last:{sid:r.sid,at:m}}}export{x as transcriptInsert};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chatpanel/events",
3
- "version": "0.221.0",
3
+ "version": "0.226.0",
4
4
  "description": "The canonical ChatPanel event-log and capability contracts — typed durable facts, clock-free deterministic linearization, schema upcasting, and the invariants the replay harness asserts. Pure, dependency-free ESM shared by the ChatPanel extension, gateway and bridge.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -216,6 +216,9 @@
216
216
  "./voice-speaker.js": "./voice-speaker.js",
217
217
  "./voice-channels.js": "./voice-channels.js",
218
218
  "./voice-scribe.js": "./voice-scribe.js",
219
+ "./capture-plan.js": "./capture-plan.js",
220
+ "./meeting-apps.js": "./meeting-apps.js",
221
+ "./note-transcript.js": "./note-transcript.js",
219
222
  "./voice-loop.js": "./voice-loop.js",
220
223
  "./voice-vad.js": "./voice-vad.js",
221
224
  "./voice-sample.js": "./voice-sample.js",
@@ -460,6 +463,9 @@
460
463
  "voice-speaker.js",
461
464
  "voice-channels.js",
462
465
  "voice-scribe.js",
466
+ "capture-plan.js",
467
+ "meeting-apps.js",
468
+ "note-transcript.js",
463
469
  "voice-loop.js",
464
470
  "voice-vad.js",
465
471
  "voice-sample.js",
package/turn-loop.js CHANGED
@@ -1,6 +1,6 @@
1
- import{runToolRound as st}from"./tool-round.js";import{toolTraits as at,effectiveToolName as G,parallelEligible as it}from"./tool-traits.js";import{createToolLoopGuard as C,roundSignature as ut,toolMadeProgress as ct,blockedToolResult as lt}from"./tool-loop-guard.js";import{createAdaptiveToolPolicy as Y,resultText as J}from"./adaptive-tool-policy.js";import{toolStatus as pt}from"./tool-hints.js";const F=60,dt=6,K=4e3,H=`
1
+ import{runToolRound as st}from"./tool-round.js";import{toolTraits as at,effectiveToolName as E,parallelEligible as it}from"./tool-traits.js";import{createToolLoopGuard as C,roundSignature as ut,toolMadeProgress as ct,blockedToolResult as lt}from"./tool-loop-guard.js";import{createAdaptiveToolPolicy as Y,adaptiveToolRetryHint as pt,resultText as F}from"./adaptive-tool-policy.js";import{toolStatus as dt}from"./tool-hints.js";const H=60,mt=6,K=4e3,G=`
2
2
 
3
- `,q=Object.freeze(["The tool budget for this turn is spent. Do not call tools again; write your answer now with what you have, including your findings.","No more tool calls will be answered. Reply with your answer as plain text, now — a partial answer beats none.","FINAL: any further tool call ends this turn with no answer. Write what you have found, as text, in this message."]),mt="You have repeated the same tool call several times. Do not call tools again; answer now with what you have.",Rt='_(Reached the action limit for one turn — say "continue" to keep going.)_';function At({tools:t,agent:o,settings:e,fallback:n=F}={}){if(!t)return 1;const s=Math.max(1,Number(n)||F),i=Number(o?.maxRequestsPerTurn)||0;if(i>0)return Math.min(s,i);const m=Number(e?.ui?.maxToolRoundsPerTurn??e?.maxToolRoundsPerTurn)||0;return m>0?Math.min(s,m):s}function z(t){if(!t)return{};if(typeof t=="object")return t;try{return JSON.parse(t)}catch{return{}}}const Q=t=>typeof t.arguments=="string"?t.arguments:JSON.stringify(t.arguments??t.input??{});function ft(t){const o=String(J(t)||"");return o.length>K?`${o.slice(0,K)}…`:o}function ht(t,o){const e=G(t,o),n=o&&typeof o=="object"&&o.args&&typeof o.args=="object"?o.args:o||{},s=["query","id","tool","location","ref"].find(i=>typeof n[i]=="string"&&n[i]);return s?`${e} "${String(n[s]).slice(0,80)}"`:e}function Nt(t,o){const e=Array.isArray(t)?[...t]:[],n=String(o||"").trim();if(!n)return e;const s=e.findIndex(i=>i?.role==="system"&&typeof i.content=="string");return s>=0?(e[s]={...e[s],content:`${e[s].content}
3
+ `,q=Object.freeze(["The tool budget for this turn is spent. Do not call tools again; write your answer now with what you have, including your findings.","No more tool calls will be answered. Reply with your answer as plain text, now — a partial answer beats none.","FINAL: any further tool call ends this turn with no answer. Write what you have found, as text, in this message."]),ft="You have repeated the same tool call several times. Do not call tools again; answer now with what you have.",Nt='_(Reached the action limit for one turn — say "continue" to keep going.)_';function At({tools:t,agent:o,settings:e,fallback:n=H}={}){if(!t)return 1;const s=Math.max(1,Number(n)||H),i=Number(o?.maxRequestsPerTurn)||0;if(i>0)return Math.min(s,i);const m=Number(e?.ui?.maxToolRoundsPerTurn??e?.maxToolRoundsPerTurn)||0;return m>0?Math.min(s,m):s}function z(t){if(!t)return{};if(typeof t=="object")return t;try{return JSON.parse(t)}catch{return{}}}const Q=t=>typeof t.arguments=="string"?t.arguments:JSON.stringify(t.arguments??t.input??{});function ht(t){const o=String(F(t)||"");return o.length>K?`${o.slice(0,K)}…`:o}function yt(t,o){const e=E(t,o),n=o&&typeof o=="object"&&o.args&&typeof o.args=="object"?o.args:o||{},s=["query","id","tool","location","ref"].find(i=>typeof n[i]=="string"&&n[i]);return s?`${e} "${String(n[s]).slice(0,80)}"`:e}function Ot(t,o){const e=Array.isArray(t)?[...t]:[],n=String(o||"").trim();if(!n)return e;const s=e.findIndex(i=>i?.role==="system"&&typeof i.content=="string");return s>=0?(e[s]={...e[s],content:`${e[s].content}
4
4
 
5
- ${n}`},e):[{role:"system",content:n},...e]}const _=t=>Number(t)||0;function Z(t){if(!t||typeof t!="object")return null;const o=_(t.inputTokens??t.input_tokens??t.prompt_tokens),e=_(t.outputTokens??t.output_tokens??t.completion_tokens),n=_(t.cacheReadTokens??t.cache_read_input_tokens??t.prompt_tokens_details?.cached_tokens),s=_(t.cacheWriteTokens??t.cache_creation_input_tokens),i={inputTokens:o,outputTokens:e,cacheReadTokens:n,cacheWriteTokens:s,prompt_tokens:o,completion_tokens:e,total_tokens:_(t.total_tokens)||o+e,calls:_(t.calls)||1,reported:t.reported!==!1&&(o>0||e>0)},m=_(t.usd??t.cost);return m&&(i.usd=m),i}function yt(t,o){const e=Z(t),n=Z(o);if(!n)return e;if(!e)return n;const s={inputTokens:e.inputTokens+n.inputTokens,outputTokens:e.outputTokens+n.outputTokens,cacheReadTokens:e.cacheReadTokens+n.cacheReadTokens,cacheWriteTokens:e.cacheWriteTokens+n.cacheWriteTokens,calls:e.calls+n.calls,reported:e.reported||n.reported};s.prompt_tokens=s.inputTokens,s.completion_tokens=s.outputTokens,s.total_tokens=e.total_tokens+n.total_tokens;const i=_(e.usd)+_(n.usd);return i&&(s.usd=i),s}function tt(t){return Math.max(0,Math.round(String(t||"").length/4))}function kt(t,o){const e=(t||[]).map(n=>typeof n?.content=="string"?n.content:JSON.stringify(n?.content||"")).join(`
6
- `);return{inputTokens:tt(e),outputTokens:tt(o),cacheReadTokens:0,cacheWriteTokens:0,estimated:!0}}const gt=Object.freeze({asked(t,o){return{role:"assistant",content:String(t?.text||"")||null,tool_calls:o.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:Q(e)}}))}},answered(t,{noVision:o=!1}={}){const e=t.map(({call:n,result:s})=>({role:"tool",tool_call_id:n.id,content:J(s)}));for(const{call:n,result:s}of t){const i=s&&typeof s=="object"?s.image:null;i&&e.push(o?{role:"user",content:`(Screenshot from ${n.name} omitted — this model has no vision. Rely on read_canvas / inspect_page / tool results.)`}:{role:"user",content:[{type:"text",text:`(Screenshot from ${n.name})`},{type:"image_url",image_url:{url:i}}]})}return e},nudge(t,o){return[{role:"assistant",content:null,tool_calls:t.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:Q(e)}}))},...t.map(e=>({role:"tool",tool_call_id:e.id,content:o}))]},system:t=>({role:"system",content:t}),said:t=>({role:"assistant",content:t})}),Ot=Object.freeze({asked(t,o){return{role:"assistant",content:Array.isArray(t?.blocks)&&t.blocks.length?t.blocks.filter(n=>n&&(n.type==="tool_use"||n.type==="text"&&n.text)).map(n=>n.type==="tool_use"?{type:"tool_use",id:n.id,name:n.name,input:n.input??z(n.json)}:{type:"text",text:n.text}):[...t?.text?[{type:"text",text:String(t.text)}]:[],...o.map(n=>({type:"tool_use",id:n.id,name:n.name,input:n.input}))]}},answered(t){return[{role:"user",content:t.map(({call:o,result:e})=>{const n=J(e),s=e&&typeof e=="object"?e.image:null;if(!s)return{type:"tool_result",tool_use_id:o.id,content:n};const i=/^data:([^;]+);base64,(.+)$/s.exec(s),m=[];return i&&m.push({type:"image",source:{type:"base64",media_type:i[1],data:i[2]}}),m.push({type:"text",text:n}),{type:"tool_result",tool_use_id:o.id,content:m}})}]},nudge(t,o){return[{role:"assistant",content:t.map(e=>({type:"tool_use",id:e.id,name:e.name,input:e.input}))},{role:"user",content:t.map(e=>({type:"tool_result",tool_use_id:e.id,content:o}))}]},system:t=>({role:"user",content:t}),said:t=>({role:"assistant",content:t})});function Tt({tools:t,guard:o=C(),policy:e=Y(),modelLabel:n=()=>null,maxCalls:s=0,onStep:i=null,steps:m=[]}={}){let y=0;const A=r=>{const a=G(r.name,r.input);return t?.traits?.get(a)||t?.traits?.get(r.name)||at({name:a})},E=(r,a,u)=>{const T={phase:a,callId:r.id,name:r.name,action:G(r.name,r.input),input:r.input,text:ht(r.name,r.input),model:n()};if(a==="done"){const f=u&&typeof u=="object"?u.image:void 0;Object.assign(T,{status:pt(u),result:ft(u),...f?{image:f}:{}})}return T},x=r=>{try{i?.(E(r,"start"))}catch{}},N=(r,a)=>{const u=E(r,"done",a);m.push(u);try{i?.(u)}catch{}},U=(r,a,u)=>{e.recordResult(r.name,u),!a.blocked&&!a.replayed&&ct(r.name,u,r.input)&&o.reset(a.key),a.replayed||o.remember(a.key,r.name,r.input,u,{readOnly:!!A(r)?.readOnly})},v=r=>lt(r.name,q[Math.min(Math.max(0,y-s-1),q.length-1)],{budget:"spent",calls:y,maxCalls:s}),O=async(r,a,u)=>(y+=1,s>0&&y>s?v(r):a.blocked||a.replayed?a.result:typeof t?.execute!="function"?JSON.stringify({error:"no tools armed"}):t.execute(r.name,r.input,{callId:r.id,...u||{}}));return{guard:o,policy:e,steps:m,traitsOf:A,get calls(){return y},get exhausted(){return s>0&&y>=s},async one(r,a=null){const u={id:r.id,name:r.name,input:r.input??z(r.arguments)};x(u);const T=o.check(u.name,u.input);let f;try{f=await O(u,T,a)}catch(c){f=JSON.stringify({error:String(c?.message||c)})}return U(u,T,f),N(u,f),f},async round(r){const a=r.map(c=>({id:c.id,name:c.name,input:c.input??z(c.arguments)})),u=a.map(c=>o.check(c.name,c.input)),{results:T}=await st(a,{execute:(c,g)=>O(c,u[g]),traitsOf:A,concurrent:(c,g)=>it(t,c,g),onStart:c=>x(c),onDone:(c,g,D)=>N(c,D)});T.forEach((c,g)=>U(a[g],u[g],c));const f=u.filter(c=>c.blocked).length;return o.noteRound(f,a.length,ut(a)),{calls:a,results:T,blocked:f}}}}async function jt({model:t,messages:o,tools:e,signal:n,redaction:s,run:i,stream:m,transcript:y=gt,maxRounds:A=F,maxFinishTries:E=dt,guard:x=C(),policy:N=Y(),modelLabel:U=()=>t||null,usageLabel:v=null,onDelta:O=null,onEvent:r=null,onStep:a=null,onMessage:u=null,onActivity:T=null}={}){if(typeof m!="function")throw new Error("runTurnLoop: stream required");const f=!!(e&&Array.isArray(e.specs)&&e.specs.length),c=f?e.specs:null,g=f?Math.max(1,Number(A)||F):1,D=[],et=Tt({tools:e,guard:x,policy:N,modelLabel:U,steps:D,onStep:k=>{try{a?.(k)}catch{}try{r?.({type:"tool",...k})}catch{}}});let b=[...o||[]],p="",S=null,R=0,X=!1,I=0,W=!1;const j=k=>{for(const d of k){b=[...b,d];try{u?.(d)}catch{}}},M=k=>{try{r?.({type:"finish",reason:k})}catch{}},V=k=>{if(!r)return;const d=S&&S.reported?{...S,estimated:!1}:kt(b,k);try{r({type:"usage",provider:v?.provider||"unknown",model:v?.model||t||null,inputTokens:d.inputTokens,outputTokens:d.outputTokens,cacheReadTokens:d.cacheReadTokens,cacheWriteTokens:d.cacheWriteTokens,estimated:!!d.estimated,requests:R+1})}catch{}},B=k=>({ok:!0,text:p,usage:S,rounds:R,steps:D,transcript:b,exhausted:W,aborted:!1,...k}),P=(k,d={})=>{const w=String(k||"");return w.trim()&&j([y.said(w)]),B(d)};for(;;){R+=1;const d=!f||R>=g||x.stalled||x.looping||I>0?null:c.filter(l=>!N.isSuppressed(l?.name));let w="";const h=await m({model:t,messages:b,tools:d&&d.length?d:null,signal:n,onActivity:T,...s!==void 0?{redaction:s}:{},...i?{run:i}:{},onDelta:l=>{if(l){if(!w&&p){p+=H;try{O?.(H,p)}catch{}}w+=l,p+=l;try{O?.(l,p)}catch{}}}});h?.usage&&(S=yt(S,h.usage)),h?.noVision&&(X=!0);const $=String(h?.text||"");if($&&!w&&(p&&(p+=H),p+=$,w=$),!h?.ok)return M("error"),B({ok:!1,error:h?.error||"the model did not answer",...h?.status?{status:h.status}:{},aborted:!!h?.aborted,transcript:$.trim()?[...b,y.said(p)]:b});if(h.aborted||n?.aborted)return M("aborted"),P(p,{aborted:!0});const L=(Array.isArray(h.toolCalls)?h.toolCalls:[]).filter(l=>l&&l.name).map(l=>({id:l.id,name:l.name,input:l.input??z(l.arguments),arguments:l.arguments}));if(!L.length)return M(h.finish||"stop"),V(p),P(p);if(!d||!d.length){if(I+=1,I>E)return M("tool-step-limit"),V(p),P(p,{exhausted:!0});W=W||R>=g,j(y.nudge(L,q[Math.min(I-1,q.length-1)]));continue}j([y.asked(h,L)]);const{calls:nt,results:ot}=await et.round(L);if(j(y.answered(nt.map((l,rt)=>({call:l,result:ot[rt]})),{noVision:X})),n?.aborted)return M("aborted"),P(p,{aborted:!0});x.looping&&j([y.system(mt)]),R+1>=g&&(W=!0)}}export{dt as DEFAULT_MAX_FINISH_TRIES,F as DEFAULT_MAX_ROUNDS,Rt as EXHAUSTED_NOTE,q as FINISH_NUDGES,mt as LOOPING_NUDGE,H as ROUND_SEPARATOR,K as STEP_RESULT_MAX_CHARS,yt as addUsage,Ot as anthropicTranscript,Tt as createCallRunner,ht as describeCall,tt as estimateTokens,Z as normalizeUsage,gt as openAiTranscript,J as resultText,At as roundCap,jt as runTurnLoop,ft as stepResultText,Nt as withToolSystem};
5
+ ${n}`},e):[{role:"system",content:n},...e]}const _=t=>Number(t)||0;function Z(t){if(!t||typeof t!="object")return null;const o=_(t.inputTokens??t.input_tokens??t.prompt_tokens),e=_(t.outputTokens??t.output_tokens??t.completion_tokens),n=_(t.cacheReadTokens??t.cache_read_input_tokens??t.prompt_tokens_details?.cached_tokens),s=_(t.cacheWriteTokens??t.cache_creation_input_tokens),i={inputTokens:o,outputTokens:e,cacheReadTokens:n,cacheWriteTokens:s,prompt_tokens:o,completion_tokens:e,total_tokens:_(t.total_tokens)||o+e,calls:_(t.calls)||1,reported:t.reported!==!1&&(o>0||e>0)},m=_(t.usd??t.cost);return m&&(i.usd=m),i}function kt(t,o){const e=Z(t),n=Z(o);if(!n)return e;if(!e)return n;const s={inputTokens:e.inputTokens+n.inputTokens,outputTokens:e.outputTokens+n.outputTokens,cacheReadTokens:e.cacheReadTokens+n.cacheReadTokens,cacheWriteTokens:e.cacheWriteTokens+n.cacheWriteTokens,calls:e.calls+n.calls,reported:e.reported||n.reported};s.prompt_tokens=s.inputTokens,s.completion_tokens=s.outputTokens,s.total_tokens=e.total_tokens+n.total_tokens;const i=_(e.usd)+_(n.usd);return i&&(s.usd=i),s}function tt(t){return Math.max(0,Math.round(String(t||"").length/4))}function gt(t,o){const e=(t||[]).map(n=>typeof n?.content=="string"?n.content:JSON.stringify(n?.content||"")).join(`
6
+ `);return{inputTokens:tt(e),outputTokens:tt(o),cacheReadTokens:0,cacheWriteTokens:0,estimated:!0}}const Tt=Object.freeze({asked(t,o){return{role:"assistant",content:String(t?.text||"")||null,tool_calls:o.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:Q(e)}}))}},answered(t,{noVision:o=!1}={}){const e=t.map(({call:n,result:s})=>({role:"tool",tool_call_id:n.id,content:F(s)}));for(const{call:n,result:s}of t){const i=s&&typeof s=="object"?s.image:null;i&&e.push(o?{role:"user",content:`(Screenshot from ${n.name} omitted — this model has no vision. Rely on read_canvas / inspect_page / tool results.)`}:{role:"user",content:[{type:"text",text:`(Screenshot from ${n.name})`},{type:"image_url",image_url:{url:i}}]})}return e},nudge(t,o){return[{role:"assistant",content:null,tool_calls:t.map(e=>({id:e.id,type:"function",function:{name:e.name,arguments:Q(e)}}))},...t.map(e=>({role:"tool",tool_call_id:e.id,content:o}))]},system:t=>({role:"system",content:t}),said:t=>({role:"assistant",content:t})}),jt=Object.freeze({asked(t,o){return{role:"assistant",content:Array.isArray(t?.blocks)&&t.blocks.length?t.blocks.filter(n=>n&&(n.type==="tool_use"||n.type==="text"&&n.text)).map(n=>n.type==="tool_use"?{type:"tool_use",id:n.id,name:n.name,input:n.input??z(n.json)}:{type:"text",text:n.text}):[...t?.text?[{type:"text",text:String(t.text)}]:[],...o.map(n=>({type:"tool_use",id:n.id,name:n.name,input:n.input}))]}},answered(t){return[{role:"user",content:t.map(({call:o,result:e})=>{const n=F(e),s=e&&typeof e=="object"?e.image:null;if(!s)return{type:"tool_result",tool_use_id:o.id,content:n};const i=/^data:([^;]+);base64,(.+)$/s.exec(s),m=[];return i&&m.push({type:"image",source:{type:"base64",media_type:i[1],data:i[2]}}),m.push({type:"text",text:n}),{type:"tool_result",tool_use_id:o.id,content:m}})}]},nudge(t,o){return[{role:"assistant",content:t.map(e=>({type:"tool_use",id:e.id,name:e.name,input:e.input}))},{role:"user",content:t.map(e=>({type:"tool_result",tool_use_id:e.id,content:o}))}]},system:t=>({role:"user",content:t}),said:t=>({role:"assistant",content:t})});function _t({tools:t,guard:o=C(),policy:e=Y(),modelLabel:n=()=>null,maxCalls:s=0,onStep:i=null,steps:m=[]}={}){let k=0;const N=r=>{const a=E(r.name,r.input);return t?.traits?.get(a)||t?.traits?.get(r.name)||at({name:a})},v=(r,a,u)=>{const f={phase:a,callId:r.id,name:r.name,action:E(r.name,r.input),input:r.input,text:yt(r.name,r.input),model:n()};if(a==="done"){const h=u&&typeof u=="object"?u.image:void 0;Object.assign(f,{status:dt(u),result:ht(u),...h?{image:h}:{}})}return f},x=r=>{try{i?.(v(r,"start"))}catch{}},A=(r,a)=>{const u=v(r,"done",a);m.push(u);try{i?.(u)}catch{}},U=(r,a,u)=>{e.recordResult(E(r.name,r.input),u),!a.blocked&&!a.replayed&&ct(r.name,u,r.input)&&o.reset(a.key),a.replayed||o.remember(a.key,r.name,r.input,u,{readOnly:!!N(r)?.readOnly})},D=r=>lt(r.name,q[Math.min(Math.max(0,k-s-1),q.length-1)],{budget:"spent",calls:k,maxCalls:s}),O=async(r,a,u)=>{if(k+=1,s>0&&k>s)return D(r);if(a.blocked||a.replayed)return a.result;if(typeof t?.execute!="function")return JSON.stringify({error:"no tools armed"});const f=E(r.name,r.input);return f!==r.name&&e.isSuppressed(f)?JSON.stringify({error:`${f} rejected its parameters earlier in this turn and is off for the rest of it.`,retry_hint:pt(f)}):t.execute(r.name,r.input,{callId:r.id,...u||{}})};return{guard:o,policy:e,steps:m,traitsOf:N,get calls(){return k},get exhausted(){return s>0&&k>=s},async one(r,a=null){const u={id:r.id,name:r.name,input:r.input??z(r.arguments)};x(u);const f=o.check(u.name,u.input);let h;try{h=await O(u,f,a)}catch(c){h=JSON.stringify({error:String(c?.message||c)})}return U(u,f,h),A(u,h),h},async round(r){const a=r.map(c=>({id:c.id,name:c.name,input:c.input??z(c.arguments)})),u=a.map(c=>o.check(c.name,c.input)),{results:f}=await st(a,{execute:(c,T)=>O(c,u[T]),traitsOf:N,concurrent:(c,T)=>it(t,c,T),onStart:c=>x(c),onDone:(c,T,I)=>A(c,I)});f.forEach((c,T)=>U(a[T],u[T],c));const h=u.filter(c=>c.blocked).length;return o.noteRound(h,a.length,ut(a)),{calls:a,results:f,blocked:h}}}}async function Mt({model:t,messages:o,tools:e,signal:n,redaction:s,run:i,stream:m,transcript:k=Tt,maxRounds:N=H,maxFinishTries:v=mt,guard:x=C(),policy:A=Y(),modelLabel:U=()=>t||null,usageLabel:D=null,onDelta:O=null,onEvent:r=null,onStep:a=null,onMessage:u=null,onActivity:f=null}={}){if(typeof m!="function")throw new Error("runTurnLoop: stream required");const h=!!(e&&Array.isArray(e.specs)&&e.specs.length),c=h?e.specs:null,T=h?Math.max(1,Number(N)||H):1,I=[],et=_t({tools:e,guard:x,policy:A,modelLabel:U,steps:I,onStep:g=>{try{a?.(g)}catch{}try{r?.({type:"tool",...g})}catch{}}});let b=[...o||[]],p="",w=null,R=0,X=!1,W=0,$=!1;const j=g=>{for(const d of g){b=[...b,d];try{u?.(d)}catch{}}},M=g=>{try{r?.({type:"finish",reason:g})}catch{}},V=g=>{if(!r)return;const d=w&&w.reported?{...w,estimated:!1}:gt(b,g);try{r({type:"usage",provider:D?.provider||"unknown",model:D?.model||t||null,inputTokens:d.inputTokens,outputTokens:d.outputTokens,cacheReadTokens:d.cacheReadTokens,cacheWriteTokens:d.cacheWriteTokens,estimated:!!d.estimated,requests:R+1})}catch{}},B=g=>({ok:!0,text:p,usage:w,rounds:R,steps:I,transcript:b,exhausted:$,aborted:!1,...g}),P=(g,d={})=>{const S=String(g||"");return S.trim()&&j([k.said(S)]),B(d)};for(;;){R+=1;const d=!h||R>=T||x.stalled||x.looping||W>0?null:c.filter(l=>!A.isSuppressed(l?.name));let S="";const y=await m({model:t,messages:b,tools:d&&d.length?d:null,signal:n,onActivity:f,...s!==void 0?{redaction:s}:{},...i?{run:i}:{},onDelta:l=>{if(l){if(!S&&p){p+=G;try{O?.(G,p)}catch{}}S+=l,p+=l;try{O?.(l,p)}catch{}}}});y?.usage&&(w=kt(w,y.usage)),y?.noVision&&(X=!0);const J=String(y?.text||"");if(J&&!S&&(p&&(p+=G),p+=J,S=J),!y?.ok)return M("error"),B({ok:!1,error:y?.error||"the model did not answer",...y?.status?{status:y.status}:{},aborted:!!y?.aborted,transcript:J.trim()?[...b,k.said(p)]:b});if(y.aborted||n?.aborted)return M("aborted"),P(p,{aborted:!0});const L=(Array.isArray(y.toolCalls)?y.toolCalls:[]).filter(l=>l&&l.name).map(l=>({id:l.id,name:l.name,input:l.input??z(l.arguments),arguments:l.arguments}));if(!L.length)return M(y.finish||"stop"),V(p),P(p);if(!d||!d.length){if(W+=1,W>v)return M("tool-step-limit"),V(p),P(p,{exhausted:!0});$=$||R>=T,j(k.nudge(L,q[Math.min(W-1,q.length-1)]));continue}j([k.asked(y,L)]);const{calls:nt,results:ot}=await et.round(L);if(j(k.answered(nt.map((l,rt)=>({call:l,result:ot[rt]})),{noVision:X})),n?.aborted)return M("aborted"),P(p,{aborted:!0});x.looping&&j([k.system(ft)]),R+1>=T&&($=!0)}}export{mt as DEFAULT_MAX_FINISH_TRIES,H as DEFAULT_MAX_ROUNDS,Nt as EXHAUSTED_NOTE,q as FINISH_NUDGES,ft as LOOPING_NUDGE,G as ROUND_SEPARATOR,K as STEP_RESULT_MAX_CHARS,kt as addUsage,jt as anthropicTranscript,_t as createCallRunner,yt as describeCall,tt as estimateTokens,Z as normalizeUsage,Tt as openAiTranscript,F as resultText,At as roundCap,Mt as runTurnLoop,ht as stepResultText,Ot as withToolSystem};
package/voice-channels.js CHANGED
@@ -1 +1 @@
1
- import{PINNED_SELF as $}from"./voice-speaker.js";const O=Object.freeze(["mic","playback"]),_=$,S="Speaker",w="In room",L=Object.freeze(["self","room"]),A=6e3,I=4e3,j=new Set(["thank you","thanks","you","uh","um","hmm","hm","mm","amen","bye","okay","ok","yeah","oh","the","that","so","and","i","a","me","we","yes","no","you you","thank you thank you"]);function C(n,r=null){if(r!=null&&r>2e3)return!1;const l=String(n||"").toLowerCase().replace(/[^\p{L}\p{N}\s]/gu,"").replace(/\s+/g," ").trim();return!l||j.has(l)}const R=n=>String(n||"").split(/\s+/).filter(Boolean).slice(0,2).map(r=>r[0].toUpperCase()).join("")||"?",D=n=>{if(!n)return S;const r=typeof n=="string"?n:n.label||n.id;return String(r||"").trim()||S};function P(n,r,{mic:l="self",playback:h=!0}={}){if(n==="mic"&&l!=="room")return _;const f=D(r);return n!=="mic"||!h?f:/^Speaker\b/.test(f)?f.replace(/^Speaker\b/,w):`${w} · ${f}`}const b=n=>String(n||"").replace(/\s+/g," ").trim();function B({now:n=Date.now,mic:r="self",playback:l=!0,seed:h=[]}={}){if(!L.includes(r))throw new Error(`unknown mic mode: ${r}`);const f={mic:r,playback:l},s=[],k={mic:"",playback:""};let g=0;for(const e of Array.isArray(h)?h:[]){if(!e||!e.text)continue;const t=e.speaker===_||r==="room"&&!l?"mic":"playback";s.push({sid:`s:${++g}`,t:Number(e.t)||0,channel:t,speaker:String(e.speaker||S),text:b(e.text),open:!1,seed:!0})}const N=e=>{for(let t=s.length-1;t>=0;t--)if(s[t].channel===e)return s[t];return null};return{final(e,t,{speaker:i,endOfTurn:a,durationMs:c=null}={}){if(!O.includes(e))throw new Error(`unknown channel: ${e}`);const u=n(),p=b(t);if(!p||(k[e]="",C(p,c)))return null;const d=P(e,i,f),o=s[s.length-1],m=c!=null?u-c-o?.t:null,y=m!=null?m<=I:u-(o?.t||0)<=A;if(o&&!o.seed&&o.channel===e&&o.speaker===d&&(o.open||y))return o.text=`${o.text} ${p}`,o.t=u,o.open=a===!1,{...o,joined:!0};const E={sid:`a:${++g}`,t:u,channel:e,speaker:d,text:p,open:a===!1};return s.push(E),{...E,joined:!1}},interim(e,t){O.includes(e)&&(k[e]=b(t))},interims:()=>({...k}),segments:()=>s.map(({sid:e,t,channel:i,speaker:a,text:c})=>({sid:e,t,channel:i,speaker:a,text:c})),delta:(e=0,t=40)=>s.filter(i=>i.t>=e).slice(-t).map(({sid:i,t:a,speaker:c,text:u})=>({sid:i,t:a,speaker:c,text:u})),speakers(){const e={mic:[],playback:[]};for(const t of s)e[t.channel].includes(t.speaker)||e[t.channel].push(t.speaker);return e},last:e=>{const t=N(e);return t?{...t}:null},record({id:e,title:t,startedAt:i,status:a="live",endReason:c=null,participants:u}={}){const p=a==="ended",d=this.speakers();return{id:e,schemaVersion:1,platform:"audio",meetingKey:`${l?"audio":"room"}:${i}`,title:t||(l?"Audio transcript":"Room transcript"),url:"",status:a,endReason:p?c||"ended":null,startedAt:i,endedAt:p?n():null,participants:u||[...d.mic,...d.playback].map(m=>({name:m,initials:R(m)})),segments:s.map(({t:m,speaker:y,text:x})=>({t:m,speaker:y,text:x})),chat:[]}}}}export{O as CHANNELS,A as JOIN_GAP_MS,I as JOIN_PAUSE_MS,_ as MIC_LABEL,L as MIC_MODES,S as OTHER_LABEL,w as ROOM_PREFIX,P as channelSpeaker,B as createChannelTranscript,C as isNoiseFinal};
1
+ import{PINNED_SELF as B}from"./voice-speaker.js";const $=Object.freeze(["mic","playback"]),A=B,_="Speaker",M="In room",W=Object.freeze(["self","room"]),z=6e3,F=4e3,v=new Set(["thank you","thanks","you","uh","um","hmm","hm","mm","amen","bye","okay","ok","yeah","oh","the","that","so","and","i","a","me","we","yes","no","you you","thank you thank you"]);function J(n,o=null){if(o!=null&&o>2e3)return!1;const r=String(n||"").toLowerCase().replace(/[^\p{L}\p{N}\s]/gu,"").replace(/\s+/g," ").trim();return!r||v.has(r)}const j=15e3,T=4,U=.7,R=n=>String(n||"").toLowerCase().replace(/[^\p{L}\p{N}\s']/gu," ").split(/\s+/).filter(Boolean);function q(n,o){const r=new Map;for(const i of o)r.set(i,(r.get(i)||0)+1);let m=0;for(const i of n){const k=r.get(i)||0;k>0&&(m++,r.set(i,k-1))}return n.length?m/n.length:0}const G=n=>String(n||"").split(/\s+/).filter(Boolean).slice(0,2).map(o=>o[0].toUpperCase()).join("")||"?",K=n=>{if(!n)return _;const o=typeof n=="string"?n:n.label||n.id;return String(o||"").trim()||_};function V(n,o,{mic:r="self",playback:m=!0}={}){if(n==="mic"&&r!=="room")return A;const i=K(o);return n!=="mic"||!m?i:/^Speaker\b/.test(i)?i.replace(/^Speaker\b/,M):`${M} · ${i}`}const b=n=>String(n||"").replace(/\s+/g," ").trim();function Q({now:n=Date.now,mic:o="self",playback:r=!0,seed:m=[],echoGuard:i=!1}={}){if(!W.includes(o))throw new Error(`unknown mic mode: ${o}`);const k={mic:o,playback:r},s=[],x={mic:"",playback:""},D=!!i&&!!r;let S=[],E=0;const w=e=>(S=S.filter(t=>e-t.t<=j),S.flatMap(t=>t.words)),N=(e,t)=>e.length>=T&&q(e,t)>=U;for(const e of Array.isArray(m)?m:[]){if(!e||!e.text)continue;const t=e.speaker===A||o==="room"&&!r?"mic":"playback";s.push({sid:`s:${++E}`,t:Number(e.t)||0,channel:t,speaker:String(e.speaker||_),text:b(e.text),open:!1,seed:!0})}const H=e=>{for(let t=s.length-1;t>=0;t--)if(s[t].channel===e)return s[t];return null};return{final(e,t,{speaker:a,endOfTurn:u,durationMs:p=null}={}){if(!$.includes(e))throw new Error(`unknown channel: ${e}`);const c=n(),f=b(t);if(!f||(x[e]="",J(f,p)))return null;if(D){const I=R(f);if(e==="mic"){if(N(I,w(c)))return null}else{S.push({t:c,words:I});const P=w(c);for(let g=s.length-1;g>=0&&c-s[g].t<=j;g--){const O=s[g];O.channel==="mic"&&!O.seed&&N(R(O.text),P)&&s.splice(g,1)}}}const d=V(e,a,k),l=s[s.length-1],h=p!=null?c-p-l?.t:null,y=h!=null?h<=F:c-(l?.t||0)<=z;if(l&&!l.seed&&l.channel===e&&l.speaker===d&&(l.open||y))return l.text=`${l.text} ${f}`,l.t=c,l.open=u===!1,{...l,joined:!0};const L={sid:`a:${++E}`,t:c,channel:e,speaker:d,text:f,open:u===!1};return s.push(L),{...L,joined:!1}},interim(e,t){$.includes(e)&&(x[e]=b(t))},interims:()=>({...x}),segments:()=>s.map(({sid:e,t,channel:a,speaker:u,text:p})=>({sid:e,t,channel:a,speaker:u,text:p})),delta:(e=0,t=40)=>s.filter(a=>a.t>=e).slice(-t).map(({sid:a,t:u,speaker:p,text:c})=>({sid:a,t:u,speaker:p,text:c})),speakers(){const e={mic:[],playback:[]};for(const t of s)e[t.channel].includes(t.speaker)||e[t.channel].push(t.speaker);return e},last:e=>{const t=H(e);return t?{...t}:null},record({id:e,title:t,startedAt:a,status:u="live",endReason:p=null,participants:c}={}){const f=u==="ended",d=this.speakers();return{id:e,schemaVersion:1,platform:"audio",meetingKey:`${r?"audio":"room"}:${a}`,title:t||(r?"Audio transcript":"Room transcript"),url:"",status:u,endReason:f?p||"ended":null,startedAt:a,endedAt:f?n():null,participants:c||[...d.mic,...d.playback].map(h=>({name:h,initials:G(h)})),segments:s.map(({t:h,speaker:y,text:C})=>({t:h,speaker:y,text:C})),chat:[]}}}}export{$ as CHANNELS,U as ECHO_MATCH,T as ECHO_MIN_WORDS,j as ECHO_WINDOW_MS,z as JOIN_GAP_MS,F as JOIN_PAUSE_MS,A as MIC_LABEL,W as MIC_MODES,_ as OTHER_LABEL,M as ROOM_PREFIX,V as channelSpeaker,Q as createChannelTranscript,J as isNoiseFinal};
package/voice-scribe.js CHANGED
@@ -1 +1 @@
1
- import{createChannelTranscript as P}from"./voice-channels.js";const j=4e3,L=3e4,N={setTimeout:(e,i)=>setTimeout(e,i),clearTimeout:e=>clearTimeout(e),setInterval:(e,i)=>setInterval(e,i),clearInterval:e=>clearInterval(e)},G=()=>Math.random().toString(36).slice(2,8),J=e=>{const i=new Date(e);return`${i.getHours()}:${String(i.getMinutes()).padStart(2,"0")}`};function Q({mic:e="self",playback:i=!0,resume:a=null,live:h=!1,openEar:y,capturePlayback:f,persist:I,onUpdate:c,onEnd:H,onNotice:w,now:A=Date.now,newId:q=G,timers:k=N,flushDebounceMs:x=j,heartbeatMs:z=L}={}){if(typeof y!="function")throw new Error("createAudioScribe: openEar is required");if(typeof I!="function")throw new Error("createAudioScribe: persist is required");if(i&&typeof f!="function")throw new Error("createAudioScribe: capturePlayback is required when playback is on");return{async start(){let n=null;if(i)try{n=await f({onEnded:()=>T("ended")})}catch(t){return t?.code!=="cancelled"&&w?.({level:"error",text:t?.message||"Could not capture what is playing"}),null}const v=a?.startedAt||A(),S=a?.meetingId||`mtg_${n?"audio":"room"}_${v.toString(36)}_${q()}`,s=P({now:A,mic:e,playback:!!n,seed:a?.segments||[]});let m=!0,_=!1,F=a?.segments?.length?Math.max(...a.segments.map(t=>Number(t.t)||0))+1:0,R=0,g=null,M=null,E=!1;const d={mic:null,playback:null},l={mic:"starting",playback:n?"starting":"off",lang:null},O=()=>{if(a?.title)return a.title;const t=J(v);return n?n.surface==="screen"?`System audio · ${t}`:n.surface==="tab"?`Tab audio · ${t}`:`Audio · ${t}`:`Room · ${t}`};async function b(t="live",$){if(E)return;const r=s.record({id:S,startedAt:v,status:t,endReason:$,title:O()}),u=s.delta(F);let p=null;try{p=await I(r,u)}catch{return}if(p?.limit){E=!0,T("limit");return}if(p?.ok===!1)return;R=A();const D=r.segments[r.segments.length-1];D&&(F=D.t)}function B(){if(m){if(A()-R>=x){b("live");return}g||(g=k.setTimeout(()=>{g=null,m&&b("live")},x))}}const C=(t,$)=>y(t,{...$,on:{onStart:()=>{l[t]="listening",c?.(o())},onInterim:r=>{s.interim(t,r),c?.(o())},onFinal:(r,u)=>{s.final(t,r,u||{})&&(B(),c?.(o()))},onStatus:r=>{r?.state==="language"&&r.lang?l.lang=r.lang:r?.state&&r.state!=="ready"&&(l[t]=r.state==="diarize"?"loading speaker model":r.state),c?.(o())},onError:({message:r,fatal:u}={})=>{l[t]=u?"failed":"listening",w?.({level:"error",text:`${t==="mic"?"Microphone":"Playback"}: ${r||"failed"}`});const p=t==="mic"?l.playback:l.mic;u&&(p==="failed"||p==="off")&&T("ended"),c?.(o())},onEnd:()=>{m&&l[t]!=="failed"&&(l[t]="stopped"),c?.(o())}}});d.mic=C("mic",{diarize:e==="room",interims:!!h,stream:null}),d.mic.start(),n&&(d.playback=C("playback",{diarize:!0,interims:!!h,stream:n.stream}),d.playback.start()),M=k.setInterval(()=>{m&&b("live")},z);function o(){return{meetingId:S,startedAt:v,mic:e,surface:n?n.surface:"mic",status:{...l},audio:{mic:d.mic?.stats?.()||null,playback:d.playback?.stats?.()||null},speakers:s.speakers(),interims:s.interims(),lines:s.segments().length,last:s.last("playback")||s.last("mic")}}function T(t="user"){if(_)return;_=!0,m=!1,k.clearInterval(M),g&&(k.clearTimeout(g),g=null);for(const u of Object.values(d))try{u?.stop()}catch{}try{n?.stop()}catch{}(E?Promise.resolve():b("ended",t==="user"?"user":t==="interrupted"?"interrupted":"ended")).finally(()=>H?.({meetingId:S,reason:t}))}return c?.(o()),{meetingId:S,isRunning:()=>m,snapshot:o,stop:T,flush:()=>b("live")}}}}function V(e,{now:i=Date.now()}={}){if(!e?.id)return null;const{id:a,title:h,tags:y,...f}=e;return{id:`meeting:${a}`,title:h||"Audio transcript",...y?{tags:y}:{},createdAt:e.startedAt||i,updatedAt:e.endedAt||i,body:{...f,segments:Array.isArray(f.segments)?f.segments:[]},meta:{origin:"capture",readOnly:!1,live:e.status!=="ended"}}}export{j as FLUSH_DEBOUNCE_MS,L as HEARTBEAT_MS,Q as createAudioScribe,V as meetingRecordFromCapture};
1
+ import{createChannelTranscript as W}from"./voice-channels.js";const X=4e3,Y=3e4,F=3e3,Z={setTimeout:(r,n)=>setTimeout(r,n),clearTimeout:r=>clearTimeout(r),setInterval:(r,n)=>setInterval(r,n),clearInterval:r=>clearInterval(r)},G=()=>Math.random().toString(36).slice(2,8),U=r=>{const n=new Date(r);return`${n.getHours()}:${String(n.getMinutes()).padStart(2,"0")}`};function et({mic:r="self",playback:n=!0,resume:o=null,live:v=!1,echoGuard:A=!1,openEar:y,capturePlayback:R,persist:w,onUpdate:m,onEnd:P,onNotice:C,onLine:_,now:f=Date.now,newId:j=G,timers:b=Z,flushDebounceMs:D=X,heartbeatMs:L=Y}={}){if(typeof y!="function")throw new Error("createAudioScribe: openEar is required");if(typeof w!="function")throw new Error("createAudioScribe: persist is required");if(n&&typeof R!="function")throw new Error("createAudioScribe: capturePlayback is required when playback is on");return{async start(){let i=null;if(n)try{i=await R({onEnded:()=>I("ended")})}catch(t){return t?.code!=="cancelled"&&C?.({level:"error",text:t?.message||"Could not capture what is playing"}),null}const E=o?.startedAt||f(),$=o?.meetingId||`mtg_${i?"audio":"room"}_${E.toString(36)}_${j()}`,l=W({now:f,mic:r,playback:!!i,seed:o?.segments||[],echoGuard:A});let h=!0,H=!1,q=o?.segments?.length?Math.max(...o.segments.map(t=>Number(t.t)||0))+1:0,z=0,T=null,O=null,x=!1;const g={mic:null,playback:null};let p=[],k=null;const J=t=>l.segments().some(s=>s.sid===t);function M(t=!1){const s=t?p:p.filter(e=>f()-e.at>=F);p=t?[]:p.filter(e=>f()-e.at<F);for(const e of s)J(e.line.sid)&&_?.(e.line);k&&(b.clearTimeout(k),k=null),p.length&&(k=b.setTimeout(()=>{k=null,M()},Math.max(0,F-(f()-p[0].at))))}function K(t,s,e){if(!_)return;const a={sid:s.sid,t:s.t,channel:t,speaker:s.speaker,text:e};if(t==="mic"&&A&&i){p.push({at:f(),line:a}),k||M();return}_(a)}const u={mic:"starting",playback:i?"starting":"off",lang:null},Q=()=>{if(o?.title)return o.title;const t=U(E);return i?i.surface==="screen"?`System audio · ${t}`:i.surface==="tab"?`Tab audio · ${t}`:`Audio · ${t}`:`Room · ${t}`};async function S(t="live",s){if(x)return;const e=l.record({id:$,startedAt:E,status:t,endReason:s,title:Q()}),a=l.delta(q);let c=null;try{c=await w(e,a)}catch{return}if(c?.limit){x=!0,I("limit");return}if(c?.ok===!1)return;z=f();const N=e.segments[e.segments.length-1];N&&(q=N.t)}function V(){if(h){if(f()-z>=D){S("live");return}T||(T=b.setTimeout(()=>{T=null,h&&S("live")},D))}}const B=(t,s)=>y(t,{...s,on:{onStart:()=>{u[t]="listening",m?.(d())},onInterim:e=>{l.interim(t,e),m?.(d())},onFinal:(e,a)=>{const c=l.final(t,e,a||{});c&&(K(t,c,String(e).replace(/\s+/g," ").trim()),V(),m?.(d()))},onStatus:e=>{e?.state==="language"&&e.lang?u.lang=e.lang:e?.state&&e.state!=="ready"&&(u[t]=e.state==="diarize"?"loading speaker model":e.state),m?.(d())},onError:({message:e,fatal:a}={})=>{u[t]=a?"failed":"listening",C?.({level:"error",text:`${t==="mic"?"Microphone":"Playback"}: ${e||"failed"}`});const c=t==="mic"?u.playback:u.mic;a&&(c==="failed"||c==="off")&&I("ended"),m?.(d())},onEnd:()=>{h&&u[t]!=="failed"&&(u[t]="stopped"),m?.(d())}}});g.mic=B("mic",{diarize:r==="room",interims:!!v,stream:null}),g.mic.start(),i&&(g.playback=B("playback",{diarize:!0,interims:!!v,stream:i.stream}),g.playback.start()),O=b.setInterval(()=>{h&&S("live")},L);function d(){return{meetingId:$,startedAt:E,mic:r,surface:i?i.surface:"mic",status:{...u},audio:{mic:g.mic?.stats?.()||null,playback:g.playback?.stats?.()||null},speakers:l.speakers(),interims:l.interims(),lines:l.segments().length,last:l.last("playback")||l.last("mic")}}function I(t="user"){if(H)return;H=!0,h=!1,b.clearInterval(O),T&&(b.clearTimeout(T),T=null),M(!0);for(const a of Object.values(g))try{a?.stop()}catch{}try{i?.stop()}catch{}(x?Promise.resolve():S("ended",t==="user"?"user":t==="interrupted"?"interrupted":"ended")).finally(()=>P?.({meetingId:$,reason:t}))}return m?.(d()),{meetingId:$,isRunning:()=>h,snapshot:d,stop:I,flush:()=>S("live")}}}}function rt(r,{now:n=Date.now()}={}){if(!r?.id)return null;const{id:o,title:v,tags:A,...y}=r;return{id:`meeting:${o}`,title:v||"Audio transcript",...A?{tags:A}:{},createdAt:r.startedAt||n,updatedAt:r.endedAt||n,body:{...y,segments:Array.isArray(y.segments)?y.segments:[]},meta:{origin:"capture",readOnly:!1,live:r.status!=="ended"}}}export{X as FLUSH_DEBOUNCE_MS,Y as HEARTBEAT_MS,F as LINE_SETTLE_MS,et as createAudioScribe,rt as meetingRecordFromCapture};