@chatpanel/events 0.128.0 → 0.143.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/model-roles.js ADDED
@@ -0,0 +1 @@
1
+ import{reachOfProvider as v}from"./capability-client.js";const j=Object.freeze([{id:"chat",label:"Chat & reasoning",kinds:["generate","think","see"],jump:"endpoints",page:"models",blurb:"Answers, drafts, code — the language model a turn goes to."},{id:"agents",label:"Coding agents",kinds:["generate","tool"],jump:"bridge-agents",page:"agent-tools",blurb:"Claude Code, Codex and the others — run here, with their own login."},{id:"detect",label:"Entity detection",kinds:["detect"],jump:"gw-models",page:"redaction",blurb:"Names, places, addresses, secrets — redaction and the fast path."},{id:"transcribe",label:"Transcription",kinds:["transcribe"],jump:"gw-stt-models",page:"voice",blurb:"Dictation and meetings, speech to text."},{id:"speak",label:"Voice",kinds:["speak"],jump:"gw-tts-models",page:"voice",blurb:"Read-aloud and voice conversation, text to speech."},{id:"diarize",label:"Speaker identification",kinds:["transcribe"],jump:"gw-diarize-models",page:"voice",blurb:"Who said what in a meeting."},{id:"rerank",label:"Ranking",kinds:["rerank"],jump:"endpoints",page:"models",blurb:"Order sources by relevance — research in plan notes, search."},{id:"embed",label:"Embeddings",kinds:["embed"],jump:"endpoints",page:"models",blurb:"Vectors for retrieval."},{id:"decide",label:"Decisions",kinds:["decide"],jump:"endpoints",page:"models",blurb:"Typed choices with a probability — sentiment, routing, triage."}]),x={device:"this device",trusted:"your server",any:"cloud",agent:"local agent, its own login",browser:"in this browser"};function E(n){return x[n]||n||"—"}function f(n){return n?n.kind==="webllm"?"browser":v({baseUrl:n.baseUrl||""}):"any"}const c=n=>String(n||"").split("/").pop();function R({settings:n={},gateway:u=null,ner:i=null,stt:y=null,tts:p=null,diarize:w=null}={}){const h=(n.endpoints||[]).filter(t=>t&&t.enabled!==!1),k=n.agents||[],g=n.activeAgentId,a=[],d=t=>j.find(e=>e.id===t),m=t=>h.filter(e=>Array.isArray(e.provides)&&e.provides.includes(t)).map(e=>({name:e.name||e.baseUrl,model:e.providesInfo?.[t]?.models?.[0]||null,where:f(e),note:"a server you probed"}));{const t=h.map(e=>({name:e.name||e.baseUrl||"endpoint",model:e.model||null,where:f(e),active:e.id===g})).sort((e,r)=>(r.active?1:0)-(e.active?1:0));a.push({...d("chat"),status:t.length?"ready":"none",current:t.slice(0,4),options:t.length,more:Math.max(0,t.length-4)})}{const t=k.filter(e=>e&&e.enabled!==!1).map(e=>({name:e.name||e.id,model:e.model||null,where:"agent",active:e.id===g})).sort((e,r)=>(r.active?1:0)-(e.active?1:0));a.push({...d("agents"),status:t.length?"ready":"none",current:t.slice(0,4),options:t.length,more:Math.max(0,t.length-4)})}{const t=n.ui?.piiRedaction?.detection||{},e=[];let r="none";if(t.backend&&t.backend!=="off"&&!t.bundled&&t.url&&(e.push({name:t.serverId?"your detector server":"your custom detector",model:t.model||null,where:v({baseUrl:t.url})}),r="external"),i?.active){const l=i.state||u?.ner?.state||"ready";e.push({name:c(i.active),model:i.active,where:"device",note:"primary"});for(const o of i.companions||[])e.push({name:c(o.model),model:o.model,where:"device",note:o.state==="ready"?"also running":o.state});for(const o of i.skipped||[])e.push({name:c(o.id),model:o.id,where:"device",note:`not loaded — ${o.why}`});r!=="external"&&(r=l==="ready"?"ready":l)}e.push(...m("detect"));const s=i?.recommendation;a.push({...d("detect"),status:r,current:e,options:(i?.available||[]).length+m("detect").length,recommended:s&&(s.primary!==i?.active||JSON.stringify(s.union||[])!==JSON.stringify(i?.union||[]))?{primary:s.primary,union:s.union,reason:s.reason}:null,alternatives:s?.alternatives||[]})}const b=(t,e,r,s={})=>{const l=r?.state||e?.state||"off",o=e?.active||r?.model||null;a.push({...d(t),status:o?l==="ready"?"ready":l:"none",current:o?[{name:c(o),model:o,where:"device",...s}]:[],options:(e?.available||[]).length})};b("transcribe",y,u?.stt),b("speak",p,u?.tts,p?.voice?{note:`voice ${p.voice}`}:{}),b("diarize",w,null);for(const t of["rerank","embed","decide"]){const e=m(t);a.push({...d(t),status:e.length?"ready":"none",current:e,options:e.length,hint:e.length?null:`No ${d(t).label.toLowerCase()} model yet — probe a server that provides it under Models, and every step of that kind starts using it.`})}return a}export{j as MODEL_ROLES,R as modelRoles,E as whereLabel};
@@ -0,0 +1 @@
1
+ const m=Object.freeze({transcript:"The live transcript (the last few minutes)",summary:"The running meeting summary",findings:"What this monitor already found",web:"Web search",history:"Your past chats, meetings & notes",mcp:"Your connected MCP tools"}),i=Object.freeze({targetId:"",windowMin:5,maxFindings:6,maxMcpTools:2,sources:Object.freeze({transcript:!0,summary:!0,findings:!0,web:!1,history:!1,mcp:!1})}),u=(t,e,r,n)=>{if(t==null||t==="")return e;const s=Number(t);return Number.isFinite(s)?Math.min(n,Math.max(r,s)):e};function f(t){const e=t?.ui?.monitors||{},r=e.sources||{};return{targetId:String(e.targetId||""),windowMin:u(e.windowMin,i.windowMin,1,60),maxFindings:u(e.maxFindings,i.maxFindings,0,40),maxMcpTools:u(e.maxMcpTools,i.maxMcpTools,0,20),sources:Object.fromEntries(Object.keys(m).map(n=>[n,n==="transcript"?!0:r[n]===void 0?i.sources[n]:!!r[n]]))}}const p=t=>Math.max(1,t?.windowMin||5)*6e4,d=t=>!!(t?.sources?.web||t?.sources?.history||t?.sources?.mcp);function h(t,e){const r=t?.specs;if(!Array.isArray(r)||!r.length)return t;const n=e?.sources||{},s=a=>{const c=String(a||"");return c.startsWith("mcp_")?!!n.mcp:/^(web_search|search_web|fetch_url)$/.test(c)?!!n.web:/^(history_search|history_get|find_related|smart_search)$/.test(c)?!!n.history:!!/^meeting_live_transcript$/.test(c)},o=r.filter(a=>s(a?.name));return o.length===r.length?t:{...t,specs:o}}function l(t,e){if(!e?.sources?.findings)return[];const r=Array.isArray(t)?t:[],n=e?.maxFindings??i.maxFindings;return n>0?r.slice(-n):[]}function g(t){const e=Object.entries(t?.sources||{}).filter(([s,o])=>o&&s!=="transcript").map(([s])=>s),r=["last "+(t?.windowMin||5)+" min of transcript",...e],n=d(t);return`${r.join(" + ")} — ${n?"with tools, slower":"no tools, fastest"}`}export{i as DEFAULT_MONITOR_PROFILE,m as MONITOR_SOURCES,g as describeMonitorProfile,h as filterMonitorTools,d as monitorNeedsTools,f as monitorProfile,p as monitorWindowMs,l as recentFindings};
package/note-plan.js CHANGED
@@ -1,15 +1,15 @@
1
- import{mergeRuns as h}from"./attribution.js";const m=Object.freeze(["research","write"]),i=Object.freeze({planner:"Planner",research:"Researcher",write:"Writer"}),S='You are a planning orchestrator. Break the goal into 3–6 concrete sub-tasks. For each, pick a role: "research" (needs facts, options, prices, or current info — it will web + history search) or "write" (drafting, structure, synthesis). Return ONLY compact JSON: {"tasks":[{"title":"short title","role":"research|write","prompt":"a focused instruction for this sub-task"}]}',_=600,x=.2;function E(t,e){return`You are drafting ONE section of a plan for the goal "${t}". Write the section titled "${e?.title||""}". Instruction: ${e?.prompt||e?.title||""}. Be concrete and actionable — bullets, - [ ] tasks, or a small table for options. Output ONLY the section's markdown content (no heading, no preamble).`}const O=700,k=.5;function w(t,e="",r=6){let n=[];try{const s=JSON.parse((String(t||"").match(/\{[\s\S]*\}/)||["{}"])[0]);n=(Array.isArray(s.tasks)?s.tasks:[]).slice(0,r).map(a=>p(a))}catch{}return n=n.filter(s=>s.title||s.prompt),!n.length&&String(e).trim()&&(n=[p({title:f(e),role:"write",prompt:e})]),n}const p=t=>({title:String(t?.title||"Task").slice(0,80),role:t?.role==="research"?"research":"write",prompt:String(t?.prompt||t?.title||""),done:!1,working:!1,output:""});function f(t,e=60){return String(t||"").replace(/[#*_`>~[\]]/g,"").replace(/\s+/g," ").trim().slice(0,e)}function u(t,e){const r=Array.isArray(e)?e:[],n=r.filter(o=>o.done).length,s=r.map((o,c)=>`- [${o.done?"x":" "}] ${c+1}. ${o.title}${o.working?" — _working…_":""}`).join(`
2
- `),a=[{author:i.planner,text:`# ${t}
1
+ import{mergeRuns as g}from"./attribution.js";const S=Object.freeze(["research","write"]),p=Object.freeze({planner:"Planner",research:"Researcher",write:"Writer"}),w='You are a planning orchestrator. Break the goal into 3–6 concrete sub-tasks. For each, pick a role: "research" (needs facts, options, prices, or current info — it will web + history search) or "write" (drafting, structure, synthesis). Return ONLY compact JSON: {"tasks":[{"title":"short title","role":"research|write","prompt":"a focused instruction for this sub-task"}]}',E=600,_=.2;function O(e,t){return`You are drafting ONE section of a plan for the goal "${e}". Write the section titled "${t?.title||""}". Instruction: ${t?.prompt||t?.title||""}. Be concrete and actionable — bullets, - [ ] tasks, or a small table for options. Output ONLY the section's markdown content (no heading, no preamble).`}const A=700,b=.5;function $(e,t="",o=6){let r=[];try{const s=JSON.parse((String(e||"").match(/\{[\s\S]*\}/)||["{}"])[0]);r=(Array.isArray(s.tasks)?s.tasks:[]).slice(0,o).map(a=>f(a))}catch{}return r=r.filter(s=>s.title||s.prompt),!r.length&&String(t).trim()&&(r=[f({title:k(t),role:"write",prompt:t})]),r}const f=e=>({title:String(e?.title||"Task").slice(0,80),role:e?.role==="research"?"research":"write",prompt:String(e?.prompt||e?.title||""),done:!1,working:!1,output:""});function k(e,t=60){return String(e||"").replace(/[#*_`>~[\]]/g,"").replace(/\s+/g," ").trim().slice(0,t)}function d(e,t){const o=Array.isArray(t)?t:[],r=o.filter(n=>n.done).length,s=o.map((n,i)=>`- [${n.done?"x":" "}] ${i+1}. ${n.title}${n.working?" — _working…_":""}`).join(`
2
+ `),a=[{author:p.planner,text:`# ${e}
3
3
 
4
- **Plan** — ${n}/${r.length} sub-tasks done
4
+ **Plan** — ${r}/${o.length} sub-tasks done
5
5
 
6
6
  ${s}
7
7
 
8
8
  ---
9
9
 
10
- `}];return r.forEach((o,c)=>{const l=o.role==="research"?i.research:i.write;a.push({author:i.planner,text:`## ${c+1}. ${o.title}
10
+ `}];return o.forEach((n,i)=>{const l=n.role==="research"?p.research:p.write;a.push({author:p.planner,text:`## ${i+1}. ${n.title}
11
11
 
12
- `}),a.push({author:o.output?l:i.planner,text:o.output||(o.working?`_⏳ ${l} working…_`:"_pending_")}),a.push({author:i.planner,text:c<r.length-1?`
12
+ `}),a.push({author:n.output?l:p.planner,text:n.output||(n.working?`_⏳ ${l} working…_`:"_pending_")}),a.push({author:p.planner,text:i<o.length-1?`
13
13
 
14
14
  `:`
15
- `})}),a}function A(t,e){return u(t,e).map(r=>r.text).join("")}function N(t,e,r=Date.now()){return h(u(t,e).map(n=>({len:n.text.length,author:n.author,at:r})))}export{i as PLAN_AUTHORS,_ as PLAN_DECOMPOSE_MAX_TOKENS,S as PLAN_DECOMPOSE_SYSTEM,x as PLAN_DECOMPOSE_TEMPERATURE,m as PLAN_ROLES,O as PLAN_SECTION_MAX_TOKENS,k as PLAN_SECTION_TEMPERATURE,w as parsePlanTasks,N as planAttribution,A as planBody,u as planParts,E as planSectionSystem,f as planTitleFor};
15
+ `})}),a}function P(e,t){return d(e,t).map(o=>o.text).join("")}function N(e,t,o=Date.now()){return g(d(e,t).map(r=>({len:r.text.length,author:r.author,at:o})))}import{defineKind as m}from"./plan.js";m({id:"research",label:"Research",class:"R",fallback:"skip",description:"History + web search, cited bullets — no model."});const h=(e,t)=>`t${e}-${t}`;function y(e,t,{parallelResearch:o=!0}={}){const r=[];let s=null,a=null;const n=[];return(Array.isArray(t)?t:[]).forEach((i,l)=>{if(i.role==="research"){const c=h(l,"research"),u=h(l,"rerank");r.push({id:c,kind:"research",title:i.title,task:l,needs:o||!a?[]:[a],input:{from:"goal"},fallback:"skip"}),r.push({id:u,kind:"rerank",title:`Rank sources for “${i.title}”`,task:l,needs:[c],input:{from:c},requires:{maxLatencyMs:2e3},fallback:"skip",passthrough:!0}),n.push(u),a=u}else{const c=h(l,"write"),u=[...n,...s?[s]:[]];r.push({id:c,kind:"generate",title:i.title,task:l,role:"writer",needs:u,input:{from:"goal"},fallback:"skip"}),s=c}}),{id:`note-plan-${k(e,24).toLowerCase().replace(/[^a-z0-9]+/g,"-")}`,origin:"note",goal:e,steps:r}}export{p as PLAN_AUTHORS,E as PLAN_DECOMPOSE_MAX_TOKENS,w as PLAN_DECOMPOSE_SYSTEM,_ as PLAN_DECOMPOSE_TEMPERATURE,S as PLAN_ROLES,A as PLAN_SECTION_MAX_TOKENS,b as PLAN_SECTION_TEMPERATURE,y as notePlanSteps,$ as parsePlanTasks,N as planAttribution,P as planBody,d as planParts,O as planSectionSystem,h as planStepId,k as planTitleFor};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chatpanel/events",
3
- "version": "0.128.0",
3
+ "version": "0.143.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",
@@ -14,14 +14,23 @@
14
14
  "./backup-records.js": "./backup-records.js",
15
15
  "./budget.js": "./budget.js",
16
16
  "./capability.js": "./capability.js",
17
+ "./capability-endpoints.js": "./capability-endpoints.js",
18
+ "./capability-client.js": "./capability-client.js",
19
+ "./fast-path.js": "./fast-path.js",
20
+ "./plan.js": "./plan.js",
21
+ "./plan-executor.js": "./plan-executor.js",
22
+ "./model-roles.js": "./model-roles.js",
17
23
  "./citations.js": "./citations.js",
18
24
  "./client-prefs.js": "./client-prefs.js",
25
+ "./composer-chips.js": "./composer-chips.js",
26
+ "./settings-registry.js": "./settings-registry.js",
19
27
  "./context-attachments.js": "./context-attachments.js",
20
28
  "./cowriter-router.js": "./cowriter-router.js",
21
29
  "./cowriter-writer.js": "./cowriter-writer.js",
22
30
  "./cowriter-factcheck.js": "./cowriter-factcheck.js",
23
31
  "./cowriter.js": "./cowriter.js",
24
32
  "./curate.js": "./curate.js",
33
+ "./default-skills.js": "./default-skills.js",
25
34
  "./distance.js": "./distance.js",
26
35
  "./entitlement.js": "./entitlement.js",
27
36
  "./engine.js": "./engine.js",
@@ -44,10 +53,12 @@
44
53
  "./markdown-render.js": "./markdown-render.js",
45
54
  "./sideline.js": "./sideline.js",
46
55
  "./mcp-client.js": "./mcp-client.js",
56
+ "./mcp-config-import.js": "./mcp-config-import.js",
47
57
  "./mcp-dispatch.js": "./mcp-dispatch.js",
48
58
  "./mcp-errors.js": "./mcp-errors.js",
49
59
  "./mcp-manager.js": "./mcp-manager.js",
50
60
  "./mcp-registry.js": "./mcp-registry.js",
61
+ "./model-registry.js": "./model-registry.js",
51
62
  "./media-transcript.js": "./media-transcript.js",
52
63
  "./meeting-analyzers.js": "./meeting-analyzers.js",
53
64
  "./meeting-insights.js": "./meeting-insights.js",
@@ -59,6 +70,7 @@
59
70
  "./model-health.js": "./model-health.js",
60
71
  "./model-ledger.js": "./model-ledger.js",
61
72
  "./model-picker.js": "./model-picker.js",
73
+ "./monitor-profile.js": "./monitor-profile.js",
62
74
  "./note-actions.js": "./note-actions.js",
63
75
  "./note-tool.js": "./note-tool.js",
64
76
  "./note-graph.js": "./note-graph.js",
@@ -78,6 +90,7 @@
78
90
  "./response-language.js": "./response-language.js",
79
91
  "./recruit.js": "./recruit.js",
80
92
  "./record-list.js": "./record-list.js",
93
+ "./redaction-dictionary.js": "./redaction-dictionary.js",
81
94
  "./redaction-tokens.js": "./redaction-tokens.js",
82
95
  "./ref.js": "./ref.js",
83
96
  "./registry.js": "./registry.js",
@@ -86,6 +99,7 @@
86
99
  "./router.js": "./router.js",
87
100
  "./rrf.js": "./rrf.js",
88
101
  "./rules.js": "./rules.js",
102
+ "./run-details.js": "./run-details.js",
89
103
  "./schedule.js": "./schedule.js",
90
104
  "./scm-connection.js": "./scm-connection.js",
91
105
  "./scopes.js": "./scopes.js",
@@ -93,6 +107,8 @@
93
107
  "./skill-manifest.js": "./skill-manifest.js",
94
108
  "./skill-runtime.js": "./skill-runtime.js",
95
109
  "./skill-files.js": "./skill-files.js",
110
+ "./attached-paths.js": "./attached-paths.js",
111
+ "./extract-capability.js": "./extract-capability.js",
96
112
  "./skill-scan.js": "./skill-scan.js",
97
113
  "./skill-sources.js": "./skill-sources.js",
98
114
  "./skill-vars.js": "./skill-vars.js",
@@ -152,6 +168,8 @@
152
168
  "./voice-speaker.js": "./voice-speaker.js",
153
169
  "./voice-loop.js": "./voice-loop.js",
154
170
  "./voice-vad.js": "./voice-vad.js",
171
+ "./voice-sample.js": "./voice-sample.js",
172
+ "./voice-models.js": "./voice-models.js",
155
173
  "./speak-stream.js": "./speak-stream.js",
156
174
  "./weather-tool.js": "./weather-tool.js",
157
175
  "./weather.js": "./weather.js",
@@ -163,7 +181,12 @@
163
181
  "./prefetch.js": "./prefetch.js",
164
182
  "./fetched.js": "./fetched.js",
165
183
  "./context-window.js": "./context-window.js",
166
- "./compaction.js": "./compaction.js"
184
+ "./compaction.js": "./compaction.js",
185
+ "./site-policy.js": "./site-policy.js",
186
+ "./read-document.js": "./read-document.js",
187
+ "./serp-anchors.js": "./serp-anchors.js",
188
+ "./search-searxng.js": "./search-searxng.js",
189
+ "./sandbox-policy.js": "./sandbox-policy.js"
167
190
  },
