@chatpanel/events 0.193.0 → 0.212.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/a2a-board.js +2 -0
- package/a2a-client.js +2 -0
- package/a2a-task.js +4 -0
- package/access-request.js +1 -0
- 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/attached-paths.js +15 -15
- package/client-prefs.js +1 -1
- package/device-proof.js +1 -0
- 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/entitlement.js +1 -1
- package/frontmatter.js +14 -0
- package/harness-cards.js +1 -1
- 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 +37 -1
- package/policy.js +1 -1
- package/recruit.js +1 -1
- package/router.js +2 -2
- package/sandbox-policy.js +1 -1
- package/secret-names.js +1 -0
- 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/policy.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
class a extends Error{constructor(n){super(n),this.name="PolicyError"}}const x=1,
|
|
1
|
+
class a extends Error{constructor(n){super(n),this.name="PolicyError"}}const x=1,S="policy",d=Object.freeze(["off","basic","full"]),A=Object.freeze({off:0,basic:1,full:2}),O=Object.freeze(["gateway","endpoints","redaction","features","agents"]),k=Object.freeze(["webllm","meetings","channels","agents"]),y=Object.freeze(["plan","default","acceptEdits","bypassPermissions"]),E=Object.freeze({plan:0,default:1,acceptEdits:2,bypassPermissions:3}),T=Object.freeze(["api.chatpanel.net","dl.chatpanel.net","huggingface.co","registry.npmjs.org","api.github.com"]),f=e=>typeof e=="string"?e.trim():"",c=e=>Array.isArray(e)?e.map(f).filter(Boolean):[];function h(e){const n=f(e).toLowerCase().replace(/^https?:\/\//,"").replace(/\/.*$/,"");if(!n)return"";if(!/^(\*\.)?[a-z0-9.-]+(:\d{1,5})?$/.test(n)&&!/^\[[0-9a-f:]+\](:\d{1,5})?$/.test(n)&&n!=="*")throw new a(`invalid host pattern "${e}"`);return n}function b(e){if(e==null)return b({});if(typeof e!="object"||Array.isArray(e))throw new a("policy must be an object");const n=e.v==null?x:Number(e.v);if(n!==x)throw new a(`unsupported policy version ${e.v}`);const t={v:n};if(e.org!=null){const r=f(e.org.id);if(!r||!/^[a-z0-9][a-z0-9._-]{0,63}$/i.test(r))throw new a("org.id must be a short identifier");t.org={id:r,name:f(e.org.name)||r}}const o=(r,s)=>{if(r==null)return;if(typeof r!="object")throw new a(`${s} must be an object`);const u={};return r.allow!=null&&(u.allow=c(r.allow).map(h).filter(Boolean)),r.deny!=null&&(u.deny=c(r.deny).map(h).filter(Boolean)),u},i=o(e.endpoints,"endpoints");i&&(t.endpoints=i);const l=o(e.egress,"egress");if(l&&(t.egress=l),e.models!=null){if(typeof e.models!="object")throw new a("models must be an object");t.models={},e.models.allow!=null&&(t.models.allow=c(e.models.allow)),e.models.deny!=null&&(t.models.deny=c(e.models.deny))}if(e.agents!=null){if(typeof e.agents!="object")throw new a("agents must be an object");const r={};if(e.agents.allow!=null&&(r.allow=c(e.agents.allow).map(s=>s.toLowerCase())),e.agents.deny!=null&&(r.deny=c(e.agents.deny).map(s=>s.toLowerCase())),e.agents.permissionModeCap!=null){const s=f(e.agents.permissionModeCap);if(!y.includes(s))throw new a(`agents.permissionModeCap must be one of ${y.join(", ")}`);r.permissionModeCap=s}t.agents=r}if(e.routing!=null){if(typeof e.routing!="object")throw new a("routing must be an object");const r=Array.isArray(e.routing.rules)?e.routing.rules:[];t.routing={rules:r.map((s,u)=>{if(!s||typeof s!="object")throw new a(`routing.rules[${u}] must be an object`);const g=c(s.models),$=c(s.endpoints).map(h).filter(Boolean);if(!g.length)throw new a(`routing.rules[${u}] needs at least one model pattern`);if(!$.length)throw new a(`routing.rules[${u}] needs at least one endpoint`);return{models:g,endpoints:$}})}}if(e.redaction!=null){if(typeof e.redaction!="object")throw new a("redaction must be an object");const r={};if(e.redaction.floor!=null){const s=f(e.redaction.floor).toLowerCase();if(!d.includes(s))throw new a(`redaction.floor must be one of ${d.join(", ")}`);r.floor=s}e.redaction.dictionary!=null&&(r.dictionary=c(e.redaction.dictionary)),e.redaction.requireBeforeCloud!=null&&(r.requireBeforeCloud=!!e.redaction.requireBeforeCloud),t.redaction=r}if(e.client!=null){if(typeof e.client!="object")throw new a("client must be an object");const r={};if(e.client.gatewayUrl!=null){const s=f(e.client.gatewayUrl);if(s&&!/^https?:\/\/[^\s/]+(\/.*)?$/.test(s))throw new a("client.gatewayUrl must be an http(s) URL");r.gatewayUrl=s.replace(/\/+$/,"")}if(e.client.managedRequired!=null&&(r.managedRequired=!!e.client.managedRequired),e.client.lock!=null){const s=c(e.client.lock);for(const u of s)if(!O.includes(u))throw new a(`client.lock: unknown setting "${u}" (one of ${O.join(", ")})`);r.lock=[...new Set(s)]}if(e.client.features!=null){if(typeof e.client.features!="object")throw new a("client.features must be an object");r.features={};for(const[s,u]of Object.entries(e.client.features)){if(!k.includes(s))throw new a(`client.features: unknown feature "${s}" (one of ${k.join(", ")})`);r.features[s]=!!u}}t.client=r}if(e.access!=null){if(typeof e.access!="object"||Array.isArray(e.access))throw new a("access must be an object");const r={};if(e.access.delegation!=null){const s=f(e.access.delegation);if(!C.includes(s))throw new a(`access.delegation must be one of ${C.join(", ")}`);r.delegation=s}for(const s of["deny","allow"]){if(e.access[s]==null)continue;const u=c(e.access[s]).map(g=>String(g).trim()).filter(Boolean);for(const g of u)if(g.length>1024||g.includes("\0"))throw new a(`access.${s}: not a path`);r[s]=u}Object.keys(r).length&&(t.access=r)}return t}const C=Object.freeze(["allowed","never"]);function I(e){return e?.access?.delegation==="never"?"never":"allowed"}function p(e){const n=f(e).toLowerCase();if(!n)return{host:"",port:""};try{const t=new URL(/^[a-z][a-z0-9+.-]*:\/\//.test(n)?n:`http://${n}`);return{host:t.hostname.replace(/^\[|\]$/g,""),port:t.port||(t.protocol==="https:"?"443":t.protocol==="http:"?"80":"")}}catch{return{host:n.split(":")[0],port:""}}}function R(e,n,t){if(e==="*")return!0;const[o,i]=e.startsWith("[")?[e.replace(/^\[([^\]]+)\].*$/,"$1"),e.replace(/^\[[^\]]+\]:?/,"")]:(()=>{const l=e.lastIndexOf(":");return l>0?[e.slice(0,l),e.slice(l+1)]:[e,""]})();if(i&&i!==t)return!1;if(o.startsWith("*.")){const l=o.slice(1);return n.endsWith(l)&&n.length>l.length}return n===o}function w(e,n,t){return(e||[]).some(o=>R(o,n,t))}function m(e){return new RegExp(`^${String(e).split("*").map(n=>n.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join(".*")}$`,"i")}function U(e,n){const t=e?.endpoints;if(!t)return!0;const{host:o,port:i}=p(n);return!o||w(t.deny,o,i)?!1:t.allow&&t.allow.length?w(t.allow,o,i):!0}function z(e,n){const t=e?.models;if(!t)return!0;const o=f(n);return(t.deny||[]).some(i=>m(i).test(o))?!1:t.allow&&t.allow.length?t.allow.some(i=>m(i).test(o)):!0}function L(e,n){const t=e?.agents;if(!t)return!0;const o=f(n).toLowerCase();return(t.deny||[]).includes(o)?!1:t.allow&&t.allow.length?t.allow.includes(o):!0}function N(e,n){const t=e?.agents?.permissionModeCap,o=y.includes(n)?n:"default";return t?E[o]<=E[t]?o:t:o}function _(e,{model:n="",endpoint:t=""}={}){if(!e)return{ok:!0,reason:""};if(n&&!z(e,n))return{ok:!1,reason:`model "${n}" is not allowed by your organisation's policy`};if(t&&!U(e,t))return{ok:!1,reason:`endpoint ${p(t).host} is not allowed by your organisation's policy`};const o=e.routing?.rules||[];if(n&&t&&o.length){const i=o.find(l=>l.models.some(r=>m(r).test(n)));if(i){const{host:l,port:r}=p(t);if(!w(i.endpoints,l,r))return{ok:!1,reason:`model "${n}" may only be sent to ${i.endpoints.join(", ")} under your organisation's policy`}}}return{ok:!0,reason:""}}function P(e,n){const t=e?.redaction?.floor,o=d.includes(n)?n:"basic";return t?A[o]>=A[t]?o:t:o}function B(e,n,{local:t=!1}={}){const o=e?.egress;if(!o)return!0;const{host:i,port:l}=p(n);return!i||w(o.deny,i,l)?!1:t||T.includes(i)||e.endpoints?.allow?.length&&w(e.endpoints.allow,i,l)&&!w(e.endpoints?.deny,i,l)?!0:w(o.allow,i,l)}function q(e,n){return!!e?.client?.lock?.includes(n)}function M(e,n){const t=e?.client?.features;return!t||t[n]==null?!0:!!t[n]}function v(e,n){const t={...n||{}},o=[];if(!e)return{settings:t,changed:o};const i=e.client||{};if(i.gatewayUrl&&t.gatewayUrl!==i.gatewayUrl&&(t.gatewayUrl=i.gatewayUrl,o.push("gatewayUrl")),Array.isArray(t.endpoints)&&e.endpoints){const l=t.endpoints.filter(r=>!r||typeof r!="object"?!1:!r.baseUrl||i.gatewayUrl&&p(r.baseUrl).host===p(i.gatewayUrl).host&&p(r.baseUrl).port===p(i.gatewayUrl).port?!0:U(e,r.baseUrl));l.length!==t.endpoints.length&&(t.endpoints=l,o.push("endpoints"))}if(Array.isArray(t.endpoints)&&e.agents){const l=t.endpoints.filter(r=>r?.kind!=="bridge"||L(e,r.bridgeAgent||r.agent||r.id));l.length!==t.endpoints.length&&(t.endpoints=l,o.push("agents"))}if(Array.isArray(t.endpoints)&&!M(e,"webllm")){const l=t.endpoints.filter(r=>r?.kind!=="webllm");l.length!==t.endpoints.length&&(t.endpoints=l,o.push("webllm"))}if(e.redaction?.floor&&(t.redaction?.tier!=null||t.redactionTier!=null)){const l=t.redaction?.tier!=null?t.redaction.tier:t.redactionTier,r=P(e,l);r!==l&&(t.redaction?.tier!=null?t.redaction={...t.redaction,tier:r}:t.redactionTier=r,o.push("redaction"))}return{settings:t,changed:o}}function D(e){const n=e?.org?.name||e?.org?.id;return n?`Managed by ${n}`:"Managed"}function j(e){return Array.isArray(e)?`[${e.map(j).join(",")}]`:e&&typeof e=="object"?`{${Object.keys(e).sort().map(n=>`${JSON.stringify(n)}:${j(e[n])}`).join(",")}}`:JSON.stringify(e)}async function H(e,{subtle:n=null}={}){const t=n||globalThis.crypto?.subtle;if(!t)throw new a("no WebCrypto available on this runtime");const o=new TextEncoder().encode(j(b(e))),i=await t.digest("SHA-256",o);return[...new Uint8Array(i)].map(l=>l.toString(16).padStart(2,"0")).join("")}async function K(e,{verify:n,...t}={}){if(typeof n!="function")throw new a("verifyPolicyToken needs a verify function (entitlement.js verifySignedToken)");const o=await n(e,{...t,typ:S});if(!o||!o.policy)return null;try{return b(o.policy)}catch{return null}}export{C as ACCESS_DELEGATION,k as FEATURES,O as LOCKABLE,y as PERMISSION_MODES,S as POLICY_TOKEN_TYPE,x as POLICY_VERSION,T as PRODUCT_HOSTS,a as PolicyError,d as REDACTION_TIERS,I as accessDelegation,L as agentAllowed,v as applyPolicyToSettings,B as egressAllowed,U as endpointAllowed,M as featureEnabled,m as globToRegExp,z as modelAllowed,b as normalizeOrgPolicy,N as permissionMode,H as policyHash,D as policyLabel,P as redactionTier,_ as routeAllowed,q as settingLocked,K as verifyPolicyToken};
|
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/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};
|
package/sandbox-policy.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{EventError as b}from"./event.js";import{normalizeGrant as A}from"./sandbox-grant.js";const y=Object.freeze(["none","process","container","kubernetes"]),E=Object.freeze(["open","allowlist","none","gateway"]),h=Object.freeze(["~/.chatpanel","~/.ssh","~/.gnupg","~/.aws","~/.azure","~/.config/gcloud","~/.kube","~/.netrc","~/.docker/config.json","~/.npmrc","~/.pypirc"]),x=Object.freeze(["/tmp","/private/tmp","~/.cache","~/.npm","~/.local/share/uv","~/.local/state"]),_=Object.freeze({codex:Object.freeze({hosts:["api.openai.com","chatgpt.com","auth.openai.com","*.openai.com"],write:["~/.codex"]}),claude:Object.freeze({hosts:["api.anthropic.com","*.anthropic.com","claude.ai","statsig.anthropic.com"],write:["~/.claude","~/.claude.json"]}),antigravity:Object.freeze({hosts:["*.googleapis.com","*.google.com","oauth2.googleapis.com"],write:["~/.gemini","~/.antigravity","~/.config/antigravity"]}),custom:Object.freeze({hosts:[],write:[]}),mcp:Object.freeze({hosts:[],write:[]}),extract:Object.freeze({hosts:[],write:[]}),"model-server":Object.freeze({hosts:["huggingface.co","*.huggingface.co","*.hf.co","cdn-lfs.huggingface.co","cas-bridge.xethub.hf.co","dl.chatpanel.net"],write:[]})}),R=Object.freeze(["github.com","*.github.com","*.githubusercontent.com","gitlab.com","bitbucket.org","registry.npmjs.org","pypi.org","files.pythonhosted.org","crates.io","static.crates.io","proxy.golang.org","sum.golang.org","huggingface.co","*.huggingface.co"]),p=e=>!!e&&typeof e=="object"&&!Array.isArray(e),g=e=>Array.isArray(e)&&e.every(o=>typeof o=="string"&&o.length>0),l=(e,o)=>{if(!e)throw new b("SHAPE",o)},f=e=>[...new Set(e)];function O(e){l(p(e),"kit: must be an object"),l(typeof e.id=="string"&&e.id.length>0,"kit: id required"),l(p(e.network)&&E.includes(e.network.mode),`kit ${e.id}: network.mode must be one of ${E.join(", ")}`),l(g(e.network.allowedDomains||[]),`kit ${e.id}: network.allowedDomains must be string[]`),l(g(e.network.deniedDomains||[]),`kit ${e.id}: network.deniedDomains must be string[]`),l(p(e.filesystem),`kit ${e.id}: filesystem required`);for(const o of["allowWrite","denyWrite","allowRead","denyRead"])l(g(e.filesystem[o]||[]),`kit ${e.id}: filesystem.${o} must be string[]`);return l(g(e.filesystem.allowWrite)&&e.filesystem.allowWrite.length>0,`kit ${e.id}: filesystem.allowWrite must name at least the working directory`),e.image!=null&&l(typeof e.image=="string",`kit ${e.id}: image must be a string`),e.credentials!=null&&l(Array.isArray(e.credentials)&&e.credentials.every(o=>p(o)&&typeof o.name=="string"&&typeof o.forHost=="string"),`kit ${e.id}: credentials must be [{ name, forHost }]`),{id:e.id,kind:e.kind||"process",image:e.image||null,network:{mode:e.network.mode,allowedDomains:f(e.network.allowedDomains||[]),deniedDomains:f(e.network.deniedDomains||[])},filesystem:{allowWrite:f(e.filesystem.allowWrite),denyWrite:f(e.filesystem.denyWrite||[]),allowRead:f(e.filesystem.allowRead||[]),denyRead:f(e.filesystem.denyRead||[])},credentials:e.credentials||[],limits:p(e.limits)?{...e.limits}:{}}}import{normalizeGrant as M,mergeGrants as k,parseHostList as q}from"./sandbox-grant.js";function z({engine:e="custom",cwd:o,mode:t="open",extraHosts:r=[],extraWrite:n=[],extraDenyRead:s=[],grant:c=null}={}){const d=_[e]||_.custom;l(typeof o=="string"&&o.length>0,"kit: cwd required");const a=A(c);return O({id:`${e}:${t}`,kind:"process",network:{mode:t,allowedDomains:t==="open"?["*"]:t==="none"?[]:f([...d.hosts,...R,...r,...a.hosts]),deniedDomains:[]},filesystem:{allowWrite:f([o,...x,...d.write,...n,...a.write.filter(i=>!h.some(u=>i===u||i.startsWith(`${u}/`)))]),denyWrite:[],allowRead:[o],denyRead:f([...h,...s])}})}function N(e,{loopback:o=[],home:t="",platform:r="darwin"}={}){const n=O(e),s=d=>t&&d.startsWith("~")?t+d.slice(1):d,c=n.network.mode==="none"?[]:o.map(d=>`127.0.0.1:${d}`);return{network:{allowedDomains:f([...n.network.allowedDomains,...c]),deniedDomains:n.network.deniedDomains,allowLocalBinding:r==="darwin"&&c.length>0},filesystem:{denyRead:n.filesystem.denyRead.map(s),allowRead:n.filesystem.allowRead.map(s),allowWrite:n.filesystem.allowWrite.map(s),denyWrite:n.filesystem.denyWrite.map(s)}}}function C({layer:e="none",runtime:o=null,kitId:t=null,mode:r=null,reason:n=null,hosts:s=null}={}){return l(y.includes(e),`sandbox record: layer must be one of ${y.join(", ")}`),{layer:e,runtime:o,kit:t,mode:r,...e==="none"&&n?{reason:n}:{},...Array.isArray(s)&&s.length?{hosts:f(s)}:{}}}function S(e,{platform:o="darwin"}={}){const t=String(e);if(o==="win32"){l(!/[\r\n]/.test(t),"win32 command line: an argument holds a newline, which cmd.exe cannot carry");let r=t;if(t===""||/[ \t\v"]/.test(t)){r='"';for(let n=0;n<t.length;n++){let s=0;for(;n<t.length&&t[n]==="\\";)s++,n++;if(n===t.length){r+="\\".repeat(s*2);break}t[n]==='"'?r+="\\".repeat(s*2+1)+'"':r+="\\".repeat(s)+t[n]}r+='"'}return r.replace(/[()%!^"<>&|]/g,"^$&")}return t===""?"''":/^[A-Za-z0-9_\-./=:@%+,]+$/.test(t)?t:`'${t.replace(/'/g,"'\\''")}'`}const I=Object.freeze(["SSL_CERT_FILE","REQUESTS_CA_BUNDLE","CURL_CA_BUNDLE","GIT_SSL_CAINFO"]);function H(e={},{platform:o="darwin",caBundle:t=""}={}){const r={NODE_USE_ENV_PROXY:"1"};if(t)for(const n of I)e[n]||(r[n]=t);if(o==="linux")for(const n of["no_proxy","NO_PROXY"])typeof e[n]=="string"&&(r[n]=e[n].split(",").map(s=>s.trim()).filter(s=>s&&!/^(localhost|127\.0\.0\.1|::1|\[::1\])$/i.test(s)).join(","));return r}function L(e,o=[],{platform:t="darwin"}={}){return[e,...o].map(r=>S(r,{platform:t})).join(" ")}const T=/[\\/]+/,m=e=>String(e||"").replace(/\//g,"\\").replace(/\\+$/,"").toLowerCase(),D=e=>/^[a-z]:$/i.test(m(e))||m(e)==="";function w(e,o){const t=m(e),r=m(o);return!!r&&t!==r&&t.startsWith(r+"\\")}function j(e){const o=String(e||"").replace(/\//g,"\\").split("\\");if(o.length<2)return"";const t=o.findIndex(r=>r.toLowerCase()==="node_modules");return(t>0?o.slice(0,t):o.slice(0,-1)).join("\\")}function K({kit:e,files:o=[],home:t}){l(typeof t=="string"&&t.length>0,"windows grants: home required");const r=a=>(a.startsWith("~")?t+a.slice(1):a).replace(/\//g,"\\"),n=[];for(const a of e?.filesystem?.allowWrite||[]){const i=r(a);!/^[a-z]:\\/i.test(i)&&!i.startsWith("\\\\")||(l(!D(i)&&m(i)!==m(t),`windows grants: a write on ${i} would hand the sandbox account the whole profile`),w(i,t)&&n.push(i))}const s=(a,i)=>i.some(u=>m(a)===m(u)||w(a,u)),c=[];for(const a of o){const i=j(a);i&&w(i,t)&&c.push(i)}for(const a of e?.filesystem?.allowRead||[]){const i=r(a);w(i,t)&&c.push(i)}const d=f(c).filter(a=>!s(a,n));return{read:d.filter(a=>!d.some(i=>i!==a&&w(a,i))),write:f(n)}}const W=Object.freeze(["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","CLAUDE_CONFIG_DIR","OPENAI_API_KEY","OPENAI_BASE_URL","OPENAI_API_BASE","CODEX_HOME","GEMINI_API_KEY","GOOGLE_API_KEY","DEEPSEEK_API_KEY","DSH_HOME","OPENROUTER_API_KEY","GROQ_API_KEY","XAI_API_KEY","MISTRAL_API_KEY"]);function v({engine:e="custom",home:o,env:t={},base:r={},carry:n=W}={}){l(typeof o=="string"&&o.length>0,"windows env: home required");const s=o.replace(/\//g,"\\"),c=/^[a-z]:/i.test(s)?s.slice(0,2):"",d={USERPROFILE:s,...c?{HOMEDRIVE:c,HOMEPATH:s.slice(2)}:{}};for(const[a,i]of Object.entries(t))typeof i=="string"&&(r[a]!==i||n.includes(a))&&(d[a]=i);return e==="codex"&&!d.CODEX_HOME&&(d.CODEX_HOME=s+"\\.codex"),d}function Y(e,o){l(Array.isArray(e),"srt-win argv: must be an array");const t=e.indexOf("exec"),r=t>=0?e.indexOf("--",t+1):-1;l(t>=0&&r>t,"srt-win argv: expected `exec … -- <shell> <command>`");const n=new Set;for(let c=t+1;c<r;c++)e[c]==="--env"&&typeof e[c+1]=="string"&&n.add(e[c+1].split("=")[0].toUpperCase());const s=[];for(const[c,d]of Object.entries(o||{}))l(/^[A-Za-z_][A-Za-z0-9_]*$/.test(c),`srt-win env: bad key ${c}`),l(!/[\r\n]/.test(d),`srt-win env: ${c} holds a newline`),n.has(c.toUpperCase())||s.push("--env",`${c}=${d}`);return[...e.slice(0,r),...s,...e.slice(r)]}export{x as COMMON_WRITE,R as DEVELOPER_HOSTS,_ as ENGINE_KITS,E as NETWORK_MODES,y as SANDBOX_LAYERS,h as SECRET_PATHS,W as WINDOWS_CARRY_KEYS,z as kitFor,k as mergeGrants,M as normalizeGrant,q as parseHostList,H as sandboxEnvOverlay,C as sandboxRecord,L as shellJoin,S as shellQuote,N as toSrtSettings,w as underWindowsHome,O as validateKit,K as windowsGrantsFor,j as windowsInstallRoot,v as windowsSandboxEnv,Y as withSrtWinEnv};
|
|
1
|
+
import{EventError as D}from"./event.js";import{normalizeGrant as O}from"./sandbox-grant.js";import{SECRET_DIR_NAMES as $,SECRET_DIR_PAIRS as j}from"./secret-names.js";const b=Object.freeze(["none","process","container","kubernetes"]),A=Object.freeze(["open","allowlist","none","gateway"]),_=Object.freeze(["~/.chatpanel","~/.ssh","~/.gnupg","~/.aws","~/.azure","~/.config/gcloud","~/.kube","~/.netrc","~/.docker/config.json","~/.npmrc","~/.pypirc"]),g=e=>{let t=String(e||"").trim();for(;t.length>1&&(t.endsWith("/")||t.endsWith("\\"));)t=t.slice(0,-1);return t},R=(e,t)=>t&&(e==="~"||e.startsWith("~/")||e.startsWith("~\\"))?t+e.slice(1):e,y=e=>String(e||"").replace(/\\/g,"/"),x=(e,t)=>{const n=y(g(e)),r=y(g(t));return!!n&&!!r&&(n===r||n.startsWith(`${r}/`))},C=_.map(e=>y(g(e)).replace(/^~\//,"").split("/").filter(Boolean));function S(e,t=""){const n=y(g(R(g(e),t)));if(!n)return!1;for(const o of _)if(x(n,o)||t&&x(n,R(o,t)))return!0;const r=n.split("/").filter(Boolean).map(o=>o.toLowerCase());return C.some(o=>{for(let i=0;i+o.length<=r.length;i+=1)if(o.every((c,l)=>c.toLowerCase()===r[i+l]))return!0;return!1})}const P=Object.freeze([...[...$].map(e=>`~/**/${e}`),...j.map(([e,t])=>`~/**/${e}/${t}`),...[".env",".netrc","_netrc",".git-credentials",".pgpass",".my.cnf",".npmrc",".pypirc",".htpasswd",".terraformrc",".vault-token","credentials","credentials.toml","id_rsa","id_dsa","id_ecdsa","id_ed25519","*.pem","*.p12","*.pfx","*.jks","*.keystore","*.kdbx","*.ppk"].map(e=>`~/**/${e}`)]),v=Object.freeze(["~/.npm","~/.cache","~/.local","~/Library/Caches","~/.nvm","~/.volta","~/.asdf","~/.nodenv","~/.bun","~/.deno","~/.pyenv","~/.rye","~/.pdm","~/.cargo","~/.rustup","~/go","~/.goenv","~/.m2","~/.gradle","~/.sdkman","~/.jenv","~/.gem","~/.rbenv","~/.bundle","~/.composer","~/.nuget","~/.dotnet","~/.stack","~/.ghcup","~/.opam","~/.pub-cache","~/.gitconfig","~/.config/git"]),z=Object.freeze(["/tmp","/private/tmp","~/.cache","~/.npm","~/.local/share/uv","~/.local/state"]),I=Object.freeze({codex:Object.freeze({hosts:["api.openai.com","chatgpt.com","auth.openai.com","*.openai.com"],write:["~/.codex"]}),claude:Object.freeze({hosts:["api.anthropic.com","*.anthropic.com","claude.ai","statsig.anthropic.com"],write:["~/.claude","~/.claude.json"]}),antigravity:Object.freeze({hosts:["*.googleapis.com","*.google.com","oauth2.googleapis.com"],write:["~/.gemini","~/.antigravity","~/.config/antigravity"]}),custom:Object.freeze({hosts:[],write:[]}),mcp:Object.freeze({hosts:[],write:[]}),extract:Object.freeze({hosts:[],write:[]}),"model-server":Object.freeze({hosts:["huggingface.co","*.huggingface.co","*.hf.co","cdn-lfs.huggingface.co","cas-bridge.xethub.hf.co","dl.chatpanel.net"],write:[]})}),N=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"]),w=e=>!!e&&typeof e=="object"&&!Array.isArray(e),E=e=>Array.isArray(e)&&e.every(t=>typeof t=="string"&&t.length>0),f=(e,t)=>{if(!e)throw new D("SHAPE",t)},p=e=>[...new Set(e)];function W(e){f(w(e),"kit: must be an object"),f(typeof e.id=="string"&&e.id.length>0,"kit: id required"),f(w(e.network)&&A.includes(e.network.mode),`kit ${e.id}: network.mode must be one of ${A.join(", ")}`),f(E(e.network.allowedDomains||[]),`kit ${e.id}: network.allowedDomains must be string[]`),f(E(e.network.deniedDomains||[]),`kit ${e.id}: network.deniedDomains must be string[]`),f(w(e.filesystem),`kit ${e.id}: filesystem required`);for(const t of["allowWrite","denyWrite","allowRead","denyRead"])f(E(e.filesystem[t]||[]),`kit ${e.id}: filesystem.${t} must be string[]`);return f(E(e.filesystem.allowWrite)&&e.filesystem.allowWrite.length>0,`kit ${e.id}: filesystem.allowWrite must name at least the working directory`),e.image!=null&&f(typeof e.image=="string",`kit ${e.id}: image must be a string`),e.credentials!=null&&f(Array.isArray(e.credentials)&&e.credentials.every(t=>w(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:p(e.network.allowedDomains||[]),deniedDomains:p(e.network.deniedDomains||[])},filesystem:{allowWrite:p(e.filesystem.allowWrite),denyWrite:p(e.filesystem.denyWrite||[]),allowRead:p(e.filesystem.allowRead||[]),denyRead:p(e.filesystem.denyRead||[])},credentials:e.credentials||[],limits:w(e.limits)?{...e.limits}:{}}}import{normalizeGrant as oe,mergeGrants as re,parseHostList as se}from"./sandbox-grant.js";function B({engine:e="custom",cwd:t,mode:n="open",extraHosts:r=[],extraWrite:o=[],extraDenyRead:i=[],grant:c=null,home:l="",reads:a="enumerated"}={}){const s=I[e]||I.custom;f(typeof t=="string"&&t.length>0,"kit: cwd required");const d=O(c);return W({id:`${e}:${n}`,kind:"process",network:{mode:n,allowedDomains:n==="open"?["*"]:n==="none"?[]:p([...s.hosts,...N,...r,...d.hosts]),deniedDomains:[]},filesystem:{allowWrite:p([t,...z,...s.write,...[...o,...d.write].filter(u=>!S(u,l))]),denyWrite:[],allowRead:a==="inverted"?p([t,...v,...s.write,...L({grant:d,extraWrite:o,cwd:t,home:l})]):[t],denyRead:p([...a==="inverted"?["~",...l?[l]:[]]:[],..._,...P,...i])}})}function L({grant:e=null,extraWrite:t=[],cwd:n="",home:r=""}={}){const o=s=>r&&(s==="~"||s.startsWith("~/")||s.startsWith("~\\"))?r+s.slice(1):s,i=s=>{let d=String(s||"").trim();for(;d.length>1&&(d.endsWith("/")||d.endsWith("\\"));)d=d.slice(0,-1);return d},c=(s,d)=>s===d||s.startsWith(`${d}/`)||s.startsWith(`${d}\\`),l=i(o(n)),a=[];for(const s of[...O(e).write,...Array.isArray(t)?t:[]]){const d=i(o(i(s)));if(d&&!S(d,r)&&!(l&&c(d,l))&&!a.some(u=>c(d,u))){for(let u=a.length-1;u>=0;u--)c(a[u],d)&&a.splice(u,1);a.push(d)}}return a}function q(e,{loopback:t=[],home:n="",platform:r="darwin"}={}){const o=W(e),i=l=>n&&l.startsWith("~")?n+l.slice(1):l,c=o.network.mode==="none"?[]:t.map(l=>`127.0.0.1:${l}`);return{network:{allowedDomains:p([...o.network.allowedDomains,...c]),deniedDomains:o.network.deniedDomains,allowLocalBinding:r==="darwin"&&c.length>0},filesystem:{denyRead:o.filesystem.denyRead.map(i),allowRead:o.filesystem.allowRead.map(i),allowWrite:o.filesystem.allowWrite.map(i),denyWrite:o.filesystem.denyWrite.map(i)}}}function X({layer:e="none",runtime:t=null,kitId:n=null,mode:r=null,reason:o=null,hosts:i=null}={}){return f(b.includes(e),`sandbox record: layer must be one of ${b.join(", ")}`),{layer:e,runtime:t,kit:n,mode:r,...e==="none"&&o?{reason:o}:{},...Array.isArray(i)&&i.length?{hosts:p(i)}:{}}}function T(e,{platform:t="darwin"}={}){const n=String(e);if(t==="win32"){f(!/[\r\n]/.test(n),"win32 command line: an argument holds a newline, which cmd.exe cannot carry");let r=n;if(n===""||/[ \t\v"]/.test(n)){r='"';for(let o=0;o<n.length;o++){let i=0;for(;o<n.length&&n[o]==="\\";)i++,o++;if(o===n.length){r+="\\".repeat(i*2);break}n[o]==='"'?r+="\\".repeat(i*2+1)+'"':r+="\\".repeat(i)+n[o]}r+='"'}return r.replace(/[()%!^"<>&|]/g,"^$&")}return n===""?"''":/^[A-Za-z0-9_\-./=:@%+,]+$/.test(n)?n:`'${n.replace(/'/g,"'\\''")}'`}const H=Object.freeze(["SSL_CERT_FILE","REQUESTS_CA_BUNDLE","CURL_CA_BUNDLE","GIT_SSL_CAINFO"]);function F(e={},{platform:t="darwin",caBundle:n=""}={}){const r={NODE_USE_ENV_PROXY:"1"};if(n)for(const o of H)e[o]||(r[o]=n);if(t==="linux")for(const o of["no_proxy","NO_PROXY"])typeof e[o]=="string"&&(r[o]=e[o].split(",").map(i=>i.trim()).filter(i=>i&&!/^(localhost|127\.0\.0\.1|::1|\[::1\])$/i.test(i)).join(","));return r}function V(e,t=[],{platform:n="darwin"}={}){return[e,...t].map(r=>T(r,{platform:n})).join(" ")}const Q=/[\\/]+/,m=e=>String(e||"").replace(/\//g,"\\").replace(/\\+$/,"").toLowerCase(),k=e=>/^[a-z]:$/i.test(m(e))||m(e)==="";function h(e,t){const n=m(e),r=m(t);return!!r&&n!==r&&n.startsWith(r+"\\")}function K(e){const t=String(e||"").replace(/\//g,"\\").split("\\");if(t.length<2)return"";const n=t.findIndex(r=>r.toLowerCase()==="node_modules");return(n>0?t.slice(0,n):t.slice(0,-1)).join("\\")}function Z({kit:e,files:t=[],home:n}){f(typeof n=="string"&&n.length>0,"windows grants: home required");const r=a=>(a.startsWith("~")?n+a.slice(1):a).replace(/\//g,"\\"),o=[];for(const a of e?.filesystem?.allowWrite||[]){const s=r(a);!/^[a-z]:\\/i.test(s)&&!s.startsWith("\\\\")||(f(!k(s)&&m(s)!==m(n),`windows grants: a write on ${s} would hand the sandbox account the whole profile`),h(s,n)&&o.push(s))}const i=(a,s)=>s.some(d=>m(a)===m(d)||h(a,d)),c=[];for(const a of t){const s=K(a);s&&h(s,n)&&c.push(s)}for(const a of e?.filesystem?.allowRead||[]){const s=r(a);h(s,n)&&c.push(s)}const l=p(c).filter(a=>!i(a,o));return{read:l.filter(a=>!l.some(s=>s!==a&&h(a,s))),write:p(o)}}const Y=Object.freeze(["ANTHROPIC_API_KEY","ANTHROPIC_AUTH_TOKEN","ANTHROPIC_BASE_URL","CLAUDE_CONFIG_DIR","OPENAI_API_KEY","OPENAI_BASE_URL","OPENAI_API_BASE","CODEX_HOME","GEMINI_API_KEY","GOOGLE_API_KEY","DEEPSEEK_API_KEY","DSH_HOME","OPENROUTER_API_KEY","GROQ_API_KEY","XAI_API_KEY","MISTRAL_API_KEY"]);function J({engine:e="custom",home:t,env:n={},base:r={},carry:o=Y}={}){f(typeof t=="string"&&t.length>0,"windows env: home required");const i=t.replace(/\//g,"\\"),c=/^[a-z]:/i.test(i)?i.slice(0,2):"",l={USERPROFILE:i,...c?{HOMEDRIVE:c,HOMEPATH:i.slice(2)}:{}};for(const[a,s]of Object.entries(n))typeof s=="string"&&(r[a]!==s||o.includes(a))&&(l[a]=s);return e==="codex"&&!l.CODEX_HOME&&(l.CODEX_HOME=i+"\\.codex"),l}function ee(e,t){f(Array.isArray(e),"srt-win argv: must be an array");const n=e.indexOf("exec"),r=n>=0?e.indexOf("--",n+1):-1;f(n>=0&&r>n,"srt-win argv: expected `exec … -- <shell> <command>`");const o=new Set;for(let c=n+1;c<r;c++)e[c]==="--env"&&typeof e[c+1]=="string"&&o.add(e[c+1].split("=")[0].toUpperCase());const i=[];for(const[c,l]of Object.entries(t||{}))f(/^[A-Za-z_][A-Za-z0-9_]*$/.test(c),`srt-win env: bad key ${c}`),f(!/[\r\n]/.test(l),`srt-win env: ${c} holds a newline`),o.has(c.toUpperCase())||i.push("--env",`${c}=${l}`);return[...e.slice(0,r),...i,...e.slice(r)]}export{z as COMMON_WRITE,N as DEVELOPER_HOSTS,I as ENGINE_KITS,A as NETWORK_MODES,b as SANDBOX_LAYERS,_ as SECRET_PATHS,P as SECRET_READ_GLOBS,v as TOOLCHAIN_READ,Y as WINDOWS_CARRY_KEYS,S as isSecretWritePath,B as kitFor,re as mergeGrants,oe as normalizeGrant,se as parseHostList,F as sandboxEnvOverlay,X as sandboxRecord,V as shellJoin,T as shellQuote,q as toSrtSettings,h as underWindowsHome,W as validateKit,Z as windowsGrantsFor,K as windowsInstallRoot,J as windowsSandboxEnv,ee as withSrtWinEnv,L as writableRoots};
|
package/secret-names.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=new Set([".ssh",".aws",".gnupg",".gpg",".kube",".azure",".gcloud",".docker",".chatpanel",".password-store",".1password",".op","Keychains",".vault-token",".oci",".bluemix",".ibmcloud",".doctl",".linode",".scaleway",".hcloud",".civo",".terraform.d",".pulumi",".wrangler",".netlify",".vercel",".supabase",".heroku",".databricks",".snowflake",".kaggle",".circleci",".okta",".aliyun",".tencentcloud"]),s=[[".config","gh"],[".config","gcloud"],[".config","hub"],["Library","Keychains"],["Library","Cookies"],[".config","doctl"],[".config","fly"],[".config","openstack"],[".config","containers"],[".m2","settings.xml"],[".gradle","gradle.properties"],[".cargo","credentials.toml"],[".cargo","credentials"],[".gem","credentials"],[".composer","auth.json"],[".cache","huggingface"],[".ansible","vault_pass"],[".aws","sso"]],a=[/^\.env(\..+)?$/i,/^id_(rsa|dsa|ecdsa|ed25519)$/,/\.(pem|key|p12|pfx|jks|keystore|kdbx|ppk|gpg|pgp|asc|keychain|keychain-db)$/i,/^(credentials(\.json)?|\.netrc|_netrc|\.npmrc|\.pypirc|\.git-credentials|\.htpasswd|\.pgpass|\.my\.cnf|token\.json|\.vault-token)$/i,/^secrets?(\.(json|ya?ml|toml|env|txt))?$/i,/\.tfstate(\.backup)?$/i,/\.tfvars$/i,/^service[-_]?account.*\.json$/i,/^\.(bash|zsh|sh|python|node_repl|mysql|psql|irb|lesshst)_?history$/],o=/^\.env\.(example|sample|template|dist)$/i;export{e as SECRET_DIR_NAMES,s as SECRET_DIR_PAIRS,o as SECRET_FILE_ALLOW,a as SECRET_FILE_RES};
|