@chatpanel/events 0.127.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.127.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",
@@ -151,6 +167,9 @@
151
167
  "./voice-intents.js": "./voice-intents.js",
152
168
  "./voice-speaker.js": "./voice-speaker.js",
153
169
  "./voice-loop.js": "./voice-loop.js",
170
+ "./voice-vad.js": "./voice-vad.js",
171
+ "./voice-sample.js": "./voice-sample.js",
172
+ "./voice-models.js": "./voice-models.js",
154
173
  "./speak-stream.js": "./speak-stream.js",
155
174
  "./weather-tool.js": "./weather-tool.js",
156
175
  "./weather.js": "./weather.js",
@@ -162,7 +181,12 @@
162
181
  "./prefetch.js": "./prefetch.js",
163
182
  "./fetched.js": "./fetched.js",
164
183
  "./context-window.js": "./context-window.js",
165
- "./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"
166
190
  },
167
191
  "files": [
168
192
  "LICENSE",
@@ -175,14 +199,23 @@
175
199
  "backup-records.js",
176
200
  "budget.js",
177
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",
178
208
  "citations.js",
179
209
  "client-prefs.js",
210
+ "composer-chips.js",
211
+ "settings-registry.js",
180
212
  "context-attachments.js",
181
213
  "cowriter-router.js",
182
214
  "cowriter-writer.js",
183
215
  "cowriter-factcheck.js",
184
216
  "cowriter.js",
185
217
  "curate.js",
218
+ "default-skills.js",
186
219
  "distance.js",
187
220
  "entitlement.js",
188
221
  "engine.js",
@@ -206,10 +239,12 @@
206
239
  "markdown-render.js",
207
240
  "sideline.js",
208
241
  "mcp-client.js",
242
+ "mcp-config-import.js",
209
243
  "mcp-dispatch.js",
210
244
  "mcp-errors.js",
211
245
  "mcp-manager.js",
212
246
  "mcp-registry.js",
247
+ "model-registry.js",
213
248
  "media-transcript.js",
214
249
  "meeting-analyzers.js",
215
250
  "meeting-insights.js",
@@ -221,6 +256,7 @@
221
256
  "model-health.js",
222
257
  "model-ledger.js",
223
258
  "model-picker.js",
259
+ "monitor-profile.js",
224
260
  "note-actions.js",
225
261
  "note-tool.js",
226
262
  "note-graph.js",
@@ -246,6 +282,7 @@
246
282
  "response-language.js",
247
283
  "recruit.js",
248
284
  "record-list.js",
285
+ "redaction-dictionary.js",
249
286
  "redaction-tokens.js",
250
287
  "ref.js",
251
288
  "registry.js",
@@ -254,6 +291,7 @@
254
291
  "router.js",
255
292
  "rrf.js",
256
293
  "rules.js",
294
+ "run-details.js",
257
295
  "schedule.js",
258
296
  "scm-connection.js",
259
297
  "scopes.js",
@@ -261,6 +299,8 @@
261
299
  "skill-manifest.js",
262
300
  "skill-runtime.js",
263
301
  "skill-files.js",
302
+ "attached-paths.js",
303
+ "extract-capability.js",
264
304
  "skill-scan.js",
265
305
  "skill-sources.js",
266
306
  "skill-vars.js",
@@ -319,12 +359,20 @@
319
359
  "voice-intents.js",
320
360
  "voice-speaker.js",
321
361
  "voice-loop.js",
362
+ "voice-vad.js",
363
+ "voice-sample.js",
364
+ "voice-models.js",
322
365
  "speak-stream.js",
323
366
  "weather-tool.js",
324
367
  "weather.js",
325
368
  "web-search-tool.js",
326
369
  "web-search.js",
327
- "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"
328
376
  ],
329
377
  "repository": {
330
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};