168
191
  "files": [
169
192
  "LICENSE",
@@ -176,14 +199,23 @@
176
199
  "backup-records.js",
177
200
  "budget.js",
178
201
  "capability.js",
202
+ "capability-endpoints.js",
203
+ "capability-client.js",
204
+ "fast-path.js",
205
+ "plan.js",
206
+ "plan-executor.js",
207
+ "model-roles.js",
179
208
  "citations.js",
180
209
  "client-prefs.js",
210
+ "composer-chips.js",
211
+ "settings-registry.js",
181
212
  "context-attachments.js",
182
213
  "cowriter-router.js",
183
214
  "cowriter-writer.js",
184
215
  "cowriter-factcheck.js",
185
216
  "cowriter.js",
186
217
  "curate.js",
218
+ "default-skills.js",
187
219
  "distance.js",
188
220
  "entitlement.js",
189
221
  "engine.js",
@@ -207,10 +239,12 @@
207
239
  "markdown-render.js",
208
240
  "sideline.js",
209
241
  "mcp-client.js",
242
+ "mcp-config-import.js",
210
243
  "mcp-dispatch.js",
211
244
  "mcp-errors.js",
212
245
  "mcp-manager.js",
213
246
  "mcp-registry.js",
247
+ "model-registry.js",
214
248
  "media-transcript.js",
215
249
  "meeting-analyzers.js",
216
250
  "meeting-insights.js",
@@ -222,6 +256,7 @@
222
256
  "model-health.js",
223
257
  "model-ledger.js",
224
258
  "model-picker.js",
259
+ "monitor-profile.js",
225
260
  "note-actions.js",
226
261
  "note-tool.js",
227
262
  "note-graph.js",
@@ -247,6 +282,7 @@
247
282
  "response-language.js",
248
283
  "recruit.js",
249
284
  "record-list.js",
285
+ "redaction-dictionary.js",
250
286
  "redaction-tokens.js",
251
287
  "ref.js",
252
288
  "registry.js",
@@ -255,6 +291,7 @@
255
291
  "router.js",
256
292
  "rrf.js",
257
293
  "rules.js",
294
+ "run-details.js",
258
295
  "schedule.js",
259
296
  "scm-connection.js",
260
297
  "scopes.js",
@@ -262,6 +299,8 @@
262
299
  "skill-manifest.js",
263
300
  "skill-runtime.js",
264
301
  "skill-files.js",
302
+ "attached-paths.js",
303
+ "extract-capability.js",
265
304
  "skill-scan.js",
266
305
  "skill-sources.js",
267
306
  "skill-vars.js",
@@ -321,12 +360,19 @@
321
360
  "voice-speaker.js",
322
361
  "voice-loop.js",
323
362
  "voice-vad.js",
363
+ "voice-sample.js",
364
+ "voice-models.js",
324
365
  "speak-stream.js",
325
366
  "weather-tool.js",
326
367
  "weather.js",
327
368
  "web-search-tool.js",
328
369
  "web-search.js",
329
- "widget.js"
370
+ "widget.js",
371
+ "site-policy.js",
372
+ "read-document.js",
373
+ "serp-anchors.js",
374
+ "search-searxng.js",
375
+ "sandbox-policy.js"
330
376
  ],
