@chatpanel/events 0.192.0 → 0.200.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/agent-card-view.js +1 -0
- package/agent-card.js +1 -0
- package/agent-dialects.js +1 -0
- package/agent-portability.js +1 -0
- package/agent.js +2 -2
- package/client-prefs.js +1 -1
- package/dialect-a2a.js +3 -0
- package/dialect-chatpanel.js +2 -0
- package/dialect-claude.js +3 -0
- package/dialect-codex.js +1 -0
- package/frontmatter.js +14 -0
- package/index.js +1 -1
- package/mcp-args-env.js +3 -0
- package/mcp-config-import.js +2 -6
- package/model-candidates.js +1 -1
- package/model-picker.js +1 -1
- package/package.json +27 -1
- package/recruit.js +1 -1
- package/registries.js +1 -0
- package/router.js +2 -2
- package/settings-registry.js +1 -1
- package/skill-package.js +3 -0
- package/source-gate.js +1 -1
- package/team-observe.js +1 -1
- package/toml-lite.js +12 -0
- package/voice-models.js +1 -1
package/mcp-config-import.js
CHANGED
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
function
|
|
2
|
-
|
|
3
|
-
`)}function A(n){try{return JSON.parse(n)}catch{return null}}function v(n){const t=n?.mcpServers||n?.mcp_servers||n?.servers||n;return!t||typeof t!="object"?[]:t.command||t.url?[f("Imported MCP server",t)]:Object.entries(t).map(([e,i])=>f(e,i)).filter(Boolean)}function b(n){const t=[],e=/^\s*\[(mcp_servers|mcpServers)\.([^\]]+)\]\s*$/gm;let i;for(;i=e.exec(n);)t.push({name:i[2].trim().replace(/^["']|["']$/g,""),start:e.lastIndex});return t.map((r,s)=>{const o=t[s+1]?.start?n.lastIndexOf(`
|
|
4
|
-
`,t[s+1].start-t[s+1].name.length-15):n.length,l=n.slice(r.start,o<r.start?n.length:o);return f(r.name,j(l))}).filter(Boolean)}function j(n){const t={};for(const o of["type","transport","command","url"]){const l=u(n,o);l!=null&&(t[o]=p(l))}const e=u(n,"args");e!=null&&(t.args=h(e));const i=u(n,"env")??u(n,"environment")??u(n,"environmentVariables");i!=null&&(t.env=m(i));const r=u(n,"headers");r!=null&&(t.headers=m(r));const s=u(n,"authorization")??u(n,"auth_header");return s!=null&&(t.headers={...t.headers||{},Authorization:p(s)}),t}function f(n,t={}){if(!t||typeof t!="object")return null;const e=d(t.command),i=d(t.url),r=String(t.type||t.transport||(e?"stdio":"http")).toLowerCase(),s={name:$(n),enabled:t.enabled!==!1};return e||r==="stdio"?e?{...s,transport:"stdio",command:e,args:S(t.args),env:g(t.env||t.environment||t.environmentVariables)}:null:i?{...s,transport:"http",url:i,headers:g(t.headers)}:null}function u(n,t){const e=String(n||"").split(/\r?\n/);for(let i=0;i<e.length;i++){const r=new RegExp(`^\\s*${C(t)}\\s*=\\s*(.*)$`).exec(e[i]);if(!r)continue;let s=x(r[1]).trim();if(!s)return"";const o=s[0],l=o==="["?"]":o==="{"?"}":"";if(!l)return s;let a=y(s,o,l);for(;a>0&&i+1<e.length;)i+=1,s+=`
|
|
5
|
-
${x(e[i])}`,a=y(s,o,l);return s.trim()}return null}function h(n){const t=String(n||"").trim(),e=t.startsWith("[")&&t.endsWith("]")?t.slice(1,-1):t,i=[];let r=0;for(;r<e.length;){for(;r<e.length&&/[\s,]/.test(e[r]);)r+=1;if(r>=e.length)break;const s=e[r];if(s==='"'||s==="'"){const a=c(e,r);i.push(a.value),r=a.next;continue}let o=r;for(;o<e.length&&e[o]!==",";)o+=1;const l=e.slice(r,o).trim();l&&i.push(l),r=o+1}return i}function m(n){const t=String(n||"").trim(),e=t.startsWith("{")&&t.endsWith("}")?t.slice(1,-1):t,i={};let r=0;for(;r<e.length;){for(;r<e.length&&/[\s,]/.test(e[r]);)r+=1;if(r>=e.length)break;let s="";if(e[r]==='"'||e[r]==="'"){const o=c(e,r);s=o.value,r=o.next}else{let o=r;for(;o<e.length&&e[o]!=="="&&e[o]!==":";)o+=1;s=e.slice(r,o).trim(),r=o}for(;r<e.length&&/[\s=:]/.test(e[r]);)r+=1;if(!s)break;if(e[r]==='"'||e[r]==="'"){const o=c(e,r);i[s]=o.value,r=o.next}else{let o=r;for(;o<e.length&&e[o]!==",";)o+=1;i[s]=p(e.slice(r,o).trim()),r=o+1}}return i}function w(n){const t=[];let e="",i="",r=!1;for(const s of String(n||"")){if(r){e+=s,r=!1;continue}if(s==="\\"){r=!0;continue}if(i){s===i?i="":e+=s;continue}if(s==='"'||s==="'"){i=s;continue}if(/\s/.test(s)){e&&(t.push(e),e="");continue}e+=s}return e&&t.push(e),t}function c(n,t){const e=n[t];let i="",r=!1;for(let s=t+1;s<n.length;s++){const o=n[s];if(r){i+=e==='"'?O(o):o,r=!1;continue}if(o==="\\"&&e==='"'){r=!0;continue}if(o===e)return{value:i,next:s+1};i+=o}return{value:i,next:n.length}}function p(n){const t=String(n||"").trim().replace(/,+$/,"");return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?c(t,0).value:t==="true"?!0:t==="false"?!1:t}function g(n){return!n||typeof n!="object"||Array.isArray(n)?{}:Object.fromEntries(Object.entries(n).map(([t,e])=>[t,String(e)]))}function $(n){return String(n||"MCP server").replace(/[_-]+/g," ").replace(/\b[a-z]/g,t=>t.toUpperCase())}function d(n){return typeof n=="string"?n.trim():""}function x(n){let t="";for(let e=0;e<n.length;e++){const i=n[e];if(t){i===t&&(t=""),i==="\\"&&t==='"'&&(e+=1);continue}if(i==='"'||i==="'")t=i;else if(i==="#")return n.slice(0,e)}return n}function y(n,t,e){let i=0,r="";for(let s=0;s<n.length;s++){const o=n[s];if(r){o==="\\"&&r==='"'?s+=1:o===r&&(r="");continue}o==='"'||o==="'"?r=o:o===t?i+=1:o===e&&(i-=1)}return i}function O(n){return{n:`
|
|
6
|
-
`,r:"\r",t:" ",'"':'"',"\\":"\\"}[n]??n}function C(n){return n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}export{T as argsToText,z as envLikeArgs,I as envToText,S as parseArgsInput,_ as parseEnvInput,W as parseMcpConfig};
|
|
1
|
+
import{tomlValue as o,parseArray as d,parseInlineTable as l,parseScalar as m}from"./toml-lite.js";import{parseArgsInput as h}from"./mcp-args-env.js";import{parseArgsInput as b,argsToText as j,parseEnvInput as z,envToText as _,envLikeArgs as w}from"./mcp-args-env.js";function I(e){const r=String(e||"").trim();if(!r)return[];const n=v(r);return n?g(n):y(r)}function v(e){try{return JSON.parse(e)}catch{return null}}function g(e){const r=e?.mcpServers||e?.mcp_servers||e?.servers||e;return!r||typeof r!="object"?[]:r.command||r.url?[p("Imported MCP server",r)]:Object.entries(r).map(([n,t])=>p(n,t)).filter(Boolean)}function y(e){const r=[],n=/^\s*\[(mcp_servers|mcpServers)\.([^\]]+)\]\s*$/gm;let t;for(;t=n.exec(e);)r.push({name:t[2].trim().replace(/^["']|["']$/g,""),start:n.lastIndex});return r.map((a,s)=>{const i=r[s+1]?.start?e.lastIndexOf(`
|
|
2
|
+
`,r[s+1].start-r[s+1].name.length-15):e.length,u=e.slice(a.start,i<a.start?e.length:i);return p(a.name,S(u))}).filter(Boolean)}function S(e){const r={};for(const i of["type","transport","command","url"]){const u=o(e,i);u!=null&&(r[i]=m(u))}const n=o(e,"args");n!=null&&(r.args=d(n));const t=o(e,"env")??o(e,"environment")??o(e,"environmentVariables");t!=null&&(r.env=l(t));const a=o(e,"headers");a!=null&&(r.headers=l(a));const s=o(e,"authorization")??o(e,"auth_header");return s!=null&&(r.headers={...r.headers||{},Authorization:m(s)}),r}function p(e,r={}){if(!r||typeof r!="object")return null;const n=f(r.command),t=f(r.url),a=String(r.type||r.transport||(n?"stdio":"http")).toLowerCase(),s={name:x(e),enabled:r.enabled!==!1};return n||a==="stdio"?n?{...s,transport:"stdio",command:n,args:h(r.args),env:c(r.env||r.environment||r.environmentVariables)}:null:t?{...s,transport:"http",url:t,headers:c(r.headers)}:null}function c(e){return!e||typeof e!="object"||Array.isArray(e)?{}:Object.fromEntries(Object.entries(e).map(([r,n])=>[r,String(n)]))}function x(e){return String(e||"MCP server").replace(/[_-]+/g," ").replace(/\b[a-z]/g,r=>r.toUpperCase())}function f(e){return typeof e=="string"?e.trim():""}export{j as argsToText,w as envLikeArgs,_ as envToText,b as parseArgsInput,z as parseEnvInput,I as parseMcpConfig};
|
package/model-candidates.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{classifySource as
|
|
1
|
+
import{classifySource as R}from"./sources.js";import{defineModel as A}from"./router.js";import{windowOf as S}from"./context-window.js";const L=/^(ollama|lm-?studio|llama[-.]?cpp|llamafile|localai|local|vllm|mlx|mlx-lm|koboldcpp|jan|gpt4all|textgen|oobabooga)$/i;function b(e){const n=String(e||"").trim(),t=n.indexOf("/");return t>0&&L.test(n.slice(0,t))?"device":"any"}function g(e,n=null){if(e&&c.includes(e.reach))return e.reach;if(e?.provider_type==="agent"||e?.owned_by==="chatpanel-bridge"||n?.type==="agent"){const a=String(e?.id||""),o=e?.model||(a.includes("/")?a.slice(a.indexOf("/")+1):"");return b(o)}const i=String(n?.baseUrl||"");return i?p({baseUrl:i}):"any"}function p(e){if(e.kind==="bridge")return b(e.model);if(e.gatewayModel)return g(e);if(e.gateway){const i=String(e.model||""),a=(Array.isArray(e.modelOptions)?e.modelOptions:[]).find(o=>o&&typeof o=="object"&&o.id===i);return a?g(a):"any"}if(e.kind==="webllm")return"device";const n=String(e.baseUrl||e.url||"");if(/^https?:\/\/(localhost|127\.0\.0\.1|\[::1\]|0\.0\.0\.0)(:|\/|$)/i.test(n))return"device";const t=R(n);return t.internal&&t.matched!=="unparseable"?"trusted":"any"}const I=Object.freeze([{id:"tools",label:"Tools",hint:"Can call functions — needed for page actions, search and MCP."},{id:"vision",label:"Vision",hint:"Can read images and screenshots."},{id:"reasoning",label:"Reasoning",hint:"Thinks before answering — worth the wait on hard tasks."},{id:"long-context",label:"Long context",hint:"Handles large documents and long meetings."},{id:"coding",label:"Coding",hint:"Strong at writing and refactoring code."},{id:"json",label:"Structured output",hint:"Reliably returns valid JSON."},{id:"speech-in",label:"Speech in",hint:"Takes audio as input — a meeting, a voice note."},{id:"speech-out",label:"Speech out",hint:"Speaks its answer."},{id:"audio",label:"Audio",hint:"Understands audio content beyond speech — music, sounds."},{id:"image-out",label:"Image out",hint:"Generates images."}]);function E(e){const n=String(e.model||"").toLowerCase(),t=new Set(["json"]);return(e.kind==="bridge"||e.model)&&t.add("tools"),/gpt-4|gpt-5|claude|gemini|vision|vl\b|llava|pixtral/.test(n)&&t.add("vision"),/o1|o3|r1|reason|think|opus|sonnet|deepseek-r/.test(n)&&t.add("reasoning"),/200k|1m\b|long|gemini|claude|gpt-4\.1|gpt-5/.test(n)&&t.add("long-context"),/code|coder|codex|deepseek|qwen|opus|sonnet/.test(n)&&t.add("coding"),e.kind==="bridge"&&(t.add("coding"),t.add("reasoning")),[...t]}const y=[/localhost|127\.0\.0\.1|ollama|lm.?studio/i,/anthropic|openai\.com|api\.deepseek|googleapis|x\.ai/i,/(^|\W)bridge(\W|$)/i,/openrouter|huggingface|together|groq|fireworks|nvidia|replicate/i],k=1e3;function _(e,n){const t=`${e.baseUrl||e.url||""} ${e.name||""} ${n||e.kind||""}`;for(let i=0;i<y.length;i++)if(y[i].test(t))return k+i*10;return k+50}function w(e){const n=`${e.model||""} ${e.name||""}`.toLowerCase(),t=Number(/(\d+(?:\.\d+)?)\s*b\b/.exec(n)?.[1]);return Number.isFinite(t)?t>=60?.85:t>=20?.6:.3:/instant|mini|nano|tiny|lite|-small\b|haiku/.test(n)?.3:/opus|gpt-5|o1|o3|\bpro\b|ultra|deepseek-r|thinking/.test(n)?.9:/sonnet|gpt-4|flash|gemini|deepseek|qwen|mistral|codestral/.test(n)?.6:e.kind==="bridge"?.8:.5}function x(e,n){const t=e==="device"?1500:700,i=Number.isFinite(n)?n:.5;return Math.round(t*(.6+i))}function M(e,n){if(n==="device")return 0;const t=String(e.model||"").toLowerCase();return/opus|gpt-4|pro\b/.test(t)?5:/sonnet|mini|flash|haiku/.test(t)?1:2}function m(e){if(e==null||e===""||typeof e=="boolean")return null;const n=Number(e);return Number.isFinite(n)?n:null}function f(e,n={},{declared:t=!1}={}){if(!n||typeof n!="object")return e;const i={...e},a=m(n.providerRank);a!==null&&(i.providerRank=a,i.orderPinned=!0),Array.isArray(n.capabilities)&&(i.capabilities=[...n.capabilities]);for(const o of["costPer1k","latencyMs","quality","window"]){const l=m(n[o]);l!==null&&(i[o]=l)}if(typeof n.available=="boolean"&&(i.available=n.available),n.reach&&c.includes(n.reach)){const o=c.includes(e.reachDetected)?e.reachDetected:e.reach;i.reachDetected=o,s[n.reach]>s[e.reach]?i.reach=n.reach:t&&s[n.reach]<s[o]&&s[n.reach]>=s[v]&&(i.reach=n.reach,i.reachDeclared=!0)}return i}import{DEFAULT_MIN_CALLS as O,cardOverride as D}from"./model-ledger.js";import{cardOverride as V}from"./model-ledger.js";function H(e,n,{minCalls:t=O,jobKind:i=null,userOverride:a=null}={}){const{override:o,observed:l}=D(n,{minCalls:t,jobKind:i});let r=f(e,o);const u=new Set(n?.capabilities?.withdrawn||[]);return u.size&&Array.isArray(r.capabilities)&&(r={...r,capabilities:r.capabilities.filter(d=>!u.has(d))},l.push("capabilities")),a&&(r=f(r,a,{declared:!0})),{...r,observed:l}}const s={device:0,trusted:1,any:2},c=["device","trusted","any"],v="trusted";function N(e){const n=c.indexOf(e);return n<0?[...c]:c.slice(Math.min(n,s[v]))}function P(e,n){return!c.includes(n)||!c.includes(e)?!1:s[n]<s[e]}const C=Object.freeze([{id:"device",label:"On this device",hint:"The words never leave this machine."},{id:"trusted",label:"My machine/network",hint:"Your own machine, your own network, or a service your organisation runs and controls."},{id:"any",label:"Third party",hint:"Someone else’s service."}]),h=e=>C.find(n=>n.id===e)?.label||String(e||""),q='How far a request travels to reach it. ChatPanel reads this from the address, so a coding agent that answers from its vendor comes out as a third party — and you can say otherwise: further out to hold it at arm’s length, or "My machine/network" when your organisation’s own controls put it inside yours. That is your word rather than a detection, and the row says so. "On this device" is never offered: it means the words never leave this machine, which is a fact we detect rather than a level of trust anyone can grant.';function U(e){return N(e).map(n=>{const t=P(e,n);return{value:n,label:n===e?`${h(n)} (detected)`:t?`${h(n)} (you declare)`:h(n),detected:n===e,declares:t,hint:t?`ChatPanel detects ${h(e)}. Choose this only if it really is inside your machine or network — content from an internal source will then be allowed to reach it.`:C.find(i=>i.id===n)?.hint||""}})}function z(e,n=null){const t=p(e||{});return!n||typeof n!="object"||!n.reach?t:f({reach:t,reachDetected:t},n,{declared:!0}).reach}function B(e,n,{override:t=null,health:i=null}={}){if(!e||!e.model&&n!=="bridge"&&e.kind!=="bridge")return null;const a=e.id||e.name||e.model;if(!a)return null;const o=[e.name,e.model&&e.model!==e.name?e.model:null].filter(Boolean).join(" · ")||[e.bridgeAgent,e.model].filter(Boolean).join(" · ")||n||e.kind||String(a),l=n||e.kind,r=p(l==="bridge"?{...e,kind:"bridge"}:e),u={id:a,label:o,model:e.model||"",reach:r,reachDetected:r,classUsed:r==="device"?"L":l==="bridge"?"A":"C",capabilities:E({...e,kind:l}),window:S({...e,kind:l,reach:r}),costPer1k:M(e,r),latencyMs:x(r,w({...e,kind:l})),quality:w({...e,kind:l}),providerRank:_(e,l),available:e.enabled!==!1},d=f(u,t||{},{declared:!0});return e.enabled===!1&&(d.available=!1),m(t?.latencyMs)===null&&(d.latencyMs=x(r,d.quality)),A({...d,available:d.available&&(i?i.available!==!1:!0),rateLimited:!!i?.rateLimited})}export{O as DEFAULT_MIN_CALLS,I as KNOWN_CAPABILITIES,C as REACH_CHOICES,v as REACH_DECLARABLE_FLOOR,q as REACH_HELP,s as REACH_RANK,b as agentModelReach,H as applyCard,f as applyOverride,E as capabilitiesOf,V as cardOverride,M as costOf,B as inferCandidate,x as latencyOf,m as numericOverride,_ as providerRankOf,w as qualityOf,N as reachChoicesFor,z as reachFor,P as reachIsDeclaration,h as reachLabel,p as reachOf,g as reachOfGatewayModel,U as reachOptionsFor};
|
package/model-picker.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
const c=e=>e?.providerType==="agent"||e?.viaBridge===!0,f=e=>String(e?.provider||e?.owner||"").trim(),d={openai:"OpenAI",openrouter:"OpenRouter",deepseek:"DeepSeek",xai:"xAI",vllm:"vLLM",lmstudio:"LM Studio",llamacpp:"llama.cpp","llama.cpp":"llama.cpp",huggingface:"Hugging Face",togetherai:"Together AI",together:"Together AI",githubcopilot:"GitHub Copilot",awsbedrock:"AWS Bedrock",bedrock:"AWS Bedrock",azureopenai:"Azure OpenAI",googleai:"Google AI",vertexai:"Vertex AI"};function p(e){const t=String(e||"").trim();if(!t)return"Other";const o=d[t.toLowerCase().replace(/[\s_-]/g,"")];return o||(/[A-Z ]/.test(t)?t:t.charAt(0).toUpperCase()+t.slice(1))}const u=(e,t)=>(e.available===!1)-(t.available===!1)||String(e.id).localeCompare(String(t.id));function b(e,{selectedId:t=""}={}){const o=Array.isArray(e)?e.filter(Boolean):[],r=[],n=new Map;for(const a of o){if(c(a)){r.push(a);continue}const s=f(a)||"other";n.has(s)||n.set(s,[]),n.get(s).push(a)}const l=a=>({...a,label:a.label||a.id,selected:!!t&&a.id===t}),i=[];r.length&&i.push({key:"agents",label:"
|
|
1
|
+
const c=e=>e?.providerType==="agent"||e?.viaBridge===!0,f=e=>String(e?.provider||e?.owner||"").trim(),d={openai:"OpenAI",openrouter:"OpenRouter",deepseek:"DeepSeek",xai:"xAI",vllm:"vLLM",lmstudio:"LM Studio",llamacpp:"llama.cpp","llama.cpp":"llama.cpp",huggingface:"Hugging Face",togetherai:"Together AI",together:"Together AI",githubcopilot:"GitHub Copilot",awsbedrock:"AWS Bedrock",bedrock:"AWS Bedrock",azureopenai:"Azure OpenAI",googleai:"Google AI",vertexai:"Vertex AI"};function p(e){const t=String(e||"").trim();if(!t)return"Other";const o=d[t.toLowerCase().replace(/[\s_-]/g,"")];return o||(/[A-Z ]/.test(t)?t:t.charAt(0).toUpperCase()+t.slice(1))}const u=(e,t)=>(e.available===!1)-(t.available===!1)||String(e.id).localeCompare(String(t.id));function b(e,{selectedId:t=""}={}){const o=Array.isArray(e)?e.filter(Boolean):[],r=[],n=new Map;for(const a of o){if(c(a)){r.push(a);continue}const s=f(a)||"other";n.has(s)||n.set(s,[]),n.get(s).push(a)}const l=a=>({...a,label:a.label||a.id,selected:!!t&&a.id===t}),i=[];r.length&&i.push({key:"agents",label:"Coding Agents",kind:"agent",items:r.slice().sort(u).map(l)});for(const a of[...n.keys()].sort((s,g)=>s.localeCompare(g)))i.push({key:`provider:${a}`,label:p(a),kind:"provider",items:n.get(a).slice().sort(u).map(l)});return i}function h(e,t){const o=String(t||"").trim().toLowerCase();if(!o)return e;const r=[];for(const n of e){if(n.label.toLowerCase().includes(o)){r.push(n);continue}const l=n.items.filter(i=>String(i.label).toLowerCase().includes(o)||String(i.id).toLowerCase().includes(o));l.length&&r.push({...n,items:l})}return r}function A(e){const t=Array.isArray(e)?e.filter(Boolean):[],o=t.filter(r=>r.available!==!1);return(o.find(c)||o[0]||t[0]||{}).id||""}function y(e,t){const o=Array.isArray(e)?e.filter(Boolean):[],r=o.find(n=>n.id===t);return r?{label:r.label||r.id,available:r.available!==!1,reason:r.reason||"",agent:c(r),provider:p(f(r))}:{label:t||"No model",available:o.length?!1:null,reason:o.length&&t?`${t} is not offered by the gateway any more`:"",agent:!1,provider:""}}function m(e,t=[],{max:o=5}={}){const r=new Map;for(const l of e||[])for(const i of l.items||[])r.has(i.id)||r.set(i.id,i);const n=[];for(const l of t||[]){const i=r.get(l);if(i&&!n.includes(i)&&n.push(i),n.length>=o)break}return n.length?[{key:"recent",label:"Recent",kind:"recent",items:n},...e||[]]:e||[]}function v(e=[],t,{max:o=5}={}){return t?[t,...(Array.isArray(e)?e:[]).filter(r=>r&&r!==t)].slice(0,o):Array.isArray(e)?e.slice(0,o):[]}export{A as defaultModelId,h as filterSections,b as groupModels,y as modelSummary,v as rememberRecent,m as withRecent};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chatpanel/events",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.200.1",
|
|
4
4
|
"description": "The canonical ChatPanel event-log and capability contracts — typed durable facts, clock-free deterministic linearization, schema upcasting, and the invariants the replay harness asserts. Pure, dependency-free ESM shared by the ChatPanel extension, gateway and bridge.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
"./adapters.js": "./adapters.js",
|
|
10
10
|
"./adaptive-tool-policy.js": "./adaptive-tool-policy.js",
|
|
11
11
|
"./agent.js": "./agent.js",
|
|
12
|
+
"./agent-card.js": "./agent-card.js",
|
|
13
|
+
"./agent-card-view.js": "./agent-card-view.js",
|
|
14
|
+
"./agent-dialects.js": "./agent-dialects.js",
|
|
15
|
+
"./agent-portability.js": "./agent-portability.js",
|
|
12
16
|
"./attribution.js": "./attribution.js",
|
|
13
17
|
"./backup-envelope.js": "./backup-envelope.js",
|
|
14
18
|
"./blob-envelope.js": "./blob-envelope.js",
|
|
@@ -23,6 +27,7 @@
|
|
|
23
27
|
"./capability-providers.js": "./capability-providers.js",
|
|
24
28
|
"./capability-tools.js": "./capability-tools.js",
|
|
25
29
|
"./fast-path.js": "./fast-path.js",
|
|
30
|
+
"./frontmatter.js": "./frontmatter.js",
|
|
26
31
|
"./plan.js": "./plan.js",
|
|
27
32
|
"./plan-executor.js": "./plan-executor.js",
|
|
28
33
|
"./model-roles.js": "./model-roles.js",
|
|
@@ -46,6 +51,10 @@
|
|
|
46
51
|
"./default-mcp-servers.js": "./default-mcp-servers.js",
|
|
47
52
|
"./default-skills.js": "./default-skills.js",
|
|
48
53
|
"./distance.js": "./distance.js",
|
|
54
|
+
"./dialect-a2a.js": "./dialect-a2a.js",
|
|
55
|
+
"./dialect-chatpanel.js": "./dialect-chatpanel.js",
|
|
56
|
+
"./dialect-claude.js": "./dialect-claude.js",
|
|
57
|
+
"./dialect-codex.js": "./dialect-codex.js",
|
|
49
58
|
"./entitlement.js": "./entitlement.js",
|
|
50
59
|
"./engine.js": "./engine.js",
|
|
51
60
|
"./entity.js": "./entity.js",
|
|
@@ -69,6 +78,7 @@
|
|
|
69
78
|
"./sideline.js": "./sideline.js",
|
|
70
79
|
"./mcp-client.js": "./mcp-client.js",
|
|
71
80
|
"./mcp-config-import.js": "./mcp-config-import.js",
|
|
81
|
+
"./mcp-args-env.js": "./mcp-args-env.js",
|
|
72
82
|
"./mcp-dispatch.js": "./mcp-dispatch.js",
|
|
73
83
|
"./mcp-errors.js": "./mcp-errors.js",
|
|
74
84
|
"./mcp-manager.js": "./mcp-manager.js",
|
|
@@ -107,6 +117,7 @@
|
|
|
107
117
|
"./reach.js": "./reach.js",
|
|
108
118
|
"./recipe-tool.js": "./recipe-tool.js",
|
|
109
119
|
"./recipe.js": "./recipe.js",
|
|
120
|
+
"./registries.js": "./registries.js",
|
|
110
121
|
"./response-language.js": "./response-language.js",
|
|
111
122
|
"./recruit.js": "./recruit.js",
|
|
112
123
|
"./record-list.js": "./record-list.js",
|
|
@@ -127,6 +138,7 @@
|
|
|
127
138
|
"./search-engines.js": "./search-engines.js",
|
|
128
139
|
"./search-gateway.js": "./search-gateway.js",
|
|
129
140
|
"./skill-manifest.js": "./skill-manifest.js",
|
|
141
|
+
"./skill-package.js": "./skill-package.js",
|
|
130
142
|
"./skill-runtime.js": "./skill-runtime.js",
|
|
131
143
|
"./skill-files.js": "./skill-files.js",
|
|
132
144
|
"./attached-paths.js": "./attached-paths.js",
|
|
@@ -181,6 +193,7 @@
|
|
|
181
193
|
"./tool-round.js": "./tool-round.js",
|
|
182
194
|
"./tool-schema.js": "./tool-schema.js",
|
|
183
195
|
"./tool-traits.js": "./tool-traits.js",
|
|
196
|
+
"./toml-lite.js": "./toml-lite.js",
|
|
184
197
|
"./toolset.js": "./toolset.js",
|
|
185
198
|
"./trajectory.js": "./trajectory.js",
|
|
186
199
|
"./turn-loop.js": "./turn-loop.js",
|
|
@@ -222,6 +235,10 @@
|
|
|
222
235
|
"adapters.js",
|
|
223
236
|
"adaptive-tool-policy.js",
|
|
224
237
|
"agent.js",
|
|
238
|
+
"agent-card.js",
|
|
239
|
+
"agent-card-view.js",
|
|
240
|
+
"agent-dialects.js",
|
|
241
|
+
"agent-portability.js",
|
|
225
242
|
"attribution.js",
|
|
226
243
|
"backup-envelope.js",
|
|
227
244
|
"blob-envelope.js",
|
|
@@ -236,6 +253,7 @@
|
|
|
236
253
|
"capability-providers.js",
|
|
237
254
|
"capability-tools.js",
|
|
238
255
|
"fast-path.js",
|
|
256
|
+
"frontmatter.js",
|
|
239
257
|
"plan.js",
|
|
240
258
|
"plan-executor.js",
|
|
241
259
|
"model-roles.js",
|
|
@@ -256,6 +274,10 @@
|
|
|
256
274
|
"default-mcp-servers.js",
|
|
257
275
|
"default-skills.js",
|
|
258
276
|
"distance.js",
|
|
277
|
+
"dialect-a2a.js",
|
|
278
|
+
"dialect-chatpanel.js",
|
|
279
|
+
"dialect-claude.js",
|
|
280
|
+
"dialect-codex.js",
|
|
259
281
|
"entitlement.js",
|
|
260
282
|
"engine.js",
|
|
261
283
|
"entity.js",
|
|
@@ -282,6 +304,7 @@
|
|
|
282
304
|
"sideline.js",
|
|
283
305
|
"mcp-client.js",
|
|
284
306
|
"mcp-config-import.js",
|
|
307
|
+
"mcp-args-env.js",
|
|
285
308
|
"mcp-dispatch.js",
|
|
286
309
|
"mcp-errors.js",
|
|
287
310
|
"mcp-manager.js",
|
|
@@ -326,6 +349,7 @@
|
|
|
326
349
|
"queue.js",
|
|
327
350
|
"reach.js",
|
|
328
351
|
"recipe-tool.js",
|
|
352
|
+
"registries.js",
|
|
329
353
|
"recipe.js",
|
|
330
354
|
"response-language.js",
|
|
331
355
|
"recruit.js",
|
|
@@ -347,6 +371,7 @@
|
|
|
347
371
|
"search-engines.js",
|
|
348
372
|
"search-gateway.js",
|
|
349
373
|
"skill-manifest.js",
|
|
374
|
+
"skill-package.js",
|
|
350
375
|
"skill-runtime.js",
|
|
351
376
|
"skill-files.js",
|
|
352
377
|
"attached-paths.js",
|
|
@@ -401,6 +426,7 @@
|
|
|
401
426
|
"tool-round.js",
|
|
402
427
|
"tool-schema.js",
|
|
403
428
|
"tool-traits.js",
|
|
429
|
+
"toml-lite.js",
|
|
404
430
|
"toolset.js",
|
|
405
431
|
"trajectory.js",
|
|
406
432
|
"turn-loop.js",
|
package/recruit.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{fit as K,engineKey as j,normalizeEngine as E}from"./scorecard.js";import{cardOverride as G,DEFAULT_MIN_CALLS as J}from"./model-ledger.js";import{engineKeyOf as Y,describeEngine as T}from"./engine.js";import{engineOf as H,agentFromForm as X,normalizeAgent as Q,resolveTeam as V}from"./agent.js";import{applyAll as Z,jobToRole as ee}from"./job.js";import{WORK_GRANTS as A}from"./team.js";import{defineSchema as ne,describeSchema as te,coerce as se}from"./structured.js";import{normalizeBudget as ie}from"./budget.js";const q=.5,oe=5,ae=1500,I={device:0,trusted:1,any:2},B=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),F=e=>e==null||!Number.isFinite(e)?null:Math.round(e*1e3)/1e3,k=(e,l)=>String(e||"").trim().slice(0,l),M=e=>(Array.isArray(e)?e:[]).map(l=>String(l).toLowerCase()),S=ne({name:"recruit",purpose:"which applicant gets the job, or that none fits and what agent should exist",fields:{pick:{type:"string",max:64,describe:'the id of the ONE applicant to recruit, or "" when none fits'},why:{type:"string",required:!0,max:400,describe:"one or two sentences a person reads on the job page"},confidence:{type:"number",describe:"0 to 1"},proposalName:{type:"string",max:60,describe:"when none fits: the agent that should exist"},proposalPurpose:{type:"string",max:300},proposalSkills:{type:"string[]",maxItems:12},proposalGrants:{type:"string[]",maxItems:8,describe:"from: data, web, history, mcp, shell, fs:write, scm:read, scm:push, scm:pr"}},nothing:{pick:"",why:"none fits"}});function _(e,{card:l=null,minCalls:t=J,jobKind:s=null}={}){if(!B(e))return null;const o=e;let a=o.engine?E(o.engine):null;if(!a){const d=String(o.model||o.id||"");if(!d)return null;if(o.kind==="bridge"||o.kind==="harness"||o.classUsed==="A"){const f=d.indexOf("/");a=f>0?{kind:"harness",id:d.slice(0,f),model:d.slice(f+1)}:{kind:"harness",id:d}}else a={kind:"model",id:d}}const r=j(a);if(!r)return null;const{override:i,observed:c}=G(l,{minCalls:t,jobKind:s}),n=new Set(l?.capabilities?.withdrawn||[]),h=[...new Set(M(o.capabilities))].filter(d=>!n.has(d));n.size&&M(o.capabilities).some(d=>n.has(d))&&c.push("capabilities");const p=d=>d==null||d===""||!Number.isFinite(Number(d))?null:Number(d),u=I[o.reach]!=null?o.reach:"any",g=i.costPer1k??p(o.costPer1k)??(u==="device"&&a.kind==="model"?0:null);return{key:r,engine:a,label:k(o.label||o.name||le(a),120),reach:u,capabilities:h,quality:i.quality??p(o.quality),latencyMs:i.latencyMs??p(o.latencyMs),costPer1k:g,costPerTask:p(l?.cost?.perTask),availability:p(l?.availability?.rate),available:i.available??(o.available!==!1&&o.usable!==!1),observed:c}}const le=e=>`${e.id}${e.model&&e.model!==e.id?`/${e.model}`:""}`;function Ne(e,{cards:l={},minCalls:t,jobKind:s}={}){const o=[],a=new Set;for(const r of Array.isArray(e)?e:[]){const i=_(r,{card:null,minCalls:t,jobKind:s});!i||a.has(i.key)||(a.add(i.key),o.push(l[i.key]?_(r,{card:l[i.key],minCalls:t,jobKind:s}):i))}return o}function L(e,{reach:l="any"}={}){const t=M(e?.needs?.grants).filter(c=>c!=="none"),s=M(e?.needs?.tools),o=t.some(c=>A.includes(c)),a=[],r=[];(s.length||t.length)&&(a.push("tools"),r.push("the job uses tools")),o&&r.push(`a work grant (${t.filter(c=>A.includes(c)).join(", ")}) needs
|
|
1
|
+
import{fit as K,engineKey as j,normalizeEngine as E}from"./scorecard.js";import{cardOverride as G,DEFAULT_MIN_CALLS as J}from"./model-ledger.js";import{engineKeyOf as Y,describeEngine as T}from"./engine.js";import{engineOf as H,agentFromForm as X,normalizeAgent as Q,resolveTeam as V}from"./agent.js";import{applyAll as Z,jobToRole as ee}from"./job.js";import{WORK_GRANTS as A}from"./team.js";import{defineSchema as ne,describeSchema as te,coerce as se}from"./structured.js";import{normalizeBudget as ie}from"./budget.js";const q=.5,oe=5,ae=1500,I={device:0,trusted:1,any:2},B=e=>e!==null&&typeof e=="object"&&!Array.isArray(e),F=e=>e==null||!Number.isFinite(e)?null:Math.round(e*1e3)/1e3,k=(e,l)=>String(e||"").trim().slice(0,l),M=e=>(Array.isArray(e)?e:[]).map(l=>String(l).toLowerCase()),S=ne({name:"recruit",purpose:"which applicant gets the job, or that none fits and what agent should exist",fields:{pick:{type:"string",max:64,describe:'the id of the ONE applicant to recruit, or "" when none fits'},why:{type:"string",required:!0,max:400,describe:"one or two sentences a person reads on the job page"},confidence:{type:"number",describe:"0 to 1"},proposalName:{type:"string",max:60,describe:"when none fits: the agent that should exist"},proposalPurpose:{type:"string",max:300},proposalSkills:{type:"string[]",maxItems:12},proposalGrants:{type:"string[]",maxItems:8,describe:"from: data, web, history, mcp, shell, fs:write, scm:read, scm:push, scm:pr"}},nothing:{pick:"",why:"none fits"}});function _(e,{card:l=null,minCalls:t=J,jobKind:s=null}={}){if(!B(e))return null;const o=e;let a=o.engine?E(o.engine):null;if(!a){const d=String(o.model||o.id||"");if(!d)return null;if(o.kind==="bridge"||o.kind==="harness"||o.classUsed==="A"){const f=d.indexOf("/");a=f>0?{kind:"harness",id:d.slice(0,f),model:d.slice(f+1)}:{kind:"harness",id:d}}else a={kind:"model",id:d}}const r=j(a);if(!r)return null;const{override:i,observed:c}=G(l,{minCalls:t,jobKind:s}),n=new Set(l?.capabilities?.withdrawn||[]),h=[...new Set(M(o.capabilities))].filter(d=>!n.has(d));n.size&&M(o.capabilities).some(d=>n.has(d))&&c.push("capabilities");const p=d=>d==null||d===""||!Number.isFinite(Number(d))?null:Number(d),u=I[o.reach]!=null?o.reach:"any",g=i.costPer1k??p(o.costPer1k)??(u==="device"&&a.kind==="model"?0:null);return{key:r,engine:a,label:k(o.label||o.name||le(a),120),reach:u,capabilities:h,quality:i.quality??p(o.quality),latencyMs:i.latencyMs??p(o.latencyMs),costPer1k:g,costPerTask:p(l?.cost?.perTask),availability:p(l?.availability?.rate),available:i.available??(o.available!==!1&&o.usable!==!1),observed:c}}const le=e=>`${e.id}${e.model&&e.model!==e.id?`/${e.model}`:""}`;function Ne(e,{cards:l={},minCalls:t,jobKind:s}={}){const o=[],a=new Set;for(const r of Array.isArray(e)?e:[]){const i=_(r,{card:null,minCalls:t,jobKind:s});!i||a.has(i.key)||(a.add(i.key),o.push(l[i.key]?_(r,{card:l[i.key],minCalls:t,jobKind:s}):i))}return o}function L(e,{reach:l="any"}={}){const t=M(e?.needs?.grants).filter(c=>c!=="none"),s=M(e?.needs?.tools),o=t.some(c=>A.includes(c)),a=[],r=[];(s.length||t.length)&&(a.push("tools"),r.push("the job uses tools")),o&&r.push(`a work grant (${t.filter(c=>A.includes(c)).join(", ")}) needs a coding agent`);const i=I[l]!=null?l:"any";return i!=="any"&&r.push(`reach ≤ ${i} (the project's privacy setting)`),{capabilities:a,harness:o,reach:i,why:r}}const C=(e,l,t)=>{const s=[];e.available===!1&&s.push("unavailable right now"),I[e.reach]>I[l.reach]&&s.push(`reach ${e.reach} exceeds ${l.reach}`),l.harness&&e.engine.kind!=="harness"&&s.push("not a coding agent");const o=l.capabilities.filter(a=>!e.capabilities.includes(a));if(o.length&&!(e.engine.kind==="harness"&&o.every(a=>a==="tools"))&&s.push(`lacks ${o.join(", ")}`),t){const a=r=>(r||[]).some(i=>i===e.key||i===`${e.engine.kind}:${e.engine.id}`||i===e.engine.id||i===e.engine.model);t.allow?.length&&!a(t.allow)&&s.push("not on the policy's allow list"),t.deny?.length&&a(t.deny)&&s.push("on the policy's deny list"),t.floor?.quality!=null&&e.quality!=null&&e.quality<t.floor.quality&&s.push(`quality ${e.quality} under the floor ${t.floor.quality}`),t.floor?.availability!=null&&e.availability!=null&&e.availability<t.floor.availability&&s.push(`availability ${e.availability} under the floor ${t.floor.availability}`),t.ceiling?.costPerTask!=null&&e.costPerTask!=null&&e.costPerTask>t.ceiling.costPerTask&&s.push(`$${e.costPerTask}/task over the ceiling`),t.ceiling?.latencyMs!=null&&e.latencyMs!=null&&e.latencyMs>t.ceiling.latencyMs&&s.push(`${e.latencyMs} ms over the ceiling`)}return s},D=(e,l)=>(e?.byEngine||[]).find(t=>t.key===l)?.rating?.avg??null;function re(e,l,t){const s=n=>n.quality??.5,o=n=>n.costPerTask??n.costPer1k??null,a=Math.max(...e.map(n=>o(n)??0),0)||1,r=Math.max(...e.map(n=>n.latencyMs??0),0)||1,i=n=>{const h=D(t,n.key);return h==null?0:h-.5},c=n=>{switch(l){case"cheapest-that-clears":return-((o(n)??a)/a)+s(n)*.01;case"best-quality":return s(n)-(o(n)??a)/a*.01;case"fastest":return-((n.latencyMs??r)/r)+s(n)*.01;default:return s(n)*.5+(1-(o(n)??a)/a)*.25+(1-(n.latencyMs??r)/r)*.25}};return e.map(n=>({row:n,score:c(n)+i(n)*.05})).sort((n,h)=>h.score-n.score).map(n=>n.row)}const z=e=>`${e.key} (quality ${e.quality??"?"}${e.observed.includes("quality")?" observed":""}${e.costPerTask!=null?`, $${e.costPerTask}/task`:e.costPer1k!=null?`, $${e.costPer1k}/1k`:""}${e.latencyMs!=null?`, ${e.latencyMs} ms`:""})`;function ce(e,l,{rows:t=[],summary:s=null,need:o=null,reach:a="any",chatModel:r=null,explore:i=!1}={}){const c=o||L(l,{reach:a}),n=H(e,{chatModel:r}),h=Array.isArray(t)?t.filter(Boolean):[],p=m=>({engine:null,key:null,reasons:m,alternatives:[],exploration:!1,clears:!1});if(n.kind!=="auto"){const m=Y(n),v=h.find(x=>x.key===m)||h.find(x=>x.engine.kind===n.kind&&(n.kind==="harness"?x.engine.id===n.harnessId&&!n.model:(x.engine.id===n.model||x.engine.model===n.model)&&!n.providerId));if(!h.length)return{engine:E({kind:n.kind,id:n.kind==="harness"?n.harnessId:n.providerId||n.model,model:n.model}),key:m,reasons:[`${T(n)} — pinned by the agent; no roster to check it against`],alternatives:[],exploration:!1,clears:!0};if(!v)return p([`${T(n)} is pinned by the agent but is not installed or configured here`]);const R=C(v,c,null);return R.length?p([`${T(n)} is pinned by the agent but ${R.join("; ")}`]):{engine:v.engine,key:v.key,reasons:["pinned by the agent",...c.why],alternatives:[],exploration:!1,clears:!0}}if(!h.length)return p(["engine is auto and the roster is empty"]);const u=n.policy||{},g=[],d=h.filter(m=>{const $=C(m,c,u);return $.length&&g.push(`${m.key}: ${$.join("; ")}`),!$.length});if(!d.length)return p([`no engine clears ${c.harness?"a coding agent with ":""}${c.capabilities.join(", ")||"the requirements"}${c.reach!=="any"?` within reach ${c.reach}`:""}${u.prefer?` under ${u.prefer}`:""}`,...g.slice(0,4)]);const f=re(d,u.prefer||"balanced",s);let y=f[0],b=!1;const w=m=>m.costPerTask??m.costPer1k??null;if(i&&y.engine.kind!=="harness"){const m=f.filter($=>$.engine.kind!=="harness"&&w($)!=null&&w(y)!=null&&w($)<w(y)).sort(($,v)=>w(v)-w($));m.length&&(b=!0,y=m[0])}const N=[b?`exploration: one tier cheaper than the policy's pick (${f[0].key})`:`${(u.prefer||"balanced").replace(/-/g," ")}: ${z(y)}`,...c.why],O=D(s,y.key);return O!=null&&N.push(`this agent rated ${Math.round(O*100)}% on it before`),(u.floor?.quality!=null||u.ceiling?.costPerTask!=null||u.ceiling?.latencyMs!=null)&&N.push(`${d.length} of ${h.length} engines clear the policy`),{engine:y.engine,key:y.key,reasons:N,alternatives:f.filter(m=>m!==y).slice(0,4).map(m=>m.engine),exploration:b,clears:!0}}function ue(e){const l=new Map((e||[]).filter(Boolean).map(t=>[t.key,t]));return{qualityOf:t=>l.get(t)?.quality??null,costOf:t=>{const s=l.get(t);return s?s.costPerTask??null:null}}}function pe(e,l,{summaries:t={},rows:s=[],reach:o="any",chatModel:a=null,adjust:r=!0,now:i=Date.now()}={}){const c=L(e,{reach:o}),n=ue(s),h=(u,g,d)=>{const f=K(u,{...g,tools:g.tools||g.grants},d,r?n:{adjust:!1}),y=ce(g,u,{rows:s,summary:d,need:c,chatModel:a});return{score:f.score,reasons:[...f.reasons,...y.reasons].slice(0,8),...y.clears?{engine:y.engine}:{},covers:U(u,g)}},p=new Map((l||[]).map(u=>[u?.id,U(e,u)]));return Z(e,l,h,{cards:t,now:i}).map(u=>({...u,covers:p.get(u.agentId)!==!1}))}function U(e,l){const t=M(e?.needs?.skills);if(!t.length)return!0;const s=new Set(M(l?.skills));return t.some(o=>s.has(o))}function de(e,l,t=[],{rows:s=[],top:o=oe}={}){const a=new Map((t||[]).map(n=>[n.id,n])),r=new Map((s||[]).filter(Boolean).map(n=>[n.key,n])),i=e?.needs||{},c=(l||[]).slice(0,o).map(n=>{const h=a.get(n.agentId)||{},p=n.engine?j(n.engine):null,u=p?r.get(p):null;return`- ${n.agentId} (fit ${Math.round((n.fit||0)*100)}%)${h.purpose?` — ${k(h.purpose,160)}`:""}; skills: ${(h.skills||[]).join(", ")||"none"}; grants: ${(h.grants||[]).join(", ")||"none"}; ${p?`engine: ${u?z(u):p}`:"NOT RECRUITABLE NOW — no engine clears"}; ${(n.reasons||[]).slice(0,4).join("; ")}`});return[`You are the evaluator for the job "${k(e?.title,200)}" on project ${e?.projectId||"?"}. Recruit ONE applicant, or say none fits.`,`Brief: ${k(e?.brief,ae)}`,`Needs — skills: ${(i.skills||[]).join(", ")||"none named"}; tools: ${(i.tools||[]).join(", ")||"none named"}; grants: ${(i.grants||[]).join(", ")||"none"}${e?.budget?`; budget: ${Object.entries(e.budget).map(([n,h])=>`${h} ${n}`).join(", ")}`:""}.`,"","Applicants, best computed fit first (fit = the skills, tools and grants the job names, then the attested record, then size):",...c.length?c:["- (no one applied)"],"",'Rules: prefer the applicant that has what the job names and a record of clearing work like it on the engine shown; never pick one marked NOT RECRUITABLE NOW; a lower fit is right only when its reasons show the higher one lacks something the brief needs. When no applicant has the skills the job names, answer pick "" and propose the agent that should exist.',"",te(S)].join(`
|
|
2
2
|
`)}function W(e,l=[]){const t=se(e,S);if(!t)return null;const s=t.value,o=String(s.pick||"").trim(),a=o?(l||[]).find(i=>i.agentId===o):null,r=s.proposalName?{name:k(s.proposalName,60),purpose:k(s.proposalPurpose,300),skills:(s.proposalSkills||[]).map(i=>k(i,80)).filter(Boolean),grants:(s.proposalGrants||[]).map(i=>k(i,64)).filter(Boolean)}:null;return a&&a.engine?{pick:o,why:k(s.why,400)||"the evaluator's pick",confidence:F(s.confidence),proposal:null}:{pick:"",why:a?`the evaluator picked ${o}, which no engine can run right now`:k(s.why,400)||"none fits",confidence:F(s.confidence),proposal:r}}function he(e,l,{evaluation:t=null,minFit:s=q}={}){const o=l||[];if(t&&t.pick){const i=o.find(c=>c.agentId===t.pick&&c.engine);if(i)return{kind:"recruit",agentId:i.agentId,engine:i.engine,fit:i.fit,why:t.why,by:"evaluator"}}if(t&&!t.pick)return{kind:"none",why:t.why,proposal:t.proposal||P(e),by:"evaluator"};const a=o.find(i=>i.engine&&i.covers!==!1);return a&&a.fit>=s?{kind:"recruit",agentId:a.agentId,engine:a.engine,fit:a.fit,why:`best fit (${Math.round(a.fit*100)}%): ${(a.reasons||[])[0]||"meets the needs"}`,by:"fit"}:{kind:"none",why:o.length?a?`the best fit is ${Math.round(a.fit*100)}%, under the ${Math.round(s*100)}% floor: ${(a.reasons||[]).find(i=>/missing/.test(i))||a.reasons?.[0]||""}`:o.some(i=>i.engine)?`no applicant has a skill the job names (${(e?.needs?.skills||[]).join(", ")})`:`${o.length} applied but no engine clears for any of them: ${(o[0].reasons||[]).find(i=>/engine|pinned|roster/.test(i))||"see the applications"}`:"no one in the pool applies to jobs",proposal:P(e),by:"fit"}}function P(e){const l=e?.needs||{};return{name:k(e?.title,60)||"New agent",purpose:`Does jobs like "${k(e?.title,80)}".`,skills:[...l.skills||[]],grants:(l.grants||[]).length?[...l.grants]:["none"]}}function ge(e,l,{by:t="evaluator"}={}){const s=e||P(l),o=new Set(["data","web","history","mcp",...A]),a=(s.grants||[]).map(r=>String(r).toLowerCase()).filter(r=>o.has(r)||/^mcp:/.test(r));return X({name:s.name,purpose:s.purpose,skills:s.skills,prompt:`You are ${s.name}. ${s.purpose||""}
|
|
3
3
|
|
|
4
4
|
You were proposed for the job "${k(l?.title,200)}" because no agent in the pool fit it. Do work like it well; ask on the thread when the brief is unclear.`,grants:a.length?a:["none"],engine:{kind:"auto",prefer:"balanced"},appliesTo:["jobs"],createdBy:t,origin:{kind:"proposal",projectId:l?.projectId,jobId:l?.id}})}function fe(e,l=null){if(e?.budget&&Object.keys(e.budget).length)return ie(e.budget);const t=l?.page?.budget||{},s=l?.spend||{},o=Math.max(1,(l?.jobs||[]).filter(r=>["open","evaluating"].includes(r.status)).length),a={};for(const r of["tokens","calls","ms","usd"]){if(!(Number(t[r])>0))continue;const i=Math.max(0,Number(t[r])-(Number(s[r])||0));i>0&&(a[r]=r==="usd"?Math.round(i/o*100)/100:Math.max(1,Math.floor(i/o)))}return Object.keys(a).length?a:null}function ye(e,l,t,{by:s="evaluator",at:o=Date.now(),record:a=null}={}){const r=[{type:"job.updated",at:o,job:{id:e.id,status:"evaluating",applications:(l||[]).map(({covers:i,...c})=>c)},by:s}];if(t?.kind==="recruit"){const i=fe(e,a);r.push({type:"job.updated",at:o,job:{id:e.id,status:"recruited",recruited:{agentId:t.agentId,engine:t.engine,...i?{budget:i}:{},by:t.by||s,at:o,why:k(t.why,600)}},by:s})}else{r.push({type:"job.updated",at:o,job:{id:e.id,status:"open"},by:s});const i=t?.proposal;r.push({type:"project.decision",at:o,by:s,kind:"proposal",text:`No one in the pool fits "${k(e.title,120)}": ${k(t?.why,400)}${i?` Proposed: ${i.name}${i.skills?.length?` — skills ${i.skills.join(", ")}`:""}${i.grants?.length?`; grants ${i.grants.join(", ")}`:""}.`:""}`,refs:[`job:${e.id}`]})}return r}async function me(e,l,{summaries:t={},rows:s=[],reach:o="any",chatModel:a=null,record:r=null,ask:i=null,minFit:c=q,by:n="evaluator",now:h=Date.now()}={}){const p=pe(e,l,{summaries:t,rows:s,reach:o,chatModel:a,now:h}),u=de(e,p,l,{rows:s});let g=null;if(i&&p.some(f=>f.engine))try{const f=await i(u,S);g=f==null?null:W(typeof f=="string"?f:JSON.stringify(f),p)}catch{g=null}const d=he(e,p,{evaluation:g,minFit:c});return{applications:p,evaluation:g,decision:d,events:ye(e,p,d,{by:d.by==="evaluator"?n:"fit",at:h,record:r}),prompt:u}}async function Te(e,l,{rows:t=[],summaries:s={},reach:o="any",chatModel:a=null,targetFor:r=null,ask:i=null,minFit:c=q,create:n=null,now:h=Date.now()}={}){const p=(Array.isArray(l)?l:[]).filter(b=>b&&b.id);if(n&&B(n))try{const b=Q(n);p.some(w=>w.id===b.id)||p.push(b)}catch{}const u=await me(e,p,{summaries:s,rows:t,reach:o,chatModel:a,ask:i,minFit:c,now:h}),g=u.decision;if(g.kind!=="recruit"){const b=ge(g.proposal||P(e),e,{by:g.by||"evaluator"});return{why:g.why,proposal:b?.ok===!1?null:b?.agent||b,applications:u.applications,events:u.events}}const d=p.find(b=>b.id===g.agentId);let y={...ee(e,d),agent:d.id,engine:g.engine};try{y=V({name:"recruit",roles:[y],budget:{tokens:1}},p,{chatModel:a,targetFor:r}).roles[0]}catch{}return{role:y,agentId:g.agentId,engine:g.engine,why:g.why,fit:g.fit??null,applications:u.applications,events:u.events}}export{ae as MAX_BRIEF_IN_PROMPT,q as MIN_FIT,S as RECRUIT_SCHEMA,oe as TOP_APPLICANTS,pe as applications,fe as carveBudget,he as decide,_ as engineRow,Ne as engineRows,ue as engineWorth,de as evaluatorPrompt,L as needForJob,W as parseEvaluation,P as proposalFromNeeds,ge as proposalToAgent,ye as recruitEvents,Te as recruitForRun,me as recruitJob,ce as routeFor};
|
package/registries.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const p=Object.freeze({npm:"https://registry.npmjs.org",pypi:"https://pypi.org/simple",models:"https://huggingface.co",github:"https://api.github.com"}),a=Object.freeze(Object.keys(p));function h(r){const t=String(r??"").trim();if(!t)return"";let n;try{n=new URL(t)}catch{throw new Error(`registry: ${JSON.stringify(t)} is not a URL`)}if(n.protocol!=="https:"&&n.protocol!=="http:")throw new Error(`registry: ${n.protocol} is not http(s)`);if(n.username||n.password)throw new Error("registry: put credentials in your package manager's own config, not here");return`${n.origin}${n.pathname.replace(/\/+$/,"")}`}function u(r={}){const t={};for(const n of a){if(!(n in(r||{})))continue;const e=h(r[n]);e&&(t[n]=e)}return t}function f(r,t={}){if(!a.includes(r))throw new Error(`registry: unknown kind ${JSON.stringify(r)}`);return t&&t[r]||p[r]}function m(r={}){return a.some(t=>r?.[t]&&r[t]!==p[t])}function y(r,t,n={}){const e=f(r,n),i=p[r];if(e===i)return String(t);let o;try{o=new URL(String(t))}catch{return String(t)}const s=new URL(i);if(o.origin!==s.origin)return String(t);const c=o.pathname.startsWith(s.pathname)?o.pathname.slice(s.pathname.length):o.pathname;return`${e}${c.startsWith("/")?"":"/"}${c}${o.search}`}function l(r={},t={}){const n={...t},e=(c,g)=>{g&&(n[c]=g)},i=r?.npm,o=r?.pypi,s=r?.models;return e("npm_config_registry",i),e("NPM_CONFIG_REGISTRY",i),e("UV_INDEX_URL",o),e("PIP_INDEX_URL",o),e("HF_ENDPOINT",s),n}export{p as DEFAULT_REGISTRIES,a as REGISTRY_KINDS,m as hasOverrides,y as mirrorUrl,u as normalizeRegistries,l as registryEnv,f as registryFor,h as validRegistry};
|
package/router.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
class q extends Error{constructor(s,l){super(l),this.name="RouterError",this.code=s}}import{REACH as re,reachRank as ie}from"./reach.js";import{REACH as
|
|
2
|
-
`)||""),l=s.length,h=!!(t.images?.length||t.attachments?.some?.(a=>/^image\//.test(a?.type||""))),d=!!t.audio||!!t.attachments?.some?.(a=>/^audio\//.test(a?.type||"")),c=(t.attachments||[...t.messages||[]].reverse().find(a=>a?.role==="user")?.attachments||[]).filter(a=>a?.kind==="path");return{reference:c.length?{count:c.length,folders:c.filter(a=>a.isDir).length,documents:c.filter(a=>a.isDir===!1).length,pages:c.reduce((a,r)=>a+(Number(r.pages)||0),0)}:null,approxTokens:Math.round(l/4),modality:d?"audio":h?"vision":"text",code:/```/.test(s)||l>80&&/\bfunction\b|\bclass\b|=>|;\s*$|\bdef\b|\bimport\b|\bconst\b/m.test(s)||/\b(write|fix|debug|refactor|implement|optimi[sz]e|review|explain|generate|add|update|port|migrate)\b[^.?!]{0,60}\b(code|function|method|class|script|bug|regex|query|unit ?test|module|component|endpoint|snippet|compiler?|stack ?trace|typescript|javascript|python|rust|golang|sql|css|html)\b/i.test(s),complexity:l>4e3||/```/.test(s)||l>=200&&/\bstep by step\b|\bplan\b|\brefactor\b|\bmigrate\b|\banalyse|\banalyze/i.test(s)?"high":l<200?"low":"medium",nonLatin:/[^\u0000-\u024F\u2000-\u206F]/.test(s),smalltalk:l<100&&!/```/.test(s)&&!/\b(draw|click|open|fill|read|find|search|edit|write|create|update|delete|run|fix|change|add|remove|select|scroll|extract|summar\w*|analy\w*|check|review|list|show|go to|navigate|my|mine|this page|here|it|that)\b/i.test(s)&&!/\b(explain|describe|define|compare|translate|why|debug|refactor|implement|improve|optimi[sz]e|convert|calculate|generate|draft|rename|build|test|install|deploy|design|plan)\b/i.test(s)&&!/\bhow\s+(do|does|did|can|could|should|would|to|much|many|long)\b/i.test(s),chars:l}}const D=(t,s)=>`${t} ${s}${t===1?"":"s"}`;function B(t){const s=[];return t.folders&&s.push(D(t.folders,"folder")),t.documents&&s.push(`${D(t.documents,"document")}${t.pages?` (${t.pages} pages)`:""}`),s.length?s.join(" and "):D(t.count,"path")}function V(t={},{structured:s=!1,hasTools:l=!1,pageTools:h=!1,background:d=!1,minWindow:y=0}={}){const c=new Set;let a=0;const r=[];y>0&&r.push(`the turn needs a ${Math.round(y/1e3)}k window`),l&&(c.add("tools"),r.push("the turn carries tools")),t.modality==="vision"&&(c.add("vision"),r.push("the request includes an image")),h&&!t.smalltalk&&(c.add("tools"),a=Math.max(a,.55),r.push("driving a page needs exact actions")),t.approxTokens>2e4&&(c.add("long-context"),r.push("the request is large")),t.reference?.count&&(c.add("tools"),a=Math.max(a,.55),r.push(`${B(t.reference)} attached by reference — read through the files tool`)),t.code&&(c.add("coding"),r.push("the request contains code")),s&&!t.smalltalk&&(c.add("tools"),a=Math.max(a,.55),r.push("it must produce an exact structured payload")),t.complexity==="high"&&!d&&(a=Math.max(a,.55),r.push("the task is complex"));const i=t.smalltalk&&!t.reference?.count?[...c]:[...c].filter(n=>n!=="tools");return{required:[...c],negotiable:i,minQuality:a,why:r,minWindow:Math.max(0,Number(y)||0)}}function K(t={},{structured:s=!1,minQuality:l=0,hasTools:h=!1,background:d=!1}={}){return d?{prefer:"cost",why:"background work — spend as little as possible"}:s||t.complexity==="high"||t.code||t.modality==="vision"?{prefer:"quality",why:"the task is exact or hard — get it right rather than quick"}:t.smalltalk&&!h&&!l?{prefer:"latency",why:"nothing to look up — answer fast"}:{prefer:"balanced",why:"no reason to favour speed or quality"}}function O(t){return t?.orderPinned&&Number.isFinite(t.providerRank)?t.providerRank:1/0}const Q=.25,U=.25;function J(t=[],s={}){const l=i=>!!s.model&&S(i)===S(s);let h=[...t];if(s.reason==="gone"){const i=h.filter(n=>!l(n));i.length&&(h=i)}const d=i=>Number.isFinite(i.quality)?i.quality:.5,y=i=>(s.capabilities||[]).every(n=>(i.capabilities||[]).includes(n)),c=i=>!s.classUsed||i.classUsed===s.classUsed,a=Number.isFinite(s.quality)?s.quality:null;if(a!==null){const i=n=>l(n)?-1:Math.abs(d(n)-a)+(c(n)?0:Q)+(y(n)?0:U);return h.map(n=>({m:n,d:i(n)})).sort((n,p)=>n.d-p.d||O(n.m)-O(p.m)||n.m.costPer1k-p.m.costPer1k||String(n.m.id).localeCompare(String(p.m.id))).map(n=>n.m)}const r=i=>l(i)?0:c(i)&&y(i)?1:c(i)?2:y(i)?3:4;return h.sort((i,n)=>r(i)-r(n)||d(n)-d(i)||O(i)-O(n)||i.costPer1k-n.costPer1k)}function X(t,s={}){const l=String(t||""),h=String(s?.action||""),d=`${l}.${h}`;return/screenshot|marked_screenshot|read_canvas|sense_canvas/.test(d)?{required:["vision"],why:"this step reads an image"}:/structured_insert|sheet_write|fill_form|input_sequence|draw_path/.test(d)?{required:["tools"],minQuality:.55,why:"this step writes an exact payload"}:{required:l?["tools"]:[],why:""}}function Z({models:t=[],middleware:s=[],strategies:l=[],admit:h=null}={}){const d=[...t],y=[...s],c=[...l],a=r=>y.filter(i=>i.stage===r&&(!h||h(i))).sort((i,n)=>r==="request"?i.priority-n.priority:n.priority-i.priority);return{addModel(r){return d.push(r),()=>{const i=d.indexOf(r);i>=0&&d.splice(i,1)}},use(r){return y.push(r),()=>{const i=y.indexOf(r);i>=0&&y.splice(i,1)}},addStrategy(r){return c.push(r),()=>{const i=c.indexOf(r);i>=0&&c.splice(i,1)}},models:()=>[...d],middleware:()=>[...y],strategies:()=>[...c],route(r={}){const i=C.includes(r.reach)?r.reach:"any",n=r.capabilities||[],p=r.requirementReasons||[],u=[],g=d.filter(e=>{if(!e.available)return u.push({id:e.id,why:"unavailable"}),!1;if(h&&!h(e))return u.push({id:e.id,why:"disabled"}),!1;if(F(e.reach)>F(i))return u.push({id:e.id,why:`reach '${e.reach}' exceeds '${i}'`}),!1;const o=n.filter(k=>!e.capabilities.includes(k));if(o.length)return u.push({id:e.id,why:`missing ${o.join(", ")}`}),!1;if(r.minWindow>0&&Number(e.window)>0&&Number(e.window)<r.minWindow)return u.push({id:e.id,why:`a ${Math.round(e.window/1e3)}k window under the ${Math.round(r.minWindow/1e3)}k this turn needs`}),!1;if(r.maxLatencyMs>0&&e.latencyMs>r.maxLatencyMs)return u.push({id:e.id,why:`${e.latencyMs}ms exceeds the ${r.maxLatencyMs}ms deadline`}),!1;if(r.maxCostPer1k>=0&&r.maxCostPer1k!==void 0&&e.costPer1k>r.maxCostPer1k)return u.push({id:e.id,why:`costs ${e.costPer1k} over the ${r.maxCostPer1k} budget`}),!1;if(e.rateLimited)return u.push({id:e.id,why:"rate limited"}),!1;if(r.exclude?.includes?.(e.id))return u.push({id:e.id,why:"already failed this request"}),!1;if(r.minQuality>0){const k=Number.isFinite(e.quality)?e.quality:.5;if(k<r.minQuality)return u.push({id:e.id,why:`below the quality this task needs (${k} < ${r.minQuality})`}),!1}return!0});if(!g.length){if(r.minQuality>0){const e=this.route({...r,minQuality:0});if(e.model)return{...e,relaxed:!0,reasons:[...e.reasons,`no model met the quality this task needs (${r.minQuality}) — used the best available instead`]}}if(r.negotiable?.length){const e=(r.capabilities||[]).filter(k=>!r.negotiable.includes(k)),o=this.route({...r,minQuality:0,capabilities:e,negotiable:[]});if(o.model)return{...o,relaxed:!0,reasons:[...o.reasons,`no model offers ${r.negotiable.join(", ")} — used one without it, which may do this task poorly`]}}return{model:null,reasons:["no candidate satisfies the constraints"],constraints:p,rejected:u}}const b=r.prefer||"balanced",v=e=>{const o=1+Math.max(0,Math.min(1,e.load)),k=Number.isFinite(e.quality)?Math.max(.1,e.quality):.5,P=j[e.reach]??1;return b==="latency"?e.latencyMs*o*P:b==="cost"?e.costPer1k*o*P:b==="quality"?o/k:(e.latencyMs/1e3+e.costPer1k*L)*o*P/k},x=new Map,w=e=>(x.has(e)||x.set(e,v(e)),x.get(e)),$=(e,o)=>e.providerRank-o.providerRank||w(e)-w(o)||e.id.localeCompare(o.id),f=(e,o)=>w(e)-w(o)||e.providerRank-o.providerRank||e.id.localeCompare(o.id),m=new Map;for(const e of g){const o=S(e)||`#${e.id}`;m.has(o)||m.set(o,[]),m.get(o).push(e)}const _=[...m.values()].map(e=>[...e].sort(e.some(o=>o.orderPinned)?$:f));_.sort((e,o)=>w(e[0])-w(o[0])||$(e[0],o[0]));const R=[];for(const e of _){const o=R[R.length-1],k=o?w(o[0][0]):0;o&&w(e[0])<=k*(1+T)?o.push(e):R.push([e])}for(const e of R)e.sort((o,k)=>$(o[0],k[0]));let M=R.flat(2);const A=b==="balanced"?M.filter(e=>e.orderPinned).sort((e,o)=>e.providerRank-o.providerRank)[0]:null;A&&(M=[A,...M.filter(e=>e!==A)]);const N=R[0]?.length>1,I=(R[0]||[]).flat().length,E=M[0];return{model:E,eligible:M,constraints:p,strategy:A?"declared-default":"default-score",reasons:[`reach '${E.reach}' within '${i}'`,n.length?`has ${n.join(", ")}`:"no special capability needed",A?`your default (Order ${E.providerRank}) — nothing about this turn asked for anything else`:N?`order ${E.providerRank} broke a ${I}-way tie by ${b}, of ${M.length} eligible`:`best by ${b} (${M.length} eligible)`],rejected:u,runnersUp:M.slice(1).map(e=>e.id)}},async routeWith(r={},i={}){const n=this.route(r);if(!n.model||!c.length)return n;const p=new Map(n.eligible.map(u=>[u.id,u]));for(const u of c){if(h&&!h(u))continue;let g=null;try{const m=u.decide([...n.eligible],r,i);g=u.timeoutMs>0?await Promise.race([m,new Promise(_=>setTimeout(()=>_(null),u.timeoutMs))]):await m}catch{g=null}if(!g)continue;const b=Array.isArray(g)?g:Array.isArray(g?.ranked)?g.ranked:[g],v=Array.isArray(g?.why)?g.why.filter(m=>typeof m=="string"&&m):[],x=b.map(m=>typeof m=="string"?p.get(m):p.get(m?.id)).filter(Boolean),w=b.length-x.length;if(!x.length)continue;const $=n.eligible.filter(m=>!x.includes(m)),f=[...x,...$];return{...n,model:x[0],eligible:f,strategy:u.id,runnersUp:f.slice(1).map(m=>m.id),reasons:[...n.reasons.slice(0,-1),`chosen by '${u.id}' (class ${u.classUsed}) from ${n.eligible.length} eligible`,...v,...w>0?[`${w} suggestion(s) ignored — not eligible under the constraints`]:[]]}}return n},async run(r,{dispatch:i,need:n={}}={}){if(typeof i!="function")throw new q("NO_DISPATCH","run needs a dispatch function");const p=await this.routeWith(n,{request:r});if(!p.model)throw new q("NO_ROUTE",p.reasons[0]);const u=f=>!f.requiredFor||f.requiredFor(p.model,n),g=y.filter(f=>f.requiredFor&&f.requiredFor(p.model,n)),b=new Set(a("request").concat(a("response")).map(f=>f.id)),v=g.filter(f=>!b.has(f.id));if(v.length)throw new q("MISSING_REQUIRED",`route to '${p.model.id}' requires ${v.map(f=>f.id).join(", ")}, which is not active`);const x={model:p.model,need:n,decision:p};let w=r;for(const f of a("request"))u(f)&&(w=await f.run(w,x)??w);let $=await i(w,x);for(const f of a("response"))u(f)&&($=await f.run($,x)??$);return{answer:$,decision:p}}}}export{U as FAILOVER_CAPABILITY_GAP,Q as FAILOVER_CLASS_GAP,re as REACH,q as RouterError,Z as createModelRouter,G as defineMiddleware,W as defineModel,H as defineRouteStrategy,J as failoverOrder,O as pinnedOrderOf,K as preferenceFor,ie as reachRank,V as requirementsFor,X as requirementsForStep,S as sameModelKey,Y as signalsFrom};
|
|
1
|
+
class q extends Error{constructor(s,l){super(l),this.name="RouterError",this.code=s}}import{REACH as re,reachRank as ie}from"./reach.js";import{REACH as P,reachRank as F}from"./reach.js";function W({id:t,label:s,reach:l="any",classUsed:h="C",capabilities:d=[],costPer1k:y=1,latencyMs:c=1e3,load:a=0,available:r=!0,rateLimited:i=!1,observedLatencyMs:n=null,quality:p=null,model:u="",providerRank:w=50,orderPinned:x=!1,window:v=0,reachDetected:b="",reachDeclared:m=!1}){if(!t)throw new q("BAD_MODEL","model.id required");if(!P.includes(l))throw new q("BAD_MODEL",`model '${t}': unknown reach '${l}'`);return Object.freeze({id:t,label:s||t,reach:l,classUsed:h,reachDetected:P.includes(b)?b:l,reachDeclared:!!m,model:u,capabilities:[...d],costPer1k:y,latencyMs:Number.isFinite(n)?n:c,declaredLatencyMs:c,observedLatencyMs:n,load:a,available:r,rateLimited:i,providerRank:w,orderPinned:!!x,quality:p,window:Number(v)>0?Number(v):0})}function G({id:t,label:s,stage:l,priority:h=100,run:d,requiredFor:y=null}){if(!t)throw new q("BAD_MIDDLEWARE","middleware.id required");if(!["request","response"].includes(l))throw new q("BAD_MIDDLEWARE",`middleware '${t}': stage must be request or response`);if(typeof d!="function")throw new q("BAD_MIDDLEWARE",`middleware '${t}': run required`);return Object.freeze({id:t,label:s||t,stage:l,priority:h,run:d,requiredFor:y})}function H({id:t,label:s,classUsed:l="R",timeoutMs:h=0,decide:d}){if(!t)throw new q("BAD_STRATEGY","strategy.id required");if(typeof d!="function")throw new q("BAD_STRATEGY",`strategy '${t}': decide required`);return Object.freeze({id:t,label:s||t,classUsed:l,timeoutMs:h,decide:d})}const T=.1,L=5,j=Object.freeze({device:.7,trusted:.85,any:1});function S(t){return String(t?.model||t?.label||"").toLowerCase().replace(/^[^/]+\//,"").replace(/[:@].*$/,"").replace(/[^a-z0-9.]+/g,"")}function Y(t={}){const s=String(t.text||(t.messages||[]).map(a=>a?.content||"").join(`
|
|
2
|
+
`)||""),l=s.length,h=!!(t.images?.length||t.attachments?.some?.(a=>/^image\//.test(a?.type||""))),d=!!t.audio||!!t.attachments?.some?.(a=>/^audio\//.test(a?.type||"")),c=(t.attachments||[...t.messages||[]].reverse().find(a=>a?.role==="user")?.attachments||[]).filter(a=>a?.kind==="path");return{reference:c.length?{count:c.length,folders:c.filter(a=>a.isDir).length,documents:c.filter(a=>a.isDir===!1).length,pages:c.reduce((a,r)=>a+(Number(r.pages)||0),0)}:null,approxTokens:Math.round(l/4),modality:d?"audio":h?"vision":"text",code:/```/.test(s)||l>80&&/\bfunction\b|\bclass\b|=>|;\s*$|\bdef\b|\bimport\b|\bconst\b/m.test(s)||/\b(write|fix|debug|refactor|implement|optimi[sz]e|review|explain|generate|add|update|port|migrate)\b[^.?!]{0,60}\b(code|function|method|class|script|bug|regex|query|unit ?test|module|component|endpoint|snippet|compiler?|stack ?trace|typescript|javascript|python|rust|golang|sql|css|html)\b/i.test(s),complexity:l>4e3||/```/.test(s)||l>=200&&/\bstep by step\b|\bplan\b|\brefactor\b|\bmigrate\b|\banalyse|\banalyze/i.test(s)?"high":l<200?"low":"medium",nonLatin:/[^\u0000-\u024F\u2000-\u206F]/.test(s),smalltalk:l<100&&!/```/.test(s)&&!/\b(draw|click|open|fill|read|find|search|edit|write|create|update|delete|run|fix|change|add|remove|select|scroll|extract|summar\w*|analy\w*|check|review|list|show|go to|navigate|my|mine|this page|here|it|that)\b/i.test(s)&&!/\b(explain|describe|define|compare|translate|why|debug|refactor|implement|improve|optimi[sz]e|convert|calculate|generate|draft|rename|build|test|install|deploy|design|plan)\b/i.test(s)&&!/\bhow\s+(do|does|did|can|could|should|would|to|much|many|long)\b/i.test(s),chars:l}}const C=(t,s)=>`${t} ${s}${t===1?"":"s"}`;function B(t){const s=[];return t.folders&&s.push(C(t.folders,"folder")),t.documents&&s.push(`${C(t.documents,"document")}${t.pages?` (${t.pages} pages)`:""}`),s.length?s.join(" and "):C(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 D(t){return t?.orderPinned&&Number.isFinite(t.providerRank)?t.providerRank:1/0}const Q=.25,U=.25;function J(t=[],s={}){const l=i=>!!s.model&&S(i)===S(s);let h=[...t];if(s.reason==="gone"){const i=h.filter(n=>!l(n));i.length&&(h=i)}const d=i=>Number.isFinite(i.quality)?i.quality:.5,y=i=>(s.capabilities||[]).every(n=>(i.capabilities||[]).includes(n)),c=i=>!s.classUsed||i.classUsed===s.classUsed,a=Number.isFinite(s.quality)?s.quality:null;if(a!==null){const i=n=>l(n)?-1:Math.abs(d(n)-a)+(c(n)?0:Q)+(y(n)?0:U);return h.map(n=>({m:n,d:i(n)})).sort((n,p)=>n.d-p.d||D(n.m)-D(p.m)||n.m.costPer1k-p.m.costPer1k||String(n.m.id).localeCompare(String(p.m.id))).map(n=>n.m)}const r=i=>l(i)?0:c(i)&&y(i)?1:c(i)?2:y(i)?3:4;return h.sort((i,n)=>r(i)-r(n)||d(n)-d(i)||D(i)-D(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=P.includes(r.reach)?r.reach:"any",n=r.capabilities||[],p=r.requirementReasons||[],u=[],w=d.filter(e=>{if(!e.available)return u.push({id:e.id,why:"unavailable"}),!1;if(h&&!h(e))return u.push({id:e.id,why:"disabled"}),!1;if(F(e.reach)>F(i))return u.push({id:e.id,why:`reach '${e.reach}' exceeds '${i}'`}),!1;const o=n.filter(k=>!e.capabilities.includes(k));if(o.length)return u.push({id:e.id,why:`missing ${o.join(", ")}`}),!1;if(r.minWindow>0&&Number(e.window)>0&&Number(e.window)<r.minWindow)return u.push({id:e.id,why:`a ${Math.round(e.window/1e3)}k window under the ${Math.round(r.minWindow/1e3)}k this turn needs`}),!1;if(r.maxLatencyMs>0&&e.latencyMs>r.maxLatencyMs)return u.push({id:e.id,why:`${e.latencyMs}ms exceeds the ${r.maxLatencyMs}ms deadline`}),!1;if(r.maxCostPer1k>=0&&r.maxCostPer1k!==void 0&&e.costPer1k>r.maxCostPer1k)return u.push({id:e.id,why:`costs ${e.costPer1k} over the ${r.maxCostPer1k} budget`}),!1;if(e.rateLimited)return u.push({id:e.id,why:"rate limited"}),!1;if(r.exclude?.includes?.(e.id))return u.push({id:e.id,why:"already failed this request"}),!1;if(r.minQuality>0){const k=Number.isFinite(e.quality)?e.quality:.5;if(k<r.minQuality)return u.push({id:e.id,why:`below the quality this task needs (${k} < ${r.minQuality})`}),!1}return!0});if(!w.length){if(r.minQuality>0){const e=this.route({...r,minQuality:0});if(e.model)return{...e,relaxed:!0,reasons:[...e.reasons,`no model met the quality this task needs (${r.minQuality}) — used the best available instead`]}}if(r.negotiable?.length){const e=(r.capabilities||[]).filter(k=>!r.negotiable.includes(k)),o=this.route({...r,minQuality:0,capabilities:e,negotiable:[]});if(o.model)return{...o,relaxed:!0,reasons:[...o.reasons,`no model offers ${r.negotiable.join(", ")} — used one without it, which may do this task poorly`]}}return{model:null,reasons:["no candidate satisfies the constraints"],constraints:p,rejected:u}}const x=r.prefer||"balanced",v=e=>{const o=1+Math.max(0,Math.min(1,e.load)),k=Number.isFinite(e.quality)?Math.max(.1,e.quality):.5,O=j[e.reach]??1;return x==="latency"?e.latencyMs*o*O:x==="cost"?e.costPer1k*o*O:x==="quality"?o/k:(e.latencyMs/1e3+e.costPer1k*L)*o*O/k},b=new Map,m=e=>(b.has(e)||b.set(e,v(e)),b.get(e)),$=(e,o)=>e.providerRank-o.providerRank||m(e)-m(o)||e.id.localeCompare(o.id),f=(e,o)=>m(e)-m(o)||e.providerRank-o.providerRank||e.id.localeCompare(o.id),g=new Map;for(const e of w){const o=S(e)||`#${e.id}`;g.has(o)||g.set(o,[]),g.get(o).push(e)}const _=[...g.values()].map(e=>[...e].sort(e.some(o=>o.orderPinned)?$:f));_.sort((e,o)=>m(e[0])-m(o[0])||$(e[0],o[0]));const R=[];for(const e of _){const o=R[R.length-1],k=o?m(o[0][0]):0;o&&m(e[0])<=k*(1+T)?o.push(e):R.push([e])}for(const e of R)e.sort((o,k)=>$(o[0],k[0]));let M=R.flat(2);const A=x==="balanced"?M.filter(e=>e.orderPinned).sort((e,o)=>e.providerRank-o.providerRank)[0]:null;A&&(M=[A,...M.filter(e=>e!==A)]);const N=R[0]?.length>1,I=(R[0]||[]).flat().length,E=M[0];return{model:E,eligible:M,constraints:p,strategy:A?"declared-default":"default-score",reasons:[`reach '${E.reach}' within '${i}'`,n.length?`has ${n.join(", ")}`:"no special capability needed",A?`your default (Order ${E.providerRank}) — nothing about this turn asked for anything else`:N?`order ${E.providerRank} broke a ${I}-way tie by ${x}, of ${M.length} eligible`:`best by ${x} (${M.length} eligible)`],rejected:u,runnersUp:M.slice(1).map(e=>e.id)}},async routeWith(r={},i={}){const n=this.route(r);if(!n.model||!c.length)return n;const p=new Map(n.eligible.map(u=>[u.id,u]));for(const u of c){if(h&&!h(u))continue;let w=null;try{const g=u.decide([...n.eligible],r,i);w=u.timeoutMs>0?await Promise.race([g,new Promise(_=>setTimeout(()=>_(null),u.timeoutMs))]):await g}catch{w=null}if(!w)continue;const x=Array.isArray(w)?w:Array.isArray(w?.ranked)?w.ranked:[w],v=Array.isArray(w?.why)?w.why.filter(g=>typeof g=="string"&&g):[],b=x.map(g=>typeof g=="string"?p.get(g):p.get(g?.id)).filter(Boolean),m=x.length-b.length;if(!b.length)continue;const $=n.eligible.filter(g=>!b.includes(g)),f=[...b,...$];return{...n,model:b[0],eligible:f,strategy:u.id,runnersUp:f.slice(1).map(g=>g.id),reasons:[...n.reasons.slice(0,-1),`chosen by '${u.id}' (class ${u.classUsed}) from ${n.eligible.length} eligible`,...v,...m>0?[`${m} suggestion(s) ignored — not eligible under the constraints`]:[]]}}return n},async run(r,{dispatch:i,need:n={}}={}){if(typeof i!="function")throw new q("NO_DISPATCH","run needs a dispatch function");const p=await this.routeWith(n,{request:r});if(!p.model)throw new q("NO_ROUTE",p.reasons[0]);const u=f=>!f.requiredFor||f.requiredFor(p.model,n),w=y.filter(f=>f.requiredFor&&f.requiredFor(p.model,n)),x=new Set(a("request").concat(a("response")).map(f=>f.id)),v=w.filter(f=>!x.has(f.id));if(v.length)throw new q("MISSING_REQUIRED",`route to '${p.model.id}' requires ${v.map(f=>f.id).join(", ")}, which is not active`);const b={model:p.model,need:n,decision:p};let m=r;for(const f of a("request"))u(f)&&(m=await f.run(m,b)??m);let $=await i(m,b);for(const f of a("response"))u(f)&&($=await f.run($,b)??$);return{answer:$,decision:p}}}}export{U as FAILOVER_CAPABILITY_GAP,Q as FAILOVER_CLASS_GAP,re as REACH,q as RouterError,Z as createModelRouter,G as defineMiddleware,W as defineModel,H as defineRouteStrategy,J as failoverOrder,D as pinnedOrderOf,K as preferenceFor,ie as reachRank,V as requirementsFor,X as requirementsForStep,S as sameModelKey,Y as signalsFrom};
|