@lunora/agent 1.0.0-alpha.81 → 1.0.0-alpha.82

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/dist/inbound.mjs CHANGED
@@ -1 +1 @@
1
- import{createInboundEmailHandler as u,parseInboundEmail as d}from"@lunora/mail/inbound";import{h as g,B as l}from"./packem_shared/branch-marker-boZ00zmk.mjs";const m="message could not be processed",c=(t,s)=>{console.error("@lunora/agent/inbound: bouncing message —",s),t.message.setReject(m)},E=t=>{const s=u({dispatch:async(a,n)=>{for(const e of t){const r=e.agent.onEmail;if(!r)continue;const o=await r(a);if(o==null)continue;const i=n.env[e.binding];if(!i||typeof i.create!="function"){c(n,`@lunora/agent: no Workflow binding "${e.binding}" on env for an inbound agent — run codegen/dev so wrangler.jsonc declares it`);return}if(g(o)){c(n,`@lunora/agent: inbound run params ${l}`);return}await i.create({params:o});return}},parse:d,verify:a=>{const{dkim:n,dmarc:e,spf:r}=a.authentication;return e==="pass"||r==="pass"&&n==="pass"}});return async(a,n,e)=>s(a,n,e)};export{E as dispatchAgentEmail};
1
+ import{createInboundEmailHandler as m,parseInboundEmail as f}from"@lunora/mail/inbound";import{h as l,B as p}from"./packem_shared/branch-marker-boZ00zmk.mjs";const g="message could not be processed",d=(o,e)=>{console.error("@lunora/agent/inbound: bouncing message —",e),o.message.setReject(g)},E=/<([^<>]*)>$/,b=o=>{const e=E.exec(o)?.[1]??o,n=e.indexOf("@");if(!(n===-1||n!==e.lastIndexOf("@")))return e.slice(n+1).trim().toLowerCase()},v=o=>{const e=m({dispatch:async(n,r)=>{for(const a of o){const i=a.agent.onEmail;if(!i)continue;const t=await i(n);if(t==null)continue;const s=r.env[a.binding];if(!s||typeof s.create!="function"){d(r,`@lunora/agent: no Workflow binding "${a.binding}" on env for an inbound agent — run codegen/dev so wrangler.jsonc declares it`);return}if(l(t)){d(r,`@lunora/agent: inbound run params ${p}`);return}await s.create({params:t});return}},parse:f,verify:n=>{const{dkim:r,dkimDomain:a,dmarc:i,dmarcDomain:t,spf:s,spfDomain:u}=n.authentication,c=b(n.from);return c===void 0?!1:i==="pass"&&t===c||s==="pass"&&u===c||r==="pass"&&a===c}});return async(n,r,a)=>e(n,r,a)};export{v as dispatchAgentEmail};
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{runAgentLoop as t,splitForCompaction as r}from"./packem_shared/runAgentLoop-oAmn3OyN.mjs";import{collectAgenticMemoryTools as a,toSearchResults as i}from"./packem_shared/collectAgenticMemoryTools-BeMWT2qt.mjs";import{agentAsTool as l}from"./packem_shared/agentAsTool-Xg7YCl5P.mjs";import{codeTool as p}from"./packem_shared/codeTool-DC62JfaY.mjs";import{agentComponent as c,agentExtension as x}from"./component.mjs";import{default as A}from"./packem_shared/createAgentContext-iS35-Xrs.mjs";import{defineAgent as d,defineAgentTool as u,isAgentDefinition as N}from"./packem_shared/defineAgent-YTqqBCP3.mjs";import{functionTool as D}from"./packem_shared/functionTool-D3CP4f8-.mjs";import{createAgentGenerate as M,createEpisodeExtract as O,createGraphExtract as _,createStreamGenerate as C,resolveAgentModel as G}from"./packem_shared/createAgentGenerate-9bZ2YhpN.mjs";import{adaptMcpResult as F,mcpTools as L}from"./packem_shared/adaptMcpResult-CVlq-_TO.mjs";import{buildModelMessages as k}from"./packem_shared/buildModelMessages-Y4tGo1T9.mjs";import{agentBindingName as R,agentClassName as V,agentDefaultName as b,voiceBindingName as h,voiceClassName as w}from"./naming.mjs";import{AGENT_MODULE as I,DEFAULT_AGENT_FUNCTION_PATHS as P,SANDBOX_INVOKE_PATH as X,SANDBOX_MODULE as y,toFunctionReference as K}from"./packem_shared/AGENT_MODULE-M4D1EejI.mjs";import{browserTool as j,containerTool as q,fsTool as z}from"./sandbox.mjs";import{defineSkill as Q,isSkillDefinition as Y}from"./packem_shared/defineSkill-DGGvDWNq.mjs";import{default as $}from"./packem_shared/VoiceSessionDO-DHtOAsd9.mjs";import{r as oe}from"./packem_shared/voice-turn-DhxJgQW1.mjs";import{default as re}from"./packem_shared/compileAgentWorkflow-D4q6vB3j.mjs";export{I as AGENT_MODULE,P as DEFAULT_AGENT_FUNCTION_PATHS,X as SANDBOX_INVOKE_PATH,y as SANDBOX_MODULE,$ as VoiceSessionDO,F as adaptMcpResult,l as agentAsTool,R as agentBindingName,V as agentClassName,c as agentComponent,b as agentDefaultName,x as agentExtension,j as browserTool,k as buildModelMessages,p as codeTool,a as collectAgenticMemoryTools,re as compileAgentWorkflow,q as containerTool,A as createAgentContext,M as createAgentGenerate,O as createEpisodeExtract,_ as createGraphExtract,C as createStreamGenerate,d as defineAgent,u as defineAgentTool,Q as defineSkill,z as fsTool,D as functionTool,N as isAgentDefinition,Y as isSkillDefinition,L as mcpTools,G as resolveAgentModel,t as runAgentLoop,oe as runVoiceTurn,r as splitForCompaction,K as toFunctionReference,i as toSearchResults,h as voiceBindingName,w as voiceClassName};
1
+ import{runAgentLoop as t,splitForCompaction as r}from"./packem_shared/runAgentLoop-H8ILDmGK.mjs";import{collectAgenticMemoryTools as a,toSearchResults as i}from"./packem_shared/collectAgenticMemoryTools-BeMWT2qt.mjs";import{agentAsTool as l}from"./packem_shared/agentAsTool-DyYSy63H.mjs";import{codeTool as p}from"./packem_shared/codeTool-BgpKkQQE.mjs";import{agentComponent as c,agentExtension as x}from"./component.mjs";import{default as A}from"./packem_shared/createAgentContext-iS35-Xrs.mjs";import{defineAgent as d,defineAgentTool as u,isAgentDefinition as N}from"./packem_shared/defineAgent-BziHmnJC.mjs";import{functionTool as D}from"./packem_shared/functionTool-D3CP4f8-.mjs";import{createAgentGenerate as M,createEpisodeExtract as O,createGraphExtract as _,createStreamGenerate as C,resolveAgentModel as G}from"./packem_shared/createAgentGenerate-9bZ2YhpN.mjs";import{adaptMcpResult as F,mcpTools as L}from"./packem_shared/adaptMcpResult-CVlq-_TO.mjs";import{buildModelMessages as k}from"./packem_shared/buildModelMessages-Y4tGo1T9.mjs";import{agentBindingName as R,agentClassName as V,agentDefaultName as b,voiceBindingName as h,voiceClassName as w}from"./naming.mjs";import{AGENT_MODULE as I,DEFAULT_AGENT_FUNCTION_PATHS as P,SANDBOX_INVOKE_PATH as X,SANDBOX_MODULE as y,toFunctionReference as K}from"./packem_shared/AGENT_MODULE-M4D1EejI.mjs";import{browserTool as j,containerTool as q,fsTool as z}from"./sandbox.mjs";import{defineSkill as Q,isSkillDefinition as Y}from"./packem_shared/defineSkill-DGGvDWNq.mjs";import{default as $}from"./packem_shared/VoiceSessionDO-D0XzrCfB.mjs";import{r as oe}from"./packem_shared/voice-turn-KN7l3Edo.mjs";import{default as re}from"./packem_shared/compileAgentWorkflow-C-j_KNs3.mjs";export{I as AGENT_MODULE,P as DEFAULT_AGENT_FUNCTION_PATHS,X as SANDBOX_INVOKE_PATH,y as SANDBOX_MODULE,$ as VoiceSessionDO,F as adaptMcpResult,l as agentAsTool,R as agentBindingName,V as agentClassName,c as agentComponent,b as agentDefaultName,x as agentExtension,j as browserTool,k as buildModelMessages,p as codeTool,a as collectAgenticMemoryTools,re as compileAgentWorkflow,q as containerTool,A as createAgentContext,M as createAgentGenerate,O as createEpisodeExtract,_ as createGraphExtract,C as createStreamGenerate,d as defineAgent,u as defineAgentTool,Q as defineSkill,z as fsTool,D as functionTool,N as isAgentDefinition,Y as isSkillDefinition,L as mcpTools,G as resolveAgentModel,t as runAgentLoop,oe as runVoiceTurn,r as splitForCompaction,K as toFunctionReference,i as toSearchResults,h as voiceBindingName,w as voiceClassName};
@@ -0,0 +1 @@
1
+ import{createAi as S}from"@lunora/ai";import{F as A}from"./createDispatchRunner-pLyQ70FK-2_j6ocGT.mjs";import{t as b}from"./base64-5eyBfWO3.mjs";import{p as T,d as _,a as x,i as f,b as p,c as v,e as E,f as k,r as M,t as w}from"./voice-turn-KN7l3Edo.mjs";import{createStreamGenerate as I,createCompact as R}from"./createAgentGenerate-9bZ2YhpN.mjs";import{DEFAULT_AGENT_FUNCTION_PATHS as C,toFunctionReference as y}from"./AGENT_MODULE-M4D1EejI.mjs";const L="@cf/openai/whisper-large-v3-turbo",N="@cf/deepgram/aura-1",O=8*1024*1024,U=100,l=4e3,m=l*4+1024,B=4002,F=4003,D=4004,z=256*1024,g=15,W=5e3;class V{agent;ai;env;exportName;paths;streamGenerate;sttModel;ttsModel;maxSessionTurns;audioBuffers=new Map;bufferedBytes=new Map;controllers=new Map;state;constructor(e,t,s,r){this.state=e,this.env=t,this.agent=s,this.exportName=r,this.paths=C,this.ai=S({binding:t.AI,env:t}),this.streamGenerate=I(s,t),this.sttModel=s.voice?.stt??L,this.ttsModel=s.voice?.tts??N,this.maxSessionTurns=s.voice?.maxTurns??U}fetch(e){if(e.headers.get("Upgrade")!=="websocket")return new Response("Expected a WebSocket upgrade",{status:426});const s=new URL(e.url).searchParams.get("threadKey");if(!s)return new Response("Missing threadKey",{status:400});const r=globalThis.WebSocketPair,i=new r,n=i[0],o=i[1];this.state.acceptWebSocket(o);const c=crypto.randomUUID(),d=T(e.headers.get("x-lunora-identity")),a=_(e.headers.get("x-lunora-userid")),h=x(e.headers.get("x-lunora-identity-exp"));if(f(h))return p(o),new Response(null,{status:101,webSocket:n});o.serializeAttachment?.({connectionId:c,threadKey:s,turn:0,...h===void 0?{}:{expiresAt:h},...d===void 0?{}:{identity:d},...a===void 0?{}:{userId:a}}),this.send(o,{audioFormat:this.agent.voice?.audioFormat??"mp3",type:"ready"});const u=this.agent.voice?.greeting;return u&&u.length>0&&this.state.waitUntil?.(this.speakGreeting(o,c,s,a,d,u)),new Response(null,{status:101,webSocket:n})}async webSocketMessage(e,t){const s=e.deserializeAttachment?.();if(s){if(f(s.expiresAt)){p(e);return}try{if(typeof t=="string"){await this.handleControl(e,s,t);return}this.bufferAudio(s.connectionId,new Uint8Array(t),e)}catch(r){this.send(e,{message:r instanceof Error?r.message:String(r),type:"error"})}}}webSocketClose(e){this.cleanupSocket(e)}webSocketError(e){this.cleanupSocket(e)}resolveRun(e,t){const s=e===void 0&&t===void 0?void 0:{...t===void 0?{}:{claims:t},...e===void 0?{}:{userId:e}};return A({env:this.env,label:"@lunora/agent voice",...s===void 0?{}:{identity:s}})}async transcribe(e){const t=v(e);return E(await this.ai.run(this.sttModel,{audio:b(t)}))}async synthesize(e,t){const s=this.agent.voice?.speaker;return k(await this.ai.run(this.ttsModel,{text:e,...s===void 0?{}:{speaker:s}},t===void 0?void 0:{signal:t}))}async handleControl(e,t,s){if(s.length>m){this.send(e,{message:`control frame exceeds the maximum of ${String(m)} characters`,type:"error"}),this.closeSocket(e,D,"control_frame_limit");return}let r;try{r=JSON.parse(s)}catch{return}if(r.type==="interrupt"){this.controllers.get(t.connectionId)?.abort();return}if(r.type==="text"&&r.text.length>l){this.send(e,{message:`text frame exceeds the maximum of ${String(l)} characters`,type:"error"});return}if(t.turn>=this.maxSessionTurns){this.send(e,{message:`voice session reached its ${String(this.maxSessionTurns)}-turn limit — reconnect to continue`,type:"error"}),this.closeSocket(e,B,"turn_limit");return}if(this.controllers.has(t.connectionId)){this.send(e,{message:"a turn is already in progress — send an interrupt before the next utterance",type:"error"});return}if(r.type==="commit"){const i=this.drainAudio(t.connectionId);await this.runTurn(e,t,{pcm:i});return}await this.runTurn(e,t,{text:r.text})}bufferAudio(e,t,s){const r=(this.bufferedBytes.get(e)??0)+t.byteLength;if(r>O){this.audioBuffers.delete(e),this.bufferedBytes.delete(e),this.send(s,{message:"utterance exceeded the maximum buffer — send a commit sooner",type:"error"}),this.closeSocket(s,F,"utterance_too_large");return}const i=this.audioBuffers.get(e)??[];i.push(t),this.audioBuffers.set(e,i),this.bufferedBytes.set(e,r)}drainAudio(e){const t=this.audioBuffers.get(e)??[];this.audioBuffers.delete(e),this.bufferedBytes.delete(e);const s=t.reduce((n,o)=>n+o.byteLength,0),r=new Uint8Array(s);let i=0;for(const n of t)r.set(n,i),i+=n.byteLength;return r}async runTurn(e,t,s){const r=new AbortController;this.controllers.set(t.connectionId,r);try{await M({agent:this.agent,compact:R(),connectionId:t.connectionId,env:this.env,exportName:this.exportName,paths:this.paths,run:this.resolveRun(t.userId,t.identity),send:i=>{this.send(e,i)},sendAudio:i=>{this.sendAudio(e,i)},signal:r.signal,streamGenerate:this.streamGenerate,synthesize:async(i,n)=>this.synthesizeWithSignal(i,n),threadKey:t.threadKey,transcribe:async i=>this.transcribe(i),turn:t.turn,waitForDrain:async()=>this.waitForSocketDrain(e),...t.userId===void 0?{}:{owner:t.userId},...s.pcm===void 0?{}:{pcm:s.pcm},...s.text===void 0?{}:{text:s.text}})}finally{this.controllers.get(t.connectionId)===r&&this.controllers.delete(t.connectionId),e.serializeAttachment?.({...t,turn:t.turn+1})}}async speakGreeting(e,t,s,r,i,n){const o=this.resolveRun(r,i),c=new AbortController,d=()=>c.signal.aborted;this.controllers.set(t,c);try{if((await o(y(this.paths.ensureThread),{agent:this.exportName,key:s,...this.agent.initialState===void 0?{}:{initialState:this.agent.initialState},...r===void 0?{}:{owner:r}}))?.outcome!=="created")return;for await(const h of w(await this.synthesizeWithSignal(n,c.signal))){if(d()||(await this.waitForSocketDrain(e),d()))break;this.sendAudio(e,h)}d()||(await o(y(this.paths.appendMessage),{content:n,messageKey:"voice:greeting:assistant",role:"assistant",threadKey:s}),this.send(e,{text:n,type:"assistant_done"}))}catch(a){this.send(e,{message:a instanceof Error?a.message:String(a),type:"error"})}finally{this.controllers.get(t)===c&&this.controllers.delete(t)}}async synthesizeWithSignal(e,t){return t.aborted?new Uint8Array(0):this.synthesize(e,t)}cleanupSocket(e){const t=e.deserializeAttachment?.();t&&(this.controllers.get(t.connectionId)?.abort(),this.controllers.delete(t.connectionId),this.audioBuffers.delete(t.connectionId),this.bufferedBytes.delete(t.connectionId))}closeSocket(e,t,s){try{e.close?.(t,s)}catch{}}send(e,t){try{e.send(JSON.stringify(t))}catch{}}sendAudio(e,t){try{e.send(t)}catch{}}async waitForSocketDrain(e){const t=e;let s=0;for(;typeof t.bufferedAmount=="number"&&t.bufferedAmount>z&&s<W;)await new Promise(r=>{setTimeout(r,g)}),s+=g}}export{V as default};
@@ -0,0 +1 @@
1
+ import{LunoraError as d}from"@lunora/errors";import{jsonSchema as N}from"ai";import{isDuplicateInstanceError as I}from"../channels.mjs";import{agentBindingName as L}from"../naming.mjs";import{toFunctionReference as b,DEFAULT_AGENT_FUNCTION_PATHS as S}from"./AGENT_MODULE-M4D1EejI.mjs";import{i as f}from"./positive-integer-ztHqqpBk.mjs";const $=new Set(["complete","errored","terminated"]),_=120,p=3,P=500,v=t=>t!==null&&typeof t=="object"&&typeof t.status=="string"?t.status:"unknown",M=async t=>{await new Promise(e=>{setTimeout(e,t)})},R=async(t,e,n,u)=>{for(let o=0;o<e;o+=1){const i=v(await t.status());if($.has(i))return i;await u(n)}return"timeout"},D=t=>{for(let e=t.length-1;e>=0;e-=1){const n=t[e];if(n?.role==="assistant"&&(n.toolCalls===void 0||n.toolCalls.length===0))return n.content}return""},O=t=>{if(typeof t.name!="string"||t.name.length===0)throw new d("INTERNAL","@lunora/agent: agent.asTool requires a `name` (the child agent's export name, selecting its AGENT_* binding)");if(typeof t.description!="string"||t.description.length===0)throw new d("INTERNAL","@lunora/agent: agent.asTool requires a non-empty `description` (the parent model decides from it)");if(t.maxPolls!==void 0&&!f(t.maxPolls))throw new d("INTERNAL","@lunora/agent: agent.asTool `maxPolls` must be a positive integer");const{name:e}=t,n=L(e),u=t.maxPolls??_,o=t.pollIntervalMs??P,i=t.wait??M,w=b(S.listMessages),T=async(y,r)=>{const m=(f(r.depth)?r.depth:0)+1;if(m>p)return`Sub-agent "${e}" was not started: the maximum delegation depth of ${String(p)} is already reached. Answer with what you have instead of delegating further.`;const a=r.env[n];if(!a||typeof a.create!="function"||typeof a.get!="function")throw new d("INTERNAL",`@lunora/agent: agent.asTool("${e}") found no Workflow binding "${n}" on env — declare the "${e}" agent so codegen wires its binding`);const g=`${r.threadKey}::sub::${e}::${r.toolCallId}`,h=`sub-${e}-${r.toolCallId}`,A={depth:m,input:y.prompt,threadKey:g};let s;try{const c=await a.create({id:h,params:A});s=await a.get(c.id)}catch(c){if(!I(c))throw c;s=await a.get(h)}const l=await R(s,u,o,i);if(l==="errored"||l==="terminated")return`Sub-agent "${e}" ${l} before producing an answer.`;if(l==="timeout"){try{await s.terminate()}catch{}return`Sub-agent "${e}" did not finish within the allotted time.`}const E=await r.run(w,{key:g});return D(E)};return{description:t.description,execute:T,inputSchema:N({properties:{prompt:{description:"The task or question to delegate to the sub-agent.",type:"string"}},required:["prompt"],type:"object"}),isLunoraAgentTool:!0}};export{O as agentAsTool};
@@ -0,0 +1 @@
1
+ import{LunoraError as a}from"@lunora/errors";import{jsonSchema as A}from"ai";import{i as $}from"./positive-integer-ztHqqpBk.mjs";const b=16,m=4e3,T=e=>{if(e===void 0)return e;const o=typeof e=="string"?e:JSON.stringify(e);return o.length<=m?e:`${o.slice(0,m)}… [truncated]`},g=(e,o)=>{let t=e;for(const s of o.split(".")){if(t===null||typeof t!="object"||!Object.hasOwn(t,s))return;t=t[s]}return t},c=(e,o)=>{if(Array.isArray(e))return e.map(r=>c(r,o));if(e===null||typeof e!="object")return e;const t=e;if(typeof t.$from=="string"){const r=t.$from;if(!(r in o))throw new a("BAD_REQUEST",`@lunora/agent: code step references unknown result "${r}" (define it in an earlier step)`);return typeof t.$path=="string"?g(o[r],t.$path):o[r]}const s={};for(const[r,i]of Object.entries(t))r!=="__proto__"&&(s[r]=c(i,o));return s},v=async(e,o,t,s)=>{const r=Array.isArray(e.steps)?e.steps.slice(0,s):[],i={},p=[],d=new Set;for(const n of r){if(d.has(n.id))throw new a("BAD_REQUEST",`@lunora/agent: duplicate code step id "${n.id}" — each step id must be unique (later steps reference an output by id via $from)`);d.add(n.id)}for(const n of r){const l=o[n.tool];if(!l)throw new a("BAD_REQUEST",`@lunora/agent: code step calls unknown tool "${n.tool}" (available: ${Object.keys(o).join(", ")})`);const y=c(n.input??{},i),f={...t,idempotencyKey:`${t.idempotencyKey}:${n.id}`,toolCallId:`${t.toolCallId}:${n.id}`},h=()=>Promise.resolve(l.execute(y,f)),u=await t.step.do(f.idempotencyKey,h);i[n.id]=u,p.push({id:n.id,output:T(u)})}return{final:p.at(-1)?.output,results:p}},w=e=>`Compose MULTIPLE tool calls in one turn as a script, instead of one call per turn. Provide \`steps\`: an ordered array of \`{ id, tool, input }\`. A later step's \`input\` may reference an earlier step's output with \`{ "$from": "<stepId>", "$path": "optional.dot.path" }\`. Available tools: ${Object.entries(e).map(([o,t])=>`"${o}" — ${t.description}`).join("; ")}.`,S=A({properties:{steps:{description:"Ordered tool calls; a later input may reference an earlier output via { $from, $path }.",items:{additionalProperties:!1,properties:{id:{description:"A name later steps reference this output by.",type:"string"},input:{additionalProperties:!0,description:"The tool input (may embed $from refs).",type:"object"},tool:{description:"The tool to call.",type:"string"}},required:["id","tool"],type:"object"},type:"array"}},required:["steps"],type:"object"}),_=(e,o={})=>{const t=e;if(!t||typeof t!="object"||Object.keys(t).length===0)throw new a("INTERNAL","@lunora/agent: codeTool requires a non-empty map of tools to compose");for(const[r,i]of Object.entries(t))if(i.needsApproval!==void 0&&i.needsApproval!==!1)throw new a("INTERNAL",`@lunora/agent: codeTool cannot compose "${r}" — it has a \`needsApproval\` gate a code-mode script can't pause for. Expose it as a normal top-level tool, or gate the whole script via codeTool's \`needsApproval\`.`);if(o.maxSteps!==void 0&&!$(o.maxSteps))throw new a("INTERNAL","@lunora/agent: codeTool `maxSteps` must be a positive integer");const s=o.maxSteps??b;return{description:o.description??w(e),execute:(r,i)=>v(r,e,i,s),inputSchema:S,isLunoraAgentTool:!0,...o.needsApproval===void 0?{}:{needsApproval:o.needsApproval}}};export{_ as codeTool,c as resolveReferences,v as runToolScript};
@@ -1 +1 @@
1
- import{defineWorkflow as s}from"@lunora/workflow";import{runAgentLoop as m}from"./runAgentLoop-oAmn3OyN.mjs";import{createStreamGenerate as p,createAgentGenerate as l,createEpisodeExtract as f,createGraphExtract as d,createCompact as u}from"./createAgentGenerate-9bZ2YhpN.mjs";import{agentDefaultName as c}from"../naming.mjs";import{DEFAULT_AGENT_FUNCTION_PATHS as A}from"./AGENT_MODULE-M4D1EejI.mjs";import{F as T}from"./createDispatchRunner-pLyQ70FK-2_j6ocGT.mjs";import{otlpTelemetry as y}from"./otlpTelemetry-CywiFp-X.mjs";const E=(r,t,a)=>t===void 0?r:T({env:a,identity:{userId:t},label:"@lunora/agent"}),O=(r,t,a)=>{const e=t.LUNORA_OTLP_ENDPOINT;if(typeof e!="string"||e===""||r.telemetry?.isEnabled===!1)return r;const n=typeof t.LUNORA_OTLP_TOKEN=="string"?t.LUNORA_OTLP_TOKEN:void 0,i=[r.telemetry?.integrations].flat().filter(o=>o!==void 0);return{...r,telemetry:{...r.telemetry,integrations:[...i,y({conversationId:a,endpoint:e,token:n})],isEnabled:!0}}},I=(r,t,a)=>s({handler:async e=>{const n=O(r,e.env,e.params.threadKey);return m({agent:n,compact:u(),env:e.env,exportName:t,extractGraph:d(),extractEpisode:f(),generate:l(n,e.env),instanceId:e.event.instanceId,params:e.params,paths:a?.paths??A,run:E(e.run,e.params.owner,e.env),step:e.step,streamGenerate:p(n,e.env)})},name:r.name??c(t)});export{I as default};
1
+ import{defineWorkflow as s}from"@lunora/workflow";import{runAgentLoop as m}from"./runAgentLoop-H8ILDmGK.mjs";import{createStreamGenerate as p,createAgentGenerate as l,createEpisodeExtract as f,createGraphExtract as d,createCompact as u}from"./createAgentGenerate-9bZ2YhpN.mjs";import{agentDefaultName as c}from"../naming.mjs";import{DEFAULT_AGENT_FUNCTION_PATHS as A}from"./AGENT_MODULE-M4D1EejI.mjs";import{F as T}from"./createDispatchRunner-pLyQ70FK-2_j6ocGT.mjs";import{otlpTelemetry as y}from"./otlpTelemetry-CywiFp-X.mjs";const E=(r,t,a)=>t===void 0?r:T({env:a,identity:{userId:t},label:"@lunora/agent"}),O=(r,t,a)=>{const e=t.LUNORA_OTLP_ENDPOINT;if(typeof e!="string"||e===""||r.telemetry?.isEnabled===!1)return r;const n=typeof t.LUNORA_OTLP_TOKEN=="string"?t.LUNORA_OTLP_TOKEN:void 0,i=[r.telemetry?.integrations].flat().filter(o=>o!==void 0);return{...r,telemetry:{...r.telemetry,integrations:[...i,y({conversationId:a,endpoint:e,token:n})],isEnabled:!0}}},I=(r,t,a)=>s({handler:async e=>{const n=O(r,e.env,e.params.threadKey);return m({agent:n,compact:u(),env:e.env,exportName:t,extractGraph:d(),extractEpisode:f(),generate:l(n,e.env),instanceId:e.event.instanceId,params:e.params,paths:a?.paths??A,run:E(e.run,e.params.owner,e.env),step:e.step,streamGenerate:p(n,e.env)})},name:r.name??c(t)});export{I as default};
@@ -0,0 +1,3 @@
1
+ import{LunoraError as r}from"@lunora/errors";import{collectAgenticMemoryTools as f}from"./collectAgenticMemoryTools-BeMWT2qt.mjs";import{agentAsTool as g}from"./agentAsTool-DyYSy63H.mjs";import{i as m}from"./memory-JI0lUu84.mjs";import{i as c}from"./positive-integer-ztHqqpBk.mjs";import{SKILL_NAME_PATTERN as w,RESERVED_SKILL_NAME as u}from"./defineSkill-DGGvDWNq.mjs";const T=/^[a-zA-Z][\w-]*$/u,p=(e,n)=>{const o={...e.tools};for(const t of n)for(const[s,l]of Object.entries(t.tools??{})){if(Object.hasOwn(o,s))throw new r("INTERNAL",`@lunora/agent: skill "${t.name}" tool "${s}" collides with an existing tool — rename one (the agent's tool namespace is flat)`);o[s]=l}return o},N=(e,n)=>{const o=[];for(const t of[e.instructions,...n.map(s=>s.instructions)])t&&o.push(t);return o.length<=1?o[0]:t=>o.map(s=>typeof s=="function"?s(t):s).filter(s=>s.length>0).join(`
2
+
3
+ `)},k=(e,n)=>{const o=[];e.memory&&m(e.memory)&&o.push({key:"default",...e.memory});for(const t of n)t.knowledge&&m(t.knowledge)&&o.push({key:t.name,...t.knowledge});return o},A=e=>{const n=new Set;for(const o of e){if(typeof o.name!="string"||!w.test(o.name))throw new r("INTERNAL",`@lunora/agent: skill \`name\` must be a valid identifier (letters, digits, _ or -, starting with a letter), got ${JSON.stringify(o.name)}`);if(o.name===u)throw new r("INTERNAL",`@lunora/agent: skill name "${u}" is reserved (it keys the agent's own \`memory\` source / the \`memory:retrieve\` step) — choose another name`);if(n.has(o.name))throw new r("INTERNAL",`@lunora/agent: skill name "${o.name}" is used by more than one skill — rename one (a skill name keys its knowledge memory source, which must be unique)`);n.add(o.name)}},y=(e,n)=>{if(e===void 0)return;const o=Object.keys(n).filter(t=>!e.includes(t));if(o.length>0)throw new r("INTERNAL",`@lunora/agent: \`activeTools\` omits the agentic-memory tool(s) ${o.map(t=>`"${t}"`).join(", ")} — the model could never call them; add them to \`activeTools\` (or drop \`activeTools\` to expose every tool)`)},E=(e,n)=>{const o=(t,s)=>{if(t&&t.kind!=="graph"&&t.kind!=="episodic"&&t.source===void 0)throw new r("INTERNAL",`@lunora/agent: ${s} requires a \`source\` action unless \`kind: "graph"\` or \`kind: "episodic"\``)};o(e.memory,"`memory`");for(const t of n)o(t.knowledge,`skill "${t.name}" \`knowledge\``)},S=e=>{const n=e.model;if(n==null||typeof n=="string"&&n.length===0)throw new r("INTERNAL","@lunora/agent: defineAgent requires a `model` (a Workers AI id, an AI SDK LanguageModel, or an (env) => model thunk)");if(e.maxTurns!==void 0&&!c(e.maxTurns))throw new r("INTERNAL","@lunora/agent: `maxTurns` must be a positive integer");if(e.voice?.maxTurns!==void 0&&!c(e.voice.maxTurns))throw new r("INTERNAL","@lunora/agent: `voice.maxTurns` must be a positive integer");const o=e.skills??[];A(o),E(e,o);const t=p(e,o),s=f(e,o);for(const[i,h]of Object.entries(s)){if(Object.hasOwn(t,i))throw new r("INTERNAL",`@lunora/agent: agentic-memory tool "${i}" collides with an existing tool — rename one (the agent's tool namespace is flat)`);t[i]=h}const l=Object.keys(s).length>0;y(e.activeTools,s);for(const i of Object.keys(t))if(!T.test(i))throw new r("INTERNAL",`@lunora/agent: tool name "${i}" is not a valid identifier (letters, digits, _ or -, starting with a letter)`);const a=k(e,o),d=N(e,o);return{...e,asTool:g,isLunoraAgent:!0,...o.some(i=>!!i.instructions)?{instructions:d}:{},...a.length>0?{memorySources:a}:{},...o.length>0||l?{tools:t}:{}}},O=e=>typeof e=="object"&&e!==null&&e.isLunoraAgent===!0,$=e=>{if(typeof e.execute!="function")throw new r("INTERNAL","@lunora/agent: defineAgentTool requires an `execute` function");if(typeof e.description!="string"||e.description.length===0)throw new r("INTERNAL","@lunora/agent: defineAgentTool requires a non-empty `description` (the model decides from it)");return{...e,isLunoraAgentTool:!0}};export{S as defineAgent,$ as defineAgentTool,O as isAgentDefinition};
@@ -0,0 +1 @@
1
+ const i=e=>Number.isInteger(e)&&e>0;export{i};
@@ -0,0 +1,3 @@
1
+ import{d as J,b as O}from"./component-shared-IZozysYq.mjs";import{resolveAgentModel as Q}from"./createAgentGenerate-9bZ2YhpN.mjs";import{r as Y,f as Z,m as T,a as tt}from"./memory-JI0lUu84.mjs";import{buildModelMessages as F}from"./buildModelMessages-Y4tGo1T9.mjs";import{agentBindingName as q}from"../naming.mjs";import{toFunctionReference as g}from"./AGENT_MODULE-M4D1EejI.mjs";import{i as et}from"./positive-integer-ztHqqpBk.mjs";const ot=8,nt=e=>et(e)?e:0,j=e=>e===void 0?"null":JSON.stringify(e),at=e=>e===void 0?[]:[e].flat(),st=async(e,t)=>(await Promise.all(e.map(async o=>o({steps:t})))).some(Boolean),rt=(e,t)=>{if(t===void 0)return e;if(e===void 0)return{...t};const n={};for(const o of["inputTokens","outputTokens","totalTokens"])(e[o]!==void 0||t[o]!==void 0)&&(n[o]=(e[o]??0)+(t[o]??0));return n},it=async(e,t,n,o,a)=>{const{needsApproval:r}=e;return r===void 0||r===!1?!1:r===!0?!0:n.do(o,async()=>r(t,a))},ct="WorkflowTimeoutError",ut=e=>e instanceof Error&&e.name===ct,P=4320*60*1e3,dt={day:864e5,hour:36e5,minute:6e4,month:30*864e5,second:1e3,week:7*864e5,year:365*864e5},pt=/^(\d+(?:\.\d+)?) (day|hour|minute|month|second|week|year)s?$/u,lt=e=>{if(e===void 0)return P;if(typeof e=="number")return Math.min(e,O);const t=pt.exec(e);return t===null?P:Math.min(Number(t[1])*dt[t[2]],O)},mt=async(e,t)=>{const{agent:n,deleteMessage:o,instanceId:a,patchThread:r,persist:c,step:u}=e;await c({content:`Awaiting approval to run tool "${t.name}".`,messageKey:`${a}:approval:${t.id}`,role:"tool",status:"awaiting_approval",toolCallId:t.id,toolName:t.name}),await r({status:"awaiting_input"});const i=await u.waitForEvent(`approval:${t.id}`,{timeout:lt(n.approvalTimeout),type:`agent-approval:${t.id}`}).then(p=>({decision:p.payload.decision,...p.payload.note===void 0?{}:{note:p.payload.note}})).catch(p=>{if(!ut(p))throw p;return{decision:"reject",note:"approval timed out"}});return await o(`${a}:approval:${t.id}`),await r({status:"running"}),i},yt=async(e,t)=>{const{depth:n,env:o,getState:a,instanceId:r,onTokenDelta:c,persist:u,run:i,setState:p,step:s,threadKey:d,tools:l}=e,m=`tool:${t.name}:${t.id}`,h=l[t.name],f=`${r}:tool:${t.id}`;if(!h){await u({content:`Error: unknown tool "${t.name}"`,messageKey:f,role:"tool",stepName:m,toolCallId:t.id,toolName:t.name});return}const v={depth:n,env:o,getState:a,idempotencyKey:m,reportProgress:R=>{c?.({data:R,kind:"progress",threadKey:d,toolCallId:t.id})},run:i,setState:p,step:s,threadKey:d,toolCallId:t.id},x={depth:n,env:o,getState:a,idempotencyKey:m,run:i,threadKey:d,toolCallId:t.id},S=`tool:approval-gate:${t.id}`;let C;if(await it(h,t.input,s,S,x)){const{decision:R,note:K}=await mt(e,t);if(R==="reject"){const N=K===void 0?"":` Reason: ${K}`;await u({content:`Tool "${t.name}" was rejected by the user and not run.${N}`,messageKey:f,role:"tool",status:"rejected",stepName:m,toolCallId:t.id,toolName:t.name});return}C="approved"}const M=await s.do(m,()=>Promise.resolve(h.execute(t.input,v)));await u({content:typeof M=="string"?M:j(M),messageKey:f,role:"tool",stepName:m,...C===void 0?{}:{status:C},toolCallId:t.id,toolName:t.name})},vt=(e,t,n)=>{if(!t)return e;let{messages:o}=e;return t.messages!==void 0&&(o=t.messages),t.system!==void 0&&(o=[{content:t.system,role:"system"},...o]),{activeTools:t.activeTools??e.activeTools,messages:o,model:t.model===void 0?e.model:Q(t.model,n),toolChoice:t.toolChoice??e.toolChoice}},gt=(e,t)=>{if(t===void 0||e.length<=t.maxMessages)return;const n=Math.max(1,t.keepRecent??Math.ceil(t.maxMessages/2));if(e.length<=n)return;let o=e.length-n;for(;o>0&&e[o]?.role==="tool";)o-=1;if(!(o<=0))return{older:e.slice(0,o),recent:e.slice(o)}},ht=async(e,t)=>{const{agent:n,compact:o,env:a}=e,r=gt(t,n.compaction);if(r===void 0||o===void 0)return{history:t,summary:void 0};try{const c=await o({env:a,messages:F({history:r.older}),model:n.compaction?.model??n.model});return c.length>0?{history:r.recent,summary:c}:{history:t,summary:void 0}}catch{return{history:t,summary:void 0}}},ft=async(e,t,n)=>{const{agent:o,env:a,generate:r,instructions:c,listMessages:u,memoryContext:i,onTokenDelta:p,run:s,step:d,streamGenerate:l,threadKey:m}=e;return d.do(`llm:turn:${String(t)}`,async()=>{const h=await s(u,{key:m}),{history:f,summary:$}=await ht(e,h);let v={activeTools:o.activeTools,messages:F({history:f,instructions:c,memoryContext:i,summary:$}),model:void 0,toolChoice:o.toolChoice};o.prepareStep&&(v=vt(v,await o.prepareStep({messages:v.messages,stepNumber:t,steps:n}),a));const x={messages:v.messages,...v.activeTools===void 0?{}:{activeTools:v.activeTools},...v.model===void 0?{}:{model:v.model},...v.toolChoice===void 0?{}:{toolChoice:v.toolChoice}};return l&&p?l(x,S=>{p({text:S,threadKey:m,turn:t})}):r(x)})},D=async(e,t)=>{const{agent:n,step:o}=e;n.onStepFinish&&await o.do(`agent:step-finish:${String(t.turn)}`,async()=>(await n.onStepFinish?.(t),!0))},wt=e=>({text:e.text,toolCalls:e.toolCalls.map(t=>({input:t.input,toolCallId:t.id,toolName:t.name})),...e.usage===void 0?{}:{usage:e.usage}}),U=e=>{const t=e?.context;return typeof t=="string"&&t.length>0?t:void 0},Tt=e=>J({depth:e?.depth,fanOut:e?.fanOut,maxNodes:e?.maxNodes,maxSeeds:e?.maxSeeds}),xt=async(e,t,n,o)=>{if(e.source===void 0)return;const a=g(e.source),{topK:r}=e,c=T("memory:retrieve",e.key),u=await n.do(c,async()=>o(a,{query:t,...r===void 0?{}:{topK:r}}));return U(u)},St=async(e,t,n,o,a,r)=>{if(n===void 0)return;const c=T("memory:traverse",e.key),u=await a.do(c,async()=>r(o,{owner:n,query:t,...Tt(e.graph)}));return U(u)},Ct=async(e,t,n,o,a)=>{if(t===void 0)return;const r=T("memory:recall",e.key),c={owner:t,...e.episodic?.recall===void 0?{}:{limit:e.episodic.recall}},u=await o.do(r,async()=>a(n,c));return U(u)},Mt=async(e,t)=>e.kind==="episodic"?Ct(e,t.owner,t.episodeRecall,t.step,t.run):e.kind==="graph"?St(e,t.input,t.owner,t.graphTraverse,t.step,t.run):xt(e,t.input,t.step,t.run),Rt=e=>{const t=e.findIndex(n=>n.kind==="episodic");return e.filter((n,o)=>n.kind!=="episodic"||o===t)},kt=async(e,t,n,o,a,r)=>{const c=Rt(Y(e));if(c.length===0)return;const u=g(o.graphTraverse),i=g(o.episodeRecall),p=[];for(const s of c){const d=await Mt(s,{episodeRecall:i,graphTraverse:u,input:t,owner:n,run:r,step:a});d!==void 0&&p.push(d)}return p.length>0?p.join(`
2
+
3
+ `):void 0},$t=async e=>{const{agent:t,env:n,extractGraph:o,finalText:a,input:r,instanceId:c,owner:u,paths:i,run:p,step:s}=e;if(o===void 0||u===void 0||a===void 0||a.length===0)return;const d=Z(t);if(d!==void 0)try{const l={assistantText:a,env:n,model:d.graph?.extractionModel??t.model,userInput:r},m=await s.do(T("memory:extract",d.key),async()=>o(l));await p(g(i.graphUpsert),{...m,messageKey:`${c}:${T("extract",d.key)}`,owner:u})}catch{}},Kt=async e=>{const{agent:t,env:n,extractEpisode:o,finalText:a,input:r,instanceId:c,owner:u,paths:i,run:p,step:s,threadKey:d}=e;if(o===void 0||u===void 0||a===void 0||a.length===0)return;const l=tt(t);if(l!==void 0)try{const m={assistantText:a,env:n,model:l.episodic?.extractionModel??t.model,userInput:r},{summary:h}=await s.do(T("memory:episode",l.key),async()=>o(m));await p(g(i.episodeUpsert),{messageKey:`${c}:${T("episode",l.key)}`,owner:u,summary:h,threadKey:d})}catch{}},Et=async(e,t,n)=>{const o=e[q(t)];if(!(!o||typeof o.get!="function"))try{await(await o.get(n)).terminate()}catch{}},It="12 hours",Nt=async(e,t,n)=>{await e.waitForEvent(`dequeue:${n}`,{timeout:It,type:`agent-dequeue:${t}:${n}`})},At=async(e,t,n)=>{const o=e.env[q(e.exportName)];if(!o||typeof o.get!="function")return;const a=o.get.bind(o);try{await e.step.do(`dequeue-wake:${n}`,async()=>(await(await a(n)).sendEvent({payload:{threadKey:t},type:`agent-dequeue:${t}:${n}`}),n))}catch{}},Ut=async(e,t,n)=>{const{onReply:o}=e,{replyRef:a}=t.params;if(!(o===void 0||a===void 0))try{await t.step.do("agent:reply",async()=>(await o({env:t.env,replyRef:a,result:n,threadKey:t.params.threadKey}),a.channel))}catch{}},_t=async(e,t,n,o,a)=>{const{instanceId:r,persist:c}=e,u=n.usage===void 0?{}:{usage:n.usage};if(n.toolCalls.length===0){const i=n.output!==void 0&&n.text.length===0?j(n.output):n.text;return await c({content:i,messageKey:`${r}:assistant:${String(t)}`,role:"assistant"}),await D(e,{text:n.text,toolCalls:[],turn:t,...u}),{final:{stopped:"final",text:n.text,turns:t+1,...n.output===void 0?{}:{output:n.output}}}}await c({content:n.text,messageKey:`${r}:assistant:${String(t)}`,role:"assistant",toolCalls:n.toolCalls});for(const i of n.toolCalls)await yt(e,i);if(await D(e,{text:n.text,toolCalls:n.toolCalls,turn:t,...u}),o.push(wt(n)),a.length>0&&await st(a,o))return"stopCondition"},Ot=async(e,t,n,o)=>{const a=[];let r,c=!1,u=0;for(let i=0;i<t;i+=1){const p=await ft(e,i,a);o.value=rt(o.value,p.usage),u=i+1;const s=await _t(e,i,p,a,n);if(s==="stopCondition"){c=!0;break}if(s!==void 0){r=s.final;break}}return{final:r,stoppedByCondition:c,turnsRun:u}},Lt=async e=>{const{agent:t,compact:n,env:o,exportName:a,extractEpisode:r,extractGraph:c,generate:u,instanceId:i,onTokenDelta:p,params:s,paths:d,run:l,step:m,streamGenerate:h}=e,f=t.maxTurns??ot,$=at(t.stopWhen),v=g(d.appendMessage),x=g(d.completeRun),S=g(d.ensureThread),C=g(d.listMessages),M=g(d.deleteMessage),R=g(d.patchThread),K=g(d.setState),N=g(d.state),_=async y=>{await l(v,{threadKey:s.threadKey,...y})},B=async y=>{await l(R,{key:s.threadKey,...y})},G=async y=>{await l(M,{messageKey:y,threadKey:s.threadKey})},L=async()=>{await _({content:s.input,messageKey:`${i}:user`,role:"user"})},E=async y=>{const I=await l(x,{instanceId:i,key:s.threadKey,...y});I?.dequeued!==void 0&&await At({env:o,exportName:a,step:m},s.threadKey,I.dequeued)},b=async()=>await l(N,{key:s.threadKey}),W=async y=>{await l(K,{key:s.threadKey,state:y})},A=await l(S,{agent:a,instanceId:i,key:s.threadKey,...t.initialState===void 0?{}:{initialState:t.initialState},...t.onConcurrentRun===void 0?{}:{onConcurrentRun:t.onConcurrentRun},...s.owner===void 0?{}:{owner:s.owner},...s.title===void 0?{}:{title:s.title}});A?.outcome==="replaced"&&await Et(o,a,A.priorInstanceId);const z=await kt(t,s.input,s.owner,d,m,l),H=typeof t.instructions=="function"?t.instructions({env:o,input:s.input,threadKey:s.threadKey}):t.instructions,V={agent:t,compact:n,depth:nt(s.depth),env:o,generate:u,getState:b,instanceId:i,instructions:H,listMessages:C,memoryContext:z,onTokenDelta:p,deleteMessage:G,patchThread:B,persist:_,run:l,setState:W,step:m,streamGenerate:h,threadKey:s.threadKey,tools:t.tools??{}},k={value:void 0};try{A?.outcome==="queued"&&await Nt(m,s.threadKey,i),await L();const{final:y,stoppedByCondition:I,turnsRun:X}=await Ot(V,f,$,k),w=k.value===void 0?{}:{usage:k.value};return await $t({agent:t,env:o,extractGraph:c,finalText:y?.text,input:s.input,instanceId:i,owner:s.owner,paths:d,run:l,step:m}),await Kt({agent:t,env:o,extractEpisode:r,finalText:y?.text,input:s.input,instanceId:i,owner:s.owner,paths:d,run:l,step:m,threadKey:s.threadKey}),y?(await Ut(t,{env:o,params:s,step:m},{...y,...w}),await E({status:"idle",...w}),{...y,...w}):I?(await E({status:"idle",...w}),{stopped:"stopCondition",turns:X,...w}):(await E({error:`agent stopped: maxTurns (${String(f)}) reached`,status:"error",...w}),{stopped:"maxTurns",turns:f,...w})}catch(y){throw await E({error:y instanceof Error?y.message:String(y),status:"error",...k.value===void 0?{}:{usage:k.value}}),y}};export{ht as compactHistory,Lt as runAgentLoop,gt as splitForCompaction};
@@ -1 +1 @@
1
- import"./base64-5eyBfWO3.mjs";import{p as s,c as p,f as m,e as n,r as c,t as d}from"./voice-turn-DhxJgQW1.mjs";import"./runAgentLoop-oAmn3OyN.mjs";import"./buildModelMessages-Y4tGo1T9.mjs";import"./AGENT_MODULE-M4D1EejI.mjs";export{s as parseIdentity,p as pcmToWav,m as readSynthesisAudio,n as readTranscriptionText,c as runVoiceTurn,d as toByteIterable};
1
+ import"./base64-5eyBfWO3.mjs";import{p as s,c as p,f as m,e as n,r as c,t as d}from"./voice-turn-KN7l3Edo.mjs";import"./runAgentLoop-H8ILDmGK.mjs";import"./buildModelMessages-Y4tGo1T9.mjs";import"./AGENT_MODULE-M4D1EejI.mjs";export{s as parseIdentity,p as pcmToWav,m as readSynthesisAudio,n as readTranscriptionText,c as runVoiceTurn,d as toByteIterable};
@@ -1 +1 @@
1
- import{f as P,a as q}from"./base64-5eyBfWO3.mjs";import{compactHistory as z}from"./runAgentLoop-oAmn3OyN.mjs";import{buildModelMessages as G}from"./buildModelMessages-Y4tGo1T9.mjs";import{toFunctionReference as T}from"./AGENT_MODULE-M4D1EejI.mjs";const D=new TextDecoder;new TextEncoder;const N="=",Q=t=>{if(t)try{const e=t[0]==="{"?t:D.decode(P(t)),n=JSON.parse(e);if(n&&typeof n=="object"&&!Array.isArray(n))return n}catch{}},ct=t=>{if(t){if(!t.startsWith(N))return t;try{return D.decode(P(t.slice(N.length)))}catch{return}}},dt=t=>{const e=Number(t);return Number.isFinite(e)&&e>0?e:void 0},ut=t=>typeof t=="number"&&Date.now()>=t,ft=t=>{try{t.send(JSON.stringify({code:"TOKEN_EXPIRED",error:{code:"TOKEN_EXPIRED",message:"authentication token expired"},type:"error"})),t.close?.(4001,"token_expired")}catch{}},Y=16e3,Z=1,tt=16,M=/[.!?]\s/u,et=/\s/u,nt=async function*(t){if(t instanceof Uint8Array){yield t;return}if(t instanceof ReadableStream){const e=t.getReader();try{for(;;){const{done:n,value:r}=await e.read();if(n)break;yield r}}finally{e.releaseLock()}return}yield*t},yt=(t,e=Y,n=Z,r=tt)=>{const i=n*r/8,p=e*i,m=new ArrayBuffer(44+t.byteLength),s=new DataView(m),u=(l,E)=>{for(let d=0;d<E.length;d+=1)s.setUint8(l+d,E.codePointAt(d)??0)};u(0,"RIFF"),s.setUint32(4,36+t.byteLength,!0),u(8,"WAVE"),u(12,"fmt "),s.setUint32(16,16,!0),s.setUint16(20,1,!0),s.setUint16(22,n,!0),s.setUint32(24,e,!0),s.setUint32(28,p,!0),s.setUint16(32,i,!0),s.setUint16(34,r,!0),u(36,"data"),s.setUint32(40,t.byteLength,!0);const a=new Uint8Array(m);return a.set(t,44),a},st=t=>{const e=[];let n=t,r=M.exec(n);for(;r;){let i=r.index+1;for(;i<n.length&&et.test(n[i]??"");)i+=1;const p=n.slice(0,i).trim();p.length>0&&e.push(p),n=n.slice(i),r=M.exec(n)}return{rest:n,sentences:e}},pt=async t=>{const{agent:e,compact:n,connectionId:r,env:i,exportName:p,owner:m,paths:s,pcm:u,run:a,send:l,sendAudio:E,signal:d,streamGenerate:C,synthesize:H,text:L,threadKey:o,transcribe:F,turn:U,waitForDrain:O}=t,h=()=>d.aborted,v=T(s.appendMessage),$=T(s.ensureThread),B=T(s.listMessages),b=T(s.patchThread);await a($,{agent:p,key:o,...e.initialState===void 0?{}:{initialState:e.initialState},...m===void 0?{}:{owner:m}});try{const f=(L??(u?await F(u):"")).trim();if(f.length===0)return await a(b,{key:o,status:"idle"}),{assistantText:"",interrupted:!1,userText:""};l({text:f,type:"user_transcript"}),await a(v,{content:f,messageKey:`voice:${r}:${String(U)}:user`,role:"user",threadKey:o}),await a(b,{key:o,status:"running"});const I=typeof e.instructions=="function"?e.instructions({env:i,input:f,threadKey:o}):e.instructions,K=await a(B,{key:o}),{history:j,summary:R}=await z({agent:e,compact:n,env:i},K),W=G({history:j,...I===void 0?{}:{instructions:I},...R===void 0?{}:{summary:R}});let g="",w="",S=Promise.resolve();const V=async c=>{if(h()||c.length===0)return;let x=!1;try{for await(const y of nt(await H(c,d))){if(h()||(await O?.(),h()))break;E(y),x=!0}}catch(y){l({message:y instanceof Error?y.message:String(y),type:"error"})}x&&(w=w.length>0?`${w} ${c}`:c)},_=c=>{S=S.then(async()=>V(c))},X=await C({messages:W,signal:d},c=>{if(h())return;l({text:c,type:"assistant_delta"}),g+=c;const{rest:x,sentences:y}=st(g);g=x;for(const J of y)_(J)});!h()&&g.trim().length>0&&_(g.trim()),g="",await S;const A=h(),k=A?w:X.text;return await a(v,{content:k,messageKey:`voice:${r}:${String(U)}:assistant`,role:"assistant",threadKey:o}),await a(b,{key:o,status:"idle"}),l(A?{type:"interrupted"}:{text:k,type:"assistant_done"}),{assistantText:k,interrupted:A,userText:f}}catch(f){throw await a(b,{key:o,status:"idle"}),f}},lt=t=>Q(t),ht=t=>{if(typeof t=="object"&&t!==null&&"text"in t){const{text:e}=t;return typeof e=="string"?e:""}return""},gt=t=>{if(t instanceof Uint8Array||t instanceof ReadableStream)return t;if(t instanceof Response&&t.body)return t.body;if(typeof t=="object"&&t!==null&&"audio"in t){const{audio:e}=t;if(typeof e=="string")return q(e);if(e instanceof ReadableStream||e instanceof Uint8Array)return e}return new Uint8Array(0)};export{dt as a,ft as b,yt as c,ct as d,ht as e,gt as f,ut as i,lt as p,pt as r,nt as t};
1
+ import{f as P,a as q}from"./base64-5eyBfWO3.mjs";import{compactHistory as z}from"./runAgentLoop-H8ILDmGK.mjs";import{buildModelMessages as G}from"./buildModelMessages-Y4tGo1T9.mjs";import{toFunctionReference as T}from"./AGENT_MODULE-M4D1EejI.mjs";const D=new TextDecoder;new TextEncoder;const N="=",Q=t=>{if(t)try{const e=t[0]==="{"?t:D.decode(P(t)),n=JSON.parse(e);if(n&&typeof n=="object"&&!Array.isArray(n))return n}catch{}},ct=t=>{if(t){if(!t.startsWith(N))return t;try{return D.decode(P(t.slice(N.length)))}catch{return}}},dt=t=>{const e=Number(t);return Number.isFinite(e)&&e>0?e:void 0},ut=t=>typeof t=="number"&&Date.now()>=t,ft=t=>{try{t.send(JSON.stringify({code:"TOKEN_EXPIRED",error:{code:"TOKEN_EXPIRED",message:"authentication token expired"},type:"error"})),t.close?.(4001,"token_expired")}catch{}},Y=16e3,Z=1,tt=16,M=/[.!?]\s/u,et=/\s/u,nt=async function*(t){if(t instanceof Uint8Array){yield t;return}if(t instanceof ReadableStream){const e=t.getReader();try{for(;;){const{done:n,value:r}=await e.read();if(n)break;yield r}}finally{e.releaseLock()}return}yield*t},yt=(t,e=Y,n=Z,r=tt)=>{const i=n*r/8,p=e*i,m=new ArrayBuffer(44+t.byteLength),s=new DataView(m),u=(l,E)=>{for(let d=0;d<E.length;d+=1)s.setUint8(l+d,E.codePointAt(d)??0)};u(0,"RIFF"),s.setUint32(4,36+t.byteLength,!0),u(8,"WAVE"),u(12,"fmt "),s.setUint32(16,16,!0),s.setUint16(20,1,!0),s.setUint16(22,n,!0),s.setUint32(24,e,!0),s.setUint32(28,p,!0),s.setUint16(32,i,!0),s.setUint16(34,r,!0),u(36,"data"),s.setUint32(40,t.byteLength,!0);const a=new Uint8Array(m);return a.set(t,44),a},st=t=>{const e=[];let n=t,r=M.exec(n);for(;r;){let i=r.index+1;for(;i<n.length&&et.test(n[i]??"");)i+=1;const p=n.slice(0,i).trim();p.length>0&&e.push(p),n=n.slice(i),r=M.exec(n)}return{rest:n,sentences:e}},pt=async t=>{const{agent:e,compact:n,connectionId:r,env:i,exportName:p,owner:m,paths:s,pcm:u,run:a,send:l,sendAudio:E,signal:d,streamGenerate:C,synthesize:H,text:L,threadKey:o,transcribe:F,turn:U,waitForDrain:O}=t,h=()=>d.aborted,v=T(s.appendMessage),$=T(s.ensureThread),B=T(s.listMessages),b=T(s.patchThread);await a($,{agent:p,key:o,...e.initialState===void 0?{}:{initialState:e.initialState},...m===void 0?{}:{owner:m}});try{const f=(L??(u?await F(u):"")).trim();if(f.length===0)return await a(b,{key:o,status:"idle"}),{assistantText:"",interrupted:!1,userText:""};l({text:f,type:"user_transcript"}),await a(v,{content:f,messageKey:`voice:${r}:${String(U)}:user`,role:"user",threadKey:o}),await a(b,{key:o,status:"running"});const I=typeof e.instructions=="function"?e.instructions({env:i,input:f,threadKey:o}):e.instructions,K=await a(B,{key:o}),{history:j,summary:R}=await z({agent:e,compact:n,env:i},K),W=G({history:j,...I===void 0?{}:{instructions:I},...R===void 0?{}:{summary:R}});let g="",w="",S=Promise.resolve();const V=async c=>{if(h()||c.length===0)return;let x=!1;try{for await(const y of nt(await H(c,d))){if(h()||(await O?.(),h()))break;E(y),x=!0}}catch(y){l({message:y instanceof Error?y.message:String(y),type:"error"})}x&&(w=w.length>0?`${w} ${c}`:c)},_=c=>{S=S.then(async()=>V(c))},X=await C({messages:W,signal:d},c=>{if(h())return;l({text:c,type:"assistant_delta"}),g+=c;const{rest:x,sentences:y}=st(g);g=x;for(const J of y)_(J)});!h()&&g.trim().length>0&&_(g.trim()),g="",await S;const A=h(),k=A?w:X.text;return await a(v,{content:k,messageKey:`voice:${r}:${String(U)}:assistant`,role:"assistant",threadKey:o}),await a(b,{key:o,status:"idle"}),l(A?{type:"interrupted"}:{text:k,type:"assistant_done"}),{assistantText:k,interrupted:A,userText:f}}catch(f){throw await a(b,{key:o,status:"idle"}),f}},lt=t=>Q(t),ht=t=>{if(typeof t=="object"&&t!==null&&"text"in t){const{text:e}=t;return typeof e=="string"?e:""}return""},gt=t=>{if(t instanceof Uint8Array||t instanceof ReadableStream)return t;if(t instanceof Response&&t.body)return t.body;if(typeof t=="object"&&t!==null&&"audio"in t){const{audio:e}=t;if(typeof e=="string")return q(e);if(e instanceof ReadableStream||e instanceof Uint8Array)return e}return new Uint8Array(0)};export{dt as a,ft as b,yt as c,ct as d,ht as e,gt as f,ut as i,lt as p,pt as r,nt as t};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunora/agent",
3
- "version": "1.0.0-alpha.81",
3
+ "version": "1.0.0-alpha.82",
4
4
  "description": "Durable AI agents for Lunora: defineAgent compiles a replay-safe tool-loop onto Cloudflare Workflows, with DO SQLite threads and live message subscriptions",
