@skroyc/ag-ui-middleware-callbacks 1.1.0 → 2.0.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/README.md +104 -106
- package/dist/adapter.cjs +4 -0
- package/dist/adapter.d.cts +18 -0
- package/dist/adapter.d.ts +18 -0
- package/dist/adapter.js +4 -0
- package/dist/backend.cjs +4 -0
- package/dist/backend.d.cts +24 -0
- package/dist/backend.d.ts +24 -0
- package/dist/backend.js +4 -0
- package/dist/callbacks.cjs +2 -0
- package/dist/callbacks.d.cts +177 -0
- package/dist/callbacks.d.ts +177 -0
- package/dist/callbacks.js +2 -0
- package/dist/create-agui-adapter-B6ZmSEvX.d.cts +34 -0
- package/dist/create-agui-adapter-C3WiiO-D.d.ts +34 -0
- package/dist/index.cjs +2 -0
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +2 -3
- package/dist/middleware.cjs +1 -0
- package/dist/middleware.d.cts +59 -0
- package/dist/middleware.d.ts +59 -0
- package/dist/middleware.js +1 -0
- package/dist/publication.cjs +3 -0
- package/dist/publication.d.cts +29 -0
- package/dist/publication.d.ts +29 -0
- package/dist/publication.js +3 -0
- package/package.json +40 -16
- package/dist/index.d.mts +0 -236
- package/dist/index.js.map +0 -1
package/dist/backend.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import {RunAgentInputSchema,EventType,EventSchemas}from'@ag-ui/core';import {BaseCallbackHandler}from'@langchain/core/callbacks/base';import {createMiddleware}from'langchain';import {z as z$1}from'zod';import {HumanMessage,AIMessage,ToolMessage,SystemMessage,ChatMessage}from'@langchain/core/messages';import {compare}from'fast-json-patch';function H(t){return typeof t=="object"&&t!==null}function b(t){if(t==null)return t;if(Array.isArray(t))return t.map(b);if(H(t)){if((t.lc===1||t.lc_serializable===true)&&(t.kwargs||t.lc_kwargs)){let n=t.kwargs||t.lc_kwargs;return b(n)}let e={};for(let[n,s]of Object.entries(t))n==="lc"||n==="type"||n==="id"||n.startsWith("lc_")||(e[n]=b(s));return e}return t}function X(t){if(t==null)return "";let e=t;if(typeof t=="string")try{e=JSON.parse(t);}catch{return t}if(!H(e))return String(e);let n=e.kwargs||e.lc_kwargs||e;return H(n)&&n.content!==void 0?typeof n.content=="string"?n.content:JSON.stringify(n.content):e.result!==void 0?typeof e.result=="string"?e.result:JSON.stringify(e.result):e.output!==void 0?typeof e.output=="string"?e.output:JSON.stringify(e.output):JSON.stringify(b(e))}function w(){return crypto.randomUUID()}function C(t,e){if(!t)throw new Error("baseId is required for deterministic ID generation");let n=`${t}-${e}`,s=0;for(let i=0;i<n.length;i++){let l=n.charCodeAt(i);s=(s*31+l)%2147483647;}let r=Math.abs(s).toString(16).padStart(8,"0");return `${t}-${r}`}function Te(t,e){let n=e.messageId||w(),s=[];return e.role&&s.push({type:EventType.TEXT_MESSAGE_START,messageId:n,role:e.role}),e.delta&&s.push({type:EventType.TEXT_MESSAGE_CONTENT,messageId:n,delta:e.delta}),e.role&&e.delta&&s.push({type:EventType.TEXT_MESSAGE_END,messageId:n}),s.length>0?s:[t]}function ve(t,e){let n=e.toolCallId||w(),s=[];return e.toolCallName&&s.push({type:EventType.TOOL_CALL_START,toolCallId:n,toolCallName:e.toolCallName,parentMessageId:e.parentMessageId}),e.delta&&s.push({type:EventType.TOOL_CALL_ARGS,toolCallId:n,delta:e.delta}),e.toolCallName&&e.delta&&s.push({type:EventType.TOOL_CALL_END,toolCallId:n,parentMessageId:e.parentMessageId}),s.length>0?s:[t]}function F(t){switch(t.type){case EventType.TEXT_MESSAGE_CHUNK:return Te(t,t);case EventType.TOOL_CALL_CHUNK:return ve(t,t);default:return [t]}}function Ee(t){return typeof t=="object"&&t!==null&&"type"in t&&t.type==="reasoning"}function z(t){let e=t;if(e._getType()!=="ai")return [];let n=e.contentBlocks;return Array.isArray(n)?n.filter(Ee):[]}function J(t){let e=z(t),n=new Map;for(let s of e){let r=s.index??0,i=n.get(r)??[];i.push(s),n.set(r,i);}return n}var L=class extends BaseCallbackHandler{name="ag-ui-callback";messageIds=new Map;latestMessageIds=new Map;startedMessageIds=new Set;agentRunIds=new Map;parentToAuthoritativeId=new Map;toolCallInfo=new Map;toolCallNames=new Map;agentTurnTracker=new Map;pendingToolCalls=new Map;accumulatedToolArgs=new Map;streamingToolCallIds=new Map;streamedReasoningRuns=new Set;openReasoningStates=new Map;warnedMissingStreamingContentBlocks=new Set;emitCallback;_enabled;_emitTextMessages;_emitToolCalls;_emitToolResults;_emitThinking;_reasoningEventMode;maxUIPayloadSize;chunkLargeResults;constructor(e){if(super({raiseError:false}),typeof e.publish!="function")throw new TypeError("publish must be a function");this.emitCallback=e.publish,this._enabled=e?.enabled??true,this._emitTextMessages=e?.emitTextMessages??true,this._emitToolCalls=e?.emitToolCalls??true,this._emitToolResults=e?.emitToolResults??true,this._emitThinking=e?.emitThinking??true,this._reasoningEventMode=e?.reasoningEventMode??"thinking",this.maxUIPayloadSize=e?.maxUIPayloadSize??50*1024,this.chunkLargeResults=e?.chunkLargeResults??false;}get enabled(){return this._enabled}set enabled(e){this._enabled=e;}get emitTextMessages(){return this._emitTextMessages}set emitTextMessages(e){this._emitTextMessages=e;}get emitToolCalls(){return this._emitToolCalls}set emitToolCalls(e){this._emitToolCalls=e;}get emitToolResults(){return this._emitToolResults}set emitToolResults(e){this._emitToolResults=e;}get emitThinking(){return this._emitThinking}set emitThinking(e){this._emitThinking=e;}get reasoningEventMode(){return this._reasoningEventMode}set reasoningEventMode(e){this._reasoningEventMode=e;}dispose(){this.messageIds.clear(),this.latestMessageIds.clear(),this.startedMessageIds.clear(),this.agentRunIds.clear(),this.parentToAuthoritativeId.clear(),this.toolCallInfo.clear(),this.toolCallNames.clear(),this.agentTurnTracker.clear(),this.pendingToolCalls.clear(),this.accumulatedToolArgs.clear(),this.streamingToolCallIds.clear(),this.streamedReasoningRuns.clear(),this.openReasoningStates.clear(),this.warnedMissingStreamingContentBlocks.clear();}emitTextChunk(e,n,s){if(!(this.enabled&&this.emitTextMessages))return;let r=F({type:EventType.TEXT_MESSAGE_CHUNK,messageId:e,role:n,delta:s});for(let i of r)this.emitCallback(i);}emitToolChunk(e,n,s,r){if(!(this.enabled&&this.emitToolCalls))return;let i=F({type:EventType.TOOL_CALL_CHUNK,toolCallId:e,toolCallName:n,delta:s,parentMessageId:r});for(let l of i)this.emitCallback(l);}handleLLMStart(e,n,s,r,i,l,a,u){if(!(this.enabled&&this.emitTextMessages))return;let d=this.getContext(i),c=this.resolveCallbackAgentRunId(s,r,a,d);this.agentRunIds.set(s,c),r&&this.parentToAuthoritativeId.set(r,c),this.prepareAssistantMessage(s,c,this.getString(a,"agui_messageId"));}handleLLMNewToken(e,n,s,r,i,l){if(!this.enabled)return;let a=this.messageIds.get(s);if(a)try{let u=this.resolveAgentRunId(s,r);this.emitStreamingReasoning(l,a,s),e&&e.length>0&&(this.closeStreamingReasoning(s),this.ensureAssistantMessageStarted(a,u)),this.emitStreamingToken(e,a),this.emitToolCalls&&this.trackStreamingToolCallArgs(l,u);}catch{}}handleLLMEnd(e,n,s,r,i){let l=this.resolveAgentRunId(n,s);if(this.collectToolCallsFromOutput(e,l),!this.enabled){let u=this.messageIds.get(n);this.cleanupOpenLifecycles(n,u),u&&this.startedMessageIds.delete(u),this.streamedReasoningRuns.delete(n),this.warnedMissingStreamingContentBlocks.delete(n),this.messageIds.delete(n),this.clearStreamingToolCallIds(l);return}let a=this.messageIds.get(n);this.streamedReasoningRuns.has(n)||this.emitThinkingFromOutput(e,a??n),this.closeStreamingReasoning(n),this.emitAssistantMessageFromOutput(e,a,l),this.emitTextMessageEnd(a),a&&this.startedMessageIds.delete(a),this.messageIds.delete(n),this.clearStreamingToolCallIds(l),this.streamedReasoningRuns.delete(n),this.warnedMissingStreamingContentBlocks.delete(n);}detectAndEmitThinking(e,n){if(!(this.emitThinking&&this.emitTextMessages)||z(e).length===0)return;let r=J(e);for(let[i,l]of r){let a=C(`${n}-reasoning-phase`,i),u=C(`${n}-reasoning-message`,i);this.reasoningEventMode==="reasoning"?(this.emitCallback({type:EventType.REASONING_START,messageId:a,timestamp:Date.now()}),this.emitCallback({type:EventType.REASONING_MESSAGE_START,messageId:u,role:"reasoning",timestamp:Date.now()})):(this.emitCallback({type:EventType.THINKING_START,timestamp:Date.now()}),this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_START,timestamp:Date.now()}));let d=l.map(c=>c.reasoning).filter(c=>c.trim().length>0).join("");d&&(this.reasoningEventMode==="reasoning"?this.emitCallback({type:EventType.REASONING_MESSAGE_CONTENT,messageId:u,delta:d,timestamp:Date.now()}):this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_CONTENT,delta:d,timestamp:Date.now()})),this.reasoningEventMode==="reasoning"?(this.emitCallback({type:EventType.REASONING_MESSAGE_END,messageId:u,timestamp:Date.now()}),this.emitCallback({type:EventType.REASONING_END,messageId:a,timestamp:Date.now()})):(this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_END,timestamp:Date.now()}),this.emitCallback({type:EventType.THINKING_END,timestamp:Date.now()}));}}handleLLMError(e,n,s){let r=this.messageIds.get(n),i=this.resolveAgentRunId(n,s);if(!this.enabled){this.cleanupOpenLifecycles(n,r),r&&this.startedMessageIds.delete(r),this.messageIds.delete(n),this.pendingToolCalls.delete(i),this.agentRunIds.delete(n),this.streamedReasoningRuns.delete(n),this.warnedMissingStreamingContentBlocks.delete(n),this.clearStreamingToolCallIds(i);return}r&&this.startedMessageIds.delete(r),this.messageIds.delete(n),this.pendingToolCalls.delete(i),this.agentRunIds.delete(n),this.closeStreamingReasoning(n),this.streamedReasoningRuns.delete(n),this.warnedMissingStreamingContentBlocks.delete(n),this.clearStreamingToolCallIds(i);}handleToolStart(e,n,s,r,i,l,a){if(!(this.enabled&&this.emitToolCalls))return;let u=this.resolveToolInput(e,n,s,l,a),d={id:u.toolCallId??s,name:u.toolCallName??this.getToolCallName(e,a)};this.toolCallInfo.set(s,d);let c=this.resolveParentAgentRunId(r),p=this.latestMessageIds.get(c);this.emitToolStartSequence(d,p,u.argsDelta);}handleToolEnd(e,n,s){if(!(this.enabled&&this.emitToolCalls))return;let r=this.toolCallInfo.get(n);this.toolCallInfo.delete(n),r?.id&&this.toolCallNames.delete(r.id);let i=this.latestMessageIds.get(this.resolveParentAgentRunId(s));try{let l=r?.id??n;this.emitCallback({type:EventType.TOOL_CALL_END,toolCallId:l,timestamp:Date.now()}),this.emitToolResults&&this.emitToolResultWithPolicy(e,l,i,r?.name);}catch{}}handleToolError(e,n,s){if(!(this.enabled&&this.emitToolCalls))return;let r=this.toolCallInfo.get(n);this.toolCallInfo.delete(n),r?.id&&this.accumulatedToolArgs.delete(r.id);try{this.emitCallback({type:EventType.TOOL_CALL_END,toolCallId:r?.id??n,timestamp:Date.now()});}catch{}}chunkString(e,n){let s=[],r=e;for(;r.length>0;){if(new Blob([r]).size<=n){s.push(r);break}let i=n,l=r.lastIndexOf(" ",n),a=r.lastIndexOf(`
|
|
2
|
+
`,n),u=Math.max(l,a);if(u>n*.5)i=u;else {for(;i>0&&r.charCodeAt(i-1)>127;)i--;i===0&&(i=n);}s.push(r.substring(0,i)),r=r.substring(i).trim();}return s}emitToolResultWithPolicy(e,n,s,r){let i=X(e),l=w(),a=new Blob([i]).size;if(a<=this.maxUIPayloadSize){this.emitCallback({type:EventType.TOOL_CALL_RESULT,messageId:l,toolCallId:n,content:i,role:"tool",timestamp:Date.now()});return}if(this.chunkLargeResults){let p=this.chunkString(i,this.maxUIPayloadSize);for(let g=0;g<p.length;g++)this.emitCallback({type:EventType.CUSTOM,name:"LARGE_RESULT_CHUNK",value:{toolCallId:n,chunk:p[g],index:g,total:p.length}});return}let u=` [Truncated: ${a-this.maxUIPayloadSize+50} bytes]`,d=this.maxUIPayloadSize-u.length,c=i.substring(0,Math.max(0,d))+u;this.emitCallback({type:EventType.TOOL_CALL_RESULT,messageId:l,toolCallId:n,content:c,role:"tool",timestamp:Date.now()});}asRecord(e){if(typeof e=="object"&&e!==null)return e}getString(e,n){let s=e?.[n];return typeof s=="string"?s:void 0}getContext(e){return this.asRecord(this.asRecord(e)?.options)?.context}resolveCallbackAgentRunId(e,n,s,r){return this.getString(s,"run_id")||this.getString(s,"runId")||this.getString(r,"run_id")||this.getString(r,"runId")||this.getString(s,"agui_runId")||n||e}resolveAgentRunId(e,n){return this.agentRunIds.get(e)||(n?this.parentToAuthoritativeId.get(n):void 0)||n||e}resolveParentAgentRunId(e){return (e?this.parentToAuthoritativeId.get(e):void 0)||e||""}prepareAssistantMessage(e,n,s){let r=s??this.createAssistantMessageId(n);this.messageIds.set(e,r);}ensureAssistantMessageStarted(e,n){this.startedMessageIds.has(e)||(this.startedMessageIds.add(e),this.latestMessageIds.set(n,e),this.emitCallback({type:EventType.TEXT_MESSAGE_START,messageId:e,role:"assistant",timestamp:Date.now()}));}createAssistantMessageId(e){let n=this.agentTurnTracker.get(e)||0;return this.agentTurnTracker.set(e,n+1),C(e,n)}emitStreamingToken(e,n){e&&e.length>0&&this.emitTextMessages&&this.emitCallback({type:EventType.TEXT_MESSAGE_CONTENT,messageId:n,delta:e,timestamp:Date.now()});}emitAssistantMessageFromOutput(e,n,s){if(!(n&&this.emitTextMessages)||this.startedMessageIds.has(n))return;let r=this.getOutputTextContent(e);typeof r=="string"&&r.length>0&&(this.ensureAssistantMessageStarted(n,s),this.emitStreamingToken(r,n));}trackStreamingToolCallArgs(e,n){let s=this.getToolCallChunks(e);if(s.length===0)return;let r=[...this.pendingToolCalls.get(n)||[]],i=false;for(let l of s){let a=this.resolveStreamingToolCallId(n,l);if(a){if(l.name&&this.toolCallNames.set(a,l.name),typeof l.args=="string"){let u=this.accumulatedToolArgs.get(a)||"",d=u+l.args;d!==u&&this.accumulatedToolArgs.set(a,d);}r.includes(a)||(r.push(a),i=true);}}i&&this.pendingToolCalls.set(n,r);}emitStreamingReasoning(e,n,s){if(!(this.emitThinking&&this.emitTextMessages))return;let r=this.getStreamingReasoningChunks(e,s);if(r.length!==0){this.streamedReasoningRuns.add(s);for(let i of r){let l=this.ensureStreamingReasoningState(s,n,i.index);typeof i.reasoning=="string"&&i.reasoning.length>0&&(this.reasoningEventMode==="reasoning"?this.emitCallback({type:EventType.REASONING_MESSAGE_CONTENT,messageId:l.messageId,delta:i.reasoning,timestamp:Date.now()}):this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_CONTENT,delta:i.reasoning,timestamp:Date.now()}));}}}getStreamingReasoningChunks(e,n){let r=this.asRecord(this.asRecord(e)?.chunk)?.message,i=this.asRecord(r),l=this.getStreamingContentBlocks(r);return l.length===0&&this.hasRawStreamingReasoning(i)&&this.warnMissingStreamingContentBlocks(n),l.map(a=>this.asRecord(a)).flatMap(a=>{let u=this.getString(a,"reasoning");return a?.type!=="reasoning"?[]:[{index:typeof a.index=="number"?a.index:0,reasoning:u}]})}getStreamingContentBlocks(e){let n=this.asRecord(e);return Array.isArray(n?.contentBlocks)?n.contentBlocks:[]}hasRawStreamingReasoning(e){return Array.isArray(e?.content)?e.content.some(n=>{let s=this.asRecord(n);return s?.type==="reasoning"&&typeof s.reasoning=="string"}):false}warnMissingStreamingContentBlocks(e){!e||this.warnedMissingStreamingContentBlocks.has(e)||(this.warnedMissingStreamingContentBlocks.add(e),console.warn("[AG-UI] Stream chunk exposed reasoning outside LangChain contentBlocks; reasoning events were skipped for this chunk."));}ensureStreamingReasoningState(e,n,s){let r=`${e}:${s}`,i=this.openReasoningStates.get(r);if(i)return i;let l={phaseId:C(`${n}-reasoning-phase`,s),messageId:C(`${n}-reasoning-message`,s)};return this.openReasoningStates.set(r,l),this.reasoningEventMode==="reasoning"?(this.emitCallback({type:EventType.REASONING_START,messageId:l.phaseId,timestamp:Date.now()}),this.emitCallback({type:EventType.REASONING_MESSAGE_START,messageId:l.messageId,role:"reasoning",timestamp:Date.now()})):(this.emitCallback({type:EventType.THINKING_START,timestamp:Date.now()}),this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_START,timestamp:Date.now()})),l}closeStreamingReasoning(e){let n=`${e}:`;for(let[s,r]of this.openReasoningStates)s.startsWith(n)&&(this.reasoningEventMode==="reasoning"?(this.emitCallback({type:EventType.REASONING_MESSAGE_END,messageId:r.messageId,timestamp:Date.now()}),this.emitCallback({type:EventType.REASONING_END,messageId:r.phaseId,timestamp:Date.now()})):(this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_END,timestamp:Date.now()}),this.emitCallback({type:EventType.THINKING_END,timestamp:Date.now()})),this.openReasoningStates.delete(s));}getToolCallChunks(e){let n=this.asRecord(this.asRecord(e)?.chunk),s=this.asRecord(n?.message),r=this.asRecord(s?.kwargs),i=s?.tool_call_chunks??r?.tool_call_chunks;return Array.isArray(i)?i.map(l=>{let a=this.asRecord(l);return {id:this.getString(a,"id"),name:this.getString(a,"name"),args:this.getString(a,"args"),index:typeof a?.index=="number"?a.index:void 0}}):[]}resolveStreamingToolCallId(e,n){if(n.id){let r=this.getStreamingToolCallKey(e,n.index);return r&&this.streamingToolCallIds.set(r,n.id),n.id}let s=this.getStreamingToolCallKey(e,n.index);if(s)return this.streamingToolCallIds.get(s)}getStreamingToolCallKey(e,n){if(typeof n=="number")return `${e}:${n}`}clearStreamingToolCallIds(e){let n=`${e}:`;for(let s of this.streamingToolCallIds.keys())s.startsWith(n)&&this.streamingToolCallIds.delete(s);}collectToolCallsFromOutput(e,n){try{let s=this.getOutputToolCalls(e);if(s.length===0)return;let r=[...this.pendingToolCalls.get(n)||[]];for(let i of s)i.id&&!r.includes(i.id)&&(r.push(i.id),i.function?.name&&this.toolCallNames.set(i.id,i.function.name),i.function?.arguments&&this.accumulatedToolArgs.set(i.id,i.function.arguments));this.pendingToolCalls.set(n,r);}catch{}}getOutputToolCalls(e){let n=this.asRecord(e),s=this.asRecord(n?.kwargs),r=n?.tool_calls??s?.tool_calls;if(Array.isArray(r))return r.map(u=>{let d=this.asRecord(u),c=this.asRecord(d?.function);return {id:this.getString(d,"id"),function:{name:this.getString(c,"name"),arguments:this.getString(c,"arguments")}}});let i=this.getOutputMessage(e),a=this.asRecord(i)?.tool_calls;return Array.isArray(a)?a.map(u=>{let d=this.asRecord(u),c=this.asRecord(d?.function);return {id:this.getString(d,"id"),function:{name:this.getString(c,"name")??this.getString(d,"name"),arguments:this.getString(c,"arguments")??this.stringifyIfDefined(d?.args)}}}):[]}emitThinkingFromOutput(e,n){try{let r=this.asRecord(e)?.generations;if(!Array.isArray(r)||r.length===0)return;let i=r[0];if(!Array.isArray(i)||i.length===0)return;let a=this.asRecord(i[0])?.message;if(!a)return;this.detectAndEmitThinking(a,n);}catch{}}emitTextMessageEnd(e){e&&this.startedMessageIds.has(e)&&this.emitCallback({type:EventType.TEXT_MESSAGE_END,messageId:e,timestamp:Date.now()});}cleanupOpenLifecycles(e,n){this.closeStreamingReasoning(e),this.emitTextMessageEnd(n);}resolveToolInput(e,n,s,r,i){let l=s,a=this.getToolCallName(e,i),u=n||void 0,d=this.getString(r,"tool_call_id");if(d)return {toolCallId:d,toolCallName:this.resolveStoredToolName(d,a),argsDelta:u};let c=this.parseToolInput(n);c&&(l=this.getString(c,"tool_call_id")||this.getString(c,"id")||l,a=this.getString(c,"name")||a,u=this.resolveToolArgsDelta(c,n));let p=l===s?this.findMatchingAccumulatedToolCallId(n):void 0;return p&&(l=p),{toolCallId:l,toolCallName:this.resolveStoredToolName(l,a),argsDelta:u}}getToolCallName(e,n){if(n)return n;let s=this.asRecord(e);if(!s)return "unknown_tool";let r=s.getName?.();return typeof r=="string"&&r.length>0?r:s.kwargs?.name||s.name||s.func?.name||s.toolName||s._name||"unknown_tool"}parseToolInput(e){if(e)try{return this.asRecord(JSON.parse(e))}catch{return}}findMatchingAccumulatedToolCallId(e){if(e){for(let[n,s]of this.accumulatedToolArgs)if(e.includes(s)||s.includes(e))return n}}resolveStoredToolName(e,n){let s=this.toolCallNames.get(e);return s&&s!=="unknown_tool"?s:n}emitToolStartSequence(e,n,s){try{this.emitCallback({type:EventType.TOOL_CALL_START,toolCallId:e.id,toolCallName:e.name,parentMessageId:n,timestamp:Date.now()});let r=s??this.accumulatedToolArgs.get(e.id);if(!r)return;this.emitCallback({type:EventType.TOOL_CALL_ARGS,toolCallId:e.id,delta:r,timestamp:Date.now()}),this.accumulatedToolArgs.delete(e.id);}catch{}}getOutputMessage(e){let s=this.asRecord(e)?.generations;if(!Array.isArray(s)||s.length===0)return;let r=s[0];if(!(!Array.isArray(r)||r.length===0))return this.asRecord(r[0])?.message}getOutputTextContent(e){let n=this.asRecord(e),s=this.getOutputMessage(e),r=this.asRecord(s),i=r?.content;if(typeof i=="string"&&i.length>0)return i;let l=this.getString(this.asRecord(r?.kwargs),"text");if(l&&l.length>0)return l;let a=r?.contentBlocks;if(Array.isArray(a)){let g=a.map(m=>this.asRecord(m)).filter(m=>m?.type==="text").map(m=>this.getString(m,"text")).filter(m=>!!(m&&m.length>0)).join("");if(g.length>0)return g}let u=Array.isArray(n?.generations)?n.generations:void 0,d=Array.isArray(u?.[0])?u[0]:void 0,p=this.asRecord(d?.[0])?.text;return typeof p=="string"&&p.length>0?p:void 0}resolveToolArgsDelta(e,n){if(typeof e.args=="string")return e.args;let s=this.stringifyIfDefined(e.args);if(s)return s;if(typeof e.arguments=="string")return e.arguments;let r=this.stringifyIfDefined(e.arguments);return r||n||void 0}stringifyIfDefined(e){if(!(typeof e>"u")){if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return}}}};var Me="[unserializable content]",_e="{}";function q(t){return typeof t=="object"&&t!==null}function Q(t){try{return JSON.stringify(t)}catch{return}}function _(t){if(typeof t>"u")return "";if(typeof t=="string")return t;let e=Q(t);return typeof e=="string"?e:Me}function Be(t){return q(t)?t.type==="text"&&typeof t.text=="string":false}function xe(t){return !q(t)||t.type!=="binary"||typeof t.mimeType!="string"||t.id!==void 0&&typeof t.id!="string"||t.url!==void 0&&typeof t.url!="string"||t.data!==void 0&&typeof t.data!="string"||t.filename!==void 0&&typeof t.filename!="string"?false:typeof t.id=="string"||typeof t.url=="string"||typeof t.data=="string"}function Ge(t){return Array.isArray(t)?t.every(e=>Be(e)||xe(e)):false}function W(t){switch(t){case "assistant":case "user":case "system":case "developer":case "tool":case "reasoning":return t;default:return}}function Ne(t,e){return typeof e=="string"||t==="user"&&Ge(e)?e:_(e)}function Ue(t,e){let n=e._getType?.(),s=W(e.role),r="assistant",i,l;if(t instanceof HumanMessage||s==="user"||n==="human")return {role:"user"};if(t instanceof AIMessage||s==="assistant"||n==="ai"){let a=e.tool_calls||e.kwargs?.tool_calls;return a&&a.length>0&&(i=a.map(u=>({id:u.id||w(),type:"function",function:{name:String(u.name??"unknown_tool"),arguments:typeof u.args=="string"?u.args:Q(u.args)??_e}}))),{role:"assistant",toolCalls:i}}return t instanceof ToolMessage||s==="tool"||n==="tool"?(l=e.tool_call_id||e.kwargs?.tool_call_id,{role:"tool",toolCallId:l}):t instanceof SystemMessage||s==="system"||n==="system"?{role:"system"}:t instanceof ChatMessage?(r=W(t.role)??"assistant",{role:r}):s?{role:s}:{role:r}}function Y(t){let e=t,n=e.id||w(),{role:s,toolCalls:r,toolCallId:i}=Ue(t,e);if(s==="assistant")return {id:n,role:s,content:_(e.content),toolCalls:r,name:e.name};if(s==="tool"){if(!i)throw new Error("Cannot map a tool-role message without a toolCallId.");return {id:n,role:s,content:_(e.content),toolCallId:i}}return s==="user"?{id:n,role:s,content:Ne(s,e.content),name:e.name}:s==="system"?{id:n,role:s,content:_(e.content),name:e.name}:s==="developer"?{id:n,role:s,content:_(e.content),name:e.name}:{id:n,role:s,content:_(e.content)}}function Z(t,e){return compare(t,e)}function x(t){try{let e=EventSchemas.safeParse(t);return e.success?{success:!0,data:t}:{success:!1,error:{message:"Event validation failed",issues:e.error.issues.map(n=>({path:n.path,message:n.message}))}}}catch(e){return {success:false,error:{message:e instanceof Error?e.message:"Unknown validation error",issues:[]}}}}function ee(t){return x(t).success}function B(t){if(typeof t!="string")return;let e=t.trim();return e.length>0?e:void 0}function te(t){let e=t.context,n=B(e?.thread_id)||B(e?.threadId),s=B(e?.run_id)||B(e?.runId),r=B(t.threadIdOverride),i=B(t.runIdOverride);return {threadId:n||r||"",runId:s||i||t.createFallbackRunId()}}var ne=z$1.object({publish:z$1.custom(t=>typeof t=="function",{message:"publish must be a function"}),emitStateSnapshots:z$1.enum(["initial","final","all","none"]).default("initial"),emitActivities:z$1.boolean().default(false),threadIdOverride:z$1.string().optional(),runIdOverride:z$1.string().optional(),errorDetailLevel:z$1.enum(["full","message","code","none"]).default("message"),stateMapper:z$1.custom().optional(),activityMapper:z$1.custom().optional(),validateEvents:z$1.union([z$1.boolean(),z$1.literal("strict")]).default(false)});function Pe(t){return t===true||t==="strict"}function T(t){return typeof t=="object"&&t!==null}function He(t){return T(t)&&!Array.isArray(t)}function Fe(t){return T(t)&&"content"in t}function D(t){return T(t)&&Array.isArray(t.messages)?t.messages.filter(Fe):[]}function ze(t){if(T(t))return t.error}function je(t){if(T(t))return t.context}function Ke(t){if(T(t)&&T(t.config))return t.config.input}function $e(t){if(T(t)&&T(t.config)&&T(t.config.model))return typeof t.config.model._modelType=="string"?t.config.model._modelType:void 0}function Ve(t){return T(t)&&typeof t.type=="string"?t.type:"[unknown]"}function Xe(t){let e=D(t).at(-1);return e&&typeof e.content=="string"?e.content.substring(0,100)+(e.content.length>100?"...":""):"[no input preview]"}function Je(t){let e=D(t).at(-1);return Array.isArray(e?.toolCalls)&&e.toolCalls.length>0?"tool_calls":e?.content?"text":"unknown"}function We(t){return D(t).some(e=>Array.isArray(e.toolCalls)&&e.toolCalls.length>0)}function se(t,e,n,s,r,i,l){if(!e)return;let a=`activity-${e}-${n}`,u={status:r,timestamp:Date.now(),...l},d=i?i(u):u;if(!s.currentActivityId||s.currentActivityId!==a)s.currentActivityId=a,s.currentActivityType="AGENT_STEP",s.activityContent=d,t({type:EventType.ACTIVITY_SNAPSHOT,messageId:a,activityType:"AGENT_STEP",content:d,replace:true});else {let c=Z(s.activityContent,d);c.length>0&&(s.activityContent=d,t({type:EventType.ACTIVITY_DELTA,messageId:a,activityType:"AGENT_STEP",patch:c}));}}function re(t){let e=ne.parse(t),n=c=>{if(Pe(e.validateEvents)&&!ee(c)){let g=x(c).error;if(e.validateEvents==="strict")throw new Error(`Invalid AG-UI event: ${g?.message}`);console.warn("[AG-UI Validation] Invalid event:",Ve(c),g);}e.publish(c);},s=(c,p)=>c==="none"?false:c==="all"?true:c===p,r=c=>{let p=b(c),g=e.stateMapper?e.stateMapper(p):p;if(!e.stateMapper&&He(g)){let{messages:m,...I}=g;return I}return g},i=(c,p)=>{if(!s(e.emitStateSnapshots,c))return;let g=r(p);n({type:EventType.STATE_SNAPSHOT,snapshot:g,timestamp:Date.now()});},l=new Map,a=new WeakMap,u=z$1.object({run_id:z$1.string().optional(),runId:z$1.string().optional(),thread_id:z$1.string().optional(),threadId:z$1.string().optional()}),d=c=>{let p=T(c)?c:void 0,g=p?a.get(p):void 0,m=te({context:je(c),threadIdOverride:e.threadIdOverride,runIdOverride:e.runIdOverride,createFallbackRunId:()=>g??crypto.randomUUID()});p&&!a.has(p)&&a.set(p,m.runId);let I=l.get(m.runId);if(I)return !I.threadId&&m.threadId&&(I.threadId=m.threadId),I;let S={threadId:m.threadId,runId:m.runId,modelTurnIndex:0,activityTracker:{currentActivityId:void 0,currentActivityType:"AGENT_STEP",activityContent:{}}};return l.set(S.runId,S),S};return createMiddleware({name:"ag-ui-lifecycle",contextSchema:u,beforeAgent:(c,p)=>{let g=d(p);g.modelTurnIndex=0,g.currentStepName=void 0,g.activityTracker.currentActivityId=void 0,g.activityTracker.currentActivityType="AGENT_STEP",g.activityTracker.activityContent={};try{n({type:EventType.RUN_STARTED,threadId:g.threadId,runId:g.runId,input:b(Ke(p)),timestamp:Date.now()}),i("initial",c);let m=D(c);m.length>0&&n({type:EventType.MESSAGES_SNAPSHOT,messages:m.map(Y),timestamp:Date.now()});}catch{}return {}},beforeModel:(c,p)=>{let g=d(p),m=g.modelTurnIndex++,S=`model_call_${C(g.runId,m)}`;g.currentStepName=S;try{n({type:EventType.STEP_STARTED,stepName:S,timestamp:Date.now()}),e.emitActivities&&se(n,g.runId,m,g.activityTracker,"started",e.activityMapper,{stepName:S,modelName:$e(p)??"unknown",inputPreview:Xe(c)});}catch{}return {}},afterModel:(c,p)=>{let g=d(p);try{if(n({type:EventType.STEP_FINISHED,stepName:g.currentStepName||"",timestamp:Date.now()}),e.emitActivities&&g.currentStepName){let m=g.modelTurnIndex-1;se(n,g.runId,m,g.activityTracker,"completed",e.activityMapper,{stepName:g.currentStepName,outputType:Je(c),hasToolCalls:We(c)});}}catch{}return g.currentStepName=void 0,{}},afterAgent:(c,p)=>{let g=d(p);try{i("final",c);let m=ze(c);if(m){let I=m instanceof Error?m.message:String(m);n({type:EventType.RUN_ERROR,message:e.errorDetailLevel==="full"||e.errorDetailLevel==="message"?I:"",code:"AGENT_EXECUTION_ERROR",timestamp:Date.now()});}else n({type:EventType.RUN_FINISHED,threadId:g.threadId,runId:g.runId,timestamp:Date.now()});}catch{}return l.delete(g.runId),T(p)&&a.delete(p),{}}})}var qe=new TextEncoder,Qe="text/event-stream",Ye="no-cache",Ze="keep-alive",et={"Content-Type":Qe,"Cache-Control":Ye,Connection:Ze};function j(t){return qe.encode(`data: ${JSON.stringify(t)}
|
|
3
|
+
|
|
4
|
+
`)}function K(t){return new ReadableStream({async start(e){try{for await(let n of t)e.enqueue(j(n));e.close();}catch(n){e.error(n);}}})}function ie(t,e={}){let n=new Headers(e.headers);for(let[s,r]of Object.entries(et))n.has(s)||n.set(s,r);return new Response(t,{...e,headers:n})}var ae=j;function oe(t,e="sse"){return t||ae}function tt(t){return t===true||t==="strict"}function de(t){return typeof t=="object"&&t!==null}function M(t,e){if(!de(t))return;let n=t[e];return typeof n=="string"?n:void 0}function le(t){let e=M(t,"runId"),n=M(t,"threadId");if(!(!e||typeof n>"u"))return {runId:e,threadId:n}}function nt(t){if(typeof t=="string")return {message:t};if(t instanceof Error){let e=typeof t.code=="string"?t.code:void 0;return {message:t.message,code:e}}if(de(t)){let e=typeof t.message=="string"?t.message:"Agent execution failed",n=typeof t.code=="string"?t.code:void 0;return {message:e,code:n}}return {message:"Agent execution failed"}}function ce(t={}){let e=oe(t.serializer,t.transport??"sse"),n=t.validateEvents??false,s=new Set,r=new Set,i=[],l=[],a=new Set,u=new Set,d=new Set,c=new Set,p=false,g=false,m,I=o=>{if(tt(n)){let A=x(o);if(!A.success){if(n==="strict")throw new Error(`Invalid AG-UI event: ${A.error?.message}`);console.warn("[AG-UI Validation] Invalid event:",o.type,A.error);}}i.push(o);for(let A of s)A(o);let h=e(o);for(let A of r)A.enqueue(h);},S=()=>{for(let o of [...a])a.delete(o),I({type:EventType.TEXT_MESSAGE_END,messageId:o,timestamp:Date.now()});for(let o of [...u])u.delete(o),I({type:EventType.TOOL_CALL_END,toolCallId:o,timestamp:Date.now()});for(let o of [...d])d.delete(o),I({type:EventType.REASONING_MESSAGE_END,messageId:o,timestamp:Date.now()});for(let o of [...c])c.delete(o),I({type:EventType.REASONING_END,messageId:o,timestamp:Date.now()});},$=()=>{for(let o of r)o.close();r.clear();},N=o=>{g||(S(),g=true,I(o),$());},me=()=>{g||(g=true,$());},fe=o=>{if(!(g||p))for(p=true,m=le(o),I(o);l.length>0&&!g;){let h=l.shift();h&&V(h);}},U=(o,h,A)=>{let E=M(o,A);return E&&!h.has(E)?(h.add(E),I(o),true):false},P=(o,h,A)=>{let E=M(o,A);return E&&h.has(E)?(I(o),true):false},O=(o,h,A)=>{let E=M(o,A);return E&&h.has(E)?(h.delete(E),I(o),true):false},he=o=>{switch(o.type){case EventType.TEXT_MESSAGE_START:return U(o,a,"messageId");case EventType.TEXT_MESSAGE_CONTENT:return P(o,a,"messageId");case EventType.TEXT_MESSAGE_END:return O(o,a,"messageId");default:return false}},Ie=o=>{switch(o.type){case EventType.TOOL_CALL_START:return U(o,u,"toolCallId");case EventType.TOOL_CALL_ARGS:return P(o,u,"toolCallId");case EventType.TOOL_CALL_END:return O(o,u,"toolCallId");default:return false}},ye=o=>{switch(o.type){case EventType.REASONING_START:return U(o,c,"messageId");case EventType.REASONING_END:return O(o,c,"messageId");case EventType.REASONING_MESSAGE_START:return U(o,d,"messageId");case EventType.REASONING_MESSAGE_CONTENT:return P(o,d,"messageId");case EventType.REASONING_MESSAGE_END:return O(o,d,"messageId");default:return false}},Ae=o=>{if(o.type===EventType.RUN_ERROR)return N(o),true;if(o.type!==EventType.RUN_FINISHED)return false;let h=le(o)??m;return N({...o,runId:h?.runId??M(o,"runId"),threadId:h?.threadId??M(o,"threadId")}),true},V=o=>{if(!g){if(o.type===EventType.RUN_STARTED){fe(o);return}if(!p){l.push(o);return}he(o)||Ie(o)||ye(o)||Ae(o)||I(o);}};return {publish(o){V(o);},complete(o){if(!g){if(!m)throw new Error("Cannot complete a run that has not been started. A `RUN_STARTED` event must be published first.");N({type:EventType.RUN_FINISHED,threadId:m.threadId,runId:m.runId,result:o,timestamp:Date.now()});}},error(o){if(g)return;let h=nt(o);N({type:EventType.RUN_ERROR,message:h.message,code:h.code,timestamp:Date.now()});},close(){me();},subscribe(o){return s.add(o),()=>{s.delete(o);}},toReadableStream(){let o;return new ReadableStream({start(h){o=h;for(let A of i)h.enqueue(e(A));if(g){h.close();return}r.add(h);},cancel(){o&&r.delete(o);}})}}}function rt(t){return t instanceof DOMException&&t.name==="AbortError"||t instanceof Error&&t.name==="AbortError"}function it(t){return typeof t=="object"&&t!==null&&!Array.isArray(t)}function at(t){return it(t.state)?{...t.state,messages:t.messages}:{messages:t.messages,state:t.state}}function ot(t){return e=>{e.type!==EventType.RUN_FINISHED&&t.publish(e);}}async function lt(t){let e;for await(let n of t)e=n;return e}function dt(){let t=[],e=[],n=false,s,r=false,i=()=>{for(;t.length>0&&e.length>0;){let d=e.shift(),c=t.shift();d&&typeof c<"u"&&d.resolve({value:c,done:false});}},l=()=>{if(!(typeof s>"u"))for(let d of e.splice(0))d.reject(s);},a=()=>{if(n)for(let d of e.splice(0))d.resolve({value:void 0,done:true});},u=()=>{i(),!(t.length>0||e.length===0)&&(l(),a());};return {push(d){n||typeof s<"u"||(t.push(d),u());},close(){n||typeof s<"u"||(n=true,u());},error(d){n||typeof s<"u"||(s=d,u());},iterable:{async*[Symbol.asyncIterator](){if(r)throw new Error("AGUI adapter event streams support a single consumer.");for(r=true;;){if(t.length>0){yield t.shift();continue}if(typeof s<"u")throw s;if(n)return;let d=await new Promise((c,p)=>{e.push({resolve:c,reject:p});});if(d.done)return;yield d.value;}}}}}function ue(t){if(typeof t.agentFactory!="function")throw new TypeError("agentFactory must be a function that accepts { input, middleware } and returns an agent with a stream() method");return {stream(e,n={}){let s=ce({validateEvents:t.validateEvents}),r=dt(),i=s.subscribe(d=>{r.push(d);}),l=new L({publish:s.publish,...t.callbackOptions}),a=re({publish:ot(s),validateEvents:t.validateEvents??false,emitStateSnapshots:t.emitStateSnapshots??"initial",emitActivities:t.emitActivities??false,errorDetailLevel:t.errorDetailLevel??"message",runIdOverride:e.runId,threadIdOverride:e.threadId});return (async()=>{try{let c=await(await t.agentFactory({input:e,middleware:a})).stream(at(e),{callbacks:[l],signal:n.signal,streamMode:"values",configurable:{run_id:e.runId,thread_id:e.threadId},context:{run_id:e.runId,thread_id:e.threadId,signal:n.signal}}),p=await lt(c);n.signal?.aborted?s.close():s.complete(p);}catch(d){n.signal?.aborted||rt(d)?s.close():s.error(d);}finally{try{l.dispose();}catch(d){console.error("Failed to dispose AG-UI callback handler.",d);}try{i();}catch(d){console.error("Failed to unsubscribe AG-UI adapter listener.",d);}r.close();}})().catch(d=>{r.error(d);}),Promise.resolve(r.iterable)}}}function ge(t,e){return new Response(JSON.stringify({error:e}),{status:t,headers:{"Content-Type":"application/json"}})}function ut(t){return t.headers.get("content-type")?.toLowerCase().includes("application/json")??false}async function gt(t){let e=await t.json();return RunAgentInputSchema.parse(e)}function pe(t){let e=ue(t);return {async handle(n){if(n.method!=="POST")return new Response(JSON.stringify({error:"Method Not Allowed"}),{status:405,headers:{"Content-Type":"application/json",Allow:"POST"}});if(!ut(n))return ge(415,"Unsupported Media Type");let s;try{s=await gt(n);}catch(i){return ge(400,i instanceof Error?i.message:"Invalid request body")}let r=await e.stream(s,{signal:n.signal});return ie(K(r))}}}function hn(t){return pe(t)}export{hn as createAGUIBackend};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
'use strict';var core=require('@ag-ui/core'),base=require('@langchain/core/callbacks/base');function C(o){return typeof o=="object"&&o!==null}function k(o){if(o==null)return o;if(Array.isArray(o))return o.map(k);if(C(o)){if((o.lc===1||o.lc_serializable===true)&&(o.kwargs||o.lc_kwargs)){let t=o.kwargs||o.lc_kwargs;return k(t)}let e={};for(let[t,s]of Object.entries(o))t==="lc"||t==="type"||t==="id"||t.startsWith("lc_")||(e[t]=k(s));return e}return o}function R(o){if(o==null)return "";let e=o;if(typeof o=="string")try{e=JSON.parse(o);}catch{return o}if(!C(e))return String(e);let t=e.kwargs||e.lc_kwargs||e;return C(t)&&t.content!==void 0?typeof t.content=="string"?t.content:JSON.stringify(t.content):e.result!==void 0?typeof e.result=="string"?e.result:JSON.stringify(e.result):e.output!==void 0?typeof e.output=="string"?e.output:JSON.stringify(e.output):JSON.stringify(k(e))}function T(){return crypto.randomUUID()}function p(o,e){if(!o)throw new Error("baseId is required for deterministic ID generation");let t=`${o}-${e}`,s=0;for(let i=0;i<t.length;i++){let r=t.charCodeAt(i);s=(s*31+r)%2147483647;}let n=Math.abs(s).toString(16).padStart(8,"0");return `${o}-${n}`}function _(o,e){let t=e.messageId||T(),s=[];return e.role&&s.push({type:core.EventType.TEXT_MESSAGE_START,messageId:t,role:e.role}),e.delta&&s.push({type:core.EventType.TEXT_MESSAGE_CONTENT,messageId:t,delta:e.delta}),e.role&&e.delta&&s.push({type:core.EventType.TEXT_MESSAGE_END,messageId:t}),s.length>0?s:[o]}function I(o,e){let t=e.toolCallId||T(),s=[];return e.toolCallName&&s.push({type:core.EventType.TOOL_CALL_START,toolCallId:t,toolCallName:e.toolCallName,parentMessageId:e.parentMessageId}),e.delta&&s.push({type:core.EventType.TOOL_CALL_ARGS,toolCallId:t,delta:e.delta}),e.toolCallName&&e.delta&&s.push({type:core.EventType.TOOL_CALL_END,toolCallId:t,parentMessageId:e.parentMessageId}),s.length>0?s:[o]}function v(o){switch(o.type){case core.EventType.TEXT_MESSAGE_CHUNK:return _(o,o);case core.EventType.TOOL_CALL_CHUNK:return I(o,o);default:return [o]}}function A(o){return typeof o=="object"&&o!==null&&"type"in o&&o.type==="reasoning"}function S(o){let e=o;if(e._getType()!=="ai")return [];let t=e.contentBlocks;return Array.isArray(t)?t.filter(A):[]}function E(o){let e=S(o),t=new Map;for(let s of e){let n=s.index??0,i=t.get(n)??[];i.push(s),t.set(n,i);}return t}var y=class extends base.BaseCallbackHandler{name="ag-ui-callback";messageIds=new Map;latestMessageIds=new Map;startedMessageIds=new Set;agentRunIds=new Map;parentToAuthoritativeId=new Map;toolCallInfo=new Map;toolCallNames=new Map;agentTurnTracker=new Map;pendingToolCalls=new Map;accumulatedToolArgs=new Map;streamingToolCallIds=new Map;streamedReasoningRuns=new Set;openReasoningStates=new Map;warnedMissingStreamingContentBlocks=new Set;emitCallback;_enabled;_emitTextMessages;_emitToolCalls;_emitToolResults;_emitThinking;_reasoningEventMode;maxUIPayloadSize;chunkLargeResults;constructor(e){if(super({raiseError:false}),typeof e.publish!="function")throw new TypeError("publish must be a function");this.emitCallback=e.publish,this._enabled=e?.enabled??true,this._emitTextMessages=e?.emitTextMessages??true,this._emitToolCalls=e?.emitToolCalls??true,this._emitToolResults=e?.emitToolResults??true,this._emitThinking=e?.emitThinking??true,this._reasoningEventMode=e?.reasoningEventMode??"thinking",this.maxUIPayloadSize=e?.maxUIPayloadSize??50*1024,this.chunkLargeResults=e?.chunkLargeResults??false;}get enabled(){return this._enabled}set enabled(e){this._enabled=e;}get emitTextMessages(){return this._emitTextMessages}set emitTextMessages(e){this._emitTextMessages=e;}get emitToolCalls(){return this._emitToolCalls}set emitToolCalls(e){this._emitToolCalls=e;}get emitToolResults(){return this._emitToolResults}set emitToolResults(e){this._emitToolResults=e;}get emitThinking(){return this._emitThinking}set emitThinking(e){this._emitThinking=e;}get reasoningEventMode(){return this._reasoningEventMode}set reasoningEventMode(e){this._reasoningEventMode=e;}dispose(){this.messageIds.clear(),this.latestMessageIds.clear(),this.startedMessageIds.clear(),this.agentRunIds.clear(),this.parentToAuthoritativeId.clear(),this.toolCallInfo.clear(),this.toolCallNames.clear(),this.agentTurnTracker.clear(),this.pendingToolCalls.clear(),this.accumulatedToolArgs.clear(),this.streamingToolCallIds.clear(),this.streamedReasoningRuns.clear(),this.openReasoningStates.clear(),this.warnedMissingStreamingContentBlocks.clear();}emitTextChunk(e,t,s){if(!(this.enabled&&this.emitTextMessages))return;let n=v({type:core.EventType.TEXT_MESSAGE_CHUNK,messageId:e,role:t,delta:s});for(let i of n)this.emitCallback(i);}emitToolChunk(e,t,s,n){if(!(this.enabled&&this.emitToolCalls))return;let i=v({type:core.EventType.TOOL_CALL_CHUNK,toolCallId:e,toolCallName:t,delta:s,parentMessageId:n});for(let r of i)this.emitCallback(r);}handleLLMStart(e,t,s,n,i,r,a,l){if(!(this.enabled&&this.emitTextMessages))return;let d=this.getContext(i),c=this.resolveCallbackAgentRunId(s,n,a,d);this.agentRunIds.set(s,c),n&&this.parentToAuthoritativeId.set(n,c),this.prepareAssistantMessage(s,c,this.getString(a,"agui_messageId"));}handleLLMNewToken(e,t,s,n,i,r){if(!this.enabled)return;let a=this.messageIds.get(s);if(a)try{let l=this.resolveAgentRunId(s,n);this.emitStreamingReasoning(r,a,s),e&&e.length>0&&(this.closeStreamingReasoning(s),this.ensureAssistantMessageStarted(a,l)),this.emitStreamingToken(e,a),this.emitToolCalls&&this.trackStreamingToolCallArgs(r,l);}catch{}}handleLLMEnd(e,t,s,n,i){let r=this.resolveAgentRunId(t,s);if(this.collectToolCallsFromOutput(e,r),!this.enabled){let l=this.messageIds.get(t);this.cleanupOpenLifecycles(t,l),l&&this.startedMessageIds.delete(l),this.streamedReasoningRuns.delete(t),this.warnedMissingStreamingContentBlocks.delete(t),this.messageIds.delete(t),this.clearStreamingToolCallIds(r);return}let a=this.messageIds.get(t);this.streamedReasoningRuns.has(t)||this.emitThinkingFromOutput(e,a??t),this.closeStreamingReasoning(t),this.emitAssistantMessageFromOutput(e,a,r),this.emitTextMessageEnd(a),a&&this.startedMessageIds.delete(a),this.messageIds.delete(t),this.clearStreamingToolCallIds(r),this.streamedReasoningRuns.delete(t),this.warnedMissingStreamingContentBlocks.delete(t);}detectAndEmitThinking(e,t){if(!(this.emitThinking&&this.emitTextMessages)||S(e).length===0)return;let n=E(e);for(let[i,r]of n){let a=p(`${t}-reasoning-phase`,i),l=p(`${t}-reasoning-message`,i);this.reasoningEventMode==="reasoning"?(this.emitCallback({type:core.EventType.REASONING_START,messageId:a,timestamp:Date.now()}),this.emitCallback({type:core.EventType.REASONING_MESSAGE_START,messageId:l,role:"reasoning",timestamp:Date.now()})):(this.emitCallback({type:core.EventType.THINKING_START,timestamp:Date.now()}),this.emitCallback({type:core.EventType.THINKING_TEXT_MESSAGE_START,timestamp:Date.now()}));let d=r.map(c=>c.reasoning).filter(c=>c.trim().length>0).join("");d&&(this.reasoningEventMode==="reasoning"?this.emitCallback({type:core.EventType.REASONING_MESSAGE_CONTENT,messageId:l,delta:d,timestamp:Date.now()}):this.emitCallback({type:core.EventType.THINKING_TEXT_MESSAGE_CONTENT,delta:d,timestamp:Date.now()})),this.reasoningEventMode==="reasoning"?(this.emitCallback({type:core.EventType.REASONING_MESSAGE_END,messageId:l,timestamp:Date.now()}),this.emitCallback({type:core.EventType.REASONING_END,messageId:a,timestamp:Date.now()})):(this.emitCallback({type:core.EventType.THINKING_TEXT_MESSAGE_END,timestamp:Date.now()}),this.emitCallback({type:core.EventType.THINKING_END,timestamp:Date.now()}));}}handleLLMError(e,t,s){let n=this.messageIds.get(t),i=this.resolveAgentRunId(t,s);if(!this.enabled){this.cleanupOpenLifecycles(t,n),n&&this.startedMessageIds.delete(n),this.messageIds.delete(t),this.pendingToolCalls.delete(i),this.agentRunIds.delete(t),this.streamedReasoningRuns.delete(t),this.warnedMissingStreamingContentBlocks.delete(t),this.clearStreamingToolCallIds(i);return}n&&this.startedMessageIds.delete(n),this.messageIds.delete(t),this.pendingToolCalls.delete(i),this.agentRunIds.delete(t),this.closeStreamingReasoning(t),this.streamedReasoningRuns.delete(t),this.warnedMissingStreamingContentBlocks.delete(t),this.clearStreamingToolCallIds(i);}handleToolStart(e,t,s,n,i,r,a){if(!(this.enabled&&this.emitToolCalls))return;let l=this.resolveToolInput(e,t,s,r,a),d={id:l.toolCallId??s,name:l.toolCallName??this.getToolCallName(e,a)};this.toolCallInfo.set(s,d);let c=this.resolveParentAgentRunId(n),h=this.latestMessageIds.get(c);this.emitToolStartSequence(d,h,l.argsDelta);}handleToolEnd(e,t,s){if(!(this.enabled&&this.emitToolCalls))return;let n=this.toolCallInfo.get(t);this.toolCallInfo.delete(t),n?.id&&this.toolCallNames.delete(n.id);let i=this.latestMessageIds.get(this.resolveParentAgentRunId(s));try{let r=n?.id??t;this.emitCallback({type:core.EventType.TOOL_CALL_END,toolCallId:r,timestamp:Date.now()}),this.emitToolResults&&this.emitToolResultWithPolicy(e,r,i,n?.name);}catch{}}handleToolError(e,t,s){if(!(this.enabled&&this.emitToolCalls))return;let n=this.toolCallInfo.get(t);this.toolCallInfo.delete(t),n?.id&&this.accumulatedToolArgs.delete(n.id);try{this.emitCallback({type:core.EventType.TOOL_CALL_END,toolCallId:n?.id??t,timestamp:Date.now()});}catch{}}chunkString(e,t){let s=[],n=e;for(;n.length>0;){if(new Blob([n]).size<=t){s.push(n);break}let i=t,r=n.lastIndexOf(" ",t),a=n.lastIndexOf(`
|
|
2
|
+
`,t),l=Math.max(r,a);if(l>t*.5)i=l;else {for(;i>0&&n.charCodeAt(i-1)>127;)i--;i===0&&(i=t);}s.push(n.substring(0,i)),n=n.substring(i).trim();}return s}emitToolResultWithPolicy(e,t,s,n){let i=R(e),r=T(),a=new Blob([i]).size;if(a<=this.maxUIPayloadSize){this.emitCallback({type:core.EventType.TOOL_CALL_RESULT,messageId:r,toolCallId:t,content:i,role:"tool",timestamp:Date.now()});return}if(this.chunkLargeResults){let h=this.chunkString(i,this.maxUIPayloadSize);for(let f=0;f<h.length;f++)this.emitCallback({type:core.EventType.CUSTOM,name:"LARGE_RESULT_CHUNK",value:{toolCallId:t,chunk:h[f],index:f,total:h.length}});return}let l=` [Truncated: ${a-this.maxUIPayloadSize+50} bytes]`,d=this.maxUIPayloadSize-l.length,c=i.substring(0,Math.max(0,d))+l;this.emitCallback({type:core.EventType.TOOL_CALL_RESULT,messageId:r,toolCallId:t,content:c,role:"tool",timestamp:Date.now()});}asRecord(e){if(typeof e=="object"&&e!==null)return e}getString(e,t){let s=e?.[t];return typeof s=="string"?s:void 0}getContext(e){return this.asRecord(this.asRecord(e)?.options)?.context}resolveCallbackAgentRunId(e,t,s,n){return this.getString(s,"run_id")||this.getString(s,"runId")||this.getString(n,"run_id")||this.getString(n,"runId")||this.getString(s,"agui_runId")||t||e}resolveAgentRunId(e,t){return this.agentRunIds.get(e)||(t?this.parentToAuthoritativeId.get(t):void 0)||t||e}resolveParentAgentRunId(e){return (e?this.parentToAuthoritativeId.get(e):void 0)||e||""}prepareAssistantMessage(e,t,s){let n=s??this.createAssistantMessageId(t);this.messageIds.set(e,n);}ensureAssistantMessageStarted(e,t){this.startedMessageIds.has(e)||(this.startedMessageIds.add(e),this.latestMessageIds.set(t,e),this.emitCallback({type:core.EventType.TEXT_MESSAGE_START,messageId:e,role:"assistant",timestamp:Date.now()}));}createAssistantMessageId(e){let t=this.agentTurnTracker.get(e)||0;return this.agentTurnTracker.set(e,t+1),p(e,t)}emitStreamingToken(e,t){e&&e.length>0&&this.emitTextMessages&&this.emitCallback({type:core.EventType.TEXT_MESSAGE_CONTENT,messageId:t,delta:e,timestamp:Date.now()});}emitAssistantMessageFromOutput(e,t,s){if(!(t&&this.emitTextMessages)||this.startedMessageIds.has(t))return;let n=this.getOutputTextContent(e);typeof n=="string"&&n.length>0&&(this.ensureAssistantMessageStarted(t,s),this.emitStreamingToken(n,t));}trackStreamingToolCallArgs(e,t){let s=this.getToolCallChunks(e);if(s.length===0)return;let n=[...this.pendingToolCalls.get(t)||[]],i=false;for(let r of s){let a=this.resolveStreamingToolCallId(t,r);if(a){if(r.name&&this.toolCallNames.set(a,r.name),typeof r.args=="string"){let l=this.accumulatedToolArgs.get(a)||"",d=l+r.args;d!==l&&this.accumulatedToolArgs.set(a,d);}n.includes(a)||(n.push(a),i=true);}}i&&this.pendingToolCalls.set(t,n);}emitStreamingReasoning(e,t,s){if(!(this.emitThinking&&this.emitTextMessages))return;let n=this.getStreamingReasoningChunks(e,s);if(n.length!==0){this.streamedReasoningRuns.add(s);for(let i of n){let r=this.ensureStreamingReasoningState(s,t,i.index);typeof i.reasoning=="string"&&i.reasoning.length>0&&(this.reasoningEventMode==="reasoning"?this.emitCallback({type:core.EventType.REASONING_MESSAGE_CONTENT,messageId:r.messageId,delta:i.reasoning,timestamp:Date.now()}):this.emitCallback({type:core.EventType.THINKING_TEXT_MESSAGE_CONTENT,delta:i.reasoning,timestamp:Date.now()}));}}}getStreamingReasoningChunks(e,t){let n=this.asRecord(this.asRecord(e)?.chunk)?.message,i=this.asRecord(n),r=this.getStreamingContentBlocks(n);return r.length===0&&this.hasRawStreamingReasoning(i)&&this.warnMissingStreamingContentBlocks(t),r.map(a=>this.asRecord(a)).flatMap(a=>{let l=this.getString(a,"reasoning");return a?.type!=="reasoning"?[]:[{index:typeof a.index=="number"?a.index:0,reasoning:l}]})}getStreamingContentBlocks(e){let t=this.asRecord(e);return Array.isArray(t?.contentBlocks)?t.contentBlocks:[]}hasRawStreamingReasoning(e){return Array.isArray(e?.content)?e.content.some(t=>{let s=this.asRecord(t);return s?.type==="reasoning"&&typeof s.reasoning=="string"}):false}warnMissingStreamingContentBlocks(e){!e||this.warnedMissingStreamingContentBlocks.has(e)||(this.warnedMissingStreamingContentBlocks.add(e),console.warn("[AG-UI] Stream chunk exposed reasoning outside LangChain contentBlocks; reasoning events were skipped for this chunk."));}ensureStreamingReasoningState(e,t,s){let n=`${e}:${s}`,i=this.openReasoningStates.get(n);if(i)return i;let r={phaseId:p(`${t}-reasoning-phase`,s),messageId:p(`${t}-reasoning-message`,s)};return this.openReasoningStates.set(n,r),this.reasoningEventMode==="reasoning"?(this.emitCallback({type:core.EventType.REASONING_START,messageId:r.phaseId,timestamp:Date.now()}),this.emitCallback({type:core.EventType.REASONING_MESSAGE_START,messageId:r.messageId,role:"reasoning",timestamp:Date.now()})):(this.emitCallback({type:core.EventType.THINKING_START,timestamp:Date.now()}),this.emitCallback({type:core.EventType.THINKING_TEXT_MESSAGE_START,timestamp:Date.now()})),r}closeStreamingReasoning(e){let t=`${e}:`;for(let[s,n]of this.openReasoningStates)s.startsWith(t)&&(this.reasoningEventMode==="reasoning"?(this.emitCallback({type:core.EventType.REASONING_MESSAGE_END,messageId:n.messageId,timestamp:Date.now()}),this.emitCallback({type:core.EventType.REASONING_END,messageId:n.phaseId,timestamp:Date.now()})):(this.emitCallback({type:core.EventType.THINKING_TEXT_MESSAGE_END,timestamp:Date.now()}),this.emitCallback({type:core.EventType.THINKING_END,timestamp:Date.now()})),this.openReasoningStates.delete(s));}getToolCallChunks(e){let t=this.asRecord(this.asRecord(e)?.chunk),s=this.asRecord(t?.message),n=this.asRecord(s?.kwargs),i=s?.tool_call_chunks??n?.tool_call_chunks;return Array.isArray(i)?i.map(r=>{let a=this.asRecord(r);return {id:this.getString(a,"id"),name:this.getString(a,"name"),args:this.getString(a,"args"),index:typeof a?.index=="number"?a.index:void 0}}):[]}resolveStreamingToolCallId(e,t){if(t.id){let n=this.getStreamingToolCallKey(e,t.index);return n&&this.streamingToolCallIds.set(n,t.id),t.id}let s=this.getStreamingToolCallKey(e,t.index);if(s)return this.streamingToolCallIds.get(s)}getStreamingToolCallKey(e,t){if(typeof t=="number")return `${e}:${t}`}clearStreamingToolCallIds(e){let t=`${e}:`;for(let s of this.streamingToolCallIds.keys())s.startsWith(t)&&this.streamingToolCallIds.delete(s);}collectToolCallsFromOutput(e,t){try{let s=this.getOutputToolCalls(e);if(s.length===0)return;let n=[...this.pendingToolCalls.get(t)||[]];for(let i of s)i.id&&!n.includes(i.id)&&(n.push(i.id),i.function?.name&&this.toolCallNames.set(i.id,i.function.name),i.function?.arguments&&this.accumulatedToolArgs.set(i.id,i.function.arguments));this.pendingToolCalls.set(t,n);}catch{}}getOutputToolCalls(e){let t=this.asRecord(e),s=this.asRecord(t?.kwargs),n=t?.tool_calls??s?.tool_calls;if(Array.isArray(n))return n.map(l=>{let d=this.asRecord(l),c=this.asRecord(d?.function);return {id:this.getString(d,"id"),function:{name:this.getString(c,"name"),arguments:this.getString(c,"arguments")}}});let i=this.getOutputMessage(e),a=this.asRecord(i)?.tool_calls;return Array.isArray(a)?a.map(l=>{let d=this.asRecord(l),c=this.asRecord(d?.function);return {id:this.getString(d,"id"),function:{name:this.getString(c,"name")??this.getString(d,"name"),arguments:this.getString(c,"arguments")??this.stringifyIfDefined(d?.args)}}}):[]}emitThinkingFromOutput(e,t){try{let n=this.asRecord(e)?.generations;if(!Array.isArray(n)||n.length===0)return;let i=n[0];if(!Array.isArray(i)||i.length===0)return;let a=this.asRecord(i[0])?.message;if(!a)return;this.detectAndEmitThinking(a,t);}catch{}}emitTextMessageEnd(e){e&&this.startedMessageIds.has(e)&&this.emitCallback({type:core.EventType.TEXT_MESSAGE_END,messageId:e,timestamp:Date.now()});}cleanupOpenLifecycles(e,t){this.closeStreamingReasoning(e),this.emitTextMessageEnd(t);}resolveToolInput(e,t,s,n,i){let r=s,a=this.getToolCallName(e,i),l=t||void 0,d=this.getString(n,"tool_call_id");if(d)return {toolCallId:d,toolCallName:this.resolveStoredToolName(d,a),argsDelta:l};let c=this.parseToolInput(t);c&&(r=this.getString(c,"tool_call_id")||this.getString(c,"id")||r,a=this.getString(c,"name")||a,l=this.resolveToolArgsDelta(c,t));let h=r===s?this.findMatchingAccumulatedToolCallId(t):void 0;return h&&(r=h),{toolCallId:r,toolCallName:this.resolveStoredToolName(r,a),argsDelta:l}}getToolCallName(e,t){if(t)return t;let s=this.asRecord(e);if(!s)return "unknown_tool";let n=s.getName?.();return typeof n=="string"&&n.length>0?n:s.kwargs?.name||s.name||s.func?.name||s.toolName||s._name||"unknown_tool"}parseToolInput(e){if(e)try{return this.asRecord(JSON.parse(e))}catch{return}}findMatchingAccumulatedToolCallId(e){if(e){for(let[t,s]of this.accumulatedToolArgs)if(e.includes(s)||s.includes(e))return t}}resolveStoredToolName(e,t){let s=this.toolCallNames.get(e);return s&&s!=="unknown_tool"?s:t}emitToolStartSequence(e,t,s){try{this.emitCallback({type:core.EventType.TOOL_CALL_START,toolCallId:e.id,toolCallName:e.name,parentMessageId:t,timestamp:Date.now()});let n=s??this.accumulatedToolArgs.get(e.id);if(!n)return;this.emitCallback({type:core.EventType.TOOL_CALL_ARGS,toolCallId:e.id,delta:n,timestamp:Date.now()}),this.accumulatedToolArgs.delete(e.id);}catch{}}getOutputMessage(e){let s=this.asRecord(e)?.generations;if(!Array.isArray(s)||s.length===0)return;let n=s[0];if(!(!Array.isArray(n)||n.length===0))return this.asRecord(n[0])?.message}getOutputTextContent(e){let t=this.asRecord(e),s=this.getOutputMessage(e),n=this.asRecord(s),i=n?.content;if(typeof i=="string"&&i.length>0)return i;let r=this.getString(this.asRecord(n?.kwargs),"text");if(r&&r.length>0)return r;let a=n?.contentBlocks;if(Array.isArray(a)){let f=a.map(m=>this.asRecord(m)).filter(m=>m?.type==="text").map(m=>this.getString(m,"text")).filter(m=>!!(m&&m.length>0)).join("");if(f.length>0)return f}let l=Array.isArray(t?.generations)?t.generations:void 0,d=Array.isArray(l?.[0])?l[0]:void 0,h=this.asRecord(d?.[0])?.text;return typeof h=="string"&&h.length>0?h:void 0}resolveToolArgsDelta(e,t){if(typeof e.args=="string")return e.args;let s=this.stringifyIfDefined(e.args);if(s)return s;if(typeof e.arguments=="string")return e.arguments;let n=this.stringifyIfDefined(e.arguments);return n||t||void 0}stringifyIfDefined(e){if(!(typeof e>"u")){if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return}}}};exports.AGUICallbackHandler=y;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { BaseEvent } from '@ag-ui/core';
|
|
2
|
+
import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* AG-UI Callback Handler
|
|
6
|
+
*
|
|
7
|
+
* Handles streaming events for LLM tokens and tool calls.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Configuration options for the callback handler.
|
|
12
|
+
*/
|
|
13
|
+
interface AGUICallbackHandlerOptions {
|
|
14
|
+
/** Callback function for emitting AG-UI events */
|
|
15
|
+
publish: (event: BaseEvent) => void;
|
|
16
|
+
/** Master toggle - when false, no events are emitted (default: true) */
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
/** Emit TEXT_MESSAGE events: START, CONTENT, END (default: true) */
|
|
19
|
+
emitTextMessages?: boolean;
|
|
20
|
+
/** Emit TOOL_CALL events: START, ARGS, END, RESULT (default: true) */
|
|
21
|
+
emitToolCalls?: boolean;
|
|
22
|
+
/** Emit TOOL_CALL_RESULT events (default: true) */
|
|
23
|
+
emitToolResults?: boolean;
|
|
24
|
+
/** Emit THINKING events: START, TEXT_MESSAGE_*, END (default: true) */
|
|
25
|
+
emitThinking?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Reasoning migration mode.
|
|
28
|
+
* - "thinking" (default): emit deprecated THINKING_* events for backward compatibility
|
|
29
|
+
* - "reasoning": emit REASONING_* events
|
|
30
|
+
*/
|
|
31
|
+
reasoningEventMode?: "thinking" | "reasoning";
|
|
32
|
+
/** Maximum payload size in bytes for UI events (default: 50KB) */
|
|
33
|
+
maxUIPayloadSize?: number;
|
|
34
|
+
/** Whether to chunk large payloads instead of truncating */
|
|
35
|
+
chunkLargeResults?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Callback handler for AG-UI protocol streaming events.
|
|
39
|
+
* Handles LLM token streaming and tool call lifecycle events.
|
|
40
|
+
*/
|
|
41
|
+
declare class AGUICallbackHandler extends BaseCallbackHandler {
|
|
42
|
+
name: string;
|
|
43
|
+
private readonly messageIds;
|
|
44
|
+
private readonly latestMessageIds;
|
|
45
|
+
private readonly startedMessageIds;
|
|
46
|
+
private readonly agentRunIds;
|
|
47
|
+
private readonly parentToAuthoritativeId;
|
|
48
|
+
private readonly toolCallInfo;
|
|
49
|
+
private readonly toolCallNames;
|
|
50
|
+
private readonly agentTurnTracker;
|
|
51
|
+
private readonly pendingToolCalls;
|
|
52
|
+
private readonly accumulatedToolArgs;
|
|
53
|
+
private readonly streamingToolCallIds;
|
|
54
|
+
private readonly streamedReasoningRuns;
|
|
55
|
+
private readonly openReasoningStates;
|
|
56
|
+
private readonly warnedMissingStreamingContentBlocks;
|
|
57
|
+
private readonly emitCallback;
|
|
58
|
+
private _enabled;
|
|
59
|
+
private _emitTextMessages;
|
|
60
|
+
private _emitToolCalls;
|
|
61
|
+
private _emitToolResults;
|
|
62
|
+
private _emitThinking;
|
|
63
|
+
private _reasoningEventMode;
|
|
64
|
+
private readonly maxUIPayloadSize;
|
|
65
|
+
private readonly chunkLargeResults;
|
|
66
|
+
constructor(options: AGUICallbackHandlerOptions);
|
|
67
|
+
/** Master toggle - when false, no events are emitted */
|
|
68
|
+
get enabled(): boolean;
|
|
69
|
+
set enabled(value: boolean);
|
|
70
|
+
/** Control TEXT_MESSAGE event emission */
|
|
71
|
+
get emitTextMessages(): boolean;
|
|
72
|
+
set emitTextMessages(value: boolean);
|
|
73
|
+
/** Control TOOL_CALL event emission */
|
|
74
|
+
get emitToolCalls(): boolean;
|
|
75
|
+
set emitToolCalls(value: boolean);
|
|
76
|
+
/** Control TOOL_CALL_RESULT event emission */
|
|
77
|
+
get emitToolResults(): boolean;
|
|
78
|
+
set emitToolResults(value: boolean);
|
|
79
|
+
/** Control THINKING event emission */
|
|
80
|
+
get emitThinking(): boolean;
|
|
81
|
+
set emitThinking(value: boolean);
|
|
82
|
+
/** Control reasoning event family: THINKING_* (legacy) or REASONING_* (new) */
|
|
83
|
+
get reasoningEventMode(): "thinking" | "reasoning";
|
|
84
|
+
set reasoningEventMode(value: "thinking" | "reasoning");
|
|
85
|
+
dispose(): void;
|
|
86
|
+
/**
|
|
87
|
+
* Emit a TEXT_MESSAGE_CHUNK event (convenience method)
|
|
88
|
+
* Auto-expands to START → CONTENT → END lifecycle
|
|
89
|
+
*
|
|
90
|
+
* Use this for simple cases where you have the complete message at once
|
|
91
|
+
* instead of handling the streaming lifecycle manually.
|
|
92
|
+
*
|
|
93
|
+
* @param messageId - Unique message identifier (auto-generated if not provided)
|
|
94
|
+
* @param role - Message role (defaults to "assistant")
|
|
95
|
+
* @param delta - Text content to emit
|
|
96
|
+
*/
|
|
97
|
+
emitTextChunk(messageId: string, role: "assistant" | "user" | "system" | "developer", delta: string): void;
|
|
98
|
+
/**
|
|
99
|
+
* Emit a TOOL_CALL_CHUNK event (convenience method)
|
|
100
|
+
* Auto-expands to START → ARGS → END lifecycle
|
|
101
|
+
*
|
|
102
|
+
* Use this for simple tool calls where you have the complete arguments at once
|
|
103
|
+
* instead of handling the streaming lifecycle manually.
|
|
104
|
+
*
|
|
105
|
+
* @param toolCallId - Unique tool call identifier (auto-generated if not provided)
|
|
106
|
+
* @param toolCallName - Name of the tool being called
|
|
107
|
+
* @param delta - Tool arguments (JSON string)
|
|
108
|
+
* @param parentMessageId - ID of the message that triggered this tool call
|
|
109
|
+
*/
|
|
110
|
+
emitToolChunk(toolCallId: string, toolCallName: string, delta: string, parentMessageId?: string): void;
|
|
111
|
+
handleLLMStart(_llm: unknown, _prompts: string[], runId: string, parentRunId?: string, extraParams?: Record<string, unknown>, _tags?: string[], metadata?: Record<string, unknown>, _runName?: string): void;
|
|
112
|
+
handleLLMNewToken(token: string, _idx: unknown, runId: string, parentRunId?: string, _tags?: string[], fields?: unknown): void;
|
|
113
|
+
handleLLMEnd(output: unknown, runId: string, parentRunId?: string, _tags?: string[], _extraParams?: Record<string, unknown>): void;
|
|
114
|
+
/**
|
|
115
|
+
* Detect and emit thinking events from reasoning content blocks.
|
|
116
|
+
*
|
|
117
|
+
* Uses LangChain V1's contentBlocks API to extract reasoning content
|
|
118
|
+
* and emits either:
|
|
119
|
+
* - THINKING_START → THINKING_TEXT_MESSAGE_START → THINKING_TEXT_MESSAGE_CONTENT
|
|
120
|
+
* → THINKING_TEXT_MESSAGE_END → THINKING_END
|
|
121
|
+
* - REASONING_START → REASONING_MESSAGE_START → REASONING_MESSAGE_CONTENT
|
|
122
|
+
* → REASONING_MESSAGE_END → REASONING_END
|
|
123
|
+
*
|
|
124
|
+
* Supports multiple reasoning phases via index-based grouping
|
|
125
|
+
* (interleaved thinking pattern: think → respond → tool → think → respond).
|
|
126
|
+
*
|
|
127
|
+
* @param message - The final AIMessage containing reasoning blocks
|
|
128
|
+
* @param idBase - Stable ID base for deterministic phase/message IDs
|
|
129
|
+
*/
|
|
130
|
+
private detectAndEmitThinking;
|
|
131
|
+
handleLLMError(_error: Error, runId: string, parentRunId?: string): void;
|
|
132
|
+
handleToolStart(tool: unknown, input: string, runId: string, parentRunId?: string, _tags?: string[], metadata?: Record<string, unknown>, runName?: string): void;
|
|
133
|
+
handleToolEnd(output: unknown, runId: string, parentRunId?: string): void;
|
|
134
|
+
handleToolError(_error: Error, runId: string, _parentRunId?: string): void;
|
|
135
|
+
private chunkString;
|
|
136
|
+
private emitToolResultWithPolicy;
|
|
137
|
+
private asRecord;
|
|
138
|
+
private getString;
|
|
139
|
+
private getContext;
|
|
140
|
+
private resolveCallbackAgentRunId;
|
|
141
|
+
private resolveAgentRunId;
|
|
142
|
+
private resolveParentAgentRunId;
|
|
143
|
+
private prepareAssistantMessage;
|
|
144
|
+
private ensureAssistantMessageStarted;
|
|
145
|
+
private createAssistantMessageId;
|
|
146
|
+
private emitStreamingToken;
|
|
147
|
+
private emitAssistantMessageFromOutput;
|
|
148
|
+
private trackStreamingToolCallArgs;
|
|
149
|
+
private emitStreamingReasoning;
|
|
150
|
+
private getStreamingReasoningChunks;
|
|
151
|
+
private getStreamingContentBlocks;
|
|
152
|
+
private hasRawStreamingReasoning;
|
|
153
|
+
private warnMissingStreamingContentBlocks;
|
|
154
|
+
private ensureStreamingReasoningState;
|
|
155
|
+
private closeStreamingReasoning;
|
|
156
|
+
private getToolCallChunks;
|
|
157
|
+
private resolveStreamingToolCallId;
|
|
158
|
+
private getStreamingToolCallKey;
|
|
159
|
+
private clearStreamingToolCallIds;
|
|
160
|
+
private collectToolCallsFromOutput;
|
|
161
|
+
private getOutputToolCalls;
|
|
162
|
+
private emitThinkingFromOutput;
|
|
163
|
+
private emitTextMessageEnd;
|
|
164
|
+
private cleanupOpenLifecycles;
|
|
165
|
+
private resolveToolInput;
|
|
166
|
+
private getToolCallName;
|
|
167
|
+
private parseToolInput;
|
|
168
|
+
private findMatchingAccumulatedToolCallId;
|
|
169
|
+
private resolveStoredToolName;
|
|
170
|
+
private emitToolStartSequence;
|
|
171
|
+
private getOutputMessage;
|
|
172
|
+
private getOutputTextContent;
|
|
173
|
+
private resolveToolArgsDelta;
|
|
174
|
+
private stringifyIfDefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export { AGUICallbackHandler, type AGUICallbackHandlerOptions };
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { BaseEvent } from '@ag-ui/core';
|
|
2
|
+
import { BaseCallbackHandler } from '@langchain/core/callbacks/base';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* AG-UI Callback Handler
|
|
6
|
+
*
|
|
7
|
+
* Handles streaming events for LLM tokens and tool calls.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Configuration options for the callback handler.
|
|
12
|
+
*/
|
|
13
|
+
interface AGUICallbackHandlerOptions {
|
|
14
|
+
/** Callback function for emitting AG-UI events */
|
|
15
|
+
publish: (event: BaseEvent) => void;
|
|
16
|
+
/** Master toggle - when false, no events are emitted (default: true) */
|
|
17
|
+
enabled?: boolean;
|
|
18
|
+
/** Emit TEXT_MESSAGE events: START, CONTENT, END (default: true) */
|
|
19
|
+
emitTextMessages?: boolean;
|
|
20
|
+
/** Emit TOOL_CALL events: START, ARGS, END, RESULT (default: true) */
|
|
21
|
+
emitToolCalls?: boolean;
|
|
22
|
+
/** Emit TOOL_CALL_RESULT events (default: true) */
|
|
23
|
+
emitToolResults?: boolean;
|
|
24
|
+
/** Emit THINKING events: START, TEXT_MESSAGE_*, END (default: true) */
|
|
25
|
+
emitThinking?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Reasoning migration mode.
|
|
28
|
+
* - "thinking" (default): emit deprecated THINKING_* events for backward compatibility
|
|
29
|
+
* - "reasoning": emit REASONING_* events
|
|
30
|
+
*/
|
|
31
|
+
reasoningEventMode?: "thinking" | "reasoning";
|
|
32
|
+
/** Maximum payload size in bytes for UI events (default: 50KB) */
|
|
33
|
+
maxUIPayloadSize?: number;
|
|
34
|
+
/** Whether to chunk large payloads instead of truncating */
|
|
35
|
+
chunkLargeResults?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Callback handler for AG-UI protocol streaming events.
|
|
39
|
+
* Handles LLM token streaming and tool call lifecycle events.
|
|
40
|
+
*/
|
|
41
|
+
declare class AGUICallbackHandler extends BaseCallbackHandler {
|
|
42
|
+
name: string;
|
|
43
|
+
private readonly messageIds;
|
|
44
|
+
private readonly latestMessageIds;
|
|
45
|
+
private readonly startedMessageIds;
|
|
46
|
+
private readonly agentRunIds;
|
|
47
|
+
private readonly parentToAuthoritativeId;
|
|
48
|
+
private readonly toolCallInfo;
|
|
49
|
+
private readonly toolCallNames;
|
|
50
|
+
private readonly agentTurnTracker;
|
|
51
|
+
private readonly pendingToolCalls;
|
|
52
|
+
private readonly accumulatedToolArgs;
|
|
53
|
+
private readonly streamingToolCallIds;
|
|
54
|
+
private readonly streamedReasoningRuns;
|
|
55
|
+
private readonly openReasoningStates;
|
|
56
|
+
private readonly warnedMissingStreamingContentBlocks;
|
|
57
|
+
private readonly emitCallback;
|
|
58
|
+
private _enabled;
|
|
59
|
+
private _emitTextMessages;
|
|
60
|
+
private _emitToolCalls;
|
|
61
|
+
private _emitToolResults;
|
|
62
|
+
private _emitThinking;
|
|
63
|
+
private _reasoningEventMode;
|
|
64
|
+
private readonly maxUIPayloadSize;
|
|
65
|
+
private readonly chunkLargeResults;
|
|
66
|
+
constructor(options: AGUICallbackHandlerOptions);
|
|
67
|
+
/** Master toggle - when false, no events are emitted */
|
|
68
|
+
get enabled(): boolean;
|
|
69
|
+
set enabled(value: boolean);
|
|
70
|
+
/** Control TEXT_MESSAGE event emission */
|
|
71
|
+
get emitTextMessages(): boolean;
|
|
72
|
+
set emitTextMessages(value: boolean);
|
|
73
|
+
/** Control TOOL_CALL event emission */
|
|
74
|
+
get emitToolCalls(): boolean;
|
|
75
|
+
set emitToolCalls(value: boolean);
|
|
76
|
+
/** Control TOOL_CALL_RESULT event emission */
|
|
77
|
+
get emitToolResults(): boolean;
|
|
78
|
+
set emitToolResults(value: boolean);
|
|
79
|
+
/** Control THINKING event emission */
|
|
80
|
+
get emitThinking(): boolean;
|
|
81
|
+
set emitThinking(value: boolean);
|
|
82
|
+
/** Control reasoning event family: THINKING_* (legacy) or REASONING_* (new) */
|
|
83
|
+
get reasoningEventMode(): "thinking" | "reasoning";
|
|
84
|
+
set reasoningEventMode(value: "thinking" | "reasoning");
|
|
85
|
+
dispose(): void;
|
|
86
|
+
/**
|
|
87
|
+
* Emit a TEXT_MESSAGE_CHUNK event (convenience method)
|
|
88
|
+
* Auto-expands to START → CONTENT → END lifecycle
|
|
89
|
+
*
|
|
90
|
+
* Use this for simple cases where you have the complete message at once
|
|
91
|
+
* instead of handling the streaming lifecycle manually.
|
|
92
|
+
*
|
|
93
|
+
* @param messageId - Unique message identifier (auto-generated if not provided)
|
|
94
|
+
* @param role - Message role (defaults to "assistant")
|
|
95
|
+
* @param delta - Text content to emit
|
|
96
|
+
*/
|
|
97
|
+
emitTextChunk(messageId: string, role: "assistant" | "user" | "system" | "developer", delta: string): void;
|
|
98
|
+
/**
|
|
99
|
+
* Emit a TOOL_CALL_CHUNK event (convenience method)
|
|
100
|
+
* Auto-expands to START → ARGS → END lifecycle
|
|
101
|
+
*
|
|
102
|
+
* Use this for simple tool calls where you have the complete arguments at once
|
|
103
|
+
* instead of handling the streaming lifecycle manually.
|
|
104
|
+
*
|
|
105
|
+
* @param toolCallId - Unique tool call identifier (auto-generated if not provided)
|
|
106
|
+
* @param toolCallName - Name of the tool being called
|
|
107
|
+
* @param delta - Tool arguments (JSON string)
|
|
108
|
+
* @param parentMessageId - ID of the message that triggered this tool call
|
|
109
|
+
*/
|
|
110
|
+
emitToolChunk(toolCallId: string, toolCallName: string, delta: string, parentMessageId?: string): void;
|
|
111
|
+
handleLLMStart(_llm: unknown, _prompts: string[], runId: string, parentRunId?: string, extraParams?: Record<string, unknown>, _tags?: string[], metadata?: Record<string, unknown>, _runName?: string): void;
|
|
112
|
+
handleLLMNewToken(token: string, _idx: unknown, runId: string, parentRunId?: string, _tags?: string[], fields?: unknown): void;
|
|
113
|
+
handleLLMEnd(output: unknown, runId: string, parentRunId?: string, _tags?: string[], _extraParams?: Record<string, unknown>): void;
|
|
114
|
+
/**
|
|
115
|
+
* Detect and emit thinking events from reasoning content blocks.
|
|
116
|
+
*
|
|
117
|
+
* Uses LangChain V1's contentBlocks API to extract reasoning content
|
|
118
|
+
* and emits either:
|
|
119
|
+
* - THINKING_START → THINKING_TEXT_MESSAGE_START → THINKING_TEXT_MESSAGE_CONTENT
|
|
120
|
+
* → THINKING_TEXT_MESSAGE_END → THINKING_END
|
|
121
|
+
* - REASONING_START → REASONING_MESSAGE_START → REASONING_MESSAGE_CONTENT
|
|
122
|
+
* → REASONING_MESSAGE_END → REASONING_END
|
|
123
|
+
*
|
|
124
|
+
* Supports multiple reasoning phases via index-based grouping
|
|
125
|
+
* (interleaved thinking pattern: think → respond → tool → think → respond).
|
|
126
|
+
*
|
|
127
|
+
* @param message - The final AIMessage containing reasoning blocks
|
|
128
|
+
* @param idBase - Stable ID base for deterministic phase/message IDs
|
|
129
|
+
*/
|
|
130
|
+
private detectAndEmitThinking;
|
|
131
|
+
handleLLMError(_error: Error, runId: string, parentRunId?: string): void;
|
|
132
|
+
handleToolStart(tool: unknown, input: string, runId: string, parentRunId?: string, _tags?: string[], metadata?: Record<string, unknown>, runName?: string): void;
|
|
133
|
+
handleToolEnd(output: unknown, runId: string, parentRunId?: string): void;
|
|
134
|
+
handleToolError(_error: Error, runId: string, _parentRunId?: string): void;
|
|
135
|
+
private chunkString;
|
|
136
|
+
private emitToolResultWithPolicy;
|
|
137
|
+
private asRecord;
|
|
138
|
+
private getString;
|
|
139
|
+
private getContext;
|
|
140
|
+
private resolveCallbackAgentRunId;
|
|
141
|
+
private resolveAgentRunId;
|
|
142
|
+
private resolveParentAgentRunId;
|
|
143
|
+
private prepareAssistantMessage;
|
|
144
|
+
private ensureAssistantMessageStarted;
|
|
145
|
+
private createAssistantMessageId;
|
|
146
|
+
private emitStreamingToken;
|
|
147
|
+
private emitAssistantMessageFromOutput;
|
|
148
|
+
private trackStreamingToolCallArgs;
|
|
149
|
+
private emitStreamingReasoning;
|
|
150
|
+
private getStreamingReasoningChunks;
|
|
151
|
+
private getStreamingContentBlocks;
|
|
152
|
+
private hasRawStreamingReasoning;
|
|
153
|
+
private warnMissingStreamingContentBlocks;
|
|
154
|
+
private ensureStreamingReasoningState;
|
|
155
|
+
private closeStreamingReasoning;
|
|
156
|
+
private getToolCallChunks;
|
|
157
|
+
private resolveStreamingToolCallId;
|
|
158
|
+
private getStreamingToolCallKey;
|
|
159
|
+
private clearStreamingToolCallIds;
|
|
160
|
+
private collectToolCallsFromOutput;
|
|
161
|
+
private getOutputToolCalls;
|
|
162
|
+
private emitThinkingFromOutput;
|
|
163
|
+
private emitTextMessageEnd;
|
|
164
|
+
private cleanupOpenLifecycles;
|
|
165
|
+
private resolveToolInput;
|
|
166
|
+
private getToolCallName;
|
|
167
|
+
private parseToolInput;
|
|
168
|
+
private findMatchingAccumulatedToolCallId;
|
|
169
|
+
private resolveStoredToolName;
|
|
170
|
+
private emitToolStartSequence;
|
|
171
|
+
private getOutputMessage;
|
|
172
|
+
private getOutputTextContent;
|
|
173
|
+
private resolveToolArgsDelta;
|
|
174
|
+
private stringifyIfDefined;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
export { AGUICallbackHandler, type AGUICallbackHandlerOptions };
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import {EventType}from'@ag-ui/core';import {BaseCallbackHandler}from'@langchain/core/callbacks/base';function C(o){return typeof o=="object"&&o!==null}function k(o){if(o==null)return o;if(Array.isArray(o))return o.map(k);if(C(o)){if((o.lc===1||o.lc_serializable===true)&&(o.kwargs||o.lc_kwargs)){let t=o.kwargs||o.lc_kwargs;return k(t)}let e={};for(let[t,s]of Object.entries(o))t==="lc"||t==="type"||t==="id"||t.startsWith("lc_")||(e[t]=k(s));return e}return o}function R(o){if(o==null)return "";let e=o;if(typeof o=="string")try{e=JSON.parse(o);}catch{return o}if(!C(e))return String(e);let t=e.kwargs||e.lc_kwargs||e;return C(t)&&t.content!==void 0?typeof t.content=="string"?t.content:JSON.stringify(t.content):e.result!==void 0?typeof e.result=="string"?e.result:JSON.stringify(e.result):e.output!==void 0?typeof e.output=="string"?e.output:JSON.stringify(e.output):JSON.stringify(k(e))}function T(){return crypto.randomUUID()}function p(o,e){if(!o)throw new Error("baseId is required for deterministic ID generation");let t=`${o}-${e}`,s=0;for(let i=0;i<t.length;i++){let r=t.charCodeAt(i);s=(s*31+r)%2147483647;}let n=Math.abs(s).toString(16).padStart(8,"0");return `${o}-${n}`}function _(o,e){let t=e.messageId||T(),s=[];return e.role&&s.push({type:EventType.TEXT_MESSAGE_START,messageId:t,role:e.role}),e.delta&&s.push({type:EventType.TEXT_MESSAGE_CONTENT,messageId:t,delta:e.delta}),e.role&&e.delta&&s.push({type:EventType.TEXT_MESSAGE_END,messageId:t}),s.length>0?s:[o]}function I(o,e){let t=e.toolCallId||T(),s=[];return e.toolCallName&&s.push({type:EventType.TOOL_CALL_START,toolCallId:t,toolCallName:e.toolCallName,parentMessageId:e.parentMessageId}),e.delta&&s.push({type:EventType.TOOL_CALL_ARGS,toolCallId:t,delta:e.delta}),e.toolCallName&&e.delta&&s.push({type:EventType.TOOL_CALL_END,toolCallId:t,parentMessageId:e.parentMessageId}),s.length>0?s:[o]}function v(o){switch(o.type){case EventType.TEXT_MESSAGE_CHUNK:return _(o,o);case EventType.TOOL_CALL_CHUNK:return I(o,o);default:return [o]}}function A(o){return typeof o=="object"&&o!==null&&"type"in o&&o.type==="reasoning"}function S(o){let e=o;if(e._getType()!=="ai")return [];let t=e.contentBlocks;return Array.isArray(t)?t.filter(A):[]}function E(o){let e=S(o),t=new Map;for(let s of e){let n=s.index??0,i=t.get(n)??[];i.push(s),t.set(n,i);}return t}var y=class extends BaseCallbackHandler{name="ag-ui-callback";messageIds=new Map;latestMessageIds=new Map;startedMessageIds=new Set;agentRunIds=new Map;parentToAuthoritativeId=new Map;toolCallInfo=new Map;toolCallNames=new Map;agentTurnTracker=new Map;pendingToolCalls=new Map;accumulatedToolArgs=new Map;streamingToolCallIds=new Map;streamedReasoningRuns=new Set;openReasoningStates=new Map;warnedMissingStreamingContentBlocks=new Set;emitCallback;_enabled;_emitTextMessages;_emitToolCalls;_emitToolResults;_emitThinking;_reasoningEventMode;maxUIPayloadSize;chunkLargeResults;constructor(e){if(super({raiseError:false}),typeof e.publish!="function")throw new TypeError("publish must be a function");this.emitCallback=e.publish,this._enabled=e?.enabled??true,this._emitTextMessages=e?.emitTextMessages??true,this._emitToolCalls=e?.emitToolCalls??true,this._emitToolResults=e?.emitToolResults??true,this._emitThinking=e?.emitThinking??true,this._reasoningEventMode=e?.reasoningEventMode??"thinking",this.maxUIPayloadSize=e?.maxUIPayloadSize??50*1024,this.chunkLargeResults=e?.chunkLargeResults??false;}get enabled(){return this._enabled}set enabled(e){this._enabled=e;}get emitTextMessages(){return this._emitTextMessages}set emitTextMessages(e){this._emitTextMessages=e;}get emitToolCalls(){return this._emitToolCalls}set emitToolCalls(e){this._emitToolCalls=e;}get emitToolResults(){return this._emitToolResults}set emitToolResults(e){this._emitToolResults=e;}get emitThinking(){return this._emitThinking}set emitThinking(e){this._emitThinking=e;}get reasoningEventMode(){return this._reasoningEventMode}set reasoningEventMode(e){this._reasoningEventMode=e;}dispose(){this.messageIds.clear(),this.latestMessageIds.clear(),this.startedMessageIds.clear(),this.agentRunIds.clear(),this.parentToAuthoritativeId.clear(),this.toolCallInfo.clear(),this.toolCallNames.clear(),this.agentTurnTracker.clear(),this.pendingToolCalls.clear(),this.accumulatedToolArgs.clear(),this.streamingToolCallIds.clear(),this.streamedReasoningRuns.clear(),this.openReasoningStates.clear(),this.warnedMissingStreamingContentBlocks.clear();}emitTextChunk(e,t,s){if(!(this.enabled&&this.emitTextMessages))return;let n=v({type:EventType.TEXT_MESSAGE_CHUNK,messageId:e,role:t,delta:s});for(let i of n)this.emitCallback(i);}emitToolChunk(e,t,s,n){if(!(this.enabled&&this.emitToolCalls))return;let i=v({type:EventType.TOOL_CALL_CHUNK,toolCallId:e,toolCallName:t,delta:s,parentMessageId:n});for(let r of i)this.emitCallback(r);}handleLLMStart(e,t,s,n,i,r,a,l){if(!(this.enabled&&this.emitTextMessages))return;let d=this.getContext(i),c=this.resolveCallbackAgentRunId(s,n,a,d);this.agentRunIds.set(s,c),n&&this.parentToAuthoritativeId.set(n,c),this.prepareAssistantMessage(s,c,this.getString(a,"agui_messageId"));}handleLLMNewToken(e,t,s,n,i,r){if(!this.enabled)return;let a=this.messageIds.get(s);if(a)try{let l=this.resolveAgentRunId(s,n);this.emitStreamingReasoning(r,a,s),e&&e.length>0&&(this.closeStreamingReasoning(s),this.ensureAssistantMessageStarted(a,l)),this.emitStreamingToken(e,a),this.emitToolCalls&&this.trackStreamingToolCallArgs(r,l);}catch{}}handleLLMEnd(e,t,s,n,i){let r=this.resolveAgentRunId(t,s);if(this.collectToolCallsFromOutput(e,r),!this.enabled){let l=this.messageIds.get(t);this.cleanupOpenLifecycles(t,l),l&&this.startedMessageIds.delete(l),this.streamedReasoningRuns.delete(t),this.warnedMissingStreamingContentBlocks.delete(t),this.messageIds.delete(t),this.clearStreamingToolCallIds(r);return}let a=this.messageIds.get(t);this.streamedReasoningRuns.has(t)||this.emitThinkingFromOutput(e,a??t),this.closeStreamingReasoning(t),this.emitAssistantMessageFromOutput(e,a,r),this.emitTextMessageEnd(a),a&&this.startedMessageIds.delete(a),this.messageIds.delete(t),this.clearStreamingToolCallIds(r),this.streamedReasoningRuns.delete(t),this.warnedMissingStreamingContentBlocks.delete(t);}detectAndEmitThinking(e,t){if(!(this.emitThinking&&this.emitTextMessages)||S(e).length===0)return;let n=E(e);for(let[i,r]of n){let a=p(`${t}-reasoning-phase`,i),l=p(`${t}-reasoning-message`,i);this.reasoningEventMode==="reasoning"?(this.emitCallback({type:EventType.REASONING_START,messageId:a,timestamp:Date.now()}),this.emitCallback({type:EventType.REASONING_MESSAGE_START,messageId:l,role:"reasoning",timestamp:Date.now()})):(this.emitCallback({type:EventType.THINKING_START,timestamp:Date.now()}),this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_START,timestamp:Date.now()}));let d=r.map(c=>c.reasoning).filter(c=>c.trim().length>0).join("");d&&(this.reasoningEventMode==="reasoning"?this.emitCallback({type:EventType.REASONING_MESSAGE_CONTENT,messageId:l,delta:d,timestamp:Date.now()}):this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_CONTENT,delta:d,timestamp:Date.now()})),this.reasoningEventMode==="reasoning"?(this.emitCallback({type:EventType.REASONING_MESSAGE_END,messageId:l,timestamp:Date.now()}),this.emitCallback({type:EventType.REASONING_END,messageId:a,timestamp:Date.now()})):(this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_END,timestamp:Date.now()}),this.emitCallback({type:EventType.THINKING_END,timestamp:Date.now()}));}}handleLLMError(e,t,s){let n=this.messageIds.get(t),i=this.resolveAgentRunId(t,s);if(!this.enabled){this.cleanupOpenLifecycles(t,n),n&&this.startedMessageIds.delete(n),this.messageIds.delete(t),this.pendingToolCalls.delete(i),this.agentRunIds.delete(t),this.streamedReasoningRuns.delete(t),this.warnedMissingStreamingContentBlocks.delete(t),this.clearStreamingToolCallIds(i);return}n&&this.startedMessageIds.delete(n),this.messageIds.delete(t),this.pendingToolCalls.delete(i),this.agentRunIds.delete(t),this.closeStreamingReasoning(t),this.streamedReasoningRuns.delete(t),this.warnedMissingStreamingContentBlocks.delete(t),this.clearStreamingToolCallIds(i);}handleToolStart(e,t,s,n,i,r,a){if(!(this.enabled&&this.emitToolCalls))return;let l=this.resolveToolInput(e,t,s,r,a),d={id:l.toolCallId??s,name:l.toolCallName??this.getToolCallName(e,a)};this.toolCallInfo.set(s,d);let c=this.resolveParentAgentRunId(n),h=this.latestMessageIds.get(c);this.emitToolStartSequence(d,h,l.argsDelta);}handleToolEnd(e,t,s){if(!(this.enabled&&this.emitToolCalls))return;let n=this.toolCallInfo.get(t);this.toolCallInfo.delete(t),n?.id&&this.toolCallNames.delete(n.id);let i=this.latestMessageIds.get(this.resolveParentAgentRunId(s));try{let r=n?.id??t;this.emitCallback({type:EventType.TOOL_CALL_END,toolCallId:r,timestamp:Date.now()}),this.emitToolResults&&this.emitToolResultWithPolicy(e,r,i,n?.name);}catch{}}handleToolError(e,t,s){if(!(this.enabled&&this.emitToolCalls))return;let n=this.toolCallInfo.get(t);this.toolCallInfo.delete(t),n?.id&&this.accumulatedToolArgs.delete(n.id);try{this.emitCallback({type:EventType.TOOL_CALL_END,toolCallId:n?.id??t,timestamp:Date.now()});}catch{}}chunkString(e,t){let s=[],n=e;for(;n.length>0;){if(new Blob([n]).size<=t){s.push(n);break}let i=t,r=n.lastIndexOf(" ",t),a=n.lastIndexOf(`
|
|
2
|
+
`,t),l=Math.max(r,a);if(l>t*.5)i=l;else {for(;i>0&&n.charCodeAt(i-1)>127;)i--;i===0&&(i=t);}s.push(n.substring(0,i)),n=n.substring(i).trim();}return s}emitToolResultWithPolicy(e,t,s,n){let i=R(e),r=T(),a=new Blob([i]).size;if(a<=this.maxUIPayloadSize){this.emitCallback({type:EventType.TOOL_CALL_RESULT,messageId:r,toolCallId:t,content:i,role:"tool",timestamp:Date.now()});return}if(this.chunkLargeResults){let h=this.chunkString(i,this.maxUIPayloadSize);for(let f=0;f<h.length;f++)this.emitCallback({type:EventType.CUSTOM,name:"LARGE_RESULT_CHUNK",value:{toolCallId:t,chunk:h[f],index:f,total:h.length}});return}let l=` [Truncated: ${a-this.maxUIPayloadSize+50} bytes]`,d=this.maxUIPayloadSize-l.length,c=i.substring(0,Math.max(0,d))+l;this.emitCallback({type:EventType.TOOL_CALL_RESULT,messageId:r,toolCallId:t,content:c,role:"tool",timestamp:Date.now()});}asRecord(e){if(typeof e=="object"&&e!==null)return e}getString(e,t){let s=e?.[t];return typeof s=="string"?s:void 0}getContext(e){return this.asRecord(this.asRecord(e)?.options)?.context}resolveCallbackAgentRunId(e,t,s,n){return this.getString(s,"run_id")||this.getString(s,"runId")||this.getString(n,"run_id")||this.getString(n,"runId")||this.getString(s,"agui_runId")||t||e}resolveAgentRunId(e,t){return this.agentRunIds.get(e)||(t?this.parentToAuthoritativeId.get(t):void 0)||t||e}resolveParentAgentRunId(e){return (e?this.parentToAuthoritativeId.get(e):void 0)||e||""}prepareAssistantMessage(e,t,s){let n=s??this.createAssistantMessageId(t);this.messageIds.set(e,n);}ensureAssistantMessageStarted(e,t){this.startedMessageIds.has(e)||(this.startedMessageIds.add(e),this.latestMessageIds.set(t,e),this.emitCallback({type:EventType.TEXT_MESSAGE_START,messageId:e,role:"assistant",timestamp:Date.now()}));}createAssistantMessageId(e){let t=this.agentTurnTracker.get(e)||0;return this.agentTurnTracker.set(e,t+1),p(e,t)}emitStreamingToken(e,t){e&&e.length>0&&this.emitTextMessages&&this.emitCallback({type:EventType.TEXT_MESSAGE_CONTENT,messageId:t,delta:e,timestamp:Date.now()});}emitAssistantMessageFromOutput(e,t,s){if(!(t&&this.emitTextMessages)||this.startedMessageIds.has(t))return;let n=this.getOutputTextContent(e);typeof n=="string"&&n.length>0&&(this.ensureAssistantMessageStarted(t,s),this.emitStreamingToken(n,t));}trackStreamingToolCallArgs(e,t){let s=this.getToolCallChunks(e);if(s.length===0)return;let n=[...this.pendingToolCalls.get(t)||[]],i=false;for(let r of s){let a=this.resolveStreamingToolCallId(t,r);if(a){if(r.name&&this.toolCallNames.set(a,r.name),typeof r.args=="string"){let l=this.accumulatedToolArgs.get(a)||"",d=l+r.args;d!==l&&this.accumulatedToolArgs.set(a,d);}n.includes(a)||(n.push(a),i=true);}}i&&this.pendingToolCalls.set(t,n);}emitStreamingReasoning(e,t,s){if(!(this.emitThinking&&this.emitTextMessages))return;let n=this.getStreamingReasoningChunks(e,s);if(n.length!==0){this.streamedReasoningRuns.add(s);for(let i of n){let r=this.ensureStreamingReasoningState(s,t,i.index);typeof i.reasoning=="string"&&i.reasoning.length>0&&(this.reasoningEventMode==="reasoning"?this.emitCallback({type:EventType.REASONING_MESSAGE_CONTENT,messageId:r.messageId,delta:i.reasoning,timestamp:Date.now()}):this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_CONTENT,delta:i.reasoning,timestamp:Date.now()}));}}}getStreamingReasoningChunks(e,t){let n=this.asRecord(this.asRecord(e)?.chunk)?.message,i=this.asRecord(n),r=this.getStreamingContentBlocks(n);return r.length===0&&this.hasRawStreamingReasoning(i)&&this.warnMissingStreamingContentBlocks(t),r.map(a=>this.asRecord(a)).flatMap(a=>{let l=this.getString(a,"reasoning");return a?.type!=="reasoning"?[]:[{index:typeof a.index=="number"?a.index:0,reasoning:l}]})}getStreamingContentBlocks(e){let t=this.asRecord(e);return Array.isArray(t?.contentBlocks)?t.contentBlocks:[]}hasRawStreamingReasoning(e){return Array.isArray(e?.content)?e.content.some(t=>{let s=this.asRecord(t);return s?.type==="reasoning"&&typeof s.reasoning=="string"}):false}warnMissingStreamingContentBlocks(e){!e||this.warnedMissingStreamingContentBlocks.has(e)||(this.warnedMissingStreamingContentBlocks.add(e),console.warn("[AG-UI] Stream chunk exposed reasoning outside LangChain contentBlocks; reasoning events were skipped for this chunk."));}ensureStreamingReasoningState(e,t,s){let n=`${e}:${s}`,i=this.openReasoningStates.get(n);if(i)return i;let r={phaseId:p(`${t}-reasoning-phase`,s),messageId:p(`${t}-reasoning-message`,s)};return this.openReasoningStates.set(n,r),this.reasoningEventMode==="reasoning"?(this.emitCallback({type:EventType.REASONING_START,messageId:r.phaseId,timestamp:Date.now()}),this.emitCallback({type:EventType.REASONING_MESSAGE_START,messageId:r.messageId,role:"reasoning",timestamp:Date.now()})):(this.emitCallback({type:EventType.THINKING_START,timestamp:Date.now()}),this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_START,timestamp:Date.now()})),r}closeStreamingReasoning(e){let t=`${e}:`;for(let[s,n]of this.openReasoningStates)s.startsWith(t)&&(this.reasoningEventMode==="reasoning"?(this.emitCallback({type:EventType.REASONING_MESSAGE_END,messageId:n.messageId,timestamp:Date.now()}),this.emitCallback({type:EventType.REASONING_END,messageId:n.phaseId,timestamp:Date.now()})):(this.emitCallback({type:EventType.THINKING_TEXT_MESSAGE_END,timestamp:Date.now()}),this.emitCallback({type:EventType.THINKING_END,timestamp:Date.now()})),this.openReasoningStates.delete(s));}getToolCallChunks(e){let t=this.asRecord(this.asRecord(e)?.chunk),s=this.asRecord(t?.message),n=this.asRecord(s?.kwargs),i=s?.tool_call_chunks??n?.tool_call_chunks;return Array.isArray(i)?i.map(r=>{let a=this.asRecord(r);return {id:this.getString(a,"id"),name:this.getString(a,"name"),args:this.getString(a,"args"),index:typeof a?.index=="number"?a.index:void 0}}):[]}resolveStreamingToolCallId(e,t){if(t.id){let n=this.getStreamingToolCallKey(e,t.index);return n&&this.streamingToolCallIds.set(n,t.id),t.id}let s=this.getStreamingToolCallKey(e,t.index);if(s)return this.streamingToolCallIds.get(s)}getStreamingToolCallKey(e,t){if(typeof t=="number")return `${e}:${t}`}clearStreamingToolCallIds(e){let t=`${e}:`;for(let s of this.streamingToolCallIds.keys())s.startsWith(t)&&this.streamingToolCallIds.delete(s);}collectToolCallsFromOutput(e,t){try{let s=this.getOutputToolCalls(e);if(s.length===0)return;let n=[...this.pendingToolCalls.get(t)||[]];for(let i of s)i.id&&!n.includes(i.id)&&(n.push(i.id),i.function?.name&&this.toolCallNames.set(i.id,i.function.name),i.function?.arguments&&this.accumulatedToolArgs.set(i.id,i.function.arguments));this.pendingToolCalls.set(t,n);}catch{}}getOutputToolCalls(e){let t=this.asRecord(e),s=this.asRecord(t?.kwargs),n=t?.tool_calls??s?.tool_calls;if(Array.isArray(n))return n.map(l=>{let d=this.asRecord(l),c=this.asRecord(d?.function);return {id:this.getString(d,"id"),function:{name:this.getString(c,"name"),arguments:this.getString(c,"arguments")}}});let i=this.getOutputMessage(e),a=this.asRecord(i)?.tool_calls;return Array.isArray(a)?a.map(l=>{let d=this.asRecord(l),c=this.asRecord(d?.function);return {id:this.getString(d,"id"),function:{name:this.getString(c,"name")??this.getString(d,"name"),arguments:this.getString(c,"arguments")??this.stringifyIfDefined(d?.args)}}}):[]}emitThinkingFromOutput(e,t){try{let n=this.asRecord(e)?.generations;if(!Array.isArray(n)||n.length===0)return;let i=n[0];if(!Array.isArray(i)||i.length===0)return;let a=this.asRecord(i[0])?.message;if(!a)return;this.detectAndEmitThinking(a,t);}catch{}}emitTextMessageEnd(e){e&&this.startedMessageIds.has(e)&&this.emitCallback({type:EventType.TEXT_MESSAGE_END,messageId:e,timestamp:Date.now()});}cleanupOpenLifecycles(e,t){this.closeStreamingReasoning(e),this.emitTextMessageEnd(t);}resolveToolInput(e,t,s,n,i){let r=s,a=this.getToolCallName(e,i),l=t||void 0,d=this.getString(n,"tool_call_id");if(d)return {toolCallId:d,toolCallName:this.resolveStoredToolName(d,a),argsDelta:l};let c=this.parseToolInput(t);c&&(r=this.getString(c,"tool_call_id")||this.getString(c,"id")||r,a=this.getString(c,"name")||a,l=this.resolveToolArgsDelta(c,t));let h=r===s?this.findMatchingAccumulatedToolCallId(t):void 0;return h&&(r=h),{toolCallId:r,toolCallName:this.resolveStoredToolName(r,a),argsDelta:l}}getToolCallName(e,t){if(t)return t;let s=this.asRecord(e);if(!s)return "unknown_tool";let n=s.getName?.();return typeof n=="string"&&n.length>0?n:s.kwargs?.name||s.name||s.func?.name||s.toolName||s._name||"unknown_tool"}parseToolInput(e){if(e)try{return this.asRecord(JSON.parse(e))}catch{return}}findMatchingAccumulatedToolCallId(e){if(e){for(let[t,s]of this.accumulatedToolArgs)if(e.includes(s)||s.includes(e))return t}}resolveStoredToolName(e,t){let s=this.toolCallNames.get(e);return s&&s!=="unknown_tool"?s:t}emitToolStartSequence(e,t,s){try{this.emitCallback({type:EventType.TOOL_CALL_START,toolCallId:e.id,toolCallName:e.name,parentMessageId:t,timestamp:Date.now()});let n=s??this.accumulatedToolArgs.get(e.id);if(!n)return;this.emitCallback({type:EventType.TOOL_CALL_ARGS,toolCallId:e.id,delta:n,timestamp:Date.now()}),this.accumulatedToolArgs.delete(e.id);}catch{}}getOutputMessage(e){let s=this.asRecord(e)?.generations;if(!Array.isArray(s)||s.length===0)return;let n=s[0];if(!(!Array.isArray(n)||n.length===0))return this.asRecord(n[0])?.message}getOutputTextContent(e){let t=this.asRecord(e),s=this.getOutputMessage(e),n=this.asRecord(s),i=n?.content;if(typeof i=="string"&&i.length>0)return i;let r=this.getString(this.asRecord(n?.kwargs),"text");if(r&&r.length>0)return r;let a=n?.contentBlocks;if(Array.isArray(a)){let f=a.map(m=>this.asRecord(m)).filter(m=>m?.type==="text").map(m=>this.getString(m,"text")).filter(m=>!!(m&&m.length>0)).join("");if(f.length>0)return f}let l=Array.isArray(t?.generations)?t.generations:void 0,d=Array.isArray(l?.[0])?l[0]:void 0,h=this.asRecord(d?.[0])?.text;return typeof h=="string"&&h.length>0?h:void 0}resolveToolArgsDelta(e,t){if(typeof e.args=="string")return e.args;let s=this.stringifyIfDefined(e.args);if(s)return s;if(typeof e.arguments=="string")return e.arguments;let n=this.stringifyIfDefined(e.arguments);return n||t||void 0}stringifyIfDefined(e){if(!(typeof e>"u")){if(typeof e=="string")return e;try{return JSON.stringify(e)}catch{return}}}};export{y as AGUICallbackHandler};
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RunAgentInput, BaseEvent } from '@ag-ui/core';
|
|
2
|
+
import { AGUICallbackHandlerOptions } from './callbacks.cjs';
|
|
3
|
+
import { createAGUIMiddleware, AGUIMiddlewareOptions } from './middleware.cjs';
|
|
4
|
+
|
|
5
|
+
interface AGUIAgentRunOptions extends Record<string, unknown> {
|
|
6
|
+
callbacks?: unknown[];
|
|
7
|
+
configurable?: Record<string, unknown>;
|
|
8
|
+
context?: Record<string, unknown>;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
streamMode?: unknown;
|
|
11
|
+
}
|
|
12
|
+
interface AGUIAgentLike {
|
|
13
|
+
stream(input: Record<string, unknown>, options?: AGUIAgentRunOptions): Promise<AsyncIterable<unknown>>;
|
|
14
|
+
}
|
|
15
|
+
type AGUIAgentFactory = (args: {
|
|
16
|
+
input: RunAgentInput;
|
|
17
|
+
middleware: ReturnType<typeof createAGUIMiddleware>;
|
|
18
|
+
}) => AGUIAgentLike | Promise<AGUIAgentLike>;
|
|
19
|
+
interface AGUIAdapterRunOptions {
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}
|
|
22
|
+
interface AGUIAdapter {
|
|
23
|
+
stream(input: RunAgentInput, options?: AGUIAdapterRunOptions): Promise<AsyncIterable<BaseEvent>>;
|
|
24
|
+
}
|
|
25
|
+
interface AGUIAdapterConfig {
|
|
26
|
+
agentFactory: AGUIAgentFactory;
|
|
27
|
+
validateEvents?: boolean | "strict";
|
|
28
|
+
emitStateSnapshots?: AGUIMiddlewareOptions["emitStateSnapshots"];
|
|
29
|
+
emitActivities?: AGUIMiddlewareOptions["emitActivities"];
|
|
30
|
+
errorDetailLevel?: AGUIMiddlewareOptions["errorDetailLevel"];
|
|
31
|
+
callbackOptions?: Omit<AGUICallbackHandlerOptions, "publish">;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type { AGUIAdapter as A, AGUIAdapterConfig as a, AGUIAdapterRunOptions as b, AGUIAgentFactory as c, AGUIAgentLike as d, AGUIAgentRunOptions as e };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { RunAgentInput, BaseEvent } from '@ag-ui/core';
|
|
2
|
+
import { AGUICallbackHandlerOptions } from './callbacks.js';
|
|
3
|
+
import { createAGUIMiddleware, AGUIMiddlewareOptions } from './middleware.js';
|
|
4
|
+
|
|
5
|
+
interface AGUIAgentRunOptions extends Record<string, unknown> {
|
|
6
|
+
callbacks?: unknown[];
|
|
7
|
+
configurable?: Record<string, unknown>;
|
|
8
|
+
context?: Record<string, unknown>;
|
|
9
|
+
signal?: AbortSignal;
|
|
10
|
+
streamMode?: unknown;
|
|
11
|
+
}
|
|
12
|
+
interface AGUIAgentLike {
|
|
13
|
+
stream(input: Record<string, unknown>, options?: AGUIAgentRunOptions): Promise<AsyncIterable<unknown>>;
|
|
14
|
+
}
|
|
15
|
+
type AGUIAgentFactory = (args: {
|
|
16
|
+
input: RunAgentInput;
|
|
17
|
+
middleware: ReturnType<typeof createAGUIMiddleware>;
|
|
18
|
+
}) => AGUIAgentLike | Promise<AGUIAgentLike>;
|
|
19
|
+
interface AGUIAdapterRunOptions {
|
|
20
|
+
signal?: AbortSignal;
|
|
21
|
+
}
|
|
22
|
+
interface AGUIAdapter {
|
|
23
|
+
stream(input: RunAgentInput, options?: AGUIAdapterRunOptions): Promise<AsyncIterable<BaseEvent>>;
|
|
24
|
+
}
|
|
25
|
+
interface AGUIAdapterConfig {
|
|
26
|
+
agentFactory: AGUIAgentFactory;
|
|
27
|
+
validateEvents?: boolean | "strict";
|
|
28
|
+
emitStateSnapshots?: AGUIMiddlewareOptions["emitStateSnapshots"];
|
|
29
|
+
emitActivities?: AGUIMiddlewareOptions["emitActivities"];
|
|
30
|
+
errorDetailLevel?: AGUIMiddlewareOptions["errorDetailLevel"];
|
|
31
|
+
callbackOptions?: Omit<AGUICallbackHandlerOptions, "publish">;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type { AGUIAdapter as A, AGUIAdapterConfig as a, AGUIAdapterRunOptions as b, AGUIAgentFactory as c, AGUIAgentLike as d, AGUIAgentRunOptions as e };
|