@chatpanel/events 0.157.0 → 0.189.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chatpanel/events",
3
- "version": "0.157.0",
3
+ "version": "0.189.1",
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",
@@ -11,20 +11,32 @@
11
11
  "./agent.js": "./agent.js",
12
12
  "./attribution.js": "./attribution.js",
13
13
  "./backup-envelope.js": "./backup-envelope.js",
14
+ "./blob-envelope.js": "./blob-envelope.js",
15
+ "./bytes-b64.js": "./bytes-b64.js",
14
16
  "./backup-records.js": "./backup-records.js",
15
17
  "./budget.js": "./budget.js",
16
18
  "./capability.js": "./capability.js",
17
19
  "./capability-endpoints.js": "./capability-endpoints.js",
20
+ "./capability-uses.js": "./capability-uses.js",
18
21
  "./capability-client.js": "./capability-client.js",
22
+ "./capability-adapters.js": "./capability-adapters.js",
23
+ "./capability-providers.js": "./capability-providers.js",
24
+ "./capability-tools.js": "./capability-tools.js",
19
25
  "./fast-path.js": "./fast-path.js",
20
26
  "./plan.js": "./plan.js",
21
27
  "./plan-executor.js": "./plan-executor.js",
22
28
  "./model-roles.js": "./model-roles.js",
29
+ "./model-entries.js": "./model-entries.js",
30
+ "./model-fusion.js": "./model-fusion.js",
31
+ "./harness-cards.js": "./harness-cards.js",
23
32
  "./citations.js": "./citations.js",
24
33
  "./cloudevents.js": "./cloudevents.js",
34
+ "./event-sync.js": "./event-sync.js",
35
+ "./event-stats.js": "./event-stats.js",
25
36
  "./client-prefs.js": "./client-prefs.js",
26
37
  "./composer-chips.js": "./composer-chips.js",
27
38
  "./settings-registry.js": "./settings-registry.js",
39
+ "./feature-map.js": "./feature-map.js",
28
40
  "./context-attachments.js": "./context-attachments.js",
29
41
  "./cowriter-router.js": "./cowriter-router.js",
30
42
  "./cowriter-writer.js": "./cowriter-writer.js",
@@ -53,6 +65,7 @@
53
65
  "./manifest.js": "./manifest.js",
54
66
  "./markdown-authoring.js": "./markdown-authoring.js",
55
67
  "./markdown-render.js": "./markdown-render.js",
68
+ "./note-images.js": "./note-images.js",
56
69
  "./sideline.js": "./sideline.js",
57
70
  "./mcp-client.js": "./mcp-client.js",
58
71
  "./mcp-config-import.js": "./mcp-config-import.js",
@@ -68,6 +81,8 @@
68
81
  "./meeting-analyzers.js": "./meeting-analyzers.js",
69
82
  "./meeting-insights.js": "./meeting-insights.js",
70
83
  "./meeting-shape.js": "./meeting-shape.js",
84
+ "./meeting-speakers.js": "./meeting-speakers.js",
85
+ "./meeting-speakers-typed.js": "./meeting-speakers-typed.js",
71
86
  "./meeting-text.js": "./meeting-text.js",
72
87
  "./memory.js": "./memory.js",
73
88
  "./memory-tool.js": "./memory-tool.js",
@@ -101,6 +116,7 @@
101
116
  "./registry.js": "./registry.js",
102
117
  "./route-graph.js": "./route-graph.js",
103
118
  "./route-strategies.js": "./route-strategies.js",
119
+ "./route-decider.js": "./route-decider.js",
104
120
  "./router.js": "./router.js",
105
121
  "./rrf.js": "./rrf.js",
106
122
  "./rules.js": "./rules.js",
@@ -158,6 +174,7 @@
158
174
  "./tool-hints.js": "./tool-hints.js",
159
175
  "./tool-need.js": "./tool-need.js",
160
176
  "./tool-result.js": "./tool-result.js",
177
+ "./agent-permission.js": "./agent-permission.js",
161
178
  "./tool-loop-guard.js": "./tool-loop-guard.js",
162
179
  "./tool-round.js": "./tool-round.js",
163
180
  "./tool-schema.js": "./tool-schema.js",
@@ -172,6 +189,8 @@
172
189
  "./view.js": "./view.js",
173
190
  "./voice-intents.js": "./voice-intents.js",
174
191
  "./voice-speaker.js": "./voice-speaker.js",
192
+ "./voice-channels.js": "./voice-channels.js",
193
+ "./voice-scribe.js": "./voice-scribe.js",
175
194
  "./voice-loop.js": "./voice-loop.js",
176
195
  "./voice-vad.js": "./voice-vad.js",
177
196
  "./voice-sample.js": "./voice-sample.js",
@@ -203,20 +222,29 @@
203
222
  "agent.js",
204
223
  "attribution.js",
205
224
  "backup-envelope.js",
225
+ "blob-envelope.js",
226
+ "bytes-b64.js",
206
227
  "backup-records.js",
207
228
  "budget.js",
208
229
  "capability.js",
209
230
  "capability-endpoints.js",
231
+ "capability-uses.js",
210
232
  "capability-client.js",
233
+ "capability-adapters.js",
234
+ "capability-providers.js",
235
+ "capability-tools.js",
211
236
  "fast-path.js",
212
237
  "plan.js",
213
238
  "plan-executor.js",
214
239
  "model-roles.js",
240
+ "model-entries.js",
241
+ "harness-cards.js",
215
242
  "citations.js",
216
243
  "cloudevents.js",
217
244
  "client-prefs.js",
218
245
  "composer-chips.js",
219
246
  "settings-registry.js",
247
+ "feature-map.js",
220
248
  "context-attachments.js",
221
249
  "cowriter-router.js",
222
250
  "cowriter-writer.js",
@@ -230,6 +258,8 @@
230
258
  "engine.js",
231
259
  "entity.js",
232
260
  "event.js",
261
+ "event-sync.js",
262
+ "event-stats.js",
233
263
  "extraction.js",
234
264
  "failover.js",
235
265
  "gateway-dests.js",
@@ -246,6 +276,7 @@
246
276
  "manifest.js",
247
277
  "markdown-authoring.js",
248
278
  "markdown-render.js",
279
+ "note-images.js",
249
280
  "sideline.js",
250
281
  "mcp-client.js",
251
282
  "mcp-config-import.js",
@@ -256,11 +287,14 @@
256
287
  "mcp-launcher.js",
257
288
  "mcp-oauth.js",
258
289
  "mcp-signin.js",
290
+ "model-fusion.js",
259
291
  "model-registry.js",
260
292
  "media-transcript.js",
261
293
  "meeting-analyzers.js",
262
294
  "meeting-insights.js",
263
295
  "meeting-shape.js",
296
+ "meeting-speakers.js",
297
+ "meeting-speakers-typed.js",
264
298
  "meeting-text.js",
265
299
  "memory.js",
266
300
  "memory-tool.js",
@@ -300,6 +334,7 @@
300
334
  "registry.js",
301
335
  "route-graph.js",
302
336
  "route-strategies.js",
337
+ "route-decider.js",
303
338
  "router.js",
304
339
  "rrf.js",
305
340
  "rules.js",
@@ -357,6 +392,7 @@
357
392
  "tool-hints.js",
358
393
  "tool-need.js",
359
394
  "tool-result.js",
395
+ "agent-permission.js",
360
396
  "tool-loop-guard.js",
361
397
  "tool-round.js",
362
398
  "tool-schema.js",
@@ -371,6 +407,8 @@
371
407
  "view.js",
372
408
  "voice-intents.js",
373
409
  "voice-speaker.js",
410
+ "voice-channels.js",
411
+ "voice-scribe.js",
374
412
  "voice-loop.js",
375
413
  "voice-vad.js",
376
414
  "voice-sample.js",
