Xenova's picture
Xenova HF Staff
Upload 65 files
ea7122c verified
Raw History Blame Contribute Delete
5.91 kB
// The agent loop for the WebGPU chat bundles. Import { Agent, runAgent } from this file.
var I="The run was stopped before this call ran.",D="The run was stopped while this call ran; it may have partly completed.",F=n=>n instanceof Error?n.message:String(n);function N(){return{prompt_tokens:0,cached_tokens:0,image_tokens:0,completion_tokens:0,reasoning_tokens:0}}function v(n){let e=new Set;return n.map(t=>{if(typeof t?.name!="string"||t.name===""||typeof t.execute!="function")throw new TypeError("each tool must be { name, description?, parameters?, execute(args, context) }");if(e.has(t.name))throw new TypeError(`tool "${t.name}" is offered twice`);return e.add(t.name),{type:"function",function:{name:t.name,...t.description!==void 0?{description:t.description}:{},parameters:t.parameters??{type:"object",properties:{}}}}})}var C=class{#t=[];#s=!1;#n=!1;#r=null;#e=null;#o=null;#a;constructor(e){this.#a=e}attach(){if(this.#s)throw new TypeError("an agent run's events can be iterated once");return this.#s=!0,this.#n=!0,this}emit(e){this.#o||(this.#t.push(e),this.#r?.())}handled(){return!this.#n||this.#t.length===0&&this.#r?Promise.resolve():new Promise(e=>{this.#e=e})}end(e){this.#o=e??{},this.#r?.(),this.#e?.()}async next(){for(;;){let e=this.#t.shift();if(e)return{value:e,done:!1};if(this.#o){if("error"in this.#o)throw this.#o.error;return{value:void 0,done:!0}}await new Promise(t=>{this.#r=t,this.#e?.(),this.#e=null}),this.#r=null}}async return(){return this.#n=!1,this.#e?.(),this.#e=null,this.#o||this.#a(),{value:void 0,done:!0}}},p=class{result;#t=new AbortController;#s=new C(()=>this.cancel());constructor(e,t){let l=()=>{};if(t)if(t.aborted)this.#t.abort(t.reason);else{let s=()=>this.#t.abort(t.reason);t.addEventListener("abort",s,{once:!0}),l=()=>t.removeEventListener("abort",s)}let a=this.#s;this.result=e({emit:s=>a.emit(s),handled:()=>a.handled(),signal:this.#t.signal}).then(s=>(a.end(null),s),s=>{throw a.end({error:s}),s}).finally(l),this.result.catch(()=>{})}cancel(){this.#t.abort(new Error("The agent run was cancelled."))}[Symbol.asyncIterator](){return this.#s.attach()}};function $(n,e,t={}){return O(n,e,t,()=>{})}function O(n,e,t,l){let{tools:a=[],signal:s,max_rounds:g=8,...i}=t;if(!Number.isSafeInteger(g)||g<1)throw new RangeError("max_rounds must be a positive integer");let d=v(a),P=new Map(a.map(r=>[r.name,r])),k=[...e];return new p(async r=>{let A=[],w=o=>{A.push(o),l(o)},T=N(),U=new Map,x="",h=(o,m,u)=>({finish_reason:o,...u?{limit:u}:{},messages:A,content:x,usage:T,rounds:m});for(let o=0;o<g;o++){if(r.signal.aborted)return h("cancelled",o);r.emit({type:"turn_start",round:o});let m=n.generate([...k,...A],{...i,...d.length>0?{tools:d}:{},signal:r.signal});for await(let c of m)r.emit({...c,round:o});let u=await m.result;for(let c of Object.keys(T))T[c]+=u.usage[c]??0;if(u.finish_reason==="cancelled")return r.emit({type:"turn_end",round:o,result:u}),h("cancelled",o+1);if(w(u.message),x=u.message.content,r.emit({type:"turn_end",round:o,result:u}),await r.handled(),u.finish_reason!=="tool_calls")return h(u.finish_reason,o+1,u.limit);let b=u.message.tool_calls??[];for(let[c,y]of b.entries()){if(r.signal.aborted){for(let E of b.slice(c)){let S=M(E,I);w(S),r.emit({type:"tool_end",round:o,call:E,message:S,is_error:!0})}return h("cancelled",o+1)}r.emit({type:"tool_start",round:o,call:y});let f=await L(y,P,U,r.signal),R=M(y,f.content);w(R),r.emit({type:"tool_end",round:o,call:y,message:R,is_error:f.is_error,...f.details!==void 0?{details:f.details}:{}}),await r.handled()}}return h(r.signal.aborted?"cancelled":"max_rounds",g)},s)}function M(n,e){return{role:"tool",tool_call_id:n.id,name:n.function.name,content:e}}async function L(n,e,t,l){if(n.errors?.length)return{content:n.errors.join("; "),is_error:!0};let a=e.get(n.function.name);if(!a)return{content:`No tool named "${n.function.name}" was offered.`,is_error:!0};let s=`${n.function.name} ${JSON.stringify(n.function.arguments)}`,g=t.get(s);if(g!==void 0)return{content:`This exact call already failed: ${g}
Change the call, or tell the user what went wrong.`,is_error:!0};try{let i=await a.execute(n.function.arguments,{signal:l,call:n})??"";if(t.clear(),typeof i=="string"||Array.isArray(i))return{content:i,is_error:!1};let d=i;return{content:d.content,is_error:!1,...d.details!==void 0?{details:d.details}:{}}}catch(i){if(l.aborted)return{content:D,is_error:!0};let d=F(i);return t.set(s,d),{content:d,is_error:!0}}}var _=class{messages;#t;#s;#n=null;#r=!1;#e=null;constructor({model:e,instructions:t,messages:l=[],...a}){this.#t=e,this.#s=a,this.messages=[...t!==void 0?[{role:"system",content:t}]:[],...l]}get#o(){return this.#n?this.#n:("create_session"in this.#t?(this.#n=this.#t.create_session(),this.#r=!0):this.#n=this.#t,this.#n)}get running(){return this.#e!==null}run(e,t={}){if(this.#e)throw new Error("This agent is already running; cancel the run or wait for it.");let l=typeof e=="string"||Array.isArray(e)?{role:"user",content:e}:e,a=!1,s=O(this.#o,[...this.messages,l],{...this.#s,...t},i=>{a=!0,this.messages.push(i)});this.messages.push(l),this.#e=s;let g=()=>{this.#e=null;let i=this.messages.lastIndexOf(l);!a&&i>=0&&this.messages.splice(i,1)};return s.result.then(g,g),s}async prime(e={}){if(this.#e)throw new Error("This agent is already running.");let t=this.messages[0]?.role==="system"?[this.messages[0]]:[],{tools:l=[],max_rounds:a,...s}=this.#s,g=v(l),i=this.#o.generate([...t,{role:"user",content:""}],{...s,...g.length>0?{tools:g}:{},max_new_tokens:1,...e.signal?{signal:e.signal}:{}});for await(let d of i);await i.result}reset(){if(this.#e)throw new Error("This agent is already running.");this.messages.splice(this.messages[0]?.role==="system"?1:0)}async dispose(){let e=this.#e;e&&(e.cancel(),await e.result.catch(()=>{})),this.#r&&await this.#n?.dispose?.(),this.#n=null}};export{_ as Agent,p as AgentRun,v as agentToolSchemas,$ as runAgent};