@chatpanel/events 0.143.0 → 0.156.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/skill-manifest.js CHANGED
@@ -1 +1 @@
1
- import{DATA_SCOPES as a}from"./scopes.js";class o extends Error{constructor(t,r){super(r),this.name="SkillManifestError",this.code=t}}const u=2,S=Object.freeze(["auto","page","selection","tabs","none"]),l=Object.freeze(["none","chats","meetings","all"]),d=Object.freeze(["none","selected","default"]),I=Object.freeze(["built-in","user","community"]),m=Object.freeze(["references","scripts","assets","templates","examples"]),s=e=>typeof e=="string"&&e.length>0,h=/^[a-z0-9][a-z0-9_-]*$/;function w(e){return!(!s(e)||e.length>255||e!==e.trim()||e.includes("\\")||/[\u0000-\u001f\u007f]/.test(e)||e.startsWith("/")||/^[a-z]:/i.test(e)||e.split("/").some(r=>r===""||r==="."||r===".."))}function f(e){const t=e?.origin;return t&&typeof t=="object"&&s(t.source)&&s(t.id)?t:null}function y(e){return f(e)?"community":e?.builtin?"built-in":"user"}function p(e){const t=e?.files,r={};if(!t||typeof t!="object")return r;for(const i of m){const n=Array.isArray(t[i])?t[i].filter(w):[];n.length&&(r[i]=[...new Set(n)])}return r}function g(e){return(p(e).scripts||[]).length>0}function E(e={}){const t=p(e),r=d.includes(e.mcpMode)?e.mcpMode:"none",i=S.includes(e.context)?e.context:"auto",n=l.includes(e.historyContext)?e.historyContext:"none",c=new Set(Array.isArray(e.reads)?e.reads.filter(b=>a.includes(b)):[]);return i!=="none"&&c.add("page"),(n==="chats"||n==="all")&&c.add("chats"),(n==="meetings"||n==="all")&&c.add("meetings"),{trust:y(e),reads:[...c].sort(),page:i,history:n,mcp:r,mcpServerIds:r==="selected"&&Array.isArray(e.mcpServerIds)?[...e.mcpServerIds]:[],sources:Array.isArray(e.sources)?[...new Set(e.sources.filter(s))].sort():[],surfaces:Array.isArray(e.surfaces)?[...new Set(e.surfaces.filter(s))].sort():[],scripts:t.scripts||[],needsBridge:g(e),meeting:!!e.meeting}}function v(e){const t=f(e);return t?t.id.length>48?`${t.source} · …${t.id.slice(-40)}`:`${t.source} · ${t.id}`:y(e)==="built-in"?"Built-in":"Written here"}function O(e,t){const r=f(e),i=f(t);return!!r&&!!i&&r.source===i.source&&r.id===i.id}function j(e,t){const r=f(e);return!r||!s(r.hash)||!s(t)?null:r.hash!==t}function P(e){if(!e||typeof e!="object")throw new o("SHAPE","skill must be an object");if(!s(e.id))throw new o("SHAPE","skill.id required");if(!s(e.name))throw new o("SHAPE",`skill '${e.id}': name required`);if(e.prompt!=null&&typeof e.prompt!="string")throw new o("SHAPE",`skill '${e.id}': prompt must be a string`);if(e.command!=null&&e.command!==""&&!h.test(String(e.command)))throw new o("SHAPE",`skill '${e.id}': command must match ${h}`);for(const[t,r]of[["context",S],["historyContext",l],["mcpMode",d]])if(e[t]!=null&&!r.includes(e[t]))throw new o("SHAPE",`skill '${e.id}': ${t} must be one of ${r}`);if(e.reads!=null&&(!Array.isArray(e.reads)||!e.reads.every(t=>a.includes(t))))throw new o("SHAPE",`skill '${e.id}': reads must be within ${a}`);for(const t of["sources","surfaces"])if(e[t]!=null&&(!Array.isArray(e[t])||!e[t].every(s)))throw new o("SHAPE",`skill '${e.id}': ${t} must be an array of ids`);if(e.origin!=null){const t=e.origin;if(typeof t!="object")throw new o("SHAPE",`skill '${e.id}': origin must be an object`);if(!s(t.source)||!s(t.id))throw new o("ORIGIN",`skill '${e.id}': origin needs both source and id`)}if(e.files!=null){if(typeof e.files!="object")throw new o("SHAPE",`skill '${e.id}': files must be an object`);for(const t of Object.keys(e.files)){if(!m.includes(t))throw new o("FILES",`skill '${e.id}': unknown file kind '${t}'`);const r=e.files[t];if(!Array.isArray(r)||!r.every(s))throw new o("FILES",`skill '${e.id}': files.${t} must be an array of paths`);const i=r.find(n=>!w(n));if(i)throw new o("PATH",`skill '${e.id}': unsafe path in files.${t}: ${JSON.stringify(i)}`)}}if(!f(e)&&(e.files?.scripts||[]).length)throw new o("ORIGIN",`skill '${e.id}': scripts require an origin to be scannable`);return e}const x=Object.freeze({1:e=>({...e,v:u})});function A(e){if(!e||typeof e!="object")throw new o("SHAPE","skill must be an object");let t=typeof e.v=="number"?e:{...e,v:1},r=0;for(;t.v<u;){const i=x[t.v];if(!i)throw new o("UPCAST",`no upcaster from v${t.v}`);if(t=i(t),++r>64)throw new o("UPCAST","upcaster chain did not terminate")}if(t.v>u)throw new o("UPCAST",`skill is v${t.v}; this reader only knows v${u}`);return t}function L(e){return(Array.isArray(e)?e:[]).map(A)}function M(e){if(!e||typeof e!="object")return e;const t={...A(e)};t.enabled=t.enabled!==!1;const r=String(t.mcpMode||"none").toLowerCase();t.mcpMode=d.includes(r)?r:"none";const i=Array.isArray(t.mcpServerIds)?t.mcpServerIds:[];t.mcpServerIds=t.mcpMode==="selected"?[...new Set(i.map(c=>String(c||"").trim()).filter(Boolean))]:[],delete t.trust;const n=f(t);n?(t.builtin=!1,t.origin={source:n.source,id:n.id,...s(n.url)?{url:n.url}:{},...s(n.hash)?{hash:n.hash}:{},...n.scanned&&typeof n.scanned=="object"?{scanned:{...n.scanned}}:{}}):t.origin!=null&&delete t.origin,t.reads!=null&&(t.reads=[...new Set((Array.isArray(t.reads)?t.reads:[]).filter(c=>a.includes(c)))].sort());for(const c of["sources","surfaces"])t[c]!=null&&(t[c]=[...new Set((Array.isArray(t[c])?t[c]:[]).filter(s))]);if(t.files!=null){const c=p(t);Object.keys(c).length?t.files=c:delete t.files}return t.version!=null&&!s(t.version)&&delete t.version,t}export{S as SKILL_CONTEXTS,m as SKILL_FILE_KINDS,l as SKILL_HISTORY_SCOPES,u as SKILL_MANIFEST_VERSION,d as SKILL_MCP_MODES,I as SKILL_TRUST,x as SKILL_UPCASTERS,o as SkillManifestError,E as declaredAccess,w as isSafeSkillPath,g as needsBridge,M as normalizeSkill,v as originLabel,f as originOf,O as sameSkillOrigin,p as skillFiles,j as skillIsStale,y as trustOf,A as upcastSkill,L as upcastSkills,P as validateSkill};
1
+ import{DATA_SCOPES as u}from"./scopes.js";import{normalizeGrant as S,parseHostList as g}from"./sandbox-grant.js";class n extends Error{constructor(t,r){super(r),this.name="SkillManifestError",this.code=t}}const d=2,h=Object.freeze(["auto","page","selection","tabs","none"]),l=Object.freeze(["none","chats","meetings","all"]),p=Object.freeze(["none","selected","default"]),v=Object.freeze(["built-in","user","community"]),y=Object.freeze(["references","scripts","assets","templates","examples"]),s=e=>typeof e=="string"&&e.length>0,b=/^[a-z0-9][a-z0-9_-]*$/;function w(e){return!(!s(e)||e.length>255||e!==e.trim()||e.includes("\\")||/[\u0000-\u001f\u007f]/.test(e)||e.startsWith("/")||/^[a-z]:/i.test(e)||e.split("/").some(r=>r===""||r==="."||r===".."))}function f(e){const t=e?.origin;return t&&typeof t=="object"&&s(t.source)&&s(t.id)?t:null}function A(e){return f(e)?"community":e?.builtin?"built-in":"user"}function m(e){const t=e?.files,r={};if(!t||typeof t!="object")return r;for(const o of y){const a=Array.isArray(t[o])?t[o].filter(w):[];a.length&&(r[o]=[...new Set(a)])}return r}function $(e){return(m(e).scripts||[]).length>0}function O(e={}){const t=m(e),r=p.includes(e.mcpMode)?e.mcpMode:"none",o=h.includes(e.context)?e.context:"auto",a=l.includes(e.historyContext)?e.historyContext:"none",i=new Set(Array.isArray(e.reads)?e.reads.filter(c=>u.includes(c)):[]);return o!=="none"&&i.add("page"),(a==="chats"||a==="all")&&i.add("chats"),(a==="meetings"||a==="all")&&i.add("meetings"),{trust:A(e),reads:[...i].sort(),page:o,history:a,mcp:r,mcpServerIds:r==="selected"&&Array.isArray(e.mcpServerIds)?[...e.mcpServerIds]:[],hosts:Array.isArray(e.sandboxHosts)?[...e.sandboxHosts].sort():[],sources:Array.isArray(e.sources)?[...new Set(e.sources.filter(s))].sort():[],surfaces:Array.isArray(e.surfaces)?[...new Set(e.surfaces.filter(s))].sort():[],scripts:t.scripts||[],needsBridge:$(e),meeting:!!e.meeting}}function P(e){const t=f(e);return t?t.id.length>48?`${t.source} · …${t.id.slice(-40)}`:`${t.source} · ${t.id}`:A(e)==="built-in"?"Built-in":"Written here"}function j(e,t){const r=f(e),o=f(t);return!!r&&!!o&&r.source===o.source&&r.id===o.id}function L(e,t){const r=f(e);return!r||!s(r.hash)||!s(t)?null:r.hash!==t}function M(e){if(!e||typeof e!="object")throw new n("SHAPE","skill must be an object");if(!s(e.id))throw new n("SHAPE","skill.id required");if(!s(e.name))throw new n("SHAPE",`skill '${e.id}': name required`);if(e.prompt!=null&&typeof e.prompt!="string")throw new n("SHAPE",`skill '${e.id}': prompt must be a string`);if(e.command!=null&&e.command!==""&&!b.test(String(e.command)))throw new n("SHAPE",`skill '${e.id}': command must match ${b}`);for(const[t,r]of[["context",h],["historyContext",l],["mcpMode",p]])if(e[t]!=null&&!r.includes(e[t]))throw new n("SHAPE",`skill '${e.id}': ${t} must be one of ${r}`);if(e.reads!=null&&(!Array.isArray(e.reads)||!e.reads.every(t=>u.includes(t))))throw new n("SHAPE",`skill '${e.id}': reads must be within ${u}`);for(const t of["sources","surfaces"])if(e[t]!=null&&(!Array.isArray(e[t])||!e[t].every(s)))throw new n("SHAPE",`skill '${e.id}': ${t} must be an array of ids`);if(e.sandboxHosts!=null)try{S({hosts:e.sandboxHosts})}catch(t){throw new n("SHAPE",`skill '${e.id}': sandboxHosts — ${t.message}`)}if(e.origin!=null){const t=e.origin;if(typeof t!="object")throw new n("SHAPE",`skill '${e.id}': origin must be an object`);if(!s(t.source)||!s(t.id))throw new n("ORIGIN",`skill '${e.id}': origin needs both source and id`)}if(e.files!=null){if(typeof e.files!="object")throw new n("SHAPE",`skill '${e.id}': files must be an object`);for(const t of Object.keys(e.files)){if(!y.includes(t))throw new n("FILES",`skill '${e.id}': unknown file kind '${t}'`);const r=e.files[t];if(!Array.isArray(r)||!r.every(s))throw new n("FILES",`skill '${e.id}': files.${t} must be an array of paths`);const o=r.find(a=>!w(a));if(o)throw new n("PATH",`skill '${e.id}': unsafe path in files.${t}: ${JSON.stringify(o)}`)}}if(!f(e)&&(e.files?.scripts||[]).length)throw new n("ORIGIN",`skill '${e.id}': scripts require an origin to be scannable`);return e}const E=Object.freeze({1:e=>({...e,v:d})});function x(e){if(!e||typeof e!="object")throw new n("SHAPE","skill must be an object");let t=typeof e.v=="number"?e:{...e,v:1},r=0;for(;t.v<d;){const o=E[t.v];if(!o)throw new n("UPCAST",`no upcaster from v${t.v}`);if(t=o(t),++r>64)throw new n("UPCAST","upcaster chain did not terminate")}if(t.v>d)throw new n("UPCAST",`skill is v${t.v}; this reader only knows v${d}`);return t}function C(e){return(Array.isArray(e)?e:[]).map(x)}function _(e){if(!e||typeof e!="object")return e;const t={...x(e)};t.enabled=t.enabled!==!1;const r=String(t.mcpMode||"none").toLowerCase();t.mcpMode=p.includes(r)?r:"none";const o=Array.isArray(t.mcpServerIds)?t.mcpServerIds:[];t.mcpServerIds=t.mcpMode==="selected"?[...new Set(o.map(c=>String(c||"").trim()).filter(Boolean))]:[];const a=Array.isArray(t.sandboxHosts)?t.sandboxHosts:g(t.sandboxHosts);t.sandboxHosts=a.filter(c=>{try{return S({hosts:[c]}),!0}catch{return!1}}),t.sandboxHosts.length||delete t.sandboxHosts,delete t.trust;const i=f(t);i?(t.builtin=!1,t.origin={source:i.source,id:i.id,...s(i.url)?{url:i.url}:{},...s(i.hash)?{hash:i.hash}:{},...i.scanned&&typeof i.scanned=="object"?{scanned:{...i.scanned}}:{}}):t.origin!=null&&delete t.origin,t.reads!=null&&(t.reads=[...new Set((Array.isArray(t.reads)?t.reads:[]).filter(c=>u.includes(c)))].sort());for(const c of["sources","surfaces"])t[c]!=null&&(t[c]=[...new Set((Array.isArray(t[c])?t[c]:[]).filter(s))]);if(t.files!=null){const c=m(t);Object.keys(c).length?t.files=c:delete t.files}return t.version!=null&&!s(t.version)&&delete t.version,t}export{h as SKILL_CONTEXTS,y as SKILL_FILE_KINDS,l as SKILL_HISTORY_SCOPES,d as SKILL_MANIFEST_VERSION,p as SKILL_MCP_MODES,v as SKILL_TRUST,E as SKILL_UPCASTERS,n as SkillManifestError,O as declaredAccess,w as isSafeSkillPath,$ as needsBridge,_ as normalizeSkill,P as originLabel,f as originOf,j as sameSkillOrigin,m as skillFiles,L as skillIsStale,A as trustOf,x as upcastSkill,C as upcastSkills,M as validateSkill};
package/skill-runtime.js CHANGED
@@ -1,5 +1,5 @@
1
- import{sourceCitationSystem as g}from"./tool-hints.js";function y(e){const t=String(e||"none").toLowerCase();return t==="chat"||t==="chats"?"chats":t==="meeting"||t==="meetings"?"meetings":t==="all"||t==="both"||t==="history"?"all":"none"}function w(e){const t=String(e||"none").toLowerCase();return t==="none"||t==="off"?"none":t==="selected"||t==="select"?"selected":"default"}function S(e){return(e||[]).filter(t=>t&&t.enabled!==!1&&(t.url||t.command||t.tools?.length))}function b(e){return!!e&&e.enabled!==!1}function d(e){return(Array.isArray(e)?e:[]).filter(b)}function I(e={},{includeMeetings:t=!1}={}){const n=y(e.historyContext);let s=null;if(n!=="none"){const o=n==="meetings"||n==="all",r=o&&!t?"meetings":"";s={enabled:!r,scope:n,includeMeetings:o&&!!t,requested:n,...r?{blocked:r}:{}}}return{skillId:e.id||"",history:s,mcp:{mode:w(e.mcpMode),serverIds:Array.isArray(e.mcpServerIds)?e.mcpServerIds.filter(Boolean):[]},files:C(e),origin:e.origin&&e.origin.source?{source:e.origin.source,id:e.origin.id||""}:null}}function C(e){const t=e?.files;if(!t||typeof t!="object")return[];const n=[];for(const s of["references","assets","templates","examples"])for(const o of Array.isArray(t[s])?t[s]:[])typeof o=="string"&&o&&n.push(`${s}/${o}`);return n.slice(0,60)}function $(e,t){const n=S(e),s=t?.mcp?.mode||"none";if(s==="none")return[];if(s!=="selected")return n;const o=new Set(t?.mcp?.serverIds||[]);return o.size?n.filter(r=>o.has(r.id)):[]}function x(e){const t=(e.tools||[]).map(n=>n.name).filter(Boolean).slice(0,12);return t.length?`${e.name||e.id}: ${t.join(", ")}`:`${e.name||e.id}`}function j(e,t=[]){if(!e)return"";const n=[];if(e.history?.enabled){const s=e.history.scope==="all"?"chat and meeting history":e.history.scope==="meetings"?"meeting history":"chat history";n.push(`This skill has ${s} tools available. Use history_search first when prior local context would improve the answer, then history_get_source or history_related when useful.`)}if(e.history?.blocked==="meetings"&&n.push("Meeting history was requested for this skill, but it is not available for the current plan."),e.files?.length&&n.push(`This skill ships reference files: ${e.files.join(", ")}. Their contents are NOT included above. Call skill_file with one of those exact paths to read one, and only when the task needs it — read the smallest set that answers the question.`),e.mcp?.mode==="none")n.push("MCP tools are disabled for this skill.");else if(e.mcp?.mode==="selected"){const s=$(t,e);s.length?n.push(`This skill is scoped to these MCP servers/tools: ${s.map(x).join(" | ")}. Prefer these tools when they help complete the skill.`):n.push("This skill selected MCP tools, but none of the selected MCP servers are currently enabled.")}return(e.history?.enabled||e.mcp?.mode==="selected"||e.mcp?.mode==="default")&&n.push(g()),n.join(`
2
- `)}function u(e){return String(e?.command||e?.name||"").trim().toLowerCase()}const A=14;function L(e,t){if(!t.size)return 0;const n=`${e.name} ${e.command} ${e.description||""}`.toLowerCase(),s=new Set(n.split(/\W+/).filter(r=>r.length>3));let o=0;for(const r of t)s.has(r)&&(o+=1);return o}function v(e,t=""){const n=d(e),s=new Set(String(t||"").toLowerCase().split(/\W+/).filter(o=>o.length>3));return n.map((o,r)=>({s:o,i:r,score:L(o,s)})).sort((o,r)=>r.score-o.score||o.i-r.i).map(o=>o.s)}const M=(e,t)=>e.length>t?`${e.slice(0,t-1).trimEnd()}…`:e;function P(e,{userText:t="",cap:n=A}={}){const s=d(e),o=v(e,t);if(!o.length)return"";let r=o.slice(0,n);const c=String(t||"").toLowerCase();if(c){const i=o.filter(l=>{const f=u(l),h=String(l.name||"").toLowerCase();return f&&c.includes(f)||h.length>2&&c.includes(h)});for(const l of i)r.includes(l)||(r=[l,...r].slice(0,n))}const a=new Map(s.map((i,l)=>[i,l]));r=[...r].sort((i,l)=>(a.get(i)??0)-(a.get(l)??0));const m=i=>`- ${u(i)||i.name}: ${M(String(i.description||i.name),90)}`,p=o.length>r.length?`
3
- (+${o.length-r.length} more — the user can type /command to run any skill directly.)`:"";return["SKILLS AVAILABLE — reusable procedures the user has set up. If the request clearly matches one, call skill_open with its name to load its full instructions, then follow them. For a simple or unrelated request, answer directly and do not open a skill.",r.map(m).join(`
1
+ import{sourceCitationSystem as g}from"./tool-hints.js";function y(e){const t=String(e||"none").toLowerCase();return t==="chat"||t==="chats"?"chats":t==="meeting"||t==="meetings"?"meetings":t==="all"||t==="both"||t==="history"?"all":"none"}function w(e){const t=String(e||"none").toLowerCase();return t==="none"||t==="off"?"none":t==="selected"||t==="select"?"selected":"default"}function S(e){return(e||[]).filter(t=>t&&t.enabled!==!1&&(t.url||t.command||t.tools?.length))}function b(e){return!!e&&e.enabled!==!1}function d(e){return(Array.isArray(e)?e:[]).filter(b)}function I(e={},{includeMeetings:t=!1}={}){const o=y(e.historyContext);let s=null;if(o!=="none"){const n=o==="meetings"||o==="all",r=n&&!t?"meetings":"";s={enabled:!r,scope:o,includeMeetings:n&&!!t,requested:o,...r?{blocked:r}:{}}}return{skillId:e.id||"",history:s,mcp:{mode:w(e.mcpMode),serverIds:Array.isArray(e.mcpServerIds)?e.mcpServerIds.filter(Boolean):[]},files:C(e),origin:e.origin&&e.origin.source?{source:e.origin.source,id:e.origin.id||""}:null,hosts:Array.isArray(e.sandboxHosts)?e.sandboxHosts.filter(n=>typeof n=="string"&&n):[]}}function C(e){const t=e?.files;if(!t||typeof t!="object")return[];const o=[];for(const s of["references","assets","templates","examples"])for(const n of Array.isArray(t[s])?t[s]:[])typeof n=="string"&&n&&o.push(`${s}/${n}`);return o.slice(0,60)}function x(e,t){const o=S(e),s=t?.mcp?.mode||"none";if(s==="none")return[];if(s!=="selected")return o;const n=new Set(t?.mcp?.serverIds||[]);return n.size?o.filter(r=>n.has(r.id)):[]}function $(e){const t=(e.tools||[]).map(o=>o.name).filter(Boolean).slice(0,12);return t.length?`${e.name||e.id}: ${t.join(", ")}`:`${e.name||e.id}`}function j(e,t=[]){if(!e)return"";const o=[];if(e.history?.enabled){const s=e.history.scope==="all"?"chat and meeting history":e.history.scope==="meetings"?"meeting history":"chat history";o.push(`This skill has ${s} tools available. Use history_search first when prior local context would improve the answer, then history_get_source or history_related when useful.`)}if(e.history?.blocked==="meetings"&&o.push("Meeting history was requested for this skill, but it is not available for the current plan."),e.files?.length&&o.push(`This skill ships reference files: ${e.files.join(", ")}. Their contents are NOT included above. Call skill_file with one of those exact paths to read one, and only when the task needs it — read the smallest set that answers the question.`),e.mcp?.mode==="none")o.push("MCP tools are disabled for this skill.");else if(e.mcp?.mode==="selected"){const s=x(t,e);s.length?o.push(`This skill is scoped to these MCP servers/tools: ${s.map($).join(" | ")}. Prefer these tools when they help complete the skill.`):o.push("This skill selected MCP tools, but none of the selected MCP servers are currently enabled.")}return(e.history?.enabled||e.mcp?.mode==="selected"||e.mcp?.mode==="default")&&o.push(g()),o.join(`
2
+ `)}function u(e){return String(e?.command||e?.name||"").trim().toLowerCase()}const A=14;function L(e,t){if(!t.size)return 0;const o=`${e.name} ${e.command} ${e.description||""}`.toLowerCase(),s=new Set(o.split(/\W+/).filter(r=>r.length>3));let n=0;for(const r of t)s.has(r)&&(n+=1);return n}function v(e,t=""){const o=d(e),s=new Set(String(t||"").toLowerCase().split(/\W+/).filter(n=>n.length>3));return o.map((n,r)=>({s:n,i:r,score:L(n,s)})).sort((n,r)=>r.score-n.score||n.i-r.i).map(n=>n.s)}const M=(e,t)=>e.length>t?`${e.slice(0,t-1).trimEnd()}…`:e;function P(e,{userText:t="",cap:o=A}={}){const s=d(e),n=v(e,t);if(!n.length)return"";let r=n.slice(0,o);const c=String(t||"").toLowerCase();if(c){const i=n.filter(l=>{const f=u(l),h=String(l.name||"").toLowerCase();return f&&c.includes(f)||h.length>2&&c.includes(h)});for(const l of i)r.includes(l)||(r=[l,...r].slice(0,o))}const a=new Map(s.map((i,l)=>[i,l]));r=[...r].sort((i,l)=>(a.get(i)??0)-(a.get(l)??0));const m=i=>`- ${u(i)||i.name}: ${M(String(i.description||i.name),90)}`,p=n.length>r.length?`
3
+ (+${n.length-r.length} more — the user can type /command to run any skill directly.)`:"";return["SKILLS AVAILABLE — reusable procedures the user has set up. If the request clearly matches one, call skill_open with its name to load its full instructions, then follow them. For a simple or unrelated request, answer directly and do not open a skill.",r.map(m).join(`
4
4
  `)+p].join(`
5
- `)}export{d as enabledSkills,$ as filterMcpServersForSkill,b as isSkillEnabled,v as rankSkills,P as skillCatalogSystem,u as skillHandle,C as skillPackageFiles,I as skillRunFromSkill,j as skillToolSystem};
5
+ `)}export{d as enabledSkills,x as filterMcpServersForSkill,b as isSkillEnabled,v as rankSkills,P as skillCatalogSystem,u as skillHandle,C as skillPackageFiles,I as skillRunFromSkill,j as skillToolSystem};
package/source-gate.js CHANGED
@@ -1 +1 @@
1
- import{sourcePolicyFor as f,sourceUrlsOf as a,DEFAULT_INTERNAL_PATTERNS as d}from"./sources.js";import{reachOf as c}from"./model-candidates.js";import{REACH as l,reachRank as o}from"./reach.js";function w(e={}){const t=e||{},r=t.internalPatterns,i=Array.isArray(r)?r:r==null?d:String(r).split(/[\s,]+/);return{enabled:t.internalGuard!==!1,patterns:i.map(s=>String(s||"").trim().toLowerCase()).filter(Boolean),ceiling:t.internalCeiling==="trusted"?"trusted":"device"}}function m(e,t=[]){if(!e||!e.enabled||!t?.length)return null;const r=f(t,{patterns:e.patterns,ceiling:e.ceiling});return r.internal?r:null}function S({policy:e,messages:t=[],sources:r=[],target:i={},label:s=""}={}){const n=m(e,a(t,r));if(!n)return null;const u=l.includes(i?.reach)?i.reach:c(i||{});if(o(u)<=o(n.reach))return null;const h=n.reach==="device"?"stay on this device":"stay inside your workspace";return{blocked:!0,why:n.why,reach:n.reach,message:`Not sent: ${n.why}. "${s||"this model"}" is outside that, and content from an internal source must ${h}. Pick a local model (or run one), or remove this site under Settings → Privacy → Internal sites.`}}const v=e=>/^Not sent: /.test(String(e?.message||e||""));function x(e=[],t=null){return t?(e||[]).filter(r=>o(l.includes(r?.reach)?r.reach:c(r||{}))<=o(t.reach)):e}export{v as isSourceGateError,S as sourceGate,m as sourceGuardFor,w as sourcePolicySettings,a as sourceUrlsOf,x as withinReach};
1
+ import{sourcePolicyFor as m,sourceUrlsOf as s,DEFAULT_INTERNAL_PATTERNS as d}from"./sources.js";import{reachOf as c}from"./model-candidates.js";import{REACH as l,reachRank as i}from"./reach.js";function v(e={}){const t=e||{},r=t.internalPatterns,o=Array.isArray(r)?r:r==null?d:String(r).split(/[\s,]+/);return{enabled:t.internalGuard!==!1,patterns:o.map(a=>String(a||"").trim().toLowerCase()).filter(Boolean),ceiling:t.internalCeiling==="trusted"?"trusted":"device"}}function f(e,t=[]){if(!e||!e.enabled||!t?.length)return null;const r=m(t,{patterns:e.patterns,ceiling:e.ceiling});return r.internal?r:null}function w({policy:e,messages:t=[],sources:r=[],target:o={},label:a=""}={}){const n=f(e,s(t,r));if(!n)return null;const u=l.includes(o?.reach)?o.reach:c(o||{});if(i(u)<=i(n.reach))return null;const h=n.reach==="device"?"stay on this device":"stay inside your workspace";return{blocked:!0,why:n.why,reach:n.reach,message:`Not sent: ${n.why}. "${a||"this model"}" is outside that, and content from an internal source must ${h}. `+(n.hits?.[0]?.matched==="unparseable"?"Fix or remove that link (in the message, or the attachment carrying it), or pick a local model (or run one).":"Pick a local model (or run one), or remove this site under Settings → Privacy → Internal sites.")}}const x=e=>/^Not sent: /.test(String(e?.message||e||""));function S(e=[],t=null){return t?(e||[]).filter(r=>i(l.includes(r?.reach)?r.reach:c(r||{}))<=i(t.reach)):e}export{x as isSourceGateError,w as sourceGate,f as sourceGuardFor,v as sourcePolicySettings,s as sourceUrlsOf,S as withinReach};
package/sources.js CHANGED
@@ -1 +1 @@
1
- const h=["device","trusted","any"];function v(n,r){const t=h.indexOf(n),e=h.indexOf(r);return t<0?h.includes(r)?r:"device":e<0?n:h[Math.min(t,e)]}const x=Object.freeze([{pattern:"localhost",label:"This machine, by name"},{pattern:"127.0.0.0/8",label:"Loopback"},{pattern:"::1",label:"Loopback (IPv6)"},{pattern:"0.0.0.0/8",label:"This network"},{pattern:"10.0.0.0/8",label:"Private network"},{pattern:"172.16.0.0/12",label:"Private network"},{pattern:"192.168.0.0/16",label:"Private network (home / office)"},{pattern:"100.64.0.0/10",label:"Carrier-grade NAT — used by some corporate networks"},{pattern:"169.254.0.0/16",label:"Link-local — never routes off this segment"},{pattern:"fe80::/10",label:"Link-local (IPv6)"},{pattern:"fc00::/7",label:"Unique local (IPv6) — the 10.x of IPv6"},{pattern:"*.internal",label:"Reserved name"},{pattern:"*.intranet",label:"Reserved name"},{pattern:"*.corp",label:"Conventional corporate suffix"},{pattern:"*.lan",label:"Conventional LAN suffix"},{pattern:"*.local",label:"mDNS / Bonjour"},{pattern:"*.localdomain",label:"Default suffix on many routers"},{pattern:"*.home",label:"Home network"},{pattern:"*.home.arpa",label:"Home network (RFC 8375)"},{pattern:"*.private",label:"Conventional private suffix"},{pattern:"*.test",label:"Reserved for testing (RFC 2606)"},{pattern:"*.invalid",label:"Reserved as never-resolvable"},{pattern:"<intranet>",label:"Any bare hostname with no dots, e.g. http://wiki/ — includes localhost"}]),w=Object.freeze(x.map(n=>n.pattern)),g=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;function m(n){const r=g.exec(n);if(!r)return null;const t=r.slice(1).map(Number);return t.some(e=>e>255)?null:t.reduce((e,l)=>e*256+l,0)}function d(n){const r=String(n||"").replace(/^\[|\]$/g,"").toLowerCase();if(!r.includes(":"))return null;const[t,e,...l]=r.split("::");if(l.length)return null;const o=u=>u?u.split(":").filter(p=>p!==""):[];let s=o(t),a=e===void 0?[]:o(e);const i=(a.length?a:s)[Math.max(0,(a.length?a:s).length-1)];if(i&&i.includes(".")){const u=m(i);if(u==null)return null;const p=[(u>>>16).toString(16),(u&65535).toString(16)];a.length?a=[...a.slice(0,-1),...p]:s=[...s.slice(0,-1),...p]}const c=8-s.length-a.length;if(e===void 0?c!==0:c<0)return null;const f=[...s,...Array(Math.max(0,c)).fill("0"),...a];if(f.length!==8)return null;let b="";for(const u of f){if(!/^[0-9a-f]{1,4}$/.test(u))return null;b+=parseInt(u,16).toString(2).padStart(16,"0")}return b}function y(n,r){const[t,e]=r.split("/"),l=d(n),o=d(t);if(l||o){if(!l||!o)return!1;const f=Number(e);return!Number.isFinite(f)||f<0||f>128?!1:l.slice(0,f)===o.slice(0,f)}const s=m(n),a=m(t);if(s==null||a==null)return!1;const i=Number(e);if(!Number.isFinite(i)||i<0||i>32)return!1;const c=i===0?0:-1<<32-i>>>0;return(s&c)>>>0===(a&c)>>>0}function R(n,r){const t=String(n||"").toLowerCase().replace(/\.$/,""),e=String(r||"").toLowerCase().trim();if(!t||!e)return!1;if(e==="<intranet>")return!t.includes(".")&&!t.includes(":")&&!t.startsWith("[")&&!g.test(t);if(e.includes("/"))return y(t,e);const l=d(e);if(l)return d(t)===l;const o=e.startsWith("*.")?e.slice(2):e;return!!(t===o||t.endsWith(`.${o}`))}function k(n,{patterns:r=w}={}){const t=String(n||"").trim();if(!t)return{internal:!1,host:"",matched:null};let e="",l="";try{const o=new URL(t);e=o.hostname,l=o.protocol.replace(":","")}catch{return{internal:!0,host:"",matched:"unparseable"}}if(l==="file")return{internal:!0,host:e,matched:"file:"};if(/^(chrome|edge|about|moz|chrome-extension|data|blob)$/.test(l))return{internal:!1,host:e,matched:null};for(const o of r)if(R(e,o))return{internal:!0,host:e,matched:o};return{internal:!1,host:e,matched:null}}function A(n){const r=[],t=/\b(?:https?|file):\/\/[^\s<>"'`)\]}]+/gi;for(const e of String(n||"").matchAll(t))r.push(e[0].replace(/[.,;:!?]+$/,""));return r}function N(n=[],{patterns:r,ceiling:t="device",base:e="any"}={}){const l=(Array.isArray(n)?n:[n]).filter(Boolean),o=[];for(const a of l){const i=typeof a=="string"?a:a?.url||a?.href||"";if(!i)continue;const c=k(i,r?{patterns:r}:void 0);c.internal&&o.push({url:i,host:c.host,matched:c.matched})}if(!o.length)return{internal:!1,reach:e,hits:[],why:null};const s=h.includes(t)?t:"device";return{internal:!0,reach:v(e,s),hits:o,why:`${o[0].host||"the source"} matches '${o[0].matched}' — kept ${s==="device"?"on this device":"inside your workspace"}`}}function C(n,r=[]){const t=[];for(const e of n||[]){for(const l of e?.attachments||[])l?.url&&t.push(l.url);for(const l of A(typeof e?.content=="string"?e.content:""))t.push(l)}for(const e of r||[])e&&t.push(typeof e=="string"?e:e.url||e.href||"");return t.filter(Boolean)}export{w as DEFAULT_INTERNAL_PATTERNS,x as INTERNAL_PATTERN_CATALOG,k as classifySource,A as extractUrls,R as hostMatches,v as meetReach,N as sourcePolicyFor,C as sourceUrlsOf};
1
+ const p=["device","trusted","any"];function v(r,n){const t=p.indexOf(r),e=p.indexOf(n);return t<0?p.includes(n)?n:"device":e<0?r:p[Math.min(t,e)]}const x=Object.freeze([{pattern:"localhost",label:"This machine, by name"},{pattern:"127.0.0.0/8",label:"Loopback"},{pattern:"::1",label:"Loopback (IPv6)"},{pattern:"0.0.0.0/8",label:"This network"},{pattern:"10.0.0.0/8",label:"Private network"},{pattern:"172.16.0.0/12",label:"Private network"},{pattern:"192.168.0.0/16",label:"Private network (home / office)"},{pattern:"100.64.0.0/10",label:"Carrier-grade NAT — used by some corporate networks"},{pattern:"169.254.0.0/16",label:"Link-local — never routes off this segment"},{pattern:"fe80::/10",label:"Link-local (IPv6)"},{pattern:"fc00::/7",label:"Unique local (IPv6) — the 10.x of IPv6"},{pattern:"*.internal",label:"Reserved name"},{pattern:"*.intranet",label:"Reserved name"},{pattern:"*.corp",label:"Conventional corporate suffix"},{pattern:"*.lan",label:"Conventional LAN suffix"},{pattern:"*.local",label:"mDNS / Bonjour"},{pattern:"*.localdomain",label:"Default suffix on many routers"},{pattern:"*.home",label:"Home network"},{pattern:"*.home.arpa",label:"Home network (RFC 8375)"},{pattern:"*.private",label:"Conventional private suffix"},{pattern:"*.test",label:"Reserved for testing (RFC 2606)"},{pattern:"*.invalid",label:"Reserved as never-resolvable"},{pattern:"<intranet>",label:"Any bare hostname with no dots, e.g. http://wiki/ — includes localhost"}]),w=Object.freeze(x.map(r=>r.pattern)),g=/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/;function b(r){const n=g.exec(r);if(!n)return null;const t=n.slice(1).map(Number);return t.some(e=>e>255)?null:t.reduce((e,l)=>e*256+l,0)}function m(r){const n=String(r||"").replace(/^\[|\]$/g,"").toLowerCase();if(!n.includes(":"))return null;const[t,e,...l]=n.split("::");if(l.length)return null;const a=f=>f?f.split(":").filter(d=>d!==""):[];let i=a(t),o=e===void 0?[]:a(e);const s=(o.length?o:i)[Math.max(0,(o.length?o:i).length-1)];if(s&&s.includes(".")){const f=b(s);if(f==null)return null;const d=[(f>>>16).toString(16),(f&65535).toString(16)];o.length?o=[...o.slice(0,-1),...d]:i=[...i.slice(0,-1),...d]}const u=8-i.length-o.length;if(e===void 0?u!==0:u<0)return null;const c=[...i,...Array(Math.max(0,u)).fill("0"),...o];if(c.length!==8)return null;let h="";for(const f of c){if(!/^[0-9a-f]{1,4}$/.test(f))return null;h+=parseInt(f,16).toString(2).padStart(16,"0")}return h}function y(r,n){const[t,e]=n.split("/"),l=m(r),a=m(t);if(l||a){if(!l||!a)return!1;const c=Number(e);return!Number.isFinite(c)||c<0||c>128?!1:l.slice(0,c)===a.slice(0,c)}const i=b(r),o=b(t);if(i==null||o==null)return!1;const s=Number(e);if(!Number.isFinite(s)||s<0||s>32)return!1;const u=s===0?0:-1<<32-s>>>0;return(i&u)>>>0===(o&u)>>>0}function R(r,n){const t=String(r||"").toLowerCase().replace(/\.$/,""),e=String(n||"").toLowerCase().trim();if(!t||!e)return!1;if(e==="<intranet>")return!t.includes(".")&&!t.includes(":")&&!t.startsWith("[")&&!g.test(t);if(e.includes("/"))return y(t,e);const l=m(e);if(l)return m(t)===l;const a=e.startsWith("*.")?e.slice(2):e;return!!(t===a||t.endsWith(`.${a}`))}function k(r,{patterns:n=w}={}){const t=String(r||"").trim();if(!t)return{internal:!1,host:"",matched:null};let e="",l="";try{const a=new URL(t);e=a.hostname,l=a.protocol.replace(":","")}catch{return{internal:!0,host:"",matched:"unparseable"}}if(l==="file")return{internal:!0,host:e,matched:"file:"};if(/^(chrome|edge|about|moz|chrome-extension|data|blob)$/.test(l))return{internal:!1,host:e,matched:null};for(const a of n)if(R(e,a))return{internal:!0,host:e,matched:a};return{internal:!1,host:e,matched:null}}function A(r){const n=[],t=/\b(?:https?|file):\/\/[^\s<>"'`)\]}]+/gi;for(const e of String(r||"").matchAll(t))n.push(e[0].replace(/[.,;:!?]+$/,""));return n}function C(r=[],{patterns:n,ceiling:t="device",base:e="any"}={}){const l=(Array.isArray(r)?r:[r]).filter(Boolean),a=[];for(const u of l){const c=typeof u=="string"?u:u?.url||u?.href||"";if(!c)continue;const h=k(c,n?{patterns:n}:void 0);h.internal&&a.push({url:c,host:h.host,matched:h.matched})}if(!a.length)return{internal:!1,reach:e,hits:[],why:null};const i=p.includes(t)?t:"device",o=i==="device"?"on this device":"inside your workspace",s=a[0];return{internal:!0,reach:v(e,i),hits:a,why:s.matched==="unparseable"?`"${N(s.url)}" is not a readable address, and an address that cannot be read is kept ${o}`:`${s.host||"the source"} matches '${s.matched}' — kept ${o}`}}function N(r){const n=String(r||"").trim();return n.length>72?`${n.slice(0,69)}…`:n}function L(r,n=[]){const t=[];for(const e of r||[]){for(const l of e?.attachments||[])l?.url&&t.push(l.url);for(const l of A(typeof e?.content=="string"?e.content:""))t.push(l)}for(const e of n||[])e&&t.push(typeof e=="string"?e:e.url||e.href||"");return t.filter(Boolean)}export{w as DEFAULT_INTERNAL_PATTERNS,x as INTERNAL_PATTERN_CATALOG,k as classifySource,A as extractUrls,R as hostMatches,v as meetReach,C as sourcePolicyFor,L as sourceUrlsOf};
package/usage-pricing.js CHANGED
@@ -1 +1 @@
1
- const _=.1,C=1.25,s=[[/claude.*fable.*5|claude.*mythos.*5/,{in:10,out:50}],[/claude.*opus.*4[.-]?[678]/,{in:5,out:25}],[/claude.*opus/,{in:5,out:25}],[/claude.*sonnet/,{in:3,out:15}],[/claude.*haiku/,{in:1,out:5}],[/gpt-4o-mini|o4-mini|gpt-4\.1-mini/,{in:.15,out:.6}],[/gpt-4o|gpt-4\.1(?!-mini)/,{in:2.5,out:10}],[/o3-mini/,{in:1.1,out:4.4}],[/gemini.*flash/,{in:.15,out:.6}],[/gemini.*pro/,{in:1.25,out:5}]];function m(n){const i=String(n||"").toLowerCase();if(!i)return null;for(const[o,e]of s)if(o.test(i))return e;return null}function E({model:n,inputTokens:i=0,outputTokens:o=0,cacheReadTokens:e=0,cacheWriteTokens:a=0,costUsd:r=null,estimated:l=!1}={}){if(r!=null&&Number.isFinite(r))return{usd:r,estimated:l};const t=m(n);if(!t)return{usd:null,estimated:!0};const u=(c,f)=>(Number(c)||0)*f/1e6;return{usd:u(i,t.in)+u(o,t.out)+u(e,t.in*.1)+u(a,t.in*1.25),estimated:l}}function g(n){return n==null||!Number.isFinite(n)?"n/a":n===0?"$0.00":n<.01?"<$0.01":`$${n.toFixed(n<1?4:2)}`}export{E as costFor,g as formatUsd,m as rateFor};
1
+ const _=.1,E=1.25,b=[[/claude.*fable.*5|claude.*mythos.*5/,{in:10,out:50}],[/claude.*opus.*4[.-]?[678]/,{in:5,out:25}],[/claude.*opus/,{in:5,out:25}],[/claude.*sonnet/,{in:3,out:15}],[/claude.*haiku/,{in:1,out:5}],[/gpt-4o-mini|o4-mini|gpt-4\.1-mini/,{in:.15,out:.6,cacheRead:.25,cacheWrite:0}],[/gpt-4o|gpt-4\.1(?!-mini)/,{in:2.5,out:10,cacheRead:.5,cacheWrite:0}],[/o3-mini/,{in:1.1,out:4.4,cacheRead:.5,cacheWrite:0}],[/gemini.*flash/,{in:.15,out:.6,cacheRead:.25,cacheWrite:0}],[/gemini.*pro/,{in:1.25,out:5,cacheRead:.25,cacheWrite:0}]];function h(t){const e=String(t||"").toLowerCase();if(!e)return null;for(const[o,n]of b)if(o.test(e))return n;return null}function a({model:t,inputTokens:e=0,outputTokens:o=0,cacheReadTokens:n=0,cacheWriteTokens:i=0,costUsd:s=null,estimated:r=!1,rate:m=null}={}){if(s!=null&&Number.isFinite(s))return{usd:s,estimated:r};const u=m||h(t);if(!u)return{usd:null,estimated:!0};const c=(f,d)=>(Number(f)||0)*d/1e6;return{usd:c(e,u.in)+c(o,u.out)+c(n,u.in*(u.cacheRead??.1))+c(i,u.in*(u.cacheWrite??1.25)),estimated:r}}const l=Object.freeze(["plan","list","custom"]),A=Object.freeze({plan:"Subscription plan — tokens only, no $",list:"API key — provider list price",custom:"Custom rates per 1M tokens"}),p=t=>t==null||t===""||!Number.isFinite(Number(t))||Number(t)<0?null:Number(t);function R(t,{defaultBasis:e="plan"}={}){const o=l.includes(t?.basis)?t.basis:l.includes(e)?e:"plan";if(o!=="custom")return{basis:o};const n=p(t?.in),i=p(t?.out);return n==null||i==null?{basis:"plan"}:{basis:"custom",in:n,out:i}}function N(t,e,{defaultBasis:o="plan"}={}){const n=R(e,{defaultBasis:o}),i=t||{};if(n.basis==="plan")return{costUsd:null,costBasis:"plan"};if(n.basis==="custom"){const{usd:r}=a({...i,costUsd:null,rate:{in:n.in,out:n.out}});return{costUsd:r,costBasis:"custom"}}const{usd:s}=a(i);return{costUsd:s,costBasis:"list"}}function x(t){return t==null||!Number.isFinite(t)?"n/a":t===0?"$0.00":t<.01?"<$0.01":`$${t.toFixed(t<1?4:2)}`}export{l as PRICING_BASES,A as PRICING_LABELS,a as costFor,x as formatUsd,R as normalizePricing,N as priceUsage,h as rateFor};
package/usage.js CHANGED
@@ -1 +1,2 @@
1
- import{costFor as h}from"./usage-pricing.js";const _=500,a=e=>Number.isFinite(Number(e))?Number(e):0,l=e=>new Date(e).toISOString().slice(0,10);function m(e={}){const t={ts:e.ts||Date.now(),surface:e.surface||"other",sourceId:e.sourceId||null,agentId:e.agentId||null,provider:e.provider||null,model:e.model||null,inputTokens:a(e.inputTokens),outputTokens:a(e.outputTokens),cacheReadTokens:a(e.cacheReadTokens),cacheWriteTokens:a(e.cacheWriteTokens),estimated:!!e.estimated,costUsd:e.costUsd!=null?a(e.costUsd):null};return!t.inputTokens&&!t.outputTokens&&!t.cacheReadTokens&&!t.cacheWriteTokens?null:t}function I(e,s={}){return!e||e.type!=="usage"?null:m({surface:s.surface||"other",sourceId:s.sourceId,agentId:s.agentId,provider:e.provider,model:e.model,inputTokens:e.inputTokens,outputTokens:e.outputTokens,cacheReadTokens:e.cacheReadTokens,cacheWriteTokens:e.cacheWriteTokens,costUsd:e.costUsd,estimated:e.estimated})}function W(e,s={}){return!e||typeof e!="object"?null:m({...s,inputTokens:e.prompt_tokens??e.input_tokens,outputTokens:e.completion_tokens??e.output_tokens,cacheReadTokens:e.prompt_tokens_details?.cached_tokens??e.cache_read_input_tokens,cacheWriteTokens:e.cache_creation_input_tokens,costUsd:e.cost_usd??e.costUsd??null})}function R(e){return`${e.surface}|${e.agentId||"?"}|${e.model||"?"}|${l(e.ts)}`}function g({rollups:e={},log:s=[]}={},t,{ringMax:u=_}={}){if(!t)return{rollups:e,log:s};const d=R(t),n=e[d]||{surface:t.surface,agentId:t.agentId,model:t.model,day:l(t.ts),calls:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,estimatedCalls:0,costUsd:0};return n.calls+=1,n.inputTokens+=t.inputTokens,n.outputTokens+=t.outputTokens,n.cacheReadTokens+=t.cacheReadTokens,n.cacheWriteTokens+=t.cacheWriteTokens,t.estimated&&(n.estimatedCalls+=1),t.costUsd!=null&&(n.costUsd+=t.costUsd),e[d]=n,s.push(t),s.length>u&&s.splice(0,s.length-u),{rollups:e,log:s}}function x(e={},{surface:s,sinceDays:t,groupBy:u="surface",now:d=Date.now()}={}){const n=t?l(d-t*864e5):null,T=new Map,i={calls:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,usd:0,estimated:!1};for(const o of Object.values(e||{})){if(!o||s&&o.surface!==s||n&&o.day<n)continue;const c=u==="model"?o.model||"?":u==="agent"?o.agentId||"?":o.surface||"other",k=T.get(c)||{key:c,calls:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,usd:0,estimated:!1};for(const p of["calls","inputTokens","outputTokens","cacheReadTokens","cacheWriteTokens"])k[p]+=o[p]||0,i[p]+=o[p]||0;const{usd:r,estimated:f}=o.costUsd?{usd:o.costUsd,estimated:o.estimatedCalls>0}:h({model:o.model,inputTokens:o.inputTokens,outputTokens:o.outputTokens,cacheReadTokens:o.cacheReadTokens,cacheWriteTokens:o.cacheWriteTokens,estimated:o.estimatedCalls>0});r!=null&&(k.usd+=r,i.usd+=r),f&&(k.estimated=!0,i.estimated=!0),T.set(c,k)}return{groups:[...T.values()].sort((o,c)=>c.inputTokens+c.outputTokens-(o.inputTokens+o.outputTokens)),total:i}}export{_ as USAGE_RING_MAX,g as applyUsage,l as dayOf,R as rollupKey,x as summarizeUsage,I as usageFromEvent,W as usageFromOpenAi,m as usageRecord};
1
+ import{costFor as W,formatUsd as x}from"./usage-pricing.js";const C=500,B=Object.freeze(["plan","list","custom"]),n=s=>Number.isFinite(Number(s))?Number(s):0,h=s=>new Date(s).toISOString().slice(0,10);function m(s={}){const e={ts:s.ts||Date.now(),surface:s.surface||"other",sourceId:s.sourceId||null,agentId:s.agentId||null,provider:s.provider||null,model:s.model||null,inputTokens:n(s.inputTokens),outputTokens:n(s.outputTokens),cacheReadTokens:n(s.cacheReadTokens),cacheWriteTokens:n(s.cacheWriteTokens),estimated:!!s.estimated,costUsd:s.costUsd!=null?n(s.costUsd):null,costBasis:B.includes(s.costBasis)?s.costBasis:null};return!e.inputTokens&&!e.outputTokens&&!e.cacheReadTokens&&!e.cacheWriteTokens?null:e}function F(s,t={}){return!s||s.type!=="usage"?null:m({surface:t.surface||"other",sourceId:t.sourceId,agentId:t.agentId,provider:s.provider,model:s.model,inputTokens:s.inputTokens,outputTokens:s.outputTokens,cacheReadTokens:s.cacheReadTokens,cacheWriteTokens:s.cacheWriteTokens,costUsd:s.costUsd,costBasis:s.costBasis,estimated:s.estimated})}function O(s,t={}){if(!s||typeof s!="object")return null;const e=n(s.prompt_tokens_details?.cached_tokens??s.cache_read_input_tokens),a=s.prompt_tokens!=null?Math.max(0,n(s.prompt_tokens)-e):n(s.input_tokens);return m({...t,inputTokens:a,outputTokens:s.completion_tokens??s.output_tokens,cacheReadTokens:e,cacheWriteTokens:s.cache_creation_input_tokens,costUsd:s.cost_usd??s.costUsd??null,costBasis:s.cost_basis??s.costBasis??t.costBasis??null})}function b(s){return`${s.surface}|${s.agentId||"?"}|${s.model||"?"}|${h(s.ts)}`}function w({rollups:s={},log:t=[]}={},e,{ringMax:a=C}={}){if(!e)return{rollups:s,log:t};const i=b(e),c=s[i]||{surface:e.surface,agentId:e.agentId,model:e.model,day:h(e.ts),calls:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,estimatedCalls:0,planCalls:0,costUsd:0};return c.calls+=1,e.costBasis==="plan"&&(c.planCalls=(c.planCalls||0)+1),c.inputTokens+=e.inputTokens,c.outputTokens+=e.outputTokens,c.cacheReadTokens+=e.cacheReadTokens,c.cacheWriteTokens+=e.cacheWriteTokens,e.estimated&&(c.estimatedCalls+=1),e.costUsd!=null&&(c.costUsd+=e.costUsd),s[i]=c,t.push(e),t.length>a&&t.splice(0,t.length-a),{rollups:s,log:t}}function j(s={},{surface:t,sinceDays:e,groupBy:a="surface",now:i=Date.now()}={}){const c=e?h(i-e*864e5):null,u=new Map,d={calls:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,planCalls:0,usd:0,estimated:!1};for(const o of Object.values(s||{})){if(!o||t&&o.surface!==t||c&&o.day<c)continue;const p=a==="model"?o.model||"?":a==="agent"?o.agentId||"?":o.surface||"other",k=u.get(p)||{key:p,calls:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheWriteTokens:0,planCalls:0,usd:0,estimated:!1};for(const r of["calls","inputTokens","outputTokens","cacheReadTokens","cacheWriteTokens","planCalls"])k[r]+=o[r]||0,d[r]+=o[r]||0;const R=(o.planCalls||0)>=o.calls,{usd:T,estimated:I}=R?{usd:null,estimated:!1}:o.costUsd?{usd:o.costUsd,estimated:o.estimatedCalls>0}:W({model:o.model,inputTokens:o.inputTokens,outputTokens:o.outputTokens,cacheReadTokens:o.cacheReadTokens,cacheWriteTokens:o.cacheWriteTokens,estimated:o.estimatedCalls>0});T!=null&&(k.usd+=T,d.usd+=T),I&&(k.estimated=!0,d.estimated=!0),u.set(p,k)}const f=o=>(o.plan=o.calls>0&&o.planCalls>=o.calls,o);return{groups:[...u.values()].map(f).sort((o,p)=>p.inputTokens+p.outputTokens-(o.inputTokens+o.outputTokens)),total:f(d)}}const l=s=>s>=1e3?`${(s/1e3).toFixed(1)}k`:String(Math.round(s)),$=(s,t)=>`${t?"≈":""}${s>0&&s<.01?`$${s.toFixed(4)}`:x(s)}`;function U(s){return n(s?.inputTokens)+n(s?.cacheReadTokens)+n(s?.cacheWriteTokens)}const _=s=>s.costBasis!=="plan"&&s.costUsd!=null&&Number.isFinite(s.costUsd);function N(s){if(!s)return"";const t=s.harnessInputTokens!=null?n(s.harnessInputTokens):null,e=U(s),a=n(s.outputTokens);if(!e&&!a&&!t)return"";const i=t??e,c=s.estimated||t!=null,u=_(s)?` · ${$(s.costUsd,!!s.estimated)}`:"";return`${c?"≈":""}${l(i)} in / ${l(a)} out${u}`}function g(s){if(!s)return"";const t=s.harnessInputTokens!=null?n(s.harnessInputTokens):null,e=U(s),a=n(s.outputTokens);if(!e&&!a&&!t)return"";const i=[];t!=null&&(i.push(`≈${l(t)} tokens sent by you (message, prompt, tools)`),e>t&&i.push(`${l(e-t)} the agent's own context (its prompt, tools, history)`));const c=n(s.requests),u=[`${l(e)} in total${c>1?` over ${c} requests`:""}`];return n(s.cacheReadTokens)>0&&u.push(`${l(n(s.cacheReadTokens))} cached`),n(s.cacheWriteTokens)>0&&u.push(`${l(n(s.cacheWriteTokens))} written to cache`),i.push(`${s.estimated?"≈":""}${u.join(" · ")} / ${l(a)} out`),s.costBasis==="plan"?i.push("Subscription plan — no per-token price"):_(s)&&i.push(`${$(s.costUsd,!!s.estimated)} at ${s.costBasis==="custom"?"your rates":"list price"}, on the full count`),i.join(`
2
+ `)}export{B as COST_BASES,C as USAGE_RING_MAX,w as applyUsage,h as dayOf,g as describeTurnUsage,N as formatTurnUsage,U as promptTokensOf,b as rollupKey,j as summarizeUsage,F as usageFromEvent,O as usageFromOpenAi,m as usageRecord};
package/web-search.js CHANGED
@@ -1 +1 @@
1
- const g=Object.freeze([Object.freeze({id:"startpage",name:"Startpage",url:"https://www.startpage.com/sp/search?query=%s",enabled:!0}),Object.freeze({id:"duckduckgo",name:"DuckDuckGo",url:"https://html.duckduckgo.com/html/?q=%s",enabled:!0}),Object.freeze({id:"google",name:"Google",url:"https://www.google.com/search?q=%s",enabled:!1}),Object.freeze({id:"bing",name:"Bing",url:"https://www.bing.com/search?q=%s",enabled:!1})]),h=5;function S(n,r,{assertFetchable:e}={}){const t=String(n||"").trim();if(!/^https:\/\//i.test(t))throw new Error("Search engine URL must start with https://");if(!t.includes("%s")&&!t.includes("{q}"))throw new Error("Search engine URL must contain a %s (or {q}) query placeholder");const s=t.replace(/%s|\{q\}/g,encodeURIComponent(String(r||"").trim()));return typeof e=="function"&&e(s),s}function m(n){try{const r=new URL(n,"https://duckduckgo.com"),e=r.searchParams.get("uddg");if(e)return decodeURIComponent(e);const t=r.searchParams.get("url")||r.searchParams.get("u");return t&&/^https?:/i.test(t)?t:r.href}catch{return String(n||"")}}const d=/(^|\.)(startpage\.com|startmail\.com|startpage\.dev|mojeek\.com|buttondown\.(com|email)|ecosia\.org|duckduckgo\.com|search\.brave\.com|qwant\.com)$/i;function w(n,r=""){const e=String(n||"").toLowerCase();if(!e||d.test(e))return!1;const t=String(r||"").split(".").slice(-2).join(".").toLowerCase();return!(t&&(e===t||e.endsWith(`.${t}`)))}function b(n,{engineHost:r="",limit:e=h,fallback:t=!1}={}){const s=[],c=new Map;for(const o of n||[]){const a=m(o?.href||"");let i;try{i=new URL(a)}catch{continue}if(i.protocol!=="https:"&&i.protocol!=="http:"||!w(i.hostname,r)||t&&o.chrome)continue;const u=String(o?.text||"").replace(/\s+/g," ").trim();if(u.length<6)continue;const p=i.origin+i.pathname;if(c.has(p)){const l=c.get(p);l&&!l.snippet&&u.length>l.title.length+10&&(l.snippet=u);continue}const f={url:a,title:u,snippet:String(o?.snippet||"").replace(/\s+/g," ").trim()};if(c.set(p,f),s.push(f),s.length>=e)break}return s}function k(n,r=8){const e=[],t=new Set;for(const s of n||[])for(const c of s||[]){let o;try{const a=new URL(c.url);o=a.origin+a.pathname}catch{o=c.url}if(!t.has(o)&&(t.add(o),e.push(c),e.length>=r))return e}return e}function R(n=g){const r=(Array.isArray(n)?n:[]).filter(e=>e&&e.url&&!e.retired);return[...r.filter(e=>e.enabled!==!1),...r.filter(e=>e.enabled===!1)]}export{h as RESULTS_PER_ENGINE,g as SEARCH_ENGINES,S as buildSearchUrl,R as engineOrder,w as isResultHost,k as mergeEngineResults,b as pickResults,m as unwrapRedirect};
1
+ import{GATEWAY_ENGINE as g}from"./search-engines.js";const h=Object.freeze([g,Object.freeze({id:"startpage",name:"Startpage",url:"https://www.startpage.com/sp/search?query=%s",enabled:!0}),Object.freeze({id:"duckduckgo",name:"DuckDuckGo",url:"https://html.duckduckgo.com/html/?q=%s",enabled:!0}),Object.freeze({id:"google",name:"Google",url:"https://www.google.com/search?q=%s",enabled:!1}),Object.freeze({id:"bing",name:"Bing",url:"https://www.bing.com/search?q=%s",enabled:!1})]),m=5;function k(n,r,{assertFetchable:t}={}){const e=String(n||"").trim();if(!/^https:\/\//i.test(e))throw new Error("Search engine URL must start with https://");if(!e.includes("%s")&&!e.includes("{q}"))throw new Error("Search engine URL must contain a %s (or {q}) query placeholder");const s=e.replace(/%s|\{q\}/g,encodeURIComponent(String(r||"").trim()));return typeof t=="function"&&t(s),s}function d(n){try{const r=new URL(n,"https://duckduckgo.com"),t=r.searchParams.get("uddg");if(t)return decodeURIComponent(t);const e=r.searchParams.get("url")||r.searchParams.get("u");return e&&/^https?:/i.test(e)?e:r.href}catch{return String(n||"")}}const w=/(^|\.)(startpage\.com|startmail\.com|startpage\.dev|mojeek\.com|buttondown\.(com|email)|ecosia\.org|duckduckgo\.com|search\.brave\.com|qwant\.com)$/i;function S(n,r=""){const t=String(n||"").toLowerCase();if(!t||w.test(t))return!1;const e=String(r||"").split(".").slice(-2).join(".").toLowerCase();return!(e&&(t===e||t.endsWith(`.${e}`)))}function R(n,{engineHost:r="",limit:t=m,fallback:e=!1}={}){const s=[],c=new Map;for(const o of n||[]){const a=d(o?.href||"");let i;try{i=new URL(a)}catch{continue}if(i.protocol!=="https:"&&i.protocol!=="http:"||!S(i.hostname,r)||e&&o.chrome)continue;const u=String(o?.text||"").replace(/\s+/g," ").trim();if(u.length<6)continue;const p=i.origin+i.pathname;if(c.has(p)){const l=c.get(p);l&&!l.snippet&&u.length>l.title.length+10&&(l.snippet=u);continue}const f={url:a,title:u,snippet:String(o?.snippet||"").replace(/\s+/g," ").trim()};if(c.set(p,f),s.push(f),s.length>=t)break}return s}function E(n,r=8){const t=[],e=new Set;for(const s of n||[])for(const c of s||[]){let o;try{const a=new URL(c.url);o=a.origin+a.pathname}catch{o=c.url}if(!e.has(o)&&(e.add(o),t.push(c),t.length>=r))return t}return t}function y(n=h){const r=(Array.isArray(n)?n:[]).filter(t=>t&&(t.url||t.kind==="gateway")&&!t.retired);return[...r.filter(t=>t.enabled!==!1),...r.filter(t=>t.enabled===!1)]}export{m as RESULTS_PER_ENGINE,h as SEARCH_ENGINES,k as buildSearchUrl,y as engineOrder,S as isResultHost,E as mergeEngineResults,R as pickResults,d as unwrapRedirect};