@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.
- package/capture-plan.js +1 -0
- package/citations.js +4 -4
- package/fetched.js +2 -2
- package/meeting-apps.js +1 -0
- package/monitor-profile.js +1 -1
- package/note-transcript.js +10 -0
- package/package.json +7 -1
- package/turn-loop.js +4 -4
- package/voice-channels.js +1 -1
- package/voice-scribe.js +1 -1
package/capture-plan.js
ADDED
|
@@ -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
|
|
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
|
-
**${
|
|
5
|
-
${
|
|
6
|
-
`}const
|
|
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
|
|
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(
|
|
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};
|
package/meeting-apps.js
ADDED
|
@@ -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};
|
package/monitor-profile.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const
|
|
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.
|
|
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
|
|
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."]),
|
|
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
|
|
6
|
-
`);return{inputTokens:tt(e),outputTokens:tt(o),cacheReadTokens:0,cacheWriteTokens:0,estimated:!0}}const
|
|
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
|
|
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
|
|
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};
|