5
5
  "keywords": [
6
6
  "agent",
@@ -86,7 +86,7 @@
86
86
  "dependencies": {
87
87
  "@lunora/ai": "1.0.0-alpha.69",
88
88
  "@lunora/errors": "1.0.0-alpha.29",
89
- "@lunora/mail": "1.0.0-alpha.59",
89
+ "@lunora/mail": "1.0.0-alpha.60",
90
90
  "@lunora/server": "1.0.0-alpha.99",
91
91
  "@lunora/values": "1.0.0-alpha.37",
92
92
  "@lunora/workflow": "1.0.0-alpha.42",
@@ -1 +0,0 @@
1
- import{createAi as S}from"@lunora/ai";import{F as A}from"./createDispatchRunner-pLyQ70FK-2_j6ocGT.mjs";import{t as b}from"./base64-5eyBfWO3.mjs";import{p as T,d as _,a as x,i as f,b as p,c as v,e as E,f as k,r as M,t as w}from"./voice-turn-DhxJgQW1.mjs";import{createStreamGenerate as I,createCompact as R}from"./createAgentGenerate-9bZ2YhpN.mjs";import{DEFAULT_AGENT_FUNCTION_PATHS as C,toFunctionReference as y}from"./AGENT_MODULE-M4D1EejI.mjs";const L="@cf/openai/whisper-large-v3-turbo",N="@cf/deepgram/aura-1",O=8*1024*1024,U=100,l=4e3,m=l*4+1024,B=4002,F=4003,D=4004,z=256*1024,g=15,W=5e3;class V{agent;ai;env;exportName;paths;streamGenerate;sttModel;ttsModel;maxSessionTurns;audioBuffers=new Map;bufferedBytes=new Map;controllers=new Map;state;constructor(e,t,s,r){this.state=e,this.env=t,this.agent=s,this.exportName=r,this.paths=C,this.ai=S({binding:t.AI,env:t}),this.streamGenerate=I(s,t),this.sttModel=s.voice?.stt??L,this.ttsModel=s.voice?.tts??N;const i=s.voice?.maxTurns;this.maxSessionTurns=Number.isInteger(i)&&i>0?i:U}fetch(e){if(e.headers.get("Upgrade")!=="websocket")return new Response("Expected a WebSocket upgrade",{status:426});const s=new URL(e.url).searchParams.get("threadKey");if(!s)return new Response("Missing threadKey",{status:400});const r=globalThis.WebSocketPair,i=new r,n=i[0],o=i[1];this.state.acceptWebSocket(o);const c=crypto.randomUUID(),d=T(e.headers.get("x-lunora-identity")),a=_(e.headers.get("x-lunora-userid")),h=x(e.headers.get("x-lunora-identity-exp"));if(f(h))return p(o),new Response(null,{status:101,webSocket:n});o.serializeAttachment?.({connectionId:c,threadKey:s,turn:0,...h===void 0?{}:{expiresAt:h},...d===void 0?{}:{identity:d},...a===void 0?{}:{userId:a}}),this.send(o,{audioFormat:this.agent.voice?.audioFormat??"mp3",type:"ready"});const u=this.agent.voice?.greeting;return u&&u.length>0&&this.state.waitUntil?.(this.speakGreeting(o,c,s,a,d,u)),new Response(null,{status:101,webSocket:n})}async webSocketMessage(e,t){const s=e.deserializeAttachment?.();if(s){if(f(s.expiresAt)){p(e);return}try{if(typeof t=="string"){await this.handleControl(e,s,t);return}this.bufferAudio(s.connectionId,new Uint8Array(t),e)}catch(r){this.send(e,{message:r instanceof Error?r.message:String(r),type:"error"})}}}webSocketClose(e){this.cleanupSocket(e)}webSocketError(e){this.cleanupSocket(e)}resolveRun(e,t){const s=e===void 0&&t===void 0?void 0:{...t===void 0?{}:{claims:t},...e===void 0?{}:{userId:e}};return A({env:this.env,label:"@lunora/agent voice",...s===void 0?{}:{identity:s}})}async transcribe(e){const t=v(e);return E(await this.ai.run(this.sttModel,{audio:b(t)}))}async synthesize(e,t){const s=this.agent.voice?.speaker;return k(await this.ai.run(this.ttsModel,{text:e,...s===void 0?{}:{speaker:s}},t===void 0?void 0:{signal:t}))}async handleControl(e,t,s){if(s.length>m){this.send(e,{message:`control frame exceeds the maximum of ${String(m)} characters`,type:"error"}),this.closeSocket(e,D,"control_frame_limit");return}let r;try{r=JSON.parse(s)}catch{return}if(r.type==="interrupt"){this.controllers.get(t.connectionId)?.abort();return}if(r.type==="text"&&r.text.length>l){this.send(e,{message:`text frame exceeds the maximum of ${String(l)} characters`,type:"error"});return}if(t.turn>=this.maxSessionTurns){this.send(e,{message:`voice session reached its ${String(this.maxSessionTurns)}-turn limit — reconnect to continue`,type:"error"}),this.closeSocket(e,B,"turn_limit");return}if(this.controllers.has(t.connectionId)){this.send(e,{message:"a turn is already in progress — send an interrupt before the next utterance",type:"error"});return}if(r.type==="commit"){const i=this.drainAudio(t.connectionId);await this.runTurn(e,t,{pcm:i});return}await this.runTurn(e,t,{text:r.text})}bufferAudio(e,t,s){const r=(this.bufferedBytes.get(e)??0)+t.byteLength;if(r>O){this.audioBuffers.delete(e),this.bufferedBytes.delete(e),this.send(s,{message:"utterance exceeded the maximum buffer — send a commit sooner",type:"error"}),this.closeSocket(s,F,"utterance_too_large");return}const i=this.audioBuffers.get(e)??[];i.push(t),this.audioBuffers.set(e,i),this.bufferedBytes.set(e,r)}drainAudio(e){const t=this.audioBuffers.get(e)??[];this.audioBuffers.delete(e),this.bufferedBytes.delete(e);const s=t.reduce((n,o)=>n+o.byteLength,0),r=new Uint8Array(s);let i=0;for(const n of t)r.set(n,i),i+=n.byteLength;return r}async runTurn(e,t,s){const r=new AbortController;this.controllers.set(t.connectionId,r);try{await M({agent:this.agent,compact:R(),connectionId:t.connectionId,env:this.env,exportName:this.exportName,paths:this.paths,run:this.resolveRun(t.userId,t.identity),send:i=>{this.send(e,i)},sendAudio:i=>{this.sendAudio(e,i)},signal:r.signal,streamGenerate:this.streamGenerate,synthesize:async(i,n)=>this.synthesizeWithSignal(i,n),threadKey:t.threadKey,transcribe:async i=>this.transcribe(i),turn:t.turn,waitForDrain:async()=>this.waitForSocketDrain(e),...t.userId===void 0?{}:{owner:t.userId},...s.pcm===void 0?{}:{pcm:s.pcm},...s.text===void 0?{}:{text:s.text}})}finally{this.controllers.get(t.connectionId)===r&&this.controllers.delete(t.connectionId),e.serializeAttachment?.({...t,turn:t.turn+1})}}async speakGreeting(e,t,s,r,i,n){const o=this.resolveRun(r,i),c=new AbortController,d=()=>c.signal.aborted;this.controllers.set(t,c);try{if((await o(y(this.paths.ensureThread),{agent:this.exportName,key:s,...this.agent.initialState===void 0?{}:{initialState:this.agent.initialState},...r===void 0?{}:{owner:r}}))?.outcome!=="created")return;for await(const h of w(await this.synthesizeWithSignal(n,c.signal))){if(d()||(await this.waitForSocketDrain(e),d()))break;this.sendAudio(e,h)}d()||(await o(y(this.paths.appendMessage),{content:n,messageKey:"voice:greeting:assistant",role:"assistant",threadKey:s}),this.send(e,{text:n,type:"assistant_done"}))}catch(a){this.send(e,{message:a instanceof Error?a.message:String(a),type:"error"})}finally{this.controllers.get(t)===c&&this.controllers.delete(t)}}async synthesizeWithSignal(e,t){return t.aborted?new Uint8Array(0):this.synthesize(e,t)}cleanupSocket(e){const t=e.deserializeAttachment?.();t&&(this.controllers.get(t.connectionId)?.abort(),this.controllers.delete(t.connectionId),this.audioBuffers.delete(t.connectionId),this.bufferedBytes.delete(t.connectionId))}closeSocket(e,t,s){try{e.close?.(t,s)}catch{}}send(e,t){try{e.send(JSON.stringify(t))}catch{}}sendAudio(e,t){try{e.send(t)}catch{}}async waitForSocketDrain(e){const t=e;let s=0;for(;typeof t.bufferedAmount=="number"&&t.bufferedAmount>z&&s<W;)await new Promise(r=>{setTimeout(r,g)}),s+=g}}export{V as default};
@@ -1 +0,0 @@
1
- import{LunoraError as d}from"@lunora/errors";import{jsonSchema as N}from"ai";import{isDuplicateInstanceError as b}from"../channels.mjs";import{agentBindingName as E}from"../naming.mjs";import{toFunctionReference as I,DEFAULT_AGENT_FUNCTION_PATHS as L}from"./AGENT_MODULE-M4D1EejI.mjs";const S=new Set(["complete","errored","terminated"]),$=120,f=3,_=500,P=t=>t!==null&&typeof t=="object"&&typeof t.status=="string"?t.status:"unknown",v=async t=>{await new Promise(e=>{setTimeout(e,t)})},M=async(t,e,n,u)=>{for(let o=0;o<e;o+=1){const i=P(await t.status());if(S.has(i))return i;await u(n)}return"timeout"},R=t=>{for(let e=t.length-1;e>=0;e-=1){const n=t[e];if(n?.role==="assistant"&&(n.toolCalls===void 0||n.toolCalls.length===0))return n.content}return""},k=t=>{if(typeof t.name!="string"||t.name.length===0)throw new d("INTERNAL","@lunora/agent: agent.asTool requires a `name` (the child agent's export name, selecting its AGENT_* binding)");if(typeof t.description!="string"||t.description.length===0)throw new d("INTERNAL","@lunora/agent: agent.asTool requires a non-empty `description` (the parent model decides from it)");if(t.maxPolls!==void 0&&(!Number.isInteger(t.maxPolls)||t.maxPolls<1))throw new d("INTERNAL","@lunora/agent: agent.asTool `maxPolls` must be a positive integer");const{name:e}=t,n=E(e),u=t.maxPolls??$,o=t.pollIntervalMs??_,i=t.wait??v,p=I(L.listMessages),w=async(T,r)=>{const m=(Number.isInteger(r.depth)?r.depth:0)+1;if(m>f)return`Sub-agent "${e}" was not started: the maximum delegation depth of ${String(f)} is already reached. Answer with what you have instead of delegating further.`;const a=r.env[n];if(!a||typeof a.create!="function"||typeof a.get!="function")throw new d("INTERNAL",`@lunora/agent: agent.asTool("${e}") found no Workflow binding "${n}" on env — declare the "${e}" agent so codegen wires its binding`);const g=`${r.threadKey}::sub::${e}::${r.toolCallId}`,h=`sub-${e}-${r.toolCallId}`,y={depth:m,input:T.prompt,threadKey:g};let s;try{const c=await a.create({id:h,params:y});s=await a.get(c.id)}catch(c){if(!b(c))throw c;s=await a.get(h)}const l=await M(s,u,o,i);if(l==="errored"||l==="terminated")return`Sub-agent "${e}" ${l} before producing an answer.`;if(l==="timeout"){try{await s.terminate()}catch{}return`Sub-agent "${e}" did not finish within the allotted time.`}const A=await r.run(p,{key:g});return R(A)};return{description:t.description,execute:w,inputSchema:N({properties:{prompt:{description:"The task or question to delegate to the sub-agent.",type:"string"}},required:["prompt"],type:"object"}),isLunoraAgentTool:!0}};export{k as agentAsTool};
@@ -1 +0,0 @@
1
- import{LunoraError as a}from"@lunora/errors";import{jsonSchema as A}from"ai";const b=16,m=4e3,$=e=>{if(e===void 0)return e;const o=typeof e=="string"?e:JSON.stringify(e);return o.length<=m?e:`${o.slice(0,m)}… [truncated]`},T=(e,o)=>{let t=e;for(const s of o.split(".")){if(t===null||typeof t!="object"||!Object.hasOwn(t,s))return;t=t[s]}return t},c=(e,o)=>{if(Array.isArray(e))return e.map(r=>c(r,o));if(e===null||typeof e!="object")return e;const t=e;if(typeof t.$from=="string"){const r=t.$from;if(!(r in o))throw new a("BAD_REQUEST",`@lunora/agent: code step references unknown result "${r}" (define it in an earlier step)`);return typeof t.$path=="string"?T(o[r],t.$path):o[r]}const s={};for(const[r,i]of Object.entries(t))r!=="__proto__"&&(s[r]=c(i,o));return s},g=async(e,o,t,s)=>{const r=Array.isArray(e.steps)?e.steps.slice(0,s):[],i={},p=[],d=new Set;for(const n of r){if(d.has(n.id))throw new a("BAD_REQUEST",`@lunora/agent: duplicate code step id "${n.id}" — each step id must be unique (later steps reference an output by id via $from)`);d.add(n.id)}for(const n of r){const l=o[n.tool];if(!l)throw new a("BAD_REQUEST",`@lunora/agent: code step calls unknown tool "${n.tool}" (available: ${Object.keys(o).join(", ")})`);const y=c(n.input??{},i),f={...t,idempotencyKey:`${t.idempotencyKey}:${n.id}`,toolCallId:`${t.toolCallId}:${n.id}`},h=()=>Promise.resolve(l.execute(y,f)),u=await t.step.do(f.idempotencyKey,h);i[n.id]=u,p.push({id:n.id,output:$(u)})}return{final:p.at(-1)?.output,results:p}},S=e=>`Compose MULTIPLE tool calls in one turn as a script, instead of one call per turn. Provide \`steps\`: an ordered array of \`{ id, tool, input }\`. A later step's \`input\` may reference an earlier step's output with \`{ "$from": "<stepId>", "$path": "optional.dot.path" }\`. Available tools: ${Object.entries(e).map(([o,t])=>`"${o}" — ${t.description}`).join("; ")}.`,v=A({properties:{steps:{description:"Ordered tool calls; a later input may reference an earlier output via { $from, $path }.",items:{additionalProperties:!1,properties:{id:{description:"A name later steps reference this output by.",type:"string"},input:{additionalProperties:!0,description:"The tool input (may embed $from refs).",type:"object"},tool:{description:"The tool to call.",type:"string"}},required:["id","tool"],type:"object"},type:"array"}},required:["steps"],type:"object"}),j=(e,o={})=>{const t=e;if(!t||typeof t!="object"||Object.keys(t).length===0)throw new a("INTERNAL","@lunora/agent: codeTool requires a non-empty map of tools to compose");for(const[r,i]of Object.entries(t))if(i.needsApproval!==void 0&&i.needsApproval!==!1)throw new a("INTERNAL",`@lunora/agent: codeTool cannot compose "${r}" — it has a \`needsApproval\` gate a code-mode script can't pause for. Expose it as a normal top-level tool, or gate the whole script via codeTool's \`needsApproval\`.`);if(o.maxSteps!==void 0&&(!Number.isInteger(o.maxSteps)||o.maxSteps<1))throw new a("INTERNAL","@lunora/agent: codeTool `maxSteps` must be a positive integer");const s=o.maxSteps??b;return{description:o.description??S(e),execute:(r,i)=>g(r,e,i,s),inputSchema:v,isLunoraAgentTool:!0,...o.needsApproval===void 0?{}:{needsApproval:o.needsApproval}}};export{j as codeTool,c as resolveReferences,g as runToolScript};
@@ -1,3 +0,0 @@
1
- import{LunoraError as r}from"@lunora/errors";import{collectAgenticMemoryTools as h}from"./collectAgenticMemoryTools-BeMWT2qt.mjs";import{agentAsTool as f}from"./agentAsTool-Xg7YCl5P.mjs";import{i as m}from"./memory-JI0lUu84.mjs";import{SKILL_NAME_PATTERN as g,RESERVED_SKILL_NAME as c}from"./defineSkill-DGGvDWNq.mjs";const w=/^[a-zA-Z][\w-]*$/u,p=(e,n)=>{const o={...e.tools};for(const t of n)for(const[s,l]of Object.entries(t.tools??{})){if(Object.hasOwn(o,s))throw new r("INTERNAL",`@lunora/agent: skill "${t.name}" tool "${s}" collides with an existing tool — rename one (the agent's tool namespace is flat)`);o[s]=l}return o},T=(e,n)=>{const o=[];for(const t of[e.instructions,...n.map(s=>s.instructions)])t&&o.push(t);return o.length<=1?o[0]:t=>o.map(s=>typeof s=="function"?s(t):s).filter(s=>s.length>0).join(`
2
-
3
- `)},k=(e,n)=>{const o=[];e.memory&&m(e.memory)&&o.push({key:"default",...e.memory});for(const t of n)t.knowledge&&m(t.knowledge)&&o.push({key:t.name,...t.knowledge});return o},N=e=>{const n=new Set;for(const o of e){if(typeof o.name!="string"||!g.test(o.name))throw new r("INTERNAL",`@lunora/agent: skill \`name\` must be a valid identifier (letters, digits, _ or -, starting with a letter), got ${JSON.stringify(o.name)}`);if(o.name===c)throw new r("INTERNAL",`@lunora/agent: skill name "${c}" is reserved (it keys the agent's own \`memory\` source / the \`memory:retrieve\` step) — choose another name`);if(n.has(o.name))throw new r("INTERNAL",`@lunora/agent: skill name "${o.name}" is used by more than one skill — rename one (a skill name keys its knowledge memory source, which must be unique)`);n.add(o.name)}},A=(e,n)=>{if(e===void 0)return;const o=Object.keys(n).filter(t=>!e.includes(t));if(o.length>0)throw new r("INTERNAL",`@lunora/agent: \`activeTools\` omits the agentic-memory tool(s) ${o.map(t=>`"${t}"`).join(", ")} — the model could never call them; add them to \`activeTools\` (or drop \`activeTools\` to expose every tool)`)},y=(e,n)=>{const o=(t,s)=>{if(t&&t.kind!=="graph"&&t.kind!=="episodic"&&t.source===void 0)throw new r("INTERNAL",`@lunora/agent: ${s} requires a \`source\` action unless \`kind: "graph"\` or \`kind: "episodic"\``)};o(e.memory,"`memory`");for(const t of n)o(t.knowledge,`skill "${t.name}" \`knowledge\``)},v=e=>{const n=e.model;if(n==null||typeof n=="string"&&n.length===0)throw new r("INTERNAL","@lunora/agent: defineAgent requires a `model` (a Workers AI id, an AI SDK LanguageModel, or an (env) => model thunk)");if(e.maxTurns!==void 0&&(!Number.isInteger(e.maxTurns)||e.maxTurns<1))throw new r("INTERNAL","@lunora/agent: `maxTurns` must be a positive integer");const o=e.skills??[];N(o),y(e,o);const t=p(e,o),s=h(e,o);for(const[i,d]of Object.entries(s)){if(Object.hasOwn(t,i))throw new r("INTERNAL",`@lunora/agent: agentic-memory tool "${i}" collides with an existing tool — rename one (the agent's tool namespace is flat)`);t[i]=d}const l=Object.keys(s).length>0;A(e.activeTools,s);for(const i of Object.keys(t))if(!w.test(i))throw new r("INTERNAL",`@lunora/agent: tool name "${i}" is not a valid identifier (letters, digits, _ or -, starting with a letter)`);const a=k(e,o),u=T(e,o);return{...e,asTool:f,isLunoraAgent:!0,...o.some(i=>!!i.instructions)?{instructions:u}:{},...a.length>0?{memorySources:a}:{},...o.length>0||l?{tools:t}:{}}},S=e=>typeof e=="object"&&e!==null&&e.isLunoraAgent===!0,O=e=>{if(typeof e.execute!="function")throw new r("INTERNAL","@lunora/agent: defineAgentTool requires an `execute` function");if(typeof e.description!="string"||e.description.length===0)throw new r("INTERNAL","@lunora/agent: defineAgentTool requires a non-empty `description` (the model decides from it)");return{...e,isLunoraAgentTool:!0}};export{v as defineAgent,O as defineAgentTool,S as isAgentDefinition};
@@ -1,3 +0,0 @@
1
- import{d as J,b as O}from"./component-shared-IZozysYq.mjs";import{resolveAgentModel as Q}from"./createAgentGenerate-9bZ2YhpN.mjs";import{r as Y,f as Z,m as T,a as tt}from"./memory-JI0lUu84.mjs";import{buildModelMessages as F}from"./buildModelMessages-Y4tGo1T9.mjs";import{agentBindingName as q}from"../naming.mjs";import{toFunctionReference as g}from"./AGENT_MODULE-M4D1EejI.mjs";const et=8,ot=e=>Number.isInteger(e)&&e>0?e:0,j=e=>e===void 0?"null":JSON.stringify(e),nt=e=>e===void 0?[]:[e].flat(),at=async(e,t)=>(await Promise.all(e.map(async o=>o({steps:t})))).some(Boolean),st=(e,t)=>{if(t===void 0)return e;if(e===void 0)return{...t};const n={};for(const o of["inputTokens","outputTokens","totalTokens"])(e[o]!==void 0||t[o]!==void 0)&&(n[o]=(e[o]??0)+(t[o]??0));return n},rt=async(e,t,n,o,a)=>{const{needsApproval:r}=e;return r===void 0||r===!1?!1:r===!0?!0:n.do(o,async()=>r(t,a))},it="WorkflowTimeoutError",ct=e=>e instanceof Error&&e.name===it,P=4320*60*1e3,ut={day:864e5,hour:36e5,minute:6e4,month:30*864e5,second:1e3,week:7*864e5,year:365*864e5},dt=/^(\d+(?:\.\d+)?) (day|hour|minute|month|second|week|year)s?$/u,pt=e=>{if(e===void 0)return P;if(typeof e=="number")return Math.min(e,O);const t=dt.exec(e);return t===null?P:Math.min(Number(t[1])*ut[t[2]],O)},lt=async(e,t)=>{const{agent:n,deleteMessage:o,instanceId:a,patchThread:r,persist:c,step:u}=e;await c({content:`Awaiting approval to run tool "${t.name}".`,messageKey:`${a}:approval:${t.id}`,role:"tool",status:"awaiting_approval",toolCallId:t.id,toolName:t.name}),await r({status:"awaiting_input"});const i=await u.waitForEvent(`approval:${t.id}`,{timeout:pt(n.approvalTimeout),type:`agent-approval:${t.id}`}).then(p=>({decision:p.payload.decision,...p.payload.note===void 0?{}:{note:p.payload.note}})).catch(p=>{if(!ct(p))throw p;return{decision:"reject",note:"approval timed out"}});return await o(`${a}:approval:${t.id}`),await r({status:"running"}),i},mt=async(e,t)=>{const{depth:n,env:o,getState:a,instanceId:r,onTokenDelta:c,persist:u,run:i,setState:p,step:s,threadKey:d,tools:l}=e,m=`tool:${t.name}:${t.id}`,h=l[t.name],f=`${r}:tool:${t.id}`;if(!h){await u({content:`Error: unknown tool "${t.name}"`,messageKey:f,role:"tool",stepName:m,toolCallId:t.id,toolName:t.name});return}const v={depth:n,env:o,getState:a,idempotencyKey:m,reportProgress:R=>{c?.({data:R,kind:"progress",threadKey:d,toolCallId:t.id})},run:i,setState:p,step:s,threadKey:d,toolCallId:t.id},x={depth:n,env:o,getState:a,idempotencyKey:m,run:i,threadKey:d,toolCallId:t.id},S=`tool:approval-gate:${t.id}`;let C;if(await rt(h,t.input,s,S,x)){const{decision:R,note:K}=await lt(e,t);if(R==="reject"){const I=K===void 0?"":` Reason: ${K}`;await u({content:`Tool "${t.name}" was rejected by the user and not run.${I}`,messageKey:f,role:"tool",status:"rejected",stepName:m,toolCallId:t.id,toolName:t.name});return}C="approved"}const M=await s.do(m,()=>Promise.resolve(h.execute(t.input,v)));await u({content:typeof M=="string"?M:j(M),messageKey:f,role:"tool",stepName:m,...C===void 0?{}:{status:C},toolCallId:t.id,toolName:t.name})},yt=(e,t,n)=>{if(!t)return e;let{messages:o}=e;return t.messages!==void 0&&(o=t.messages),t.system!==void 0&&(o=[{content:t.system,role:"system"},...o]),{activeTools:t.activeTools??e.activeTools,messages:o,model:t.model===void 0?e.model:Q(t.model,n),toolChoice:t.toolChoice??e.toolChoice}},vt=(e,t)=>{if(t===void 0||e.length<=t.maxMessages)return;const n=Math.max(1,t.keepRecent??Math.ceil(t.maxMessages/2));if(e.length<=n)return;let o=e.length-n;for(;o>0&&e[o]?.role==="tool";)o-=1;if(!(o<=0))return{older:e.slice(0,o),recent:e.slice(o)}},gt=async(e,t)=>{const{agent:n,compact:o,env:a}=e,r=vt(t,n.compaction);if(r===void 0||o===void 0)return{history:t,summary:void 0};try{const c=await o({env:a,messages:F({history:r.older}),model:n.compaction?.model??n.model});return c.length>0?{history:r.recent,summary:c}:{history:t,summary:void 0}}catch{return{history:t,summary:void 0}}},ht=async(e,t,n)=>{const{agent:o,env:a,generate:r,instructions:c,listMessages:u,memoryContext:i,onTokenDelta:p,run:s,step:d,streamGenerate:l,threadKey:m}=e;return d.do(`llm:turn:${String(t)}`,async()=>{const h=await s(u,{key:m}),{history:f,summary:$}=await gt(e,h);let v={activeTools:o.activeTools,messages:F({history:f,instructions:c,memoryContext:i,summary:$}),model:void 0,toolChoice:o.toolChoice};o.prepareStep&&(v=yt(v,await o.prepareStep({messages:v.messages,stepNumber:t,steps:n}),a));const x={messages:v.messages,...v.activeTools===void 0?{}:{activeTools:v.activeTools},...v.model===void 0?{}:{model:v.model},...v.toolChoice===void 0?{}:{toolChoice:v.toolChoice}};return l&&p?l(x,S=>{p({text:S,threadKey:m,turn:t})}):r(x)})},D=async(e,t)=>{const{agent:n,step:o}=e;n.onStepFinish&&await o.do(`agent:step-finish:${String(t.turn)}`,async()=>(await n.onStepFinish?.(t),!0))},ft=e=>({text:e.text,toolCalls:e.toolCalls.map(t=>({input:t.input,toolCallId:t.id,toolName:t.name})),...e.usage===void 0?{}:{usage:e.usage}}),U=e=>{const t=e?.context;return typeof t=="string"&&t.length>0?t:void 0},wt=e=>J({depth:e?.depth,fanOut:e?.fanOut,maxNodes:e?.maxNodes,maxSeeds:e?.maxSeeds}),Tt=async(e,t,n,o)=>{if(e.source===void 0)return;const a=g(e.source),{topK:r}=e,c=T("memory:retrieve",e.key),u=await n.do(c,async()=>o(a,{query:t,...r===void 0?{}:{topK:r}}));return U(u)},xt=async(e,t,n,o,a,r)=>{if(n===void 0)return;const c=T("memory:traverse",e.key),u=await a.do(c,async()=>r(o,{owner:n,query:t,...wt(e.graph)}));return U(u)},St=async(e,t,n,o,a)=>{if(t===void 0)return;const r=T("memory:recall",e.key),c={owner:t,...e.episodic?.recall===void 0?{}:{limit:e.episodic.recall}},u=await o.do(r,async()=>a(n,c));return U(u)},Ct=async(e,t)=>e.kind==="episodic"?St(e,t.owner,t.episodeRecall,t.step,t.run):e.kind==="graph"?xt(e,t.input,t.owner,t.graphTraverse,t.step,t.run):Tt(e,t.input,t.step,t.run),Mt=e=>{const t=e.findIndex(n=>n.kind==="episodic");return e.filter((n,o)=>n.kind!=="episodic"||o===t)},Rt=async(e,t,n,o,a,r)=>{const c=Mt(Y(e));if(c.length===0)return;const u=g(o.graphTraverse),i=g(o.episodeRecall),p=[];for(const s of c){const d=await Ct(s,{episodeRecall:i,graphTraverse:u,input:t,owner:n,run:r,step:a});d!==void 0&&p.push(d)}return p.length>0?p.join(`
2
-
3
- `):void 0},kt=async e=>{const{agent:t,env:n,extractGraph:o,finalText:a,input:r,instanceId:c,owner:u,paths:i,run:p,step:s}=e;if(o===void 0||u===void 0||a===void 0||a.length===0)return;const d=Z(t);if(d!==void 0)try{const l={assistantText:a,env:n,model:d.graph?.extractionModel??t.model,userInput:r},m=await s.do(T("memory:extract",d.key),async()=>o(l));await p(g(i.graphUpsert),{...m,messageKey:`${c}:${T("extract",d.key)}`,owner:u})}catch{}},$t=async e=>{const{agent:t,env:n,extractEpisode:o,finalText:a,input:r,instanceId:c,owner:u,paths:i,run:p,step:s,threadKey:d}=e;if(o===void 0||u===void 0||a===void 0||a.length===0)return;const l=tt(t);if(l!==void 0)try{const m={assistantText:a,env:n,model:l.episodic?.extractionModel??t.model,userInput:r},{summary:h}=await s.do(T("memory:episode",l.key),async()=>o(m));await p(g(i.episodeUpsert),{messageKey:`${c}:${T("episode",l.key)}`,owner:u,summary:h,threadKey:d})}catch{}},Kt=async(e,t,n)=>{const o=e[q(t)];if(!(!o||typeof o.get!="function"))try{await(await o.get(n)).terminate()}catch{}},Et="12 hours",Nt=async(e,t,n)=>{await e.waitForEvent(`dequeue:${n}`,{timeout:Et,type:`agent-dequeue:${t}:${n}`})},It=async(e,t,n)=>{const o=e.env[q(e.exportName)];if(!o||typeof o.get!="function")return;const a=o.get.bind(o);try{await e.step.do(`dequeue-wake:${n}`,async()=>(await(await a(n)).sendEvent({payload:{threadKey:t},type:`agent-dequeue:${t}:${n}`}),n))}catch{}},At=async(e,t,n)=>{const{onReply:o}=e,{replyRef:a}=t.params;if(!(o===void 0||a===void 0))try{await t.step.do("agent:reply",async()=>(await o({env:t.env,replyRef:a,result:n,threadKey:t.params.threadKey}),a.channel))}catch{}},Ut=async(e,t,n,o,a)=>{const{instanceId:r,persist:c}=e,u=n.usage===void 0?{}:{usage:n.usage};if(n.toolCalls.length===0){const i=n.output!==void 0&&n.text.length===0?j(n.output):n.text;return await c({content:i,messageKey:`${r}:assistant:${String(t)}`,role:"assistant"}),await D(e,{text:n.text,toolCalls:[],turn:t,...u}),{final:{stopped:"final",text:n.text,turns:t+1,...n.output===void 0?{}:{output:n.output}}}}await c({content:n.text,messageKey:`${r}:assistant:${String(t)}`,role:"assistant",toolCalls:n.toolCalls});for(const i of n.toolCalls)await mt(e,i);if(await D(e,{text:n.text,toolCalls:n.toolCalls,turn:t,...u}),o.push(ft(n)),a.length>0&&await at(a,o))return"stopCondition"},_t=async(e,t,n,o)=>{const a=[];let r,c=!1,u=0;for(let i=0;i<t;i+=1){const p=await ht(e,i,a);o.value=st(o.value,p.usage),u=i+1;const s=await Ut(e,i,p,a,n);if(s==="stopCondition"){c=!0;break}if(s!==void 0){r=s.final;break}}return{final:r,stoppedByCondition:c,turnsRun:u}},Bt=async e=>{const{agent:t,compact:n,env:o,exportName:a,extractEpisode:r,extractGraph:c,generate:u,instanceId:i,onTokenDelta:p,params:s,paths:d,run:l,step:m,streamGenerate:h}=e,f=t.maxTurns??et,$=nt(t.stopWhen),v=g(d.appendMessage),x=g(d.completeRun),S=g(d.ensureThread),C=g(d.listMessages),M=g(d.deleteMessage),R=g(d.patchThread),K=g(d.setState),I=g(d.state),_=async y=>{await l(v,{threadKey:s.threadKey,...y})},B=async y=>{await l(R,{key:s.threadKey,...y})},G=async y=>{await l(M,{messageKey:y,threadKey:s.threadKey})},b=async()=>{await _({content:s.input,messageKey:`${i}:user`,role:"user"})},E=async y=>{const N=await l(x,{instanceId:i,key:s.threadKey,...y});N?.dequeued!==void 0&&await It({env:o,exportName:a,step:m},s.threadKey,N.dequeued)},L=async()=>await l(I,{key:s.threadKey}),W=async y=>{await l(K,{key:s.threadKey,state:y})},A=await l(S,{agent:a,instanceId:i,key:s.threadKey,...t.initialState===void 0?{}:{initialState:t.initialState},...t.onConcurrentRun===void 0?{}:{onConcurrentRun:t.onConcurrentRun},...s.owner===void 0?{}:{owner:s.owner},...s.title===void 0?{}:{title:s.title}});A?.outcome==="replaced"&&await Kt(o,a,A.priorInstanceId);const z=await Rt(t,s.input,s.owner,d,m,l),H=typeof t.instructions=="function"?t.instructions({env:o,input:s.input,threadKey:s.threadKey}):t.instructions,V={agent:t,compact:n,depth:ot(s.depth),env:o,generate:u,getState:L,instanceId:i,instructions:H,listMessages:C,memoryContext:z,onTokenDelta:p,deleteMessage:G,patchThread:B,persist:_,run:l,setState:W,step:m,streamGenerate:h,threadKey:s.threadKey,tools:t.tools??{}},k={value:void 0};try{A?.outcome==="queued"&&await Nt(m,s.threadKey,i),await b();const{final:y,stoppedByCondition:N,turnsRun:X}=await _t(V,f,$,k),w=k.value===void 0?{}:{usage:k.value};return await kt({agent:t,env:o,extractGraph:c,finalText:y?.text,input:s.input,instanceId:i,owner:s.owner,paths:d,run:l,step:m}),await $t({agent:t,env:o,extractEpisode:r,finalText:y?.text,input:s.input,instanceId:i,owner:s.owner,paths:d,run:l,step:m,threadKey:s.threadKey}),y?(await At(t,{env:o,params:s,step:m},{...y,...w}),await E({status:"idle",...w}),{...y,...w}):N?(await E({status:"idle",...w}),{stopped:"stopCondition",turns:X,...w}):(await E({error:`agent stopped: maxTurns (${String(f)}) reached`,status:"error",...w}),{stopped:"maxTurns",turns:f,...w})}catch(y){throw await E({error:y instanceof Error?y.message:String(y),status:"error",...k.value===void 0?{}:{usage:k.value}}),y}};export{gt as compactHistory,Bt as runAgentLoop,vt as splitForCompaction};