@@ -0,0 +1,6 @@
1
+ import{defineRouteStrategy as q}from"./router.js";function x(e){const l=Number.isFinite(e.quality)?`quality ${e.quality.toFixed(2)}`:"quality unknown",a=e.costPer1k===0?"free":`cost ${e.costPer1k}`,i=Number.isFinite(e.latencyMs)?`~${e.latencyMs} ms to first token`:"",s=e.window?`window ${Math.round(e.window/1e3)}k`:"",n=e.reach==="device"?"on this device":e.reach==="trusted"?"on a trusted host":"a third party",$=e.classUsed==="A"?"a coding agent with its own loop":e.classUsed==="L"?"a local model":"an API model",f=(e.capabilities||[]).length?`can: ${e.capabilities.join(", ")}`:"no declared abilities",r=[e.rateLimited?"rate limited now":"",e.available===!1?"unavailable":""].filter(Boolean).join(", ");return[e.label||e.id,$,n,f,l,a,i,s,r].filter(Boolean).join(" · ")}function v(e={},{text:l=!1}={}){const a=e.signals||{},i=[];i.push(`Task: ${a.smalltalk?"small talk":a.code?"coding":"a question"}; complexity ${a.complexity||"unknown"}; modality ${a.modality||"text"}; about ${a.approxTokens||0} tokens${a.nonLatin?"; non-Latin script":""}.`),a.reference&&i.push(`Material attached by reference: ${a.reference.count} item(s), ${a.reference.pages||0} pages.`),(e.capabilities||[]).length&&i.push(`Needs: ${e.capabilities.join(", ")}.`),e.minQuality&&i.push(`Quality floor ${e.minQuality}.`),e.reach&&e.reach!=="any"&&i.push(`May reach: ${e.reach} only.`),e.prefer&&i.push(`Prefer: ${e.prefer}.`);const s=l&&e.requestText?String(e.requestText).trim().slice(-600):"";return s&&i.push(`The request ends: "${s}"`),i.join(`
2
+ `)}function F({decide:e,rerank:l=null,shortlist:a=6,text:i=!1,timeoutMs:s=4e3}={}){if(typeof e!="function")throw new Error("deciderStrategy: decide is required");return q({id:"decider",label:"Decision model",classUsed:"M",timeoutMs:s,decide:async(n,$)=>{if(!Array.isArray(n)||n.length<2)return null;const f=v($,{text:i}),r=n.map(t=>({id:t.id,card:x(t)})),p=[];let h=r;if(typeof l=="function")try{const t=await l({query:f,documents:r.map(d=>d.card),top_n:r.length}),c=(t?.results||[]).map(d=>r[d.index]).filter(Boolean);c.length&&(h=[...c,...r.filter(d=>!c.includes(d))],p.push(`reranker (${t.model||"rerank"}) ordered: ${h.slice(0,a).map(d=>d.id).join(" > ")}`))}catch(t){p.push(`reranker did not answer (${t?.message||t}); the score's order stands`)}const y=h.slice(0,Math.max(2,a)),g={state:`${f}
3
+
4
+ Candidates:
5
+ ${y.map(t=>`- ${t.id}: ${t.card}`).join(`
6
+ `)}`,questions:{model:{type:"choice",instructions:"Which candidate should answer this task? Weigh what the task needs against each card: quality for hard work, speed and cost for easy work, and never a candidate that lacks an ability the task needs.",options:y.map(t=>({value:t.id,describe:t.card}))}},budgetMs:s},k=await e(g),o=k?.answers?.model;if(!o||typeof o.value!="string")return null;const u=y.find(t=>t.id===o.value);if(!u)return null;const b=[...o.options||[]].sort((t,c)=>(c.p||0)-(t.p||0)),w=b.find(t=>t.value!==o.value);p.push(`decision model (${k.model||"decide"}) picked ${u.id}${Number.isFinite(o.p)?` at ${(o.p*100).toFixed(0)}%`:""}${w?`, then ${w.value} at ${((w.p||0)*100).toFixed(0)}%`:""}${k.calibrated===!1?" (not a calibrated probability)":""}`),n[0]&&n[0].id!==u.id&&p.push(`the score would have picked ${n[0].id}`);const m=b.map(t=>t.value).filter(t=>t!==u.id&&y.some(c=>c.id===t));return{ranked:[u.id,...m,...h.map(t=>t.id).filter(t=>t!==u.id&&!m.includes(t))],why:p}}})}export{x as candidateCard,F as deciderStrategy,v as taskBrief};
package/router.js CHANGED
@@ -1,2 +1,2 @@
1
- class k extends Error{constructor(s,l){super(l),this.name="RouterError",this.code=s}}import{REACH as re,reachRank as ie}from"./reach.js";import{REACH as C,reachRank as F}from"./reach.js";function W({id:t,label:s,reach:l="any",classUsed:h="C",capabilities:d=[],costPer1k:y=1,latencyMs:c=1e3,load:a=0,available:r=!0,rateLimited:i=!1,observedLatencyMs:n=null,quality:f=null,model:u="",providerRank:g=50,orderPinned:w=!1}){if(!t)throw new k("BAD_MODEL","model.id required");if(!C.includes(l))throw new k("BAD_MODEL",`model '${t}': unknown reach '${l}'`);return Object.freeze({id:t,label:s||t,reach:l,classUsed:h,model:u,capabilities:[...d],costPer1k:y,latencyMs:Number.isFinite(n)?n:c,declaredLatencyMs:c,observedLatencyMs:n,load:a,available:r,rateLimited:i,providerRank:g,orderPinned:!!w,quality:f})}function G({id:t,label:s,stage:l,priority:h=100,run:d,requiredFor:y=null}){if(!t)throw new k("BAD_MIDDLEWARE","middleware.id required");if(!["request","response"].includes(l))throw new k("BAD_MIDDLEWARE",`middleware '${t}': stage must be request or response`);if(typeof d!="function")throw new k("BAD_MIDDLEWARE",`middleware '${t}': run required`);return Object.freeze({id:t,label:s||t,stage:l,priority:h,run:d,requiredFor:y})}function H({id:t,label:s,classUsed:l="R",timeoutMs:h=0,decide:d}){if(!t)throw new k("BAD_STRATEGY","strategy.id required");if(typeof d!="function")throw new k("BAD_STRATEGY",`strategy '${t}': decide required`);return Object.freeze({id:t,label:s||t,classUsed:l,timeoutMs:h,decide:d})}const T=.1,L=5,j=Object.freeze({device:.7,trusted:.85,any:1});function P(t){return String(t?.model||t?.label||"").toLowerCase().replace(/^[^/]+\//,"").replace(/[:@].*$/,"").replace(/[^a-z0-9.]+/g,"")}function Y(t={}){const s=String(t.text||(t.messages||[]).map(a=>a?.content||"").join(`
2
- `)||""),l=s.length,h=!!(t.images?.length||t.attachments?.some?.(a=>/^image\//.test(a?.type||""))),d=!!t.audio||!!t.attachments?.some?.(a=>/^audio\//.test(a?.type||"")),c=(t.attachments||[...t.messages||[]].reverse().find(a=>a?.role==="user")?.attachments||[]).filter(a=>a?.kind==="path");return{reference:c.length?{count:c.length,folders:c.filter(a=>a.isDir).length,documents:c.filter(a=>a.isDir===!1).length,pages:c.reduce((a,r)=>a+(Number(r.pages)||0),0)}:null,approxTokens:Math.round(l/4),modality:d?"audio":h?"vision":"text",code:/```/.test(s)||l>80&&/\bfunction\b|\bclass\b|=>|;\s*$|\bdef\b|\bimport\b|\bconst\b/m.test(s)||/\b(write|fix|debug|refactor|implement|optimi[sz]e|review|explain|generate|add|update|port|migrate)\b[^.?!]{0,60}\b(code|function|method|class|script|bug|regex|query|unit ?test|module|component|endpoint|snippet|compiler?|stack ?trace|typescript|javascript|python|rust|golang|sql|css|html)\b/i.test(s),complexity:l>4e3||/```/.test(s)||l>=200&&/\bstep by step\b|\bplan\b|\brefactor\b|\bmigrate\b|\banalyse|\banalyze/i.test(s)?"high":l<200?"low":"medium",nonLatin:/[^\u0000-\u024F\u2000-\u206F]/.test(s),smalltalk:l<100&&!/```/.test(s)&&!/\b(draw|click|open|fill|read|find|search|edit|write|create|update|delete|run|fix|change|add|remove|select|scroll|extract|summar\w*|analy\w*|check|review|list|show|go to|navigate|my|mine|this page|here|it|that)\b/i.test(s)&&!/\b(explain|describe|define|compare|translate|why|debug|refactor|implement|improve|optimi[sz]e|convert|calculate|generate|draft|rename|build|test|install|deploy|design|plan)\b/i.test(s)&&!/\bhow\s+(do|does|did|can|could|should|would|to|much|many|long)\b/i.test(s),chars:l}}const S=(t,s)=>`${t} ${s}${t===1?"":"s"}`;function B(t){const s=[];return t.folders&&s.push(S(t.folders,"folder")),t.documents&&s.push(`${S(t.documents,"document")}${t.pages?` (${t.pages} pages)`:""}`),s.length?s.join(" and "):S(t.count,"path")}function V(t={},{structured:s=!1,hasTools:l=!1,pageTools:h=!1,background:d=!1,minWindow:y=0}={}){const c=new Set;let a=0;const r=[];y>0&&r.push(`the turn needs a ${Math.round(y/1e3)}k window`),l&&(c.add("tools"),r.push("the turn carries tools")),t.modality==="vision"&&(c.add("vision"),r.push("the request includes an image")),h&&!t.smalltalk&&(c.add("tools"),a=Math.max(a,.55),r.push("driving a page needs exact actions")),t.approxTokens>2e4&&(c.add("long-context"),r.push("the request is large")),t.reference?.count&&(c.add("tools"),a=Math.max(a,.55),r.push(`${B(t.reference)} attached by reference — read through the files tool`)),t.code&&(c.add("coding"),r.push("the request contains code")),s&&!t.smalltalk&&(c.add("tools"),a=Math.max(a,.55),r.push("it must produce an exact structured payload")),t.complexity==="high"&&!d&&(a=Math.max(a,.55),r.push("the task is complex"));const i=t.smalltalk&&!t.reference?.count?[...c]:[...c].filter(n=>n!=="tools");return{required:[...c],negotiable:i,minQuality:a,why:r,minWindow:Math.max(0,Number(y)||0)}}function K(t={},{structured:s=!1,minQuality:l=0,hasTools:h=!1,background:d=!1}={}){return d?{prefer:"cost",why:"background work — spend as little as possible"}:s||t.complexity==="high"||t.code||t.modality==="vision"?{prefer:"quality",why:"the task is exact or hard — get it right rather than quick"}:t.smalltalk&&!h&&!l?{prefer:"latency",why:"nothing to look up — answer fast"}:{prefer:"balanced",why:"no reason to favour speed or quality"}}function E(t){return t?.orderPinned&&Number.isFinite(t.providerRank)?t.providerRank:1/0}const Q=.25,U=.25;function J(t=[],s={}){const l=i=>!!s.model&&P(i)===P(s);let h=[...t];if(s.reason==="gone"){const i=h.filter(n=>!l(n));i.length&&(h=i)}const d=i=>Number.isFinite(i.quality)?i.quality:.5,y=i=>(s.capabilities||[]).every(n=>(i.capabilities||[]).includes(n)),c=i=>!s.classUsed||i.classUsed===s.classUsed,a=Number.isFinite(s.quality)?s.quality:null;if(a!==null){const i=n=>l(n)?-1:Math.abs(d(n)-a)+(c(n)?0:Q)+(y(n)?0:U);return h.map(n=>({m:n,d:i(n)})).sort((n,f)=>n.d-f.d||E(n.m)-E(f.m)||n.m.costPer1k-f.m.costPer1k||String(n.m.id).localeCompare(String(f.m.id))).map(n=>n.m)}const r=i=>l(i)?0:c(i)&&y(i)?1:c(i)?2:y(i)?3:4;return h.sort((i,n)=>r(i)-r(n)||d(n)-d(i)||E(i)-E(n)||i.costPer1k-n.costPer1k)}function X(t,s={}){const l=String(t||""),h=String(s?.action||""),d=`${l}.${h}`;return/screenshot|marked_screenshot|read_canvas|sense_canvas/.test(d)?{required:["vision"],why:"this step reads an image"}:/structured_insert|sheet_write|fill_form|input_sequence|draw_path/.test(d)?{required:["tools"],minQuality:.55,why:"this step writes an exact payload"}:{required:l?["tools"]:[],why:""}}function Z({models:t=[],middleware:s=[],strategies:l=[],admit:h=null}={}){const d=[...t],y=[...s],c=[...l],a=r=>y.filter(i=>i.stage===r&&(!h||h(i))).sort((i,n)=>r==="request"?i.priority-n.priority:n.priority-i.priority);return{addModel(r){return d.push(r),()=>{const i=d.indexOf(r);i>=0&&d.splice(i,1)}},use(r){return y.push(r),()=>{const i=y.indexOf(r);i>=0&&y.splice(i,1)}},addStrategy(r){return c.push(r),()=>{const i=c.indexOf(r);i>=0&&c.splice(i,1)}},models:()=>[...d],middleware:()=>[...y],strategies:()=>[...c],route(r={}){const i=C.includes(r.reach)?r.reach:"any",n=r.capabilities||[],f=r.requirementReasons||[],u=[],g=d.filter(e=>{if(!e.available)return u.push({id:e.id,why:"unavailable"}),!1;if(h&&!h(e))return u.push({id:e.id,why:"disabled"}),!1;if(F(e.reach)>F(i))return u.push({id:e.id,why:`reach '${e.reach}' exceeds '${i}'`}),!1;const o=n.filter(x=>!e.capabilities.includes(x));if(o.length)return u.push({id:e.id,why:`missing ${o.join(", ")}`}),!1;if(r.minWindow>0&&Number(e.window)>0&&Number(e.window)<r.minWindow)return u.push({id:e.id,why:`a ${Math.round(e.window/1e3)}k window under the ${Math.round(r.minWindow/1e3)}k this turn needs`}),!1;if(r.maxLatencyMs>0&&e.latencyMs>r.maxLatencyMs)return u.push({id:e.id,why:`${e.latencyMs}ms exceeds the ${r.maxLatencyMs}ms deadline`}),!1;if(r.maxCostPer1k>=0&&r.maxCostPer1k!==void 0&&e.costPer1k>r.maxCostPer1k)return u.push({id:e.id,why:`costs ${e.costPer1k} over the ${r.maxCostPer1k} budget`}),!1;if(e.rateLimited)return u.push({id:e.id,why:"rate limited"}),!1;if(r.exclude?.includes?.(e.id))return u.push({id:e.id,why:"already failed this request"}),!1;if(r.minQuality>0){const x=Number.isFinite(e.quality)?e.quality:.5;if(x<r.minQuality)return u.push({id:e.id,why:`below the quality this task needs (${x} < ${r.minQuality})`}),!1}return!0});if(!g.length){if(r.minQuality>0){const e=this.route({...r,minQuality:0});if(e.model)return{...e,relaxed:!0,reasons:[...e.reasons,`no model met the quality this task needs (${r.minQuality}) — used the best available instead`]}}if(r.negotiable?.length){const e=(r.capabilities||[]).filter(x=>!r.negotiable.includes(x)),o=this.route({...r,minQuality:0,capabilities:e,negotiable:[]});if(o.model)return{...o,relaxed:!0,reasons:[...o.reasons,`no model offers ${r.negotiable.join(", ")} — used one without it, which may do this task poorly`]}}return{model:null,reasons:["no candidate satisfies the constraints"],constraints:f,rejected:u}}const w=r.prefer||"balanced",v=e=>{const o=1+Math.max(0,Math.min(1,e.load)),x=Number.isFinite(e.quality)?Math.max(.1,e.quality):.5,O=j[e.reach]??1;return w==="latency"?e.latencyMs*o*O:w==="cost"?e.costPer1k*o*O:w==="quality"?o/x:(e.latencyMs/1e3+e.costPer1k*L)*o*O/x},$=new Map,b=e=>($.has(e)||$.set(e,v(e)),$.get(e)),m=(e,o)=>e.providerRank-o.providerRank||b(e)-b(o)||e.id.localeCompare(o.id),p=(e,o)=>b(e)-b(o)||e.providerRank-o.providerRank||e.id.localeCompare(o.id),A=new Map;for(const e of g){const o=P(e)||`#${e.id}`;A.has(o)||A.set(o,[]),A.get(o).push(e)}const D=[...A.values()].map(e=>[...e].sort(e.some(o=>o.orderPinned)?m:p));D.sort((e,o)=>b(e[0])-b(o[0])||m(e[0],o[0]));const M=[];for(const e of D){const o=M[M.length-1],x=o?b(o[0][0]):0;o&&b(e[0])<=x*(1+T)?o.push(e):M.push([e])}for(const e of M)e.sort((o,x)=>m(o[0],x[0]));let q=M.flat(2);const R=w==="balanced"?q.filter(e=>e.orderPinned).sort((e,o)=>e.providerRank-o.providerRank)[0]:null;R&&(q=[R,...q.filter(e=>e!==R)]);const I=M[0]?.length>1,N=(M[0]||[]).flat().length,_=q[0];return{model:_,eligible:q,constraints:f,strategy:R?"declared-default":"default-score",reasons:[`reach '${_.reach}' within '${i}'`,n.length?`has ${n.join(", ")}`:"no special capability needed",R?`your default (Order ${_.providerRank}) — nothing about this turn asked for anything else`:I?`order ${_.providerRank} broke a ${N}-way tie by ${w}, of ${q.length} eligible`:`best by ${w} (${q.length} eligible)`],rejected:u,runnersUp:q.slice(1).map(e=>e.id)}},async routeWith(r={},i={}){const n=this.route(r);if(!n.model||!c.length)return n;const f=new Map(n.eligible.map(u=>[u.id,u]));for(const u of c){if(h&&!h(u))continue;let g=null;try{const m=u.decide([...n.eligible],r,i);g=u.timeoutMs>0?await Promise.race([m,new Promise(p=>setTimeout(()=>p(null),u.timeoutMs))]):await m}catch{g=null}if(!g)continue;const w=(Array.isArray(g)?g:[g]).map(m=>typeof m=="string"?f.get(m):f.get(m?.id)).filter(Boolean),v=(Array.isArray(g)?g:[g]).length-w.length;if(!w.length)continue;const $=n.eligible.filter(m=>!w.includes(m)),b=[...w,...$];return{...n,model:w[0],eligible:b,strategy:u.id,runnersUp:b.slice(1).map(m=>m.id),reasons:[...n.reasons.slice(0,-1),`chosen by '${u.id}' (class ${u.classUsed}) from ${n.eligible.length} eligible`,...v>0?[`${v} suggestion(s) ignored — not eligible under the constraints`]:[]]}}return n},async run(r,{dispatch:i,need:n={}}={}){if(typeof i!="function")throw new k("NO_DISPATCH","run needs a dispatch function");const f=await this.routeWith(n,{request:r});if(!f.model)throw new k("NO_ROUTE",f.reasons[0]);const u=p=>!p.requiredFor||p.requiredFor(f.model,n),g=y.filter(p=>p.requiredFor&&p.requiredFor(f.model,n)),w=new Set(a("request").concat(a("response")).map(p=>p.id)),v=g.filter(p=>!w.has(p.id));if(v.length)throw new k("MISSING_REQUIRED",`route to '${f.model.id}' requires ${v.map(p=>p.id).join(", ")}, which is not active`);const $={model:f.model,need:n,decision:f};let b=r;for(const p of a("request"))u(p)&&(b=await p.run(b,$)??b);let m=await i(b,$);for(const p of a("response"))u(p)&&(m=await p.run(m,$)??m);return{answer:m,decision:f}}}}export{U as FAILOVER_CAPABILITY_GAP,Q as FAILOVER_CLASS_GAP,re as REACH,k as RouterError,Z as createModelRouter,G as defineMiddleware,W as defineModel,H as defineRouteStrategy,J as failoverOrder,E as pinnedOrderOf,K as preferenceFor,ie as reachRank,V as requirementsFor,X as requirementsForStep,P as sameModelKey,Y as signalsFrom};
1
+ class q extends Error{constructor(s,l){super(l),this.name="RouterError",this.code=s}}import{REACH as re,reachRank as ie}from"./reach.js";import{REACH as C,reachRank as F}from"./reach.js";function W({id:t,label:s,reach:l="any",classUsed:h="C",capabilities:d=[],costPer1k:y=1,latencyMs:c=1e3,load:a=0,available:r=!0,rateLimited:i=!1,observedLatencyMs:n=null,quality:p=null,model:u="",providerRank:g=50,orderPinned:b=!1,window:v=0}){if(!t)throw new q("BAD_MODEL","model.id required");if(!C.includes(l))throw new q("BAD_MODEL",`model '${t}': unknown reach '${l}'`);return Object.freeze({id:t,label:s||t,reach:l,classUsed:h,model:u,capabilities:[...d],costPer1k:y,latencyMs:Number.isFinite(n)?n:c,declaredLatencyMs:c,observedLatencyMs:n,load:a,available:r,rateLimited:i,providerRank:g,orderPinned:!!b,quality:p,window:Number(v)>0?Number(v):0})}function G({id:t,label:s,stage:l,priority:h=100,run:d,requiredFor:y=null}){if(!t)throw new q("BAD_MIDDLEWARE","middleware.id required");if(!["request","response"].includes(l))throw new q("BAD_MIDDLEWARE",`middleware '${t}': stage must be request or response`);if(typeof d!="function")throw new q("BAD_MIDDLEWARE",`middleware '${t}': run required`);return Object.freeze({id:t,label:s||t,stage:l,priority:h,run:d,requiredFor:y})}function H({id:t,label:s,classUsed:l="R",timeoutMs:h=0,decide:d}){if(!t)throw new q("BAD_STRATEGY","strategy.id required");if(typeof d!="function")throw new q("BAD_STRATEGY",`strategy '${t}': decide required`);return Object.freeze({id:t,label:s||t,classUsed:l,timeoutMs:h,decide:d})}const T=.1,L=5,j=Object.freeze({device:.7,trusted:.85,any:1});function S(t){return String(t?.model||t?.label||"").toLowerCase().replace(/^[^/]+\//,"").replace(/[:@].*$/,"").replace(/[^a-z0-9.]+/g,"")}function Y(t={}){const s=String(t.text||(t.messages||[]).map(a=>a?.content||"").join(`
2
+ `)||""),l=s.length,h=!!(t.images?.length||t.attachments?.some?.(a=>/^image\//.test(a?.type||""))),d=!!t.audio||!!t.attachments?.some?.(a=>/^audio\//.test(a?.type||"")),c=(t.attachments||[...t.messages||[]].reverse().find(a=>a?.role==="user")?.attachments||[]).filter(a=>a?.kind==="path");return{reference:c.length?{count:c.length,folders:c.filter(a=>a.isDir).length,documents:c.filter(a=>a.isDir===!1).length,pages:c.reduce((a,r)=>a+(Number(r.pages)||0),0)}:null,approxTokens:Math.round(l/4),modality:d?"audio":h?"vision":"text",code:/```/.test(s)||l>80&&/\bfunction\b|\bclass\b|=>|;\s*$|\bdef\b|\bimport\b|\bconst\b/m.test(s)||/\b(write|fix|debug|refactor|implement|optimi[sz]e|review|explain|generate|add|update|port|migrate)\b[^.?!]{0,60}\b(code|function|method|class|script|bug|regex|query|unit ?test|module|component|endpoint|snippet|compiler?|stack ?trace|typescript|javascript|python|rust|golang|sql|css|html)\b/i.test(s),complexity:l>4e3||/```/.test(s)||l>=200&&/\bstep by step\b|\bplan\b|\brefactor\b|\bmigrate\b|\banalyse|\banalyze/i.test(s)?"high":l<200?"low":"medium",nonLatin:/[^\u0000-\u024F\u2000-\u206F]/.test(s),smalltalk:l<100&&!/```/.test(s)&&!/\b(draw|click|open|fill|read|find|search|edit|write|create|update|delete|run|fix|change|add|remove|select|scroll|extract|summar\w*|analy\w*|check|review|list|show|go to|navigate|my|mine|this page|here|it|that)\b/i.test(s)&&!/\b(explain|describe|define|compare|translate|why|debug|refactor|implement|improve|optimi[sz]e|convert|calculate|generate|draft|rename|build|test|install|deploy|design|plan)\b/i.test(s)&&!/\bhow\s+(do|does|did|can|could|should|would|to|much|many|long)\b/i.test(s),chars:l}}const D=(t,s)=>`${t} ${s}${t===1?"":"s"}`;function B(t){const s=[];return t.folders&&s.push(D(t.folders,"folder")),t.documents&&s.push(`${D(t.documents,"document")}${t.pages?` (${t.pages} pages)`:""}`),s.length?s.join(" and "):D(t.count,"path")}function V(t={},{structured:s=!1,hasTools:l=!1,pageTools:h=!1,background:d=!1,minWindow:y=0}={}){const c=new Set;let a=0;const r=[];y>0&&r.push(`the turn needs a ${Math.round(y/1e3)}k window`),l&&(c.add("tools"),r.push("the turn carries tools")),t.modality==="vision"&&(c.add("vision"),r.push("the request includes an image")),h&&!t.smalltalk&&(c.add("tools"),a=Math.max(a,.55),r.push("driving a page needs exact actions")),t.approxTokens>2e4&&(c.add("long-context"),r.push("the request is large")),t.reference?.count&&(c.add("tools"),a=Math.max(a,.55),r.push(`${B(t.reference)} attached by reference — read through the files tool`)),t.code&&(c.add("coding"),r.push("the request contains code")),s&&!t.smalltalk&&(c.add("tools"),a=Math.max(a,.55),r.push("it must produce an exact structured payload")),t.complexity==="high"&&!d&&(a=Math.max(a,.55),r.push("the task is complex"));const i=t.smalltalk&&!t.reference?.count?[...c]:[...c].filter(n=>n!=="tools");return{required:[...c],negotiable:i,minQuality:a,why:r,minWindow:Math.max(0,Number(y)||0)}}function K(t={},{structured:s=!1,minQuality:l=0,hasTools:h=!1,background:d=!1}={}){return d?{prefer:"cost",why:"background work — spend as little as possible"}:s||t.complexity==="high"||t.code||t.modality==="vision"?{prefer:"quality",why:"the task is exact or hard — get it right rather than quick"}:t.smalltalk&&!h&&!l?{prefer:"latency",why:"nothing to look up — answer fast"}:{prefer:"balanced",why:"no reason to favour speed or quality"}}function O(t){return t?.orderPinned&&Number.isFinite(t.providerRank)?t.providerRank:1/0}const Q=.25,U=.25;function J(t=[],s={}){const l=i=>!!s.model&&S(i)===S(s);let h=[...t];if(s.reason==="gone"){const i=h.filter(n=>!l(n));i.length&&(h=i)}const d=i=>Number.isFinite(i.quality)?i.quality:.5,y=i=>(s.capabilities||[]).every(n=>(i.capabilities||[]).includes(n)),c=i=>!s.classUsed||i.classUsed===s.classUsed,a=Number.isFinite(s.quality)?s.quality:null;if(a!==null){const i=n=>l(n)?-1:Math.abs(d(n)-a)+(c(n)?0:Q)+(y(n)?0:U);return h.map(n=>({m:n,d:i(n)})).sort((n,p)=>n.d-p.d||O(n.m)-O(p.m)||n.m.costPer1k-p.m.costPer1k||String(n.m.id).localeCompare(String(p.m.id))).map(n=>n.m)}const r=i=>l(i)?0:c(i)&&y(i)?1:c(i)?2:y(i)?3:4;return h.sort((i,n)=>r(i)-r(n)||d(n)-d(i)||O(i)-O(n)||i.costPer1k-n.costPer1k)}function X(t,s={}){const l=String(t||""),h=String(s?.action||""),d=`${l}.${h}`;return/screenshot|marked_screenshot|read_canvas|sense_canvas/.test(d)?{required:["vision"],why:"this step reads an image"}:/structured_insert|sheet_write|fill_form|input_sequence|draw_path/.test(d)?{required:["tools"],minQuality:.55,why:"this step writes an exact payload"}:{required:l?["tools"]:[],why:""}}function Z({models:t=[],middleware:s=[],strategies:l=[],admit:h=null}={}){const d=[...t],y=[...s],c=[...l],a=r=>y.filter(i=>i.stage===r&&(!h||h(i))).sort((i,n)=>r==="request"?i.priority-n.priority:n.priority-i.priority);return{addModel(r){return d.push(r),()=>{const i=d.indexOf(r);i>=0&&d.splice(i,1)}},use(r){return y.push(r),()=>{const i=y.indexOf(r);i>=0&&y.splice(i,1)}},addStrategy(r){return c.push(r),()=>{const i=c.indexOf(r);i>=0&&c.splice(i,1)}},models:()=>[...d],middleware:()=>[...y],strategies:()=>[...c],route(r={}){const i=C.includes(r.reach)?r.reach:"any",n=r.capabilities||[],p=r.requirementReasons||[],u=[],g=d.filter(e=>{if(!e.available)return u.push({id:e.id,why:"unavailable"}),!1;if(h&&!h(e))return u.push({id:e.id,why:"disabled"}),!1;if(F(e.reach)>F(i))return u.push({id:e.id,why:`reach '${e.reach}' exceeds '${i}'`}),!1;const o=n.filter(k=>!e.capabilities.includes(k));if(o.length)return u.push({id:e.id,why:`missing ${o.join(", ")}`}),!1;if(r.minWindow>0&&Number(e.window)>0&&Number(e.window)<r.minWindow)return u.push({id:e.id,why:`a ${Math.round(e.window/1e3)}k window under the ${Math.round(r.minWindow/1e3)}k this turn needs`}),!1;if(r.maxLatencyMs>0&&e.latencyMs>r.maxLatencyMs)return u.push({id:e.id,why:`${e.latencyMs}ms exceeds the ${r.maxLatencyMs}ms deadline`}),!1;if(r.maxCostPer1k>=0&&r.maxCostPer1k!==void 0&&e.costPer1k>r.maxCostPer1k)return u.push({id:e.id,why:`costs ${e.costPer1k} over the ${r.maxCostPer1k} budget`}),!1;if(e.rateLimited)return u.push({id:e.id,why:"rate limited"}),!1;if(r.exclude?.includes?.(e.id))return u.push({id:e.id,why:"already failed this request"}),!1;if(r.minQuality>0){const k=Number.isFinite(e.quality)?e.quality:.5;if(k<r.minQuality)return u.push({id:e.id,why:`below the quality this task needs (${k} < ${r.minQuality})`}),!1}return!0});if(!g.length){if(r.minQuality>0){const e=this.route({...r,minQuality:0});if(e.model)return{...e,relaxed:!0,reasons:[...e.reasons,`no model met the quality this task needs (${r.minQuality}) — used the best available instead`]}}if(r.negotiable?.length){const e=(r.capabilities||[]).filter(k=>!r.negotiable.includes(k)),o=this.route({...r,minQuality:0,capabilities:e,negotiable:[]});if(o.model)return{...o,relaxed:!0,reasons:[...o.reasons,`no model offers ${r.negotiable.join(", ")} — used one without it, which may do this task poorly`]}}return{model:null,reasons:["no candidate satisfies the constraints"],constraints:p,rejected:u}}const b=r.prefer||"balanced",v=e=>{const o=1+Math.max(0,Math.min(1,e.load)),k=Number.isFinite(e.quality)?Math.max(.1,e.quality):.5,P=j[e.reach]??1;return b==="latency"?e.latencyMs*o*P:b==="cost"?e.costPer1k*o*P:b==="quality"?o/k:(e.latencyMs/1e3+e.costPer1k*L)*o*P/k},x=new Map,w=e=>(x.has(e)||x.set(e,v(e)),x.get(e)),$=(e,o)=>e.providerRank-o.providerRank||w(e)-w(o)||e.id.localeCompare(o.id),f=(e,o)=>w(e)-w(o)||e.providerRank-o.providerRank||e.id.localeCompare(o.id),m=new Map;for(const e of g){const o=S(e)||`#${e.id}`;m.has(o)||m.set(o,[]),m.get(o).push(e)}const _=[...m.values()].map(e=>[...e].sort(e.some(o=>o.orderPinned)?$:f));_.sort((e,o)=>w(e[0])-w(o[0])||$(e[0],o[0]));const R=[];for(const e of _){const o=R[R.length-1],k=o?w(o[0][0]):0;o&&w(e[0])<=k*(1+T)?o.push(e):R.push([e])}for(const e of R)e.sort((o,k)=>$(o[0],k[0]));let M=R.flat(2);const A=b==="balanced"?M.filter(e=>e.orderPinned).sort((e,o)=>e.providerRank-o.providerRank)[0]:null;A&&(M=[A,...M.filter(e=>e!==A)]);const N=R[0]?.length>1,I=(R[0]||[]).flat().length,E=M[0];return{model:E,eligible:M,constraints:p,strategy:A?"declared-default":"default-score",reasons:[`reach '${E.reach}' within '${i}'`,n.length?`has ${n.join(", ")}`:"no special capability needed",A?`your default (Order ${E.providerRank}) — nothing about this turn asked for anything else`:N?`order ${E.providerRank} broke a ${I}-way tie by ${b}, of ${M.length} eligible`:`best by ${b} (${M.length} eligible)`],rejected:u,runnersUp:M.slice(1).map(e=>e.id)}},async routeWith(r={},i={}){const n=this.route(r);if(!n.model||!c.length)return n;const p=new Map(n.eligible.map(u=>[u.id,u]));for(const u of c){if(h&&!h(u))continue;let g=null;try{const m=u.decide([...n.eligible],r,i);g=u.timeoutMs>0?await Promise.race([m,new Promise(_=>setTimeout(()=>_(null),u.timeoutMs))]):await m}catch{g=null}if(!g)continue;const b=Array.isArray(g)?g:Array.isArray(g?.ranked)?g.ranked:[g],v=Array.isArray(g?.why)?g.why.filter(m=>typeof m=="string"&&m):[],x=b.map(m=>typeof m=="string"?p.get(m):p.get(m?.id)).filter(Boolean),w=b.length-x.length;if(!x.length)continue;const $=n.eligible.filter(m=>!x.includes(m)),f=[...x,...$];return{...n,model:x[0],eligible:f,strategy:u.id,runnersUp:f.slice(1).map(m=>m.id),reasons:[...n.reasons.slice(0,-1),`chosen by '${u.id}' (class ${u.classUsed}) from ${n.eligible.length} eligible`,...v,...w>0?[`${w} suggestion(s) ignored — not eligible under the constraints`]:[]]}}return n},async run(r,{dispatch:i,need:n={}}={}){if(typeof i!="function")throw new q("NO_DISPATCH","run needs a dispatch function");const p=await this.routeWith(n,{request:r});if(!p.model)throw new q("NO_ROUTE",p.reasons[0]);const u=f=>!f.requiredFor||f.requiredFor(p.model,n),g=y.filter(f=>f.requiredFor&&f.requiredFor(p.model,n)),b=new Set(a("request").concat(a("response")).map(f=>f.id)),v=g.filter(f=>!b.has(f.id));if(v.length)throw new q("MISSING_REQUIRED",`route to '${p.model.id}' requires ${v.map(f=>f.id).join(", ")}, which is not active`);const x={model:p.model,need:n,decision:p};let w=r;for(const f of a("request"))u(f)&&(w=await f.run(w,x)??w);let $=await i(w,x);for(const f of a("response"))u(f)&&($=await f.run($,x)??$);return{answer:$,decision:p}}}}export{U as FAILOVER_CAPABILITY_GAP,Q as FAILOVER_CLASS_GAP,re as REACH,q as RouterError,Z as createModelRouter,G as defineMiddleware,W as defineModel,H as defineRouteStrategy,J as failoverOrder,O as pinnedOrderOf,K as preferenceFor,ie as reachRank,V as requirementsFor,X as requirementsForStep,S as sameModelKey,Y as signalsFrom};
package/sandbox-policy.js CHANGED
@@ -1 +1 @@
1
- import{EventError as A}from"./event.js";import{normalizeGrant as b}from"./sandbox-grant.js";const y=Object.freeze(["none","process","container","kubernetes"]),E=Object.freeze(["open","allowlist","none","gateway"]),_=Object.freeze(["~/.chatpanel","~/.ssh","~/.gnupg","~/.aws","~/.azure","~/.config/gcloud","~/.kube","~/.netrc","~/.docker/config.json","~/.npmrc","~/.pypirc"]),x=Object.freeze(["/tmp","/private/tmp","~/.cache","~/.npm","~/.local/share/uv","~/.local/state"]),h=Object.freeze({codex:Object.freeze({hosts:["api.openai.com","chatgpt.com","auth.openai.com","*.openai.com"],write:["~/.codex"]}),claude:Object.freeze({hosts:["api.anthropic.com","*.anthropic.com","claude.ai","statsig.anthropic.com"],write:["~/.claude","~/.claude.json"]}),antigravity:Object.freeze({hosts:["*.googleapis.com","*.google.com","oauth2.googleapis.com"],write:["~/.gemini","~/.antigravity","~/.config/antigravity"]}),custom:Object.freeze({hosts:[],write:[]}),mcp:Object.freeze({hosts:[],write:[]}),extract:Object.freeze({hosts:[],write:[]})}),R=Object.freeze(["github.com","*.github.com","*.githubusercontent.com","gitlab.com","bitbucket.org","registry.npmjs.org","pypi.org","files.pythonhosted.org","crates.io","static.crates.io","proxy.golang.org","sum.golang.org","huggingface.co","*.huggingface.co"]),u=e=>!!e&&typeof e=="object"&&!Array.isArray(e),g=e=>Array.isArray(e)&&e.every(o=>typeof o=="string"&&o.length>0),c=(e,o)=>{if(!e)throw new A("SHAPE",o)},f=e=>[...new Set(e)];function O(e){c(u(e),"kit: must be an object"),c(typeof e.id=="string"&&e.id.length>0,"kit: id required"),c(u(e.network)&&E.includes(e.network.mode),`kit ${e.id}: network.mode must be one of ${E.join(", ")}`),c(g(e.network.allowedDomains||[]),`kit ${e.id}: network.allowedDomains must be string[]`),c(g(e.network.deniedDomains||[]),`kit ${e.id}: network.deniedDomains must be string[]`),c(u(e.filesystem),`kit ${e.id}: filesystem required`);for(const o of["allowWrite","denyWrite","allowRead","denyRead"])c(g(e.filesystem[o]||[]),`kit ${e.id}: filesystem.${o} must be string[]`);return c(g(e.filesystem.allowWrite)&&e.filesystem.allowWrite.length>0,`kit ${e.id}: filesystem.allowWrite must name at least the working directory`),e.image!=null&&c(typeof e.image=="string",`kit ${e.id}: image must be a string`),e.credentials!=null&&c(Array.isArray(e.credentials)&&e.credentials.every(o=>u(o)&&typeof o.name=="string"&&typeof o.forHost=="string"),`kit ${e.id}: credentials must be [{ name, forHost }]`),{id:e.id,kind:e.kind||"process",image:e.image||null,network:{mode:e.network.mode,allowedDomains:f(e.network.allowedDomains||[]),deniedDomains:f(e.network.deniedDomains||[])},filesystem:{allowWrite:f(e.filesystem.allowWrite),denyWrite:f(e.filesystem.denyWrite||[]),allowRead:f(e.filesystem.allowRead||[]),denyRead:f(e.filesystem.denyRead||[])},credentials:e.credentials||[],limits:u(e.limits)?{...e.limits}:{}}}import{normalizeGrant as M,mergeGrants as k,parseHostList as q}from"./sandbox-grant.js";function N({engine:e="custom",cwd:o,mode:t="open",extraHosts:r=[],extraWrite:n=[],extraDenyRead:s=[],grant:l=null}={}){const d=h[e]||h.custom;c(typeof o=="string"&&o.length>0,"kit: cwd required");const a=b(l);return O({id:`${e}:${t}`,kind:"process",network:{mode:t,allowedDomains:t==="open"?["*"]:t==="none"?[]:f([...d.hosts,...R,...r,...a.hosts]),deniedDomains:[]},filesystem:{allowWrite:f([o,...x,...d.write,...n,...a.write.filter(i=>!_.some(p=>i===p||i.startsWith(`${p}/`)))]),denyWrite:[],allowRead:[o],denyRead:f([..._,...s])}})}function z(e,{loopback:o=[],home:t="",platform:r="darwin"}={}){const n=O(e),s=d=>t&&d.startsWith("~")?t+d.slice(1):d,l=n.network.mode==="none"?[]:o.map(d=>`127.0.0.1:${d}`);return{network:{allowedDomains:f([...n.network.allowedDomains,...l]),deniedDomains:n.network.deniedDomains,allowLocalBinding:r==="darwin"&&l.length>0},filesystem:{denyRead:n.filesystem.denyRead.map(s),allowRead:n.filesystem.allowRead.map(s),allowWrite:n.filesystem.allowWrite.map(s),denyWrite:n.filesystem.denyWrite.map(s)}}}function C({layer:e="none",runtime:o=null,kitId:t=null,mode:r=null,reason:n=null,hosts:s=null}={}){return c(y.includes(e),`sandbox record: layer must be one of ${y.join(", ")}`),{layer:e,runtime:o,kit:t,mode:r,...e==="none"&&n?{reason:n}:{},...Array.isArray(s)&&s.length?{hosts:f(s)}:{}}}function S(e,{platform:o="darwin"}={}){const t=String(e);if(o==="win32"){c(!/[\r\n]/.test(t),"win32 command line: an argument holds a newline, which cmd.exe cannot carry");let r=t;if(t===""||/[ \t\v"]/.test(t)){r='"';for(let n=0;n<t.length;n++){let s=0;for(;n<t.length&&t[n]==="\\";)s++,n++;if(n===t.length){r+="\\".repeat(s*2);break}t[n]==='"'?r+="\\".repeat(s*2+1)+'"':r+="\\".repeat(s)+t[n]}r+='"'}return r.replace(/[()%!^"<>&|]/g,"^$&")}return t===""?"''":/^[A-Za-z0-9_\-./=:@%+,]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}const I=Object.freeze(["SSL_CERT_FILE","REQUESTS_CA_BUNDLE","CURL_CA_BUNDLE","GIT_SSL_CAINFO"]);function H(e={},{platform:o="darwin",caBundle:t=""}={}){const r={NODE_USE_ENV_PROXY:"1"};if(t)for(const n of I)e[n]||(r[n]=t);if(o==="linux")for(const n of["no_proxy","NO_PROXY"])typeof e[n]=="string"&&(r[n]=e[n].split(",").map(s=>s.trim()).filter(s=>s&&!/^(localhost|127\.0\.0\.1|::1|\[::1\])$/i.test(s)).join(","));return r}function L(e,o=[],{platform:t="darwin"}={}){return[e,...o].map(r=>S(r,{platform:t})).join(" ")}const T=/[\\/]+/,m=e=>String(e||"").replace(/\//g,"\\").replace(/\\+$/,"").toLowerCase(),D=e=>/^[a-z]:$/i.test(m(e))||m(e)==="";function w(e,o){const t=m(e),r=m(o);return!!r&&t!==r&&t.startsWith(r+"\\")}function W(e){const o=String(e||"").replace(/\//g,"\\").split("\\");if(o.length<2)return"";const t=o.findIndex(r=>r.toLowerCase()==="node_modules");return(t>0?o.slice(0,t):o.slice(0,-1)).join("\\")}function K({kit:e,files:o=[],home:t}){c(typeof t=="string"&&t.length>0,"windows grants: home required");const r=a=>(a.startsWith("~")?t+a.slice(1):a).replace(/\//g,"\\"),n=[];for(const a of e?.filesystem?.allowWrite||[]){const i=r(a);!/^[a-z]:\\/i.test(i)&&!i.startsWith("\\\\")||(c(!D(i)&&m(i)!==m(t),`windows grants: a write on ${i} would hand the sandbox account the whole profile`),w(i,t)&&n.push(i))}const s=(a,i)=>i.some(p=>m(a)===m(p)||w(a,p)),l=[];for(const a of o){const i=W(a);i&&w(i,t)&&l.push(i)}for(const a of e?.filesystem?.allowRead||[]){const i=r(a);w(i,t)&&l.push(i)}const d=f(l).filter(a=>!s(a,n));return{read:d.filter(a=>!d.some(i=>i!==a&&w(a,i))),write:f(n)}}const j=Object.freeze(["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","CLAUDE_CONFIG_DIR","OPENAI_API_KEY","OPENAI_BASE_URL","OPENAI_API_BASE","CODEX_HOME","GEMINI_API_KEY","GOOGLE_API_KEY","DEEPSEEK_API_KEY","DSH_HOME","OPENROUTER_API_KEY","GROQ_API_KEY","XAI_API_KEY","MISTRAL_API_KEY"]);function Y({engine:e="custom",home:o,env:t={},base:r={},carry:n=j}={}){c(typeof o=="string"&&o.length>0,"windows env: home required");const s=o.replace(/\//g,"\\"),l=/^[a-z]:/i.test(s)?s.slice(0,2):"",d={USERPROFILE:s,...l?{HOMEDRIVE:l,HOMEPATH:s.slice(2)}:{}};for(const[a,i]of Object.entries(t))typeof i=="string"&&(r[a]!==i||n.includes(a))&&(d[a]=i);return e==="codex"&&!d.CODEX_HOME&&(d.CODEX_HOME=s+"\\.codex"),d}function v(e,o){c(Array.isArray(e),"srt-win argv: must be an array");const t=e.indexOf("exec"),r=t>=0?e.indexOf("--",t+1):-1;c(t>=0&&r>t,"srt-win argv: expected `exec … -- <shell> <command>`");const n=new Set;for(let l=t+1;l<r;l++)e[l]==="--env"&&typeof e[l+1]=="string"&&n.add(e[l+1].split("=")[0].toUpperCase());const s=[];for(const[l,d]of Object.entries(o||{}))c(/^[A-Za-z_][A-Za-z0-9_]*$/.test(l),`srt-win env: bad key ${l}`),c(!/[\r\n]/.test(d),`srt-win env: ${l} holds a newline`),n.has(l.toUpperCase())||s.push("--env",`${l}=${d}`);return[...e.slice(0,r),...s,...e.slice(r)]}export{x as COMMON_WRITE,R as DEVELOPER_HOSTS,h as ENGINE_KITS,E as NETWORK_MODES,y as SANDBOX_LAYERS,_ as SECRET_PATHS,j as WINDOWS_CARRY_KEYS,N as kitFor,k as mergeGrants,M as normalizeGrant,q as parseHostList,H as sandboxEnvOverlay,C as sandboxRecord,L as shellJoin,S as shellQuote,z as toSrtSettings,w as underWindowsHome,O as validateKit,K as windowsGrantsFor,W as windowsInstallRoot,Y as windowsSandboxEnv,v as withSrtWinEnv};
1
+ import{EventError as b}from"./event.js";import{normalizeGrant as A}from"./sandbox-grant.js";const y=Object.freeze(["none","process","container","kubernetes"]),E=Object.freeze(["open","allowlist","none","gateway"]),h=Object.freeze(["~/.chatpanel","~/.ssh","~/.gnupg","~/.aws","~/.azure","~/.config/gcloud","~/.kube","~/.netrc","~/.docker/config.json","~/.npmrc","~/.pypirc"]),x=Object.freeze(["/tmp","/private/tmp","~/.cache","~/.npm","~/.local/share/uv","~/.local/state"]),_=Object.freeze({codex:Object.freeze({hosts:["api.openai.com","chatgpt.com","auth.openai.com","*.openai.com"],write:["~/.codex"]}),claude:Object.freeze({hosts:["api.anthropic.com","*.anthropic.com","claude.ai","statsig.anthropic.com"],write:["~/.claude","~/.claude.json"]}),antigravity:Object.freeze({hosts:["*.googleapis.com","*.google.com","oauth2.googleapis.com"],write:["~/.gemini","~/.antigravity","~/.config/antigravity"]}),custom:Object.freeze({hosts:[],write:[]}),mcp:Object.freeze({hosts:[],write:[]}),extract:Object.freeze({hosts:[],write:[]}),"model-server":Object.freeze({hosts:["huggingface.co","*.huggingface.co","*.hf.co","cdn-lfs.huggingface.co","cas-bridge.xethub.hf.co","dl.chatpanel.net"],write:[]})}),R=Object.freeze(["github.com","*.github.com","*.githubusercontent.com","gitlab.com","bitbucket.org","registry.npmjs.org","pypi.org","files.pythonhosted.org","crates.io","static.crates.io","proxy.golang.org","sum.golang.org","huggingface.co","*.huggingface.co"]),p=e=>!!e&&typeof e=="object"&&!Array.isArray(e),g=e=>Array.isArray(e)&&e.every(o=>typeof o=="string"&&o.length>0),l=(e,o)=>{if(!e)throw new b("SHAPE",o)},f=e=>[...new Set(e)];function O(e){l(p(e),"kit: must be an object"),l(typeof e.id=="string"&&e.id.length>0,"kit: id required"),l(p(e.network)&&E.includes(e.network.mode),`kit ${e.id}: network.mode must be one of ${E.join(", ")}`),l(g(e.network.allowedDomains||[]),`kit ${e.id}: network.allowedDomains must be string[]`),l(g(e.network.deniedDomains||[]),`kit ${e.id}: network.deniedDomains must be string[]`),l(p(e.filesystem),`kit ${e.id}: filesystem required`);for(const o of["allowWrite","denyWrite","allowRead","denyRead"])l(g(e.filesystem[o]||[]),`kit ${e.id}: filesystem.${o} must be string[]`);return l(g(e.filesystem.allowWrite)&&e.filesystem.allowWrite.length>0,`kit ${e.id}: filesystem.allowWrite must name at least the working directory`),e.image!=null&&l(typeof e.image=="string",`kit ${e.id}: image must be a string`),e.credentials!=null&&l(Array.isArray(e.credentials)&&e.credentials.every(o=>p(o)&&typeof o.name=="string"&&typeof o.forHost=="string"),`kit ${e.id}: credentials must be [{ name, forHost }]`),{id:e.id,kind:e.kind||"process",image:e.image||null,network:{mode:e.network.mode,allowedDomains:f(e.network.allowedDomains||[]),deniedDomains:f(e.network.deniedDomains||[])},filesystem:{allowWrite:f(e.filesystem.allowWrite),denyWrite:f(e.filesystem.denyWrite||[]),allowRead:f(e.filesystem.allowRead||[]),denyRead:f(e.filesystem.denyRead||[])},credentials:e.credentials||[],limits:p(e.limits)?{...e.limits}:{}}}import{normalizeGrant as M,mergeGrants as k,parseHostList as q}from"./sandbox-grant.js";function z({engine:e="custom",cwd:o,mode:t="open",extraHosts:r=[],extraWrite:n=[],extraDenyRead:s=[],grant:c=null}={}){const d=_[e]||_.custom;l(typeof o=="string"&&o.length>0,"kit: cwd required");const a=A(c);return O({id:`${e}:${t}`,kind:"process",network:{mode:t,allowedDomains:t==="open"?["*"]:t==="none"?[]:f([...d.hosts,...R,...r,...a.hosts]),deniedDomains:[]},filesystem:{allowWrite:f([o,...x,...d.write,...n,...a.write.filter(i=>!h.some(u=>i===u||i.startsWith(`${u}/`)))]),denyWrite:[],allowRead:[o],denyRead:f([...h,...s])}})}function N(e,{loopback:o=[],home:t="",platform:r="darwin"}={}){const n=O(e),s=d=>t&&d.startsWith("~")?t+d.slice(1):d,c=n.network.mode==="none"?[]:o.map(d=>`127.0.0.1:${d}`);return{network:{allowedDomains:f([...n.network.allowedDomains,...c]),deniedDomains:n.network.deniedDomains,allowLocalBinding:r==="darwin"&&c.length>0},filesystem:{denyRead:n.filesystem.denyRead.map(s),allowRead:n.filesystem.allowRead.map(s),allowWrite:n.filesystem.allowWrite.map(s),denyWrite:n.filesystem.denyWrite.map(s)}}}function C({layer:e="none",runtime:o=null,kitId:t=null,mode:r=null,reason:n=null,hosts:s=null}={}){return l(y.includes(e),`sandbox record: layer must be one of ${y.join(", ")}`),{layer:e,runtime:o,kit:t,mode:r,...e==="none"&&n?{reason:n}:{},...Array.isArray(s)&&s.length?{hosts:f(s)}:{}}}function S(e,{platform:o="darwin"}={}){const t=String(e);if(o==="win32"){l(!/[\r\n]/.test(t),"win32 command line: an argument holds a newline, which cmd.exe cannot carry");let r=t;if(t===""||/[ \t\v"]/.test(t)){r='"';for(let n=0;n<t.length;n++){let s=0;for(;n<t.length&&t[n]==="\\";)s++,n++;if(n===t.length){r+="\\".repeat(s*2);break}t[n]==='"'?r+="\\".repeat(s*2+1)+'"':r+="\\".repeat(s)+t[n]}r+='"'}return r.replace(/[()%!^"<>&|]/g,"^$&")}return t===""?"''":/^[A-Za-z0-9_\-./=:@%+,]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}const I=Object.freeze(["SSL_CERT_FILE","REQUESTS_CA_BUNDLE","CURL_CA_BUNDLE","GIT_SSL_CAINFO"]);function H(e={},{platform:o="darwin",caBundle:t=""}={}){const r={NODE_USE_ENV_PROXY:"1"};if(t)for(const n of I)e[n]||(r[n]=t);if(o==="linux")for(const n of["no_proxy","NO_PROXY"])typeof e[n]=="string"&&(r[n]=e[n].split(",").map(s=>s.trim()).filter(s=>s&&!/^(localhost|127\.0\.0\.1|::1|\[::1\])$/i.test(s)).join(","));return r}function L(e,o=[],{platform:t="darwin"}={}){return[e,...o].map(r=>S(r,{platform:t})).join(" ")}const T=/[\\/]+/,m=e=>String(e||"").replace(/\//g,"\\").replace(/\\+$/,"").toLowerCase(),D=e=>/^[a-z]:$/i.test(m(e))||m(e)==="";function w(e,o){const t=m(e),r=m(o);return!!r&&t!==r&&t.startsWith(r+"\\")}function j(e){const o=String(e||"").replace(/\//g,"\\").split("\\");if(o.length<2)return"";const t=o.findIndex(r=>r.toLowerCase()==="node_modules");return(t>0?o.slice(0,t):o.slice(0,-1)).join("\\")}function K({kit:e,files:o=[],home:t}){l(typeof t=="string"&&t.length>0,"windows grants: home required");const r=a=>(a.startsWith("~")?t+a.slice(1):a).replace(/\//g,"\\"),n=[];for(const a of e?.filesystem?.allowWrite||[]){const i=r(a);!/^[a-z]:\\/i.test(i)&&!i.startsWith("\\\\")||(l(!D(i)&&m(i)!==m(t),`windows grants: a write on ${i} would hand the sandbox account the whole profile`),w(i,t)&&n.push(i))}const s=(a,i)=>i.some(u=>m(a)===m(u)||w(a,u)),c=[];for(const a of o){const i=j(a);i&&w(i,t)&&c.push(i)}for(const a of e?.filesystem?.allowRead||[]){const i=r(a);w(i,t)&&c.push(i)}const d=f(c).filter(a=>!s(a,n));return{read:d.filter(a=>!d.some(i=>i!==a&&w(a,i))),write:f(n)}}const W=Object.freeze(["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","CLAUDE_CONFIG_DIR","OPENAI_API_KEY","OPENAI_BASE_URL","OPENAI_API_BASE","CODEX_HOME","GEMINI_API_KEY","GOOGLE_API_KEY","DEEPSEEK_API_KEY","DSH_HOME","OPENROUTER_API_KEY","GROQ_API_KEY","XAI_API_KEY","MISTRAL_API_KEY"]);function v({engine:e="custom",home:o,env:t={},base:r={},carry:n=W}={}){l(typeof o=="string"&&o.length>0,"windows env: home required");const s=o.replace(/\//g,"\\"),c=/^[a-z]:/i.test(s)?s.slice(0,2):"",d={USERPROFILE:s,...c?{HOMEDRIVE:c,HOMEPATH:s.slice(2)}:{}};for(const[a,i]of Object.entries(t))typeof i=="string"&&(r[a]!==i||n.includes(a))&&(d[a]=i);return e==="codex"&&!d.CODEX_HOME&&(d.CODEX_HOME=s+"\\.codex"),d}function Y(e,o){l(Array.isArray(e),"srt-win argv: must be an array");const t=e.indexOf("exec"),r=t>=0?e.indexOf("--",t+1):-1;l(t>=0&&r>t,"srt-win argv: expected `exec … -- <shell> <command>`");const n=new Set;for(let c=t+1;c<r;c++)e[c]==="--env"&&typeof e[c+1]=="string"&&n.add(e[c+1].split("=")[0].toUpperCase());const s=[];for(const[c,d]of Object.entries(o||{}))l(/^[A-Za-z_][A-Za-z0-9_]*$/.test(c),`srt-win env: bad key ${c}`),l(!/[\r\n]/.test(d),`srt-win env: ${c} holds a newline`),n.has(c.toUpperCase())||s.push("--env",`${c}=${d}`);return[...e.slice(0,r),...s,...e.slice(r)]}export{x as COMMON_WRITE,R as DEVELOPER_HOSTS,_ as ENGINE_KITS,E as NETWORK_MODES,y as SANDBOX_LAYERS,h as SECRET_PATHS,W as WINDOWS_CARRY_KEYS,z as kitFor,k as mergeGrants,M as normalizeGrant,q as parseHostList,H as sandboxEnvOverlay,C as sandboxRecord,L as shellJoin,S as shellQuote,N as toSrtSettings,w as underWindowsHome,O as validateKit,K as windowsGrantsFor,j as windowsInstallRoot,v as windowsSandboxEnv,Y as withSrtWinEnv};
package/schedule.js CHANGED
@@ -1 +1 @@
1
- class a extends Error{constructor(t,n){super(n),this.name="ScheduleError",this.code=t}}const T=Object.freeze(["once","interval","daily","weekly"]),j=Object.freeze(["timer","meeting","voice","data","channel"]),S=Object.freeze(["skill","prompt","monitor","notify"]),O=Object.freeze(["skip","runOnce","runAll"]),$=20;function g(e,{days:t=0,hour:n,minute:r=0}){const o=new Date(e);return o.setDate(o.getDate()+t),o.setHours(n,r,0,0),o.getTime()}const I=e=>{const t=new Date(e).getDay();return t===0||t===6};function E(e){if(!e||typeof e!="object")throw new a("BAD_SCHEDULE","schedule must be an object");if(!T.includes(e.kind))throw new a("BAD_SCHEDULE",`unknown schedule kind '${e.kind}'`);if(e.kind==="once"&&!(e.at>0))throw new a("BAD_SCHEDULE","once needs `at`");if(e.kind==="interval"&&!(e.everyMs>=6e4))throw new a("BAD_SCHEDULE","interval needs everyMs >= 60000");if(e.kind==="daily"||e.kind==="weekly"){if(!Number.isInteger(e.hour)||e.hour<0||e.hour>23)throw new a("BAD_SCHEDULE","hour must be 0-23");const t=e.minute??0;if(!Number.isInteger(t)||t<0||t>59)throw new a("BAD_SCHEDULE","minute must be 0-59")}if(e.kind==="weekly"&&(!Number.isInteger(e.weekday)||e.weekday<0||e.weekday>6))throw new a("BAD_SCHEDULE","weekly needs weekday 0-6 (Sunday = 0)");return e}function A(e,t){const n=E(e),r=n.minute??0;switch(n.kind){case"once":return n.at>t?n.at:null;case"interval":{const o=n.anchor??t;if(o>t)return o;const i=Math.floor((t-o)/n.everyMs)+1;return o+i*n.everyMs}case"daily":{let o=g(t,{hour:n.hour,minute:r});if(o<=t&&(o=g(t,{days:1,hour:n.hour,minute:r})),n.weekdaysOnly)for(let i=0;i<7&&I(o);i++)o=g(o,{days:1,hour:n.hour,minute:r});return o}case"weekly":{const o=new Date(t).getDay();let i=(n.weekday-o+7)%7;return i===0&&g(t,{hour:n.hour,minute:r})<=t&&(i=7),g(t,{days:i,hour:n.hour,minute:r})}default:return null}}const B=Object.freeze(["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]),w=e=>`${String(e?.hour??0).padStart(2,"0")}:${String(e?.minute??0).padStart(2,"0")}`;function Y(e){if(!e||typeof e!="object")return"";switch(e.kind){case"once":return e.at>0?`once, at ${new Date(e.at).toLocaleString()}`:"";case"interval":{const t=Number(e.everyMs)||0;if(t<6e4)return"";const n=Math.round(t/6e4);if(n%1440===0){const r=n/1440;return`every ${r===1?"day":`${r} days`}`}if(n%60===0){const r=n/60;return`every ${r===1?"hour":`${r} hours`}`}return`every ${n} minutes`}case"daily":return e.weekdaysOnly?`every weekday at ${w(e)}`:`every day at ${w(e)}`;case"weekly":{const t=B[e.weekday];return t?`every ${t} at ${w(e)}`:""}default:return""}}function L(e,t,n,r=$){const o=[];let i=t;for(;o.length<r;){const s=A(e,i);if(s===null||s>n)break;o.push(s),i=s}return o}function d({id:e,label:t,kind:n,watches:r=[],description:o="",classUsed:i="R",matches:s=null,params:u={}}){if(!e)throw new a("BAD_TRIGGER","trigger.id required");if(!j.includes(n))throw new a("BAD_TRIGGER",`trigger '${e}': unknown kind '${n}'`);if(n!=="timer"&&typeof s!="function")throw new a("BAD_TRIGGER",`trigger '${e}': an event trigger needs matches()`);return Object.freeze({id:e,label:t||e,kind:n,watches:Object.freeze([...r]),description:o,classUsed:i,matches:s,params:Object.freeze({...u})})}function V(e=[]){const t=[...e];return{add(n){return t.push(n),()=>{const r=t.indexOf(n);r>=0&&t.splice(r,1)}},list:()=>[...t],get:n=>t.find(r=>r.id===n)||null}}const C=e=>String(e||"").toLowerCase().match(/[\p{L}\p{N}']+/gu)||[],h=e=>String(e||"").trim().toLowerCase(),D=3,M=e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function p(e,t=120){const n=String(e||"").replace(/\s+/g," ").trim();if(n.length<=t)return n;const r=n.slice(0,t),o=r.lastIndexOf(" ");return`${(o>t*.6?r.slice(0,o):r).replace(/[\s,;:.!?—-]+$/,"")}…`}function R(e,t){const n=h(t);if(n.length<D)return!1;const r=/[\p{L}\p{N}]/u.test(n[0])?"\\b":"",o=/[\p{L}\p{N}]/u.test(n[n.length-1])?"\\b":"";try{return new RegExp(`${r}${M(n)}${o}`,"iu").test(String(e||""))}catch{return h(e).includes(n)}}function y(e,t,n){return e==="me"?!!n?.isSelf?.(t):e==="others"?!n?.isSelf?.(t):!0}const N=Object.freeze(new Set(["and","or","but","so","because","cause","cos","since","although","though","while","whereas","unless","until","if","when","whenever","that","which","who","whom","whose","than","as","like","what","to","of","in","on","at","by","for","from","with","without","about","into","onto","over","under","between","through","during","against","per","a","an","the","my","our","your","their","its","is","are","was","were","be","been","being","am","do","does","did","have","has","had","will","would","can","could","should","shall","may","might","must","um","uh","er"]));function Z(e){const t=String(e||"").trim();if(!t)return!1;if(/[.!?…]["'\u2019\u201d)\]]*$/.test(t))return!0;if(/[,;:\-\u2013\u2014]$/.test(t))return!1;const n=t.toLowerCase().match(/[\p{L}\p{N}']+/gu)||[],r=n[n.length-1];return r?!N.has(r):!0}const v="text.delta",_=Object.freeze(["meeting","note","chat"]),k=Object.freeze(["meeting.transcript.delta",v]);function G(e){if(e?.type==="meeting.transcript.delta")return"meeting";const t=h(e?.source);return _.includes(t)?t:""}function b(e,t){const n=G(t);if(!n)return!1;const r=(Array.isArray(e)?e:[]).map(h).filter(o=>_.includes(o));return r.length?r.includes(n):n==="meeting"}const m=d({id:"timer:schedule",label:"On a schedule",kind:"timer",description:'Once, on an interval, daily, or on a weekday — "every weekday at 8am".'}),W=d({id:"meeting:started",label:"When a meeting starts",kind:"meeting",watches:["meeting.started"],matches:(e,t={})=>t.platform&&h(e.platform)!==h(t.platform)||t.titleIncludes&&!h(e.title).includes(h(t.titleIncludes))?null:{why:`meeting started: ${e.title||e.meetingId}`}}),H=d({id:"meeting:ended",label:"When a meeting ends",kind:"meeting",watches:["meeting.ended"],matches:e=>({why:`meeting ended: ${e.title||e.meetingId}`})}),U=d({id:"meeting:person-joined",label:"When someone joins",kind:"meeting",watches:["meeting.person-joined"],matches:(e,t={})=>{const n=(t.names||[]).map(h).filter(Boolean),r=(e.people||[]).filter(o=>!n.length||n.some(i=>h(o)===i||h(o).startsWith(`${i} `)));return r.length?{why:`joined: ${r.join(", ")}`,people:r}:null}}),z=d({id:"meeting:phrase",label:"When a phrase is said",kind:"meeting",watches:k,matches:(e,t={},n={})=>{if(!b(t.sources,e))return null;const r=(t.any||[]).map(h).filter(o=>o.length>=D);if(!r.length)return null;for(const o of e.segments||[]){if(!y(t.speaker,o.speaker,n))continue;const i=r.find(s=>R(o.text,s));if(i)return{why:`“${i}” said by ${o.speaker||"someone"}`,segment:o,phrase:i}}return null}}),J=d({id:"meeting:topic",label:"When someone talks about something",kind:"meeting",watches:k,matches:(e,t={},n={})=>{if(!b(t.sources,e))return null;const r=(t.terms||[]).map(h).filter(Boolean);if(!r.length)return null;const o=Math.max(1,Math.min(t.minHits||1,r.length)),i=(e.segments||[]).filter(c=>y(t.speaker,c.speaker,n)),s=new Set(i.flatMap(c=>C(c.text))),u=r.filter(c=>c.split(/\s+/).every(l=>s.has(l)));return u.length>=o?{why:`talking about ${u.join(", ")}`,terms:u}:null}}),q=/^(who|what|when|where|why|how|which|whose|can|could|would|should|shall|do|does|did|is|are|was|were|will|have|has|any(one|body)|is there|are there)\b/i,F=d({id:"meeting:question",label:"When a question is asked",kind:"meeting",watches:k,matches:(e,t={},n={})=>{if(!b(t.sources,e))return null;for(const r of e.segments||[]){if(!y(t.speaker||"anyone",r.speaker,n))continue;const o=String(r.text||"").trim();if(!(o.length<8)&&(o.includes("?")||q.test(o)))return{why:`question from ${r.speaker||"someone"}: “${p(o,100)}”`,segment:r}}return null}}),X=d({id:"voice:command",label:"When you say the wake word",kind:"voice",watches:["voice.command"],matches:(e,t={})=>{const n=t.intents||[];return!e.command?.allowed||n.length&&!n.includes(e.command.intent)?null:{why:`you said “${e.command.command}”`,command:e.command}}}),ee=Object.freeze([m,W,H,U,z,J,F,X]);function te({id:e,name:t,trigger:n,schedule:r=null,params:o={},action:i,enabled:s=!0,onMissed:u="runOnce",limits:c={},approval:l=null,createdAt:f=0}){if(!e)throw new a("BAD_JOB","job.id required");if(!t)throw new a("BAD_JOB",`job '${e}': name required`);if(!n)throw new a("BAD_JOB",`job '${e}': trigger required`);if(!i||!S.includes(i.kind))throw new a("BAD_JOB",`job '${e}': action.kind must be one of ${S}`);if(i.kind==="skill"&&!i.skillId)throw new a("BAD_JOB",`job '${e}': skill action needs skillId`);if(!O.includes(u))throw new a("BAD_JOB",`job '${e}': unknown onMissed '${u}'`);return(n===m.id||r)&&E(r),{id:e,name:t,trigger:n,schedule:r,params:{...o},action:{...i},enabled:!!s,onMissed:u,limits:{...c},approval:l,createdAt:f||0}}function x(e,t){return`${e}@${t}`}function ne(e,{now:t,lastRun:n={},admit:r=null,max:o=$}={}){const i=[];for(const s of e||[]){if(!s.enabled||s.trigger!==m.id||!s.schedule||r&&!r(s))continue;const u=n[s.id]||s.createdAt||0;if(!u)continue;const c=L(s.schedule,u,t,o);if(!c.length)continue;const l=s.onMissed==="runAll"?c:s.onMissed==="runOnce"?[c[c.length-1]]:[];for(const f of l)i.push({job:s,at:f,key:x(s.id,f),late:t-f>6e4,missedCount:c.length});l.length||i.push({job:s,at:c[c.length-1],key:x(s.id,c[c.length-1]),skipped:!0,missedCount:c.length})}return i}function re(e,{now:t,lastRun:n={}}={}){let r=null;for(const o of e||[]){if(!o.enabled||o.trigger!==m.id||!o.schedule)continue;const i=A(o.schedule,Math.max(t,n[o.id]||0));i!==null&&(r===null||i<r)&&(r=i)}return r}const K=8;function P(e=[],{max:t=K}={}){const n=[];for(const r of e){const o=String(r?.segment?.text||r?.why||"").trim();if(!o)continue;const i=h(r?.segment?.speaker),s=r?.segment?.t||0,u=o.toLowerCase().replace(/\s+/g," "),c=n.findIndex(l=>l.who===i&&(s&&l.t?l.t===s:l.flat.startsWith(u)||u.startsWith(l.flat)));if(c>=0){o.length>n[c].text.length&&(n[c]={...n[c],match:r,text:o,flat:u});continue}n.push({who:i,t:s,match:r,text:o,flat:u})}return n.slice(-Math.max(1,t)).map(r=>r.match)}function Q(e=[]){return P(e,{max:Number.MAX_SAFE_INTEGER}).map(t=>String(t?.segment?.text||t?.why||"").trim()).filter(Boolean)}function oe(e=[],{noun:t="matches",max:n=3,chars:r=180}={}){const o=(e||[]).filter(Boolean);if(!o.length)return"";if(o.length===1)return String(o[0].why||"")||p(o[0]?.segment?.text,r);const i=Q(o);if(!i.length)return`${o.length} ${t}`;const s=i.slice(0,n),u=Math.max(40,Math.floor(r/s.length)),c=i.length-s.length;return`${i.length} ${t}: ${s.map(l=>`“${p(l,u)}”`).join(" · ")}`+(c>0?` +${c} more`:"")}function ie(e,t,{registry:n,ctx:r={},admit:o=null}={}){const i=[];for(const s of e||[]){if(!s.enabled||o&&!o(s))continue;const u=n?.get(s.trigger);if(!u||u.kind==="timer"||u.watches.length&&!u.watches.includes(t?.type))continue;let c=null;try{c=u.matches(t,s.params,r)}catch{c=null}c&&i.push({job:s,trigger:u,match:c,key:x(s.id,t.at||t.t||0)})}return i}export{ee as BUILTIN_TRIGGERS,N as DANGLING_TAILS,K as DEFAULT_COALESCE_MAX,S as JOB_ACTIONS,D as MIN_PHRASE_CHARS,O as MISSED_POLICIES,T as SCHEDULE_KINDS,a as ScheduleError,v as TEXT_DELTA,k as TEXT_WATCHES,j as TRIGGER_KINDS,_ as TRIGGER_SOURCES,B as WEEKDAY_NAMES,p as clipText,P as coalesceMatches,V as createTriggerRegistry,te as defineJob,d as defineTrigger,Y as describeSchedule,ne as dueJobs,G as eventSource,ie as jobsForEvent,oe as matchSummary,Q as matchTexts,H as meetingEndedTrigger,W as meetingStartedTrigger,A as nextFireAt,re as nextWakeAt,x as occurrenceKey,L as occurrencesBetween,U as personJoinedTrigger,z as phraseTrigger,F as questionTrigger,R as saidIn,b as sourceAllowed,m as timerTrigger,J as topicTrigger,Z as utteranceLooksComplete,E as validateSchedule,X as voiceCommandTrigger};
1
+ class l extends Error{constructor(t,n){super(n),this.name="ScheduleError",this.code=t}}const O=Object.freeze(["once","interval","daily","weekly","cron"]),B=Object.freeze(["timer","meeting","voice","data","channel"]),D=Object.freeze(["skill","prompt","monitor","notify"]),C=Object.freeze(["skip","runOnce","runAll"]),E=20;function f(e,{days:t=0,hour:n,minute:r=0}){const o=new Date(e);return o.setDate(o.getDate()+t),o.setHours(n,r,0,0),o.getTime()}const L=e=>{const t=new Date(e).getDay();return t===0||t===6};function A(e){if(!e||typeof e!="object")throw new l("BAD_SCHEDULE","schedule must be an object");if(!O.includes(e.kind))throw new l("BAD_SCHEDULE",`unknown schedule kind '${e.kind}'`);if(e.kind==="once"&&!(e.at>0))throw new l("BAD_SCHEDULE","once needs `at`");if(e.kind==="interval"&&!(e.everyMs>=6e4))throw new l("BAD_SCHEDULE","interval needs everyMs >= 60000");if(e.kind==="daily"||e.kind==="weekly"){if(!Number.isInteger(e.hour)||e.hour<0||e.hour>23)throw new l("BAD_SCHEDULE","hour must be 0-23");const t=e.minute??0;if(!Number.isInteger(t)||t<0||t>59)throw new l("BAD_SCHEDULE","minute must be 0-59")}if(e.kind==="weekly"&&(!Number.isInteger(e.weekday)||e.weekday<0||e.weekday>6))throw new l("BAD_SCHEDULE","weekly needs weekday 0-6 (Sunday = 0)");return e.kind==="cron"&&p(e.expr),e}const I=Object.freeze([{name:"minute",min:0,max:59},{name:"hour",min:0,max:23},{name:"day-of-month",min:1,max:31},{name:"month",min:1,max:12,names:["jan","feb","mar","apr","may","jun","jul","aug","sep","oct","nov","dec"]},{name:"day-of-week",min:0,max:7,names:["sun","mon","tue","wed","thu","fri","sat"]}]);function w(e,t){const n=e.toLowerCase();if(t.names){const o=t.names.indexOf(n.slice(0,3));if(o>=0&&n.length===3)return t.min===1?o+1:o}if(!/^\d+$/.test(n))throw new l("BAD_SCHEDULE",`cron: '${e}' is not a ${t.name}`);const r=Number(n);if(r<t.min||r>t.max)throw new l("BAD_SCHEDULE",`cron: ${t.name} ${r} is outside ${t.min}-${t.max}`);return r}function M(e,t){const n=new Set;for(const r of String(e).split(",")){if(!r)throw new l("BAD_SCHEDULE",`cron: empty entry in ${t.name}`);const[o,s]=r.split("/"),i=s===void 0?1:Number(s);if(!Number.isInteger(i)||i<1)throw new l("BAD_SCHEDULE",`cron: bad step '/${s}' in ${t.name}`);let c,a;if(o==="*")c=t.min,a=t.max;else if(o.includes("-")){const[u,h]=o.split("-");if(c=w(u,t),a=w(h,t),a<c)throw new l("BAD_SCHEDULE",`cron: range ${o} runs backwards in ${t.name}`)}else c=w(o,t),a=s===void 0?c:t.max;for(let u=c;u<=a;u+=i)n.add(u)}return t.name==="day-of-week"&&n.has(7)&&(n.delete(7),n.add(0)),n}function p(e){const t=String(e??"").trim().split(/\s+/);if(t.length!==5||!t[0])throw new l("BAD_SCHEDULE","cron needs five fields: minute hour day-of-month month day-of-week");const[n,r,o,s,i]=t.map((u,h)=>M(u,I[h])),c=t[2]==="*",a=t[4]==="*";return{minute:n,hour:r,dom:o,month:s,dow:i,domAny:c,dowAny:a}}const N=366*5;function H(e,t){const n=i=>{if(!e.month.has(i.getMonth()+1))return!1;const c=e.dom.has(i.getDate()),a=e.dow.has(i.getDay());return e.domAny&&e.dowAny?!0:e.domAny?a:e.dowAny?c:c||a},r=[...e.hour].sort((i,c)=>i-c),o=[...e.minute].sort((i,c)=>i-c),s=new Date(t);s.setSeconds(0,0);for(let i=0;i<N;i++){const c=new Date(s);if(c.setDate(s.getDate()+i),c.setHours(0,0,0,0),!!n(c))for(const a of r)for(const u of o){const h=new Date(c);if(h.setHours(a,u,0,0),h.getHours()===a&&h.getTime()>t)return h.getTime()}}return null}function _(e,t){const n=A(e),r=n.minute??0;switch(n.kind){case"once":return n.at>t?n.at:null;case"interval":{const o=n.anchor??t;if(o>t)return o;const s=Math.floor((t-o)/n.everyMs)+1;return o+s*n.everyMs}case"daily":{let o=f(t,{hour:n.hour,minute:r});if(o<=t&&(o=f(t,{days:1,hour:n.hour,minute:r})),n.weekdaysOnly)for(let s=0;s<7&&L(o);s++)o=f(o,{days:1,hour:n.hour,minute:r});return o}case"weekly":{const o=new Date(t).getDay();let s=(n.weekday-o+7)%7;return s===0&&f(t,{hour:n.hour,minute:r})<=t&&(s=7),f(t,{days:s,hour:n.hour,minute:r})}case"cron":return H(p(n.expr),t);default:return null}}const R=Object.freeze(["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"]),y=e=>`${String(e?.hour??0).padStart(2,"0")}:${String(e?.minute??0).padStart(2,"0")}`;function re(e){if(!e||typeof e!="object")return"";switch(e.kind){case"once":return e.at>0?`once, at ${new Date(e.at).toLocaleString()}`:"";case"interval":{const t=Number(e.everyMs)||0;if(t<6e4)return"";const n=Math.round(t/6e4);if(n%1440===0){const r=n/1440;return`every ${r===1?"day":`${r} days`}`}if(n%60===0){const r=n/60;return`every ${r===1?"hour":`${r} hours`}`}return`every ${n} minutes`}case"daily":return e.weekdaysOnly?`every weekday at ${y(e)}`:`every day at ${y(e)}`;case"weekly":{const t=R[e.weekday];return t?`every ${t} at ${y(e)}`:""}case"cron":{try{p(e.expr)}catch{return""}return`on the cron schedule ${String(e.expr).trim()}`}default:return""}}function v(e,t,n,r=E){const o=[];let s=t;for(;o.length<r;){const i=_(e,s);if(i===null||i>n)break;o.push(i),s=i}return o}function m({id:e,label:t,kind:n,watches:r=[],description:o="",classUsed:s="R",matches:i=null,params:c={}}){if(!e)throw new l("BAD_TRIGGER","trigger.id required");if(!B.includes(n))throw new l("BAD_TRIGGER",`trigger '${e}': unknown kind '${n}'`);if(n!=="timer"&&typeof i!="function")throw new l("BAD_TRIGGER",`trigger '${e}': an event trigger needs matches()`);return Object.freeze({id:e,label:t||e,kind:n,watches:Object.freeze([...r]),description:o,classUsed:s,matches:i,params:Object.freeze({...c})})}function oe(e=[]){const t=[...e];return{add(n){return t.push(n),()=>{const r=t.indexOf(n);r>=0&&t.splice(r,1)}},list:()=>[...t],get:n=>t.find(r=>r.id===n)||null}}const U=e=>String(e||"").toLowerCase().match(/[\p{L}\p{N}']+/gu)||[],d=e=>String(e||"").trim().toLowerCase(),T=3,G=e=>e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");function x(e,t=120){const n=String(e||"").replace(/\s+/g," ").trim();if(n.length<=t)return n;const r=n.slice(0,t),o=r.lastIndexOf(" ");return`${(o>t*.6?r.slice(0,o):r).replace(/[\s,;:.!?—-]+$/,"")}…`}function W(e,t){const n=d(t);if(n.length<T)return!1;const r=/[\p{L}\p{N}]/u.test(n[0])?"\\b":"",o=/[\p{L}\p{N}]/u.test(n[n.length-1])?"\\b":"";try{return new RegExp(`${r}${G(n)}${o}`,"iu").test(String(e||""))}catch{return d(e).includes(n)}}function b(e,t,n){return e==="me"?!!n?.isSelf?.(t):e==="others"?!n?.isSelf?.(t):!0}const z=Object.freeze(new Set(["and","or","but","so","because","cause","cos","since","although","though","while","whereas","unless","until","if","when","whenever","that","which","who","whom","whose","than","as","like","what","to","of","in","on","at","by","for","from","with","without","about","into","onto","over","under","between","through","during","against","per","a","an","the","my","our","your","their","its","is","are","was","were","be","been","being","am","do","does","did","have","has","had","will","would","can","could","should","shall","may","might","must","um","uh","er"]));function ie(e){const t=String(e||"").trim();if(!t)return!1;if(/[.!?…]["'\u2019\u201d)\]]*$/.test(t))return!0;if(/[,;:\-\u2013\u2014]$/.test(t))return!1;const n=t.toLowerCase().match(/[\p{L}\p{N}']+/gu)||[],r=n[n.length-1];return r?!z.has(r):!0}const J="text.delta",j=Object.freeze(["meeting","note","chat"]),k=Object.freeze(["meeting.transcript.delta",J]);function q(e){if(e?.type==="meeting.transcript.delta")return"meeting";const t=d(e?.source);return j.includes(t)?t:""}function S(e,t){const n=q(t);if(!n)return!1;const r=(Array.isArray(e)?e:[]).map(d).filter(o=>j.includes(o));return r.length?r.includes(n):n==="meeting"}const g=m({id:"timer:schedule",label:"On a schedule",kind:"timer",description:'Once, on an interval, daily, or on a weekday — "every weekday at 8am".'}),F=m({id:"meeting:started",label:"When a meeting starts",kind:"meeting",watches:["meeting.started"],matches:(e,t={})=>t.platform&&d(e.platform)!==d(t.platform)||t.titleIncludes&&!d(e.title).includes(d(t.titleIncludes))?null:{why:`meeting started: ${e.title||e.meetingId}`}}),X=m({id:"meeting:ended",label:"When a meeting ends",kind:"meeting",watches:["meeting.ended"],matches:e=>({why:`meeting ended: ${e.title||e.meetingId}`})}),K=m({id:"meeting:person-joined",label:"When someone joins",kind:"meeting",watches:["meeting.person-joined"],matches:(e,t={})=>{const n=(t.names||[]).map(d).filter(Boolean),r=(e.people||[]).filter(o=>!n.length||n.some(s=>d(o)===s||d(o).startsWith(`${s} `)));return r.length?{why:`joined: ${r.join(", ")}`,people:r}:null}}),P=m({id:"meeting:phrase",label:"When a phrase is said",kind:"meeting",watches:k,matches:(e,t={},n={})=>{if(!S(t.sources,e))return null;const r=(t.any||[]).map(d).filter(o=>o.length>=T);if(!r.length)return null;for(const o of e.segments||[]){if(!b(t.speaker,o.speaker,n))continue;const s=r.find(i=>W(o.text,i));if(s)return{why:`“${s}” said by ${o.speaker||"someone"}`,segment:o,phrase:s}}return null}}),Y=m({id:"meeting:topic",label:"When someone talks about something",kind:"meeting",watches:k,matches:(e,t={},n={})=>{if(!S(t.sources,e))return null;const r=(t.terms||[]).map(d).filter(Boolean);if(!r.length)return null;const o=Math.max(1,Math.min(t.minHits||1,r.length)),s=(e.segments||[]).filter(a=>b(t.speaker,a.speaker,n)),i=new Set(s.flatMap(a=>U(a.text))),c=r.filter(a=>a.split(/\s+/).every(u=>i.has(u)));return c.length>=o?{why:`talking about ${c.join(", ")}`,terms:c}:null}}),Q=/^(who|what|when|where|why|how|which|whose|can|could|would|should|shall|do|does|did|is|are|was|were|will|have|has|any(one|body)|is there|are there)\b/i,V=m({id:"meeting:question",label:"When a question is asked",kind:"meeting",watches:k,matches:(e,t={},n={})=>{if(!S(t.sources,e))return null;for(const r of e.segments||[]){if(!b(t.speaker||"anyone",r.speaker,n))continue;const o=String(r.text||"").trim();if(!(o.length<8)&&(o.includes("?")||Q.test(o)))return{why:`question from ${r.speaker||"someone"}: “${x(o,100)}”`,segment:r}}return null}}),Z=m({id:"voice:command",label:"When you say the wake word",kind:"voice",watches:["voice.command"],matches:(e,t={})=>{const n=t.intents||[];return!e.command?.allowed||n.length&&!n.includes(e.command.intent)?null:{why:`you said “${e.command.command}”`,command:e.command}}}),se=Object.freeze([g,F,X,K,P,Y,V,Z]);function ce({id:e,name:t,trigger:n,schedule:r=null,params:o={},action:s,enabled:i=!0,onMissed:c="runOnce",limits:a={},approval:u=null,createdAt:h=0}){if(!e)throw new l("BAD_JOB","job.id required");if(!t)throw new l("BAD_JOB",`job '${e}': name required`);if(!n)throw new l("BAD_JOB",`job '${e}': trigger required`);if(!s||!D.includes(s.kind))throw new l("BAD_JOB",`job '${e}': action.kind must be one of ${D}`);if(s.kind==="skill"&&!s.skillId)throw new l("BAD_JOB",`job '${e}': skill action needs skillId`);if(!C.includes(c))throw new l("BAD_JOB",`job '${e}': unknown onMissed '${c}'`);return(n===g.id||r)&&A(r),{id:e,name:t,trigger:n,schedule:r,params:{...o},action:{...s},enabled:!!i,onMissed:c,limits:{...a},approval:u,createdAt:h||0}}function $(e,t){return`${e}@${t}`}function ae(e,{now:t,lastRun:n={},admit:r=null,max:o=E}={}){const s=[];for(const i of e||[]){if(!i.enabled||i.trigger!==g.id||!i.schedule||r&&!r(i))continue;const c=n[i.id]||i.createdAt||0;if(!c)continue;const a=v(i.schedule,c,t,o);if(!a.length)continue;const u=i.onMissed==="runAll"?a:i.onMissed==="runOnce"?[a[a.length-1]]:[];for(const h of u)s.push({job:i,at:h,key:$(i.id,h),late:t-h>6e4,missedCount:a.length});u.length||s.push({job:i,at:a[a.length-1],key:$(i.id,a[a.length-1]),skipped:!0,missedCount:a.length})}return s}function ue(e,{now:t,lastRun:n={}}={}){let r=null;for(const o of e||[]){if(!o.enabled||o.trigger!==g.id||!o.schedule)continue;const s=_(o.schedule,Math.max(t,n[o.id]||0));s!==null&&(r===null||s<r)&&(r=s)}return r}const ee=8;function te(e=[],{max:t=ee}={}){const n=[];for(const r of e){const o=String(r?.segment?.text||r?.why||"").trim();if(!o)continue;const s=d(r?.segment?.speaker),i=r?.segment?.t||0,c=o.toLowerCase().replace(/\s+/g," "),a=n.findIndex(u=>u.who===s&&(i&&u.t?u.t===i:u.flat.startsWith(c)||c.startsWith(u.flat)));if(a>=0){o.length>n[a].text.length&&(n[a]={...n[a],match:r,text:o,flat:c});continue}n.push({who:s,t:i,match:r,text:o,flat:c})}return n.slice(-Math.max(1,t)).map(r=>r.match)}function ne(e=[]){return te(e,{max:Number.MAX_SAFE_INTEGER}).map(t=>String(t?.segment?.text||t?.why||"").trim()).filter(Boolean)}function le(e=[],{noun:t="matches",max:n=3,chars:r=180}={}){const o=(e||[]).filter(Boolean);if(!o.length)return"";if(o.length===1)return String(o[0].why||"")||x(o[0]?.segment?.text,r);const s=ne(o);if(!s.length)return`${o.length} ${t}`;const i=s.slice(0,n),c=Math.max(40,Math.floor(r/i.length)),a=s.length-i.length;return`${s.length} ${t}: ${i.map(u=>`“${x(u,c)}”`).join(" · ")}`+(a>0?` +${a} more`:"")}function he(e,t,{registry:n,ctx:r={},admit:o=null}={}){const s=[];for(const i of e||[]){if(!i.enabled||o&&!o(i))continue;const c=n?.get(i.trigger);if(!c||c.kind==="timer"||c.watches.length&&!c.watches.includes(t?.type))continue;let a=null;try{a=c.matches(t,i.params,r)}catch{a=null}a&&s.push({job:i,trigger:c,match:a,key:$(i.id,t.at||t.t||0)})}return s}export{se as BUILTIN_TRIGGERS,z as DANGLING_TAILS,ee as DEFAULT_COALESCE_MAX,D as JOB_ACTIONS,T as MIN_PHRASE_CHARS,C as MISSED_POLICIES,O as SCHEDULE_KINDS,l as ScheduleError,J as TEXT_DELTA,k as TEXT_WATCHES,B as TRIGGER_KINDS,j as TRIGGER_SOURCES,R as WEEKDAY_NAMES,x as clipText,te as coalesceMatches,oe as createTriggerRegistry,ce as defineJob,m as defineTrigger,re as describeSchedule,ae as dueJobs,q as eventSource,he as jobsForEvent,le as matchSummary,ne as matchTexts,X as meetingEndedTrigger,F as meetingStartedTrigger,_ as nextFireAt,ue as nextWakeAt,$ as occurrenceKey,v as occurrencesBetween,p as parseCron,K as personJoinedTrigger,P as phraseTrigger,V as questionTrigger,W as saidIn,S as sourceAllowed,g as timerTrigger,Y as topicTrigger,ie as utteranceLooksComplete,A as validateSchedule,Z as voiceCommandTrigger};