UNPKG

adk-typescript

Version:

TypeScript port of Google's Agent Development Kit (ADK)

153 lines (152 loc) 5.27 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.LanggraphAgent = void 0; const Event_1 = require("../events/Event"); const BaseAgent_1 = require("./BaseAgent"); /** * Extracts last human messages from given list of events. * * @param events The list of events * @returns List of last human messages */ function getLastHumanMessages(events) { const messages = []; // Start from the end and work backwards for (let i = events.length - 1; i >= 0; i--) { const event = events[i]; // If we've found a message and the current event is not from the user, break if (messages.length > 0 && event.author !== 'user') { break; } // If it's a user message with content, add it if (event.author === 'user' && event.content && event.content.parts && event.content.parts.length > 0) { messages.unshift({ type: 'human', content: event.content.parts[0].text, }); } } return messages; } /** * LangGraph agent implementation. * Currently a concept implementation, supports single and multi-turn. */ class LanggraphAgent extends BaseAgent_1.BaseAgent { /** * Creates a new LanggraphAgent. * * @param name The name of the agent * @param options Options for the agent */ constructor(name, options) { super(name, options); if (!options.graph) { throw new Error('LanggraphAgent requires a graph'); } this.graph = options.graph; this.instruction = options.instruction || ''; } /** * Implementation of the agent's async invocation logic. * * @param ctx The invocation context * @returns An async generator of events */ async *runAsyncImpl(ctx) { // Needed for langgraph checkpointer (for subsequent invocations; multi-turn) const config = { configurable: { thread_id: ctx.session.id } }; // Add instruction as SystemMessage if graph state is empty const currentGraphState = this.graph.getState(config); const graphMessages = currentGraphState.values?.messages || []; let messages = []; if (this.instruction && graphMessages.length === 0) { messages.push({ type: 'system', content: this.instruction, }); } // Add events to messages (evaluating the memory used; parent agent vs checkpointer) messages = messages.concat(this.getMessages(ctx.session.events)); // Use the Runnable const finalState = this.graph.invoke({ messages }, config); const result = finalState.messages[finalState.messages.length - 1].content; const resultEvent = new Event_1.Event({ invocationId: ctx.invocationId, author: this.name, branch: ctx.branch, content: { role: 'model', parts: [{ text: result }], }, }); yield resultEvent; } /** * Implementation of the agent's live invocation logic. * * @param ctx The invocation context * @returns An async generator of events */ async *runLiveImpl(ctx) { // For live implementation, we simply delegate to the async implementation yield* this.runAsyncImpl(ctx); } /** * Sets the user content for the agent. * This is a no-op for LanggraphAgent as it extracts content from session events. * * @param content The user content * @param invocationContext The invocation context */ setUserContent(content, invocationContext) { // LanggraphAgent doesn't need to store user content locally // It will be extracted from session events } /** * Extracts messages from given list of events. * * If the developer provides their own memory within langgraph, we return the * last user messages only. Otherwise, we return all messages between the user * and the agent. * * @param events The list of events * @returns List of messages */ getMessages(events) { if (this.graph.checkpointer) { return getLastHumanMessages(events); } else { return this.getConversationWithAgent(events); } } /** * Extracts conversation messages from given list of events. * * @param events The list of events * @returns List of messages */ getConversationWithAgent(events) { const messages = []; for (const event of events) { if (!event.content || !event.content.parts || event.content.parts.length === 0) { continue; } if (event.author === 'user') { messages.push({ type: 'human', content: event.content.parts[0].text, }); } else if (event.author === this.name) { messages.push({ type: 'ai', content: event.content.parts[0].text, }); } } return messages; } } exports.LanggraphAgent = LanggraphAgent;