331
377
  "repository": {
332
378
  "type": "git",
@@ -0,0 +1 @@
1
+ import{normalizePlan as $,schedule as j,kindOf as x}from"./plan.js";import{EventError as A}from"./event.js";function C({runners:d={},onEvent:p=()=>{},now:l=Date.now}={}){const f=new Map(Object.entries(d));function L(e,u){if(typeof u!="function")throw new A("SHAPE",`runner for ${e} must be a function`);return f.set(e,u),()=>{f.get(e)===u&&f.delete(e)}}const y=e=>f.get(e)||f.get("*")||null;async function P(e,u={}){const m=$(e),b=new Map(m.steps.map(r=>[r.id,{...r}])),o=new Map,k=new Map,S=l(),i=(r,t,n={})=>{try{p({type:r,planId:m.id,stepId:t.id,kind:t.kind,...n})}catch{}},v=r=>({...u,partial:t=>{for(const n of k.get(r.id)||[])try{n(t)}catch{}},onPartial:(t,n)=>{const a=k.get(t)||[];return a.push(n),k.set(t,a),()=>k.set(t,(k.get(t)||[]).filter(c=>c!==n))}}),h=r=>{const t=r.input.from;return{primary:t==="goal"?u.goal:t==="material"?u.material:o.get(t),from:t,outputs:Object.fromEntries(r.needs.map(a=>[a,o.get(a)]))}},F=r=>r.passthrough?h(r).primary??null:null;async function w(r,{asFallbackFor:t=null}={}){const n=r.assigned;if(!n||n.skipped)return r.status="skipped",r.output=F(r),o.set(r.id,r.output),i("plan.step.skipped",r,{reason:n?.reason||"unassigned"}),r.output;const a=y(n.runAs||r.kind);if(!a)return r.status="failed",r.error=`no runner for ${r.kind}`,i("plan.step.failed",r,{error:r.error}),E(r);const c=l();i("plan.step.started",r,{class:n.class,provider:n.provider||n.model||null,asFallbackFor:t});try{const s=await a(r,h(r),v(r));return r.cost={...r.cost||{},ms:l()-c},r.status=t?"fell-back":"done",r.output=s,o.set(r.id,s),i("plan.step.finished",r,{ms:r.cost.ms,class:n.class,provider:n.provider||n.model||null}),s}catch(s){return r.cost={...r.cost||{},ms:l()-c},r.status="failed",r.error=String(s?.message||s),i("plan.step.failed",r,{error:r.error,ms:r.cost.ms}),E(r)}}async function E(r){const t=r.fallback;if(t==="skip")return r.status="skipped",r.output=F(r),o.set(r.id,r.output),i("plan.step.skipped",r,{reason:"failed, fallback skip"}),r.output;if(t==="L"){const c=y("generate");if(!c)return o.set(r.id,null),null;const s=l();i("plan.step.started",r,{class:"L",provider:"generate",asFallbackFor:r.id});try{const g=await c({...r,kind:"generate",assigned:{class:"L",model:"fallback"}},h(r),v(r));return r.cost={...r.cost||{},fallbackMs:l()-s},r.status="fell-back",r.output=g,o.set(r.id,g),i("plan.step.finished",r,{ms:r.cost.fallbackMs,class:"L",provider:"generate",asFallbackFor:r.id}),g}catch(g){return r.error=`${r.error?r.error+"; ":""}fallback: ${g?.message||g}`,o.set(r.id,null),null}}const n=b.get(t);if(!n)return o.set(r.id,null),null;const a=await w({...n,id:n.id,input:r.input,needs:r.needs},{asFallbackFor:r.id});return r.status="fell-back",r.output=a,o.set(r.id,a),a}for(const r of j(m))await Promise.all(r.map(t=>w(b.get(t))));const M=m.steps.map(r=>b.get(r.id)),O={...m,steps:M,cost:{ms:l()-S},outputs:Object.fromEntries(o)};return i("plan.finished",{id:m.id,kind:"plan"},{ms:O.cost.ms,steps:M.map(r=>({id:r.id,kind:r.kind,status:r.status,ms:r.cost?.ms??null}))}),O}return{run:P,registerRunner:L,runners:()=>[...f.keys()]}}function D(d){const p=d.result||d.steps[d.steps.length-1]?.id;return d.outputs?.[p]??null}export{C as createExecutor,x as kindOf,D as planResult};
package/plan.js ADDED
@@ -0,0 +1 @@
1
+ import{EventError as u}from"./event.js";const k=Object.freeze(["R","M","L"]),y=Object.freeze(["complete","sentence","settled","span"]),S=Object.freeze(["chat","note","meeting","agent","team","project","voice"]),h=new Map;function c({id:e,label:s=e,class:i,fallback:n="L",description:a=""}){if(typeof e!="string"||!e)throw new u("SHAPE","kind id required");if(!k.includes(i))throw new u("SHAPE",`kind ${e}: class must be one of ${k}`);const t=Object.freeze({id:e,label:s,class:i,fallback:n,description:a});return h.set(e,t),t}function b(e){return h.get(e)||null}function q(){return[...h.values()]}c({id:"generate",label:"Generate",class:"L",fallback:"skip",description:"Prose or code from a language model."}),c({id:"think",label:"Think",class:"L",fallback:"generate",description:"A reasoning model; falls back to a plain generation."}),c({id:"see",label:"See",class:"L",fallback:"skip",description:"A vision-capable model over images."}),c({id:"detect",label:"Detect",class:"M",fallback:"L",description:"Entities with offsets — names, places, emails, secrets."}),c({id:"decide",label:"Decide",class:"M",fallback:"L",description:"A typed choice / score / yes-no with a calibrated probability."}),c({id:"rerank",label:"Rerank",class:"M",fallback:"L",description:"Order candidates by relevance to a query."}),c({id:"embed",label:"Embed",class:"M",fallback:"skip",description:"Vectors for retrieval."}),c({id:"transcribe",label:"Transcribe",class:"M",fallback:"skip",description:"Speech to text."}),c({id:"speak",label:"Speak",class:"M",fallback:"skip",description:"Text to speech, sentence by sentence."}),c({id:"tool",label:"Tool",class:"R",fallback:"skip",description:"A tool call — a read, a search, an action."}),c({id:"rule",label:"Rule",class:"R",fallback:"skip",description:"A deterministic function."});const m=e=>typeof e=="string"&&e.length>0,f=e=>!!e&&typeof e=="object"&&!Array.isArray(e),o=(e,s)=>{if(!e)throw new u("SHAPE",s)};function L(e){o(f(e)&&m(e.id),"step: id required");const s=b(e.kind);o(s,`step ${e.id}: unknown kind ${JSON.stringify(e.kind)} — defineKind it first`);const i=Array.isArray(e.needs)?e.needs.filter(m):[],n=f(e.input)?{...e.input}:{from:i[0]||"goal",on:"complete"};n.on||(n.on="complete"),o(y.includes(n.on),`step ${e.id}: input.on must be one of ${y}`);const a=f(e.requires)?{...e.requires}:{};a.class!=null&&o(k.includes(a.class),`step ${e.id}: requires.class must be one of ${k}`);const t=e.fallback!=null?e.fallback:s.fallback;return o(m(t),`step ${e.id}: fallback required`),{...e,title:e.title||s.label,needs:i,input:n,requires:a,fallback:t}}function x(e){o(f(e)&&m(e.id),"plan: id required"),o(Array.isArray(e.steps)&&e.steps.length>0,"plan: steps[] required"),e.origin!=null&&o(S.includes(e.origin),`plan: origin must be one of ${S}`);const s=e.steps.map(L),i=new Set;for(const n of s)o(!i.has(n.id),`plan: step id ${n.id} twice`),i.add(n.id);for(const n of s){for(const a of n.needs)o(i.has(a),`plan: step ${n.id} needs ${a}, which does not exist`);n.input.from&&n.input.from!=="goal"&&n.input.from!=="material"&&o(i.has(n.input.from),`plan: step ${n.id} takes input from ${n.input.from}, which does not exist`),n.fallback!=="L"&&n.fallback!=="skip"&&!b(n.fallback)&&o(i.has(n.fallback),`plan: step ${n.id} falls back to ${n.fallback}, which is neither a step nor a kind`)}return M({...e,steps:s}),{...e,steps:s,budget:f(e.budget)?e.budget:{}}}function M(e){const s=e.steps,i=new Set,n=[];let a=s.slice();for(;a.length;){const t=a.filter(l=>(l.needs||[]).every(p=>i.has(p)));if(!t.length)throw new u("SHAPE",`plan: steps ${a.map(l=>l.id).join(", ")} need each other (a cycle)`);n.push(t.map(l=>l.id));for(const l of t)i.add(l.id);a=a.filter(l=>!i.has(l.id))}return n}function E(e,s={},i={}){const n=x(e),a=n.steps.map(t=>{const l=t.requires.class||b(t.kind).class,p=(r,g=null)=>{const $=r==="R"?s.rule:r==="M"?s.capability:s.model;if(typeof $!="function")return null;const A=g?{...t,kind:g}:t;try{const w=$(A,i);return w?{class:r,...w}:null}catch{return null}};let d=p(l);if(!d&&l==="L"&&t.fallback!=="L"&&t.fallback!=="skip"&&b(t.fallback)?.class==="L"){const r=p("L",t.fallback);r&&(d={...r,fellBackFrom:t.kind,runAs:t.fallback,reason:`${r.reason||"the model"} cannot ${t.kind} — it will ${t.fallback} instead`})}if(!d&&l==="M"&&t.fallback==="L"){const r=p("L");r&&(d={...r,fellBackFrom:"M",reason:`no ${t.kind} provider fits — ${r.reason||"a language model instead"}`})}return!d&&l==="M"&&t.fallback==="skip"&&(d={class:"R",provider:"skip",skipped:!0,reason:`no ${t.kind} provider fits — skipped`}),{...t,assigned:d||null,unassignable:!d}});return{...n,steps:a,unassignable:a.filter(t=>t.unassignable).map(t=>t.id)}}function O(e){return(e.steps||[]).map(s=>{const i=s.assigned,n=i?i.skipped?"skipped":i.provider||i.model||i.class:"unassigned",a=s.cost?.ms!=null?` (${Math.round(s.cost.ms)} ms)`:i?.predictedMs!=null?` (~${i.predictedMs} ms)`:"";return`${s.kind} → ${n}${a}${i?.fellBackFrom?" ↩":""}`}).join(" · ")}function j(e){const s=new Set(e?.capabilities||[]),i={see:["vision"],think:["thinking"]};return n=>[...n.requires?.capabilities||[],...i[n.kind]||[]].filter(l=>!s.has(l)).length?null:{model:e.id,reason:`${e.name||e.id} — chosen by you`}}export{y as HANDOFFS,S as PLAN_ORIGINS,k as STEP_CLASSES,E as assign,c as defineKind,O as describePlan,b as kindOf,q as listKinds,x as normalizePlan,L as normalizeStep,j as pinnedModelSource,M as schedule};
@@ -0,0 +1,10 @@
1
+ function x(t,e=""){let i;try{i=new URL(t)}catch{return String(t||"")}i.hash="";const s=/<link\b[^>]*\brel=["']canonical["'][^>]*\bhref=["']([^"']+)["'][^>]*>/i.exec(e)||/<link\b[^>]*\bhref=["']([^"']+)["'][^>]*\brel=["']canonical["'][^>]*>/i.exec(e);if(s)try{const n=new URL(s[1],i);if(n.origin===i.origin&&(n.protocol==="http:"||n.protocol==="https:"))return n.hash="",n.toString()}catch{}return i.toString()}function h(t){return String(t||"").toLowerCase().replace(/<[^>]+>/g,"").replace(/[^\p{L}\p{N}\s-]/gu,"").trim().replace(/\s+/g,"-").slice(0,80)||"section"}const b=t=>String(t).replace(/&(amp|lt|gt|quot|#39|nbsp);/g,(e,i)=>({amp:"&",lt:"<",gt:">",quot:'"',"#39":"'",nbsp:" "})[i]);function d(t=""){const e=new Map,i=String(t||""),s=/<h([1-6])\b([^>]*)>([\s\S]*?)<\/h\1\s*>/gi;for(const n of i.matchAll(s)){let r=/\bid=["']([^"']+)["']/i.exec(n[2])?.[1]||/<a\b[^>]*\bhref=["']#([^"']+)["']/i.exec(n[3])?.[1]||null;if(!r){const l=i.slice(Math.max(0,n.index-300),n.index),u=/<(?:section|div)\b[^>]*\bid=["']([^"']+)["'][^>]*>\s*$/i.exec(l);u&&(r=u[1])}const o=n[3].replace(/<a\b[^>]*\bhref=["']#[^"']*["'][^>]*>[\s\S]*?<\/a\s*>/gi,""),c=b(o.replace(/<[^>]+>/g,"")).replace(/\s+/g," ").trim();r&&c&&!e.has(c)&&e.set(c,r)}return e}function S(t,e=new Map){const i=String(t||""),s=[],n=new Map,r=/^(#{1,6})[ \t]+(.+?)[ \t]*#*[ \t]*$/gm;let o=!1,c=0;for(const l of i.split(`
2
+ `)){const u=c;if(c+=l.length+1,/^\s*(```|~~~)/.test(l)){o=!o;continue}if(o)continue;r.lastIndex=0;const a=r.exec(l);if(!a)continue;const p=a[2].trim();let f=e.get(p)||h(p);const g=(n.get(f)||0)+1;n.set(f,g),g>1&&(f=`${f}-${g}`),s.push({id:f,heading:p,level:a[1].length,offset:u})}return s}function $(t,e,i=[]){const s=String(t||"");if(!(e>0)||s.length<=e)return{text:s,truncated:!1};const n=Math.floor(e*.8);let r=-1;for(const o of i)o.offset>=n&&o.offset<=e&&(r=o.offset);if(r<0){const o=s.lastIndexOf(`
3
+
4
+ `,e);o>=n&&(r=o)}if(r<0){const o=s.lastIndexOf(`
5
+ `,e);r=o>=n?o:e}return{text:s.slice(0,r).trimEnd(),truncated:!0}}function m(t){const e=[];t.title&&e.push(`Title: ${t.title}`),e.push(`URL Source: ${t.url}`),t.published&&e.push(`Published Time: ${t.published}`),t.author&&e.push(`Author: ${t.author}`);const i=t[t.format||"markdown"]||t.markdown||t.text||"";return`${e.join(`
6
+ `)}
7
+
8
+ ${t.format==="text"?"Text Content:":"Markdown Content:"}
9
+ ${i}
10
+ `}export{x as canonicalUrl,d as headingIds,S as sectionsOf,h as slugify,m as toJinaText,$ as truncateAtSection};
@@ -0,0 +1,2 @@
1
+ function p(i){return(i||[]).map(t=>{if(!t)return"";const e=t.pattern?`/${t.pattern}/${t.flags||""}`:t.value||"";return e?t.alias!=null&&t.alias!==""?`${e} -> ${t.alias}`:t.type&&t.type!=="TERM"?`${e} => ${t.type}`:e:""}).filter(Boolean).join(`
2
+ `)}function f(i){return String(i||"").split(/\r?\n/).map(t=>t.trim()).filter(Boolean).map(t=>{let e=t,o="TERM",l=null;const a=t.lastIndexOf("=>"),r=t.lastIndexOf("->");if(a>0&&a>=r){const n=t.slice(a+2).trim().toUpperCase().replace(/[^A-Z0-9]/g,"");n&&(e=t.slice(0,a).trim(),o=n)}else if(r>0){const n=t.slice(r+2).trim();n&&(e=t.slice(0,r).trim(),l=n)}const s=/^\/(.+)\/([a-z]*)$/.exec(e),c=s?{pattern:s[1],flags:s[2]}:{value:e};return l!=null?{...c,alias:l}:{...c,type:o}})}export{p as dictToText,f as textToDict};
package/router.js CHANGED
@@ -1,2 +1,2 @@
1
- class k extends Error{constructor(o,a){super(a),this.name="RouterError",this.code=o}}import{REACH as ee,reachRank as te}from"./reach.js";import{REACH as C,reachRank as D}from"./reach.js";function U({id:n,label:o,reach:a="any",classUsed:u="C",capabilities:c=[],costPer1k:d=1,latencyMs:h=1e3,load:m=0,available:t=!0,rateLimited:r=!1,observedLatencyMs:i=null,quality:p=null,model:l="",providerRank:w=50,orderPinned:g=!1}){if(!n)throw new k("BAD_MODEL","model.id required");if(!C.includes(a))throw new k("BAD_MODEL",`model '${n}': unknown reach '${a}'`);return Object.freeze({id:n,label:o||n,reach:a,classUsed:u,model:l,capabilities:[...c],costPer1k:d,latencyMs:Number.isFinite(i)?i:h,declaredLatencyMs:h,observedLatencyMs:i,load:m,available:t,rateLimited:r,providerRank:w,orderPinned:!!g,quality:p})}function z({id:n,label:o,stage:a,priority:u=100,run:c,requiredFor:d=null}){if(!n)throw new k("BAD_MIDDLEWARE","middleware.id required");if(!["request","response"].includes(a))throw new k("BAD_MIDDLEWARE",`middleware '${n}': stage must be request or response`);if(typeof c!="function")throw new k("BAD_MIDDLEWARE",`middleware '${n}': run required`);return Object.freeze({id:n,label:o||n,stage:a,priority:u,run:c,requiredFor:d})}function W({id:n,label:o,classUsed:a="R",timeoutMs:u=0,decide:c}){if(!n)throw new k("BAD_STRATEGY","strategy.id required");if(typeof c!="function")throw new k("BAD_STRATEGY",`strategy '${n}': decide required`);return Object.freeze({id:n,label:o||n,classUsed:a,timeoutMs:u,decide:c})}const T=.1,L=5,N=Object.freeze({device:.7,trusted:.85,any:1});function P(n){return String(n?.model||n?.label||"").toLowerCase().replace(/^[^/]+\//,"").replace(/[:@].*$/,"").replace(/[^a-z0-9.]+/g,"")}function G(n={}){const o=String(n.text||(n.messages||[]).map(d=>d?.content||"").join(`
2
- `)||""),a=o.length,u=!!(n.images?.length||n.attachments?.some?.(d=>/^image\//.test(d?.type||""))),c=!!n.audio||!!n.attachments?.some?.(d=>/^audio\//.test(d?.type||""));return{approxTokens:Math.round(a/4),modality:c?"audio":u?"vision":"text",code:/```/.test(o)||a>80&&/\bfunction\b|\bclass\b|=>|;\s*$|\bdef\b|\bimport\b|\bconst\b/m.test(o)||/\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(o),complexity:a>4e3||/```/.test(o)||a>=200&&/\bstep by step\b|\bplan\b|\brefactor\b|\bmigrate\b|\banalyse|\banalyze/i.test(o)?"high":a<200?"low":"medium",nonLatin:/[^\u0000-\u024F\u2000-\u206F]/.test(o),smalltalk:a<100&&!/```/.test(o)&&!/\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(o)&&!/\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(o)&&!/\bhow\s+(do|does|did|can|could|should|would|to|much|many|long)\b/i.test(o),chars:a}}function H(n={},{structured:o=!1,hasTools:a=!1,pageTools:u=!1,background:c=!1,minWindow:d=0}={}){const h=new Set;let m=0;const t=[];d>0&&t.push(`the turn needs a ${Math.round(d/1e3)}k window`),a&&(h.add("tools"),t.push("the turn carries tools")),n.modality==="vision"&&(h.add("vision"),t.push("the request includes an image")),u&&!n.smalltalk&&(h.add("tools"),m=Math.max(m,.55),t.push("driving a page needs exact actions")),n.approxTokens>2e4&&(h.add("long-context"),t.push("the request is large")),n.code&&(h.add("coding"),t.push("the request contains code")),o&&!n.smalltalk&&(h.add("tools"),m=Math.max(m,.55),t.push("it must produce an exact structured payload")),n.complexity==="high"&&!c&&(m=Math.max(m,.55),t.push("the task is complex"));const r=n.smalltalk?[...h]:[...h].filter(i=>i!=="tools");return{required:[...h],negotiable:r,minQuality:m,why:t,minWindow:Math.max(0,Number(d)||0)}}function Y(n={},{structured:o=!1,minQuality:a=0,hasTools:u=!1,background:c=!1}={}){return c?{prefer:"cost",why:"background work — spend as little as possible"}:o||n.complexity==="high"||n.code||n.modality==="vision"?{prefer:"quality",why:"the task is exact or hard — get it right rather than quick"}:n.smalltalk&&!u&&!a?{prefer:"latency",why:"nothing to look up — answer fast"}:{prefer:"balanced",why:"no reason to favour speed or quality"}}function E(n){return n?.orderPinned&&Number.isFinite(n.providerRank)?n.providerRank:1/0}const j=.25,B=.25;function V(n=[],o={}){const a=r=>!!o.model&&P(r)===P(o);let u=[...n];if(o.reason==="gone"){const r=u.filter(i=>!a(i));r.length&&(u=r)}const c=r=>Number.isFinite(r.quality)?r.quality:.5,d=r=>(o.capabilities||[]).every(i=>(r.capabilities||[]).includes(i)),h=r=>!o.classUsed||r.classUsed===o.classUsed,m=Number.isFinite(o.quality)?o.quality:null;if(m!==null){const r=i=>a(i)?-1:Math.abs(c(i)-m)+(h(i)?0:j)+(d(i)?0:B);return u.map(i=>({m:i,d:r(i)})).sort((i,p)=>i.d-p.d||E(i.m)-E(p.m)||i.m.costPer1k-p.m.costPer1k||String(i.m.id).localeCompare(String(p.m.id))).map(i=>i.m)}const t=r=>a(r)?0:h(r)&&d(r)?1:h(r)?2:d(r)?3:4;return u.sort((r,i)=>t(r)-t(i)||c(i)-c(r)||E(r)-E(i)||r.costPer1k-i.costPer1k)}function K(n,o={}){const a=String(n||""),u=String(o?.action||""),c=`${a}.${u}`;return/screenshot|marked_screenshot|read_canvas|sense_canvas/.test(c)?{required:["vision"],why:"this step reads an image"}:/structured_insert|sheet_write|fill_form|input_sequence|draw_path/.test(c)?{required:["tools"],minQuality:.55,why:"this step writes an exact payload"}:{required:a?["tools"]:[],why:""}}function J({models:n=[],middleware:o=[],strategies:a=[],admit:u=null}={}){const c=[...n],d=[...o],h=[...a],m=t=>d.filter(r=>r.stage===t&&(!u||u(r))).sort((r,i)=>t==="request"?r.priority-i.priority:i.priority-r.priority);return{addModel(t){return c.push(t),()=>{const r=c.indexOf(t);r>=0&&c.splice(r,1)}},use(t){return d.push(t),()=>{const r=d.indexOf(t);r>=0&&d.splice(r,1)}},addStrategy(t){return h.push(t),()=>{const r=h.indexOf(t);r>=0&&h.splice(r,1)}},models:()=>[...c],middleware:()=>[...d],strategies:()=>[...h],route(t={}){const r=C.includes(t.reach)?t.reach:"any",i=t.capabilities||[],p=t.requirementReasons||[],l=[],w=c.filter(e=>{if(!e.available)return l.push({id:e.id,why:"unavailable"}),!1;if(u&&!u(e))return l.push({id:e.id,why:"disabled"}),!1;if(D(e.reach)>D(r))return l.push({id:e.id,why:`reach '${e.reach}' exceeds '${r}'`}),!1;const s=i.filter(x=>!e.capabilities.includes(x));if(s.length)return l.push({id:e.id,why:`missing ${s.join(", ")}`}),!1;if(t.minWindow>0&&Number(e.window)>0&&Number(e.window)<t.minWindow)return l.push({id:e.id,why:`a ${Math.round(e.window/1e3)}k window under the ${Math.round(t.minWindow/1e3)}k this turn needs`}),!1;if(t.maxLatencyMs>0&&e.latencyMs>t.maxLatencyMs)return l.push({id:e.id,why:`${e.latencyMs}ms exceeds the ${t.maxLatencyMs}ms deadline`}),!1;if(t.maxCostPer1k>=0&&t.maxCostPer1k!==void 0&&e.costPer1k>t.maxCostPer1k)return l.push({id:e.id,why:`costs ${e.costPer1k} over the ${t.maxCostPer1k} budget`}),!1;if(e.rateLimited)return l.push({id:e.id,why:"rate limited"}),!1;if(t.exclude?.includes?.(e.id))return l.push({id:e.id,why:"already failed this request"}),!1;if(t.minQuality>0){const x=Number.isFinite(e.quality)?e.quality:.5;if(x<t.minQuality)return l.push({id:e.id,why:`below the quality this task needs (${x} < ${t.minQuality})`}),!1}return!0});if(!w.length){if(t.minQuality>0){const e=this.route({...t,minQuality:0});if(e.model)return{...e,relaxed:!0,reasons:[...e.reasons,`no model met the quality this task needs (${t.minQuality}) — used the best available instead`]}}if(t.negotiable?.length){const e=(t.capabilities||[]).filter(x=>!t.negotiable.includes(x)),s=this.route({...t,minQuality:0,capabilities:e,negotiable:[]});if(s.model)return{...s,relaxed:!0,reasons:[...s.reasons,`no model offers ${t.negotiable.join(", ")} — used one without it, which may do this task poorly`]}}return{model:null,reasons:["no candidate satisfies the constraints"],constraints:p,rejected:l}}const g=t.prefer||"balanced",v=e=>{const s=1+Math.max(0,Math.min(1,e.load)),x=Number.isFinite(e.quality)?Math.max(.1,e.quality):.5,O=N[e.reach]??1;return g==="latency"?e.latencyMs*s*O:g==="cost"?e.costPer1k*s*O:g==="quality"?s/x:(e.latencyMs/1e3+e.costPer1k*L)*s*O/x},q=new Map,b=e=>(q.has(e)||q.set(e,v(e)),q.get(e)),y=(e,s)=>e.providerRank-s.providerRank||b(e)-b(s)||e.id.localeCompare(s.id),f=(e,s)=>b(e)-b(s)||e.providerRank-s.providerRank||e.id.localeCompare(s.id),A=new Map;for(const e of w){const s=P(e)||`#${e.id}`;A.has(s)||A.set(s,[]),A.get(s).push(e)}const S=[...A.values()].map(e=>[...e].sort(e.some(s=>s.orderPinned)?y:f));S.sort((e,s)=>b(e[0])-b(s[0])||y(e[0],s[0]));const M=[];for(const e of S){const s=M[M.length-1],x=s?b(s[0][0]):0;s&&b(e[0])<=x*(1+T)?s.push(e):M.push([e])}for(const e of M)e.sort((s,x)=>y(s[0],x[0]));let $=M.flat(2);const R=g==="balanced"?$.filter(e=>e.orderPinned).sort((e,s)=>e.providerRank-s.providerRank)[0]:null;R&&($=[R,...$.filter(e=>e!==R)]);const F=M[0]?.length>1,I=(M[0]||[]).flat().length,_=$[0];return{model:_,eligible:$,constraints:p,strategy:R?"declared-default":"default-score",reasons:[`reach '${_.reach}' within '${r}'`,i.length?`has ${i.join(", ")}`:"no special capability needed",R?`your default (Order ${_.providerRank}) — nothing about this turn asked for anything else`:F?`order ${_.providerRank} broke a ${I}-way tie by ${g}, of ${$.length} eligible`:`best by ${g} (${$.length} eligible)`],rejected:l,runnersUp:$.slice(1).map(e=>e.id)}},async routeWith(t={},r={}){const i=this.route(t);if(!i.model||!h.length)return i;const p=new Map(i.eligible.map(l=>[l.id,l]));for(const l of h){if(u&&!u(l))continue;let w=null;try{const y=l.decide([...i.eligible],t,r);w=l.timeoutMs>0?await Promise.race([y,new Promise(f=>setTimeout(()=>f(null),l.timeoutMs))]):await y}catch{w=null}if(!w)continue;const g=(Array.isArray(w)?w:[w]).map(y=>typeof y=="string"?p.get(y):p.get(y?.id)).filter(Boolean),v=(Array.isArray(w)?w:[w]).length-g.length;if(!g.length)continue;const q=i.eligible.filter(y=>!g.includes(y)),b=[...g,...q];return{...i,model:g[0],eligible:b,strategy:l.id,runnersUp:b.slice(1).map(y=>y.id),reasons:[...i.reasons.slice(0,-1),`chosen by '${l.id}' (class ${l.classUsed}) from ${i.eligible.length} eligible`,...v>0?[`${v} suggestion(s) ignored — not eligible under the constraints`]:[]]}}return i},async run(t,{dispatch:r,need:i={}}={}){if(typeof r!="function")throw new k("NO_DISPATCH","run needs a dispatch function");const p=await this.routeWith(i,{request:t});if(!p.model)throw new k("NO_ROUTE",p.reasons[0]);const l=f=>!f.requiredFor||f.requiredFor(p.model,i),w=d.filter(f=>f.requiredFor&&f.requiredFor(p.model,i)),g=new Set(m("request").concat(m("response")).map(f=>f.id)),v=w.filter(f=>!g.has(f.id));if(v.length)throw new k("MISSING_REQUIRED",`route to '${p.model.id}' requires ${v.map(f=>f.id).join(", ")}, which is not active`);const q={model:p.model,need:i,decision:p};let b=t;for(const f of m("request"))l(f)&&(b=await f.run(b,q)??b);let y=await r(b,q);for(const f of m("response"))l(f)&&(y=await f.run(y,q)??y);return{answer:y,decision:p}}}}export{B as FAILOVER_CAPABILITY_GAP,j as FAILOVER_CLASS_GAP,ee as REACH,k as RouterError,J as createModelRouter,z as defineMiddleware,U as defineModel,W as defineRouteStrategy,V as failoverOrder,E as pinnedOrderOf,Y as preferenceFor,te as reachRank,H as requirementsFor,K as requirementsForStep,P as sameModelKey,G as signalsFrom};
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};
package/run-details.js ADDED
@@ -0,0 +1 @@
1
+ import{linearize as k}from"./order.js";const y=n=>n.payload?.turnId||null;import{displayName as O}from"./trajectory.js";import{displayName as b}from"./trajectory.js";function I(n){const l=k(n),s=new Map,o=[];for(const r of l){const i=y(r);if(!i){o.push(r);continue}s.has(i)||s.set(i,[]),s.get(i).push(r)}const t=[...s.entries()].map(([r,i])=>g(r,i));return t.sort((r,i)=>i.at-r.at),{runs:t,loose:o}}function g(n,l){const s=new Map;let o=null,t=null;const r=[],i=[],d=[];for(const a of l){const e=a.payload||{};switch(a.type){case"turn.started":t={...t||{},startedAt:a.at,kind:e.kind||"chat",agentId:e.agentId||null,background:!!e.background,sourceId:e.sourceId||null,surface:e.surface||null};break;case"turn.ended":t={...t||{},endedAt:a.at,reason:e.reason||"ok",ms:e.ms??null,stepped:e.stepped!==!1,tokensIn:e.tokensIn??null,tokensOut:e.tokensOut??null,cacheReadTokens:e.cacheReadTokens??null,model:e.model||null,provider:e.provider||null,estimated:!!e.estimated,ttftMs:e.ttftMs??null,prepMs:e.prepMs??null,mcpMs:e.mcpMs??null,requests:Array.isArray(e.requests)?e.requests:null};break;case"context.assembled":o={used:e.used||0,parts:e.parts||{},tools:e.tools||[],reachableCount:e.reachableCount||0,pageArmed:!!e.pageArmed,prepMs:e.prepMs??null,mcpMs:e.mcpMs??null};break;case"policy.changed":String(e.dial||"").startsWith("route.")&&e.to&&d.push({to:e.to,applied:e.dial==="route.applied",reasons:e.reasons||[]});break;case"automation.fired":e.ruleId==="router:failover"&&e.to&&d.push({to:e.to,applied:!0,failover:!0,reason:e.reason,from:e.from});break;case"capability.invoked":s.set(e.idempotencyKey||`${e.capability}:${a.id}`,{name:e.capability,args:e.args||{},ok:null,ms:null,summary:null,at:a.at});break;case"capability.resulted":{const u=e.idempotencyKey||`${e.capability}:${a.id}`,p=s.get(u)||{name:e.capability,args:{},at:a.at};p.ok=e.ok!==!1,p.ms=e.cost?.ms??null,p.summary=e.summary||null,s.set(u,p);break}case"capability.activated":r.push({capability:e.capability,reason:e.reason,siteKey:e.siteKey,granted:!!e.granted});break;case"capability.granted":r.push({capability:e.capability,reason:"user-granted",siteKey:e.siteKey,granted:!0});break;case"policy.guard_denied":i.push({capability:e.capability,reason:e.reason});break;default:break}}const c=[...s.values()].sort((a,e)=>a.at-e.at).map(a=>({...a,label:b(a)})),f=c.reduce((a,e)=>a+(e.ms||0),0),m=new Map;for(const a of c){const e=a.label||a.name,u=m.get(e)||{name:e,count:0,ms:0,failed:0};u.count+=1,u.ms+=a.ms||0,a.ok===!1&&(u.failed+=1),m.set(e,u)}return{turnId:n,turn:t,toolMs:f,actions:[...m.values()].sort((a,e)=>e.ms-a.ms),open:!!(t?.startedAt&&!t?.endedAt),kind:t?.kind||"chat",sourceId:t?.sourceId||null,surface:t?.surface||t?.kind||null,background:!!t?.background&&!c.length,at:t?.startedAt||l[0]?.at||0,ms:t?.ms??null,events:l.length,raw:l,context:o,toolCalls:c,capabilities:r,denials:i,failures:c.filter(a=>a.ok===!1),repeats:h(c),contextTokens:o?.used||0,tokens:(t?.tokensIn??0)+(t?.tokensOut??0)||null,tokensIn:t?.tokensIn??null,tokensOut:t?.tokensOut??null,model:t?.model||null,estimated:!!t?.estimated,ttftMs:t?.ttftMs??null,route:d,models:[...new Set(d.filter(a=>a.applied).map(a=>a.to))],failovers:d.filter(a=>a.failover).length,requests:t?.requests||null,prepMs:t?.prepMs??o?.prepMs??null,mcpMs:t?.mcpMs??o?.mcpMs??null}}function h(n,l=2){const s=new Map;for(const o of n){if(o.ok!==!1)continue;const t=`${o.label||o.name}::${(o.summary||"").slice(0,80)}`;s.set(t,(s.get(t)||0)+1)}return[...s.entries()].filter(([,o])=>o>=l).map(([o,t])=>{const[r,i]=o.split("::");return{name:r,summary:i,count:t}}).sort((o,t)=>t.count-o.count)}function w(n,l){if(typeof l!="function")return n;for(const s of n){if(s.tokensIn==null&&s.tokensOut==null)continue;const{usd:o,estimated:t}=l({model:s.model,inputTokens:s.tokensIn||0,outputTokens:s.tokensOut||0,cacheReadTokens:s.turn?.cacheReadTokens||0,estimated:s.estimated})||{};s.usd=o??null,t&&(s.estimated=!0)}return n}function M(n){if(n.open)return{level:"info",text:"Still running, or interrupted before it finished"};if(n.turn?.reason==="aborted")return{level:"info",text:"Stopped by you"};if(n.turn?.reason==="error"&&!n.failures.length)return{level:"warn",text:"The turn failed before any tool ran"};if(n.repeats.length){const l=n.repeats[0];return{level:"bad",text:`${l.name} failed ${l.count}× with the same error — likely a harness problem, not the model`}}return n.failures.length?{level:"warn",text:`${n.failures.length} tool call(s) failed`}:n.denials.length?{level:"info",text:`${n.denials.length} action(s) declined by you`}:n.toolCalls.length?{level:"ok",text:`${n.toolCalls.length} tool call(s), all succeeded`}:{level:"ok",text:"No tools used"}}function $(n){return{generated:"run-details/v1",runs:n.map(l=>({at:l.at,ms:l.ms,reason:l.turn?.reason||null,tokens:l.tokens,parts:l.context?.parts||{},toolsOffered:l.context?.reachableCount||0,calls:l.toolCalls.map(s=>({name:s.name,ok:s.ok,ms:s.ms,args:s.args})),repeats:l.repeats,denials:l.denials.map(s=>s.reason),verdict:M(l).text}))}}export{O as displayName,h as findRepeats,I as groupRuns,g as summarizeRun,$ as toSanitizedReport,M as verdict,w as withCost};
@@ -0,0 +1 @@
1
+ import{EventError as y}from"./event.js";const f=Object.freeze(["none","process","container","kubernetes"]),g=Object.freeze(["open","allowlist","gateway"]),w=Object.freeze(["~/.chatpanel","~/.ssh","~/.gnupg","~/.aws","~/.azure","~/.config/gcloud","~/.kube","~/.netrc","~/.docker/config.json","~/.npmrc","~/.pypirc"]),h=Object.freeze(["/tmp","/private/tmp","~/.cache","~/.npm","~/.local/share/uv","~/.local/state"]),u=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:[]})}),b=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"]),c=e=>!!e&&typeof e=="object"&&!Array.isArray(e),m=e=>Array.isArray(e)&&e.every(t=>typeof t=="string"&&t.length>0),n=(e,t)=>{if(!e)throw new y("SHAPE",t)},i=e=>[...new Set(e)];function p(e){n(c(e),"kit: must be an object"),n(typeof e.id=="string"&&e.id.length>0,"kit: id required"),n(c(e.network)&&g.includes(e.network.mode),`kit ${e.id}: network.mode must be one of ${g.join(", ")}`),n(m(e.network.allowedDomains||[]),`kit ${e.id}: network.allowedDomains must be string[]`),n(m(e.network.deniedDomains||[]),`kit ${e.id}: network.deniedDomains must be string[]`),n(c(e.filesystem),`kit ${e.id}: filesystem required`);for(const t of["allowWrite","denyWrite","allowRead","denyRead"])n(m(e.filesystem[t]||[]),`kit ${e.id}: filesystem.${t} must be string[]`);return n(m(e.filesystem.allowWrite)&&e.filesystem.allowWrite.length>0,`kit ${e.id}: filesystem.allowWrite must name at least the working directory`),e.image!=null&&n(typeof e.image=="string",`kit ${e.id}: image must be a string`),e.credentials!=null&&n(Array.isArray(e.credentials)&&e.credentials.every(t=>c(t)&&typeof t.name=="string"&&typeof t.forHost=="string"),`kit ${e.id}: credentials must be [{ name, forHost }]`),{id:e.id,kind:e.kind||"process",image:e.image||null,network:{mode:e.network.mode,allowedDomains:i(e.network.allowedDomains||[]),deniedDomains:i(e.network.deniedDomains||[])},filesystem:{allowWrite:i(e.filesystem.allowWrite),denyWrite:i(e.filesystem.denyWrite||[]),allowRead:i(e.filesystem.allowRead||[]),denyRead:i(e.filesystem.denyRead||[])},credentials:e.credentials||[],limits:c(e.limits)?{...e.limits}:{}}}function j({engine:e="custom",cwd:t,mode:r="open",extraHosts:s=[],extraWrite:o=[],extraDenyRead:a=[]}={}){const d=u[e]||u.custom;return n(typeof t=="string"&&t.length>0,"kit: cwd required"),p({id:`${e}:${r}`,kind:"process",network:{mode:r,allowedDomains:r==="open"?["*"]:i([...d.hosts,...b,...s]),deniedDomains:[]},filesystem:{allowWrite:i([t,...h,...d.write,...o]),denyWrite:[],allowRead:[t],denyRead:i([...w,...a])}})}function R(e,{loopback:t=[],home:r="",platform:s="darwin"}={}){const o=p(e),a=l=>r&&l.startsWith("~")?r+l.slice(1):l,d=t.map(l=>`127.0.0.1:${l}`);return{network:{allowedDomains:i([...o.network.allowedDomains,...d]),deniedDomains:o.network.deniedDomains,allowLocalBinding:s==="darwin"&&t.length>0},filesystem:{denyRead:o.filesystem.denyRead.map(a),allowRead:o.filesystem.allowRead.map(a),allowWrite:o.filesystem.allowWrite.map(a),denyWrite:o.filesystem.denyWrite.map(a)}}}function D({layer:e="none",runtime:t=null,kitId:r=null,mode:s=null,reason:o=null}={}){return n(f.includes(e),`sandbox record: layer must be one of ${f.join(", ")}`),{layer:e,runtime:t,kit:r,mode:s,...e==="none"&&o?{reason:o}:{}}}function O(e){const t=String(e);return t===""?"''":/^[A-Za-z0-9_\-./=:@%+,]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}function E(e={},{platform:t="darwin"}={}){const r={NODE_USE_ENV_PROXY:"1"};if(t==="linux")for(const s of["no_proxy","NO_PROXY"])typeof e[s]=="string"&&(r[s]=e[s].split(",").map(o=>o.trim()).filter(o=>o&&!/^(localhost|127\.0\.0\.1|::1|\[::1\])$/i.test(o)).join(","));return r}function W(e,t=[]){return[e,...t].map(O).join(" ")}export{h as COMMON_WRITE,b as DEVELOPER_HOSTS,u as ENGINE_KITS,g as NETWORK_MODES,f as SANDBOX_LAYERS,w as SECRET_PATHS,j as kitFor,E as sandboxEnvOverlay,D as sandboxRecord,W as shellJoin,O as shellQuote,R as toSrtSettings,p as validateKit};
@@ -0,0 +1 @@
1
+ const p=Object.freeze({day:"day",week:"month",month:"month",year:"year"});function f(t,r,{engines:g="",safesearch:c=null,pageno:a=1}={}){const o=String(t||"").trim();if(!/^https?:\/\//i.test(o))throw new Error("searxng: url must start with http:// or https://");const s=new URL("search",o.replace(/\/?$/,"/")),e=r.site?`site:${r.site} ${r.q}`:r.q;return s.searchParams.set("q",e),s.searchParams.set("format","json"),r.lang&&s.searchParams.set("language",r.lang),r.freshness&&s.searchParams.set("time_range",p[r.freshness]),a>1&&s.searchParams.set("pageno",String(a)),g&&s.searchParams.set("engines",g),c!=null&&s.searchParams.set("safesearch",String(c)),s.toString()}const i=t=>typeof t=="string"?t:"";function y(t,{limit:r=8,site:g=""}={}){const c=Array.isArray(t?.results)?t.results:[],a=[],o=new Set,s=String(g||"").toLowerCase();for(const e of c){let n;try{n=new URL(i(e?.url))}catch{continue}if(n.protocol!=="https:"&&n.protocol!=="http:"||s&&n.hostname.toLowerCase()!==s&&!n.hostname.toLowerCase().endsWith(`.${s}`))continue;const u=n.origin+n.pathname;if(o.has(u))continue;o.add(u);const l=Array.isArray(e.engines)?e.engines.filter(h=>typeof h=="string"):[];if(a.push({rank:a.length+1,url:n.toString(),title:i(e.title).replace(/\s+/g," ").trim()||n.toString(),snippet:i(e.content).replace(/\s+/g," ").trim(),engine:i(e.engine)||l[0]||"searxng",...l.length?{engines:l}:{},...typeof e.score=="number"?{score:e.score}:{},...i(e.publishedDate)?{publishedDate:e.publishedDate}:{}}),a.length>=r)break}return{results:a,answers:(Array.isArray(t?.answers)?t.answers:[]).map(e=>typeof e=="string"?e:i(e?.answer)).filter(Boolean),suggestions:(Array.isArray(t?.suggestions)?t.suggestions:[]).filter(e=>typeof e=="string"),unresponsive:(Array.isArray(t?.unresponsive_engines)?t.unresponsive_engines:[]).map(e=>Array.isArray(e)?e[0]:i(e)).filter(Boolean)}}export{p as FRESHNESS_TO_TIME_RANGE,f as buildSearxngUrl,y as searxngResults};
@@ -0,0 +1 @@
1
+ const m={amp:"&",lt:"<",gt:">",quot:'"',"#39":"'",apos:"'",nbsp:" "},S=i=>String(i).replace(/&(#x?[0-9a-f]+|[a-z]+);/gi,(s,p)=>{const e=p.toLowerCase();return m[e]?m[e]:e.startsWith("#x")?String.fromCodePoint(parseInt(e.slice(2),16)||32):e.startsWith("#")?String.fromCodePoint(parseInt(e.slice(1),10)||32):s}),h=i=>S(i).replace(/\s+/g," ").trim(),C=/^(header|footer|nav|aside|form|button|dialog)$/i;function w(i){const s=[],e=String(i||"").replace(/<script[\s\S]*?<\/script>/gi," ").replace(/<style[\s\S]*?<\/style>/gi," ").replace(/<!--[\s\S]*?-->/g," ");let a=0;const x=/<(\/?)([a-zA-Z][a-zA-Z0-9]*)\b([^>]*)>/g;let o,c=null,u=!1,l=0;for(;o=x.exec(e);){const[n,t,g,f]=o,d=g.toLowerCase();if(C.test(d)){t?a=Math.max(0,a-1):/\/>$/.test(n)||(a+=1);continue}if(d==="a"&&!t){const r=f.match(/\bhref\s*=\s*("([^"]*)"|'([^']*)'|([^\s"'>]+))/i);c=r?h(r[2]??r[3]??r[4]??""):null,u=a>0,l=o.index+n.length;continue}if(d==="a"&&t&&c!=null){const r=h(e.slice(l,o.index).replace(/<[^>]*>/g," "));s.push({href:c,text:r,chrome:u,at:l,end:o.index+n.length}),c=null}}for(let n=0;n<s.length;n++){const t=s[n],g=Math.min(s[n+1]?.at??e.length,t.end+1400),f=e.slice(t.end,Math.max(t.end,g)).replace(/<[^>]*>/g," ");t.snippet=h(f).slice(0,220).trim(),delete t.at,delete t.end}return s}export{w as extractAnchors};