Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions apps/dojo/e2e/tests/langchainTests/agenticChatPage.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import {
test,
expect,
waitForAIResponse,
retryOnAIFailure,
} from "../../test-isolation-helper";
import { AgenticChatPage } from "../../featurePages/AgenticChatPage";

test("[LangChain] Agentic Chat sends and receives a message", async ({
page,
}) => {
await retryOnAIFailure(async () => {
await page.goto(
"/langchain/feature/agentic_chat"
);

const chat = new AgenticChatPage(page);

await chat.openChat();
await chat.agentGreeting.isVisible;
await chat.sendMessage("Hi, I am duaa");

await waitForAIResponse(page);
await chat.assertUserMessageVisible("Hi, I am duaa");
await chat.assertAgentReplyVisible(/Hello/i);
});
});

test("[LangChain] Agentic Chat changes background on message and reset", async ({
page,
}) => {
await retryOnAIFailure(async () => {
await page.goto(
"/langchain/feature/agentic_chat"
);

const chat = new AgenticChatPage(page);

await chat.openChat();
await chat.agentGreeting.waitFor({ state: "visible" });

// Store initial background color
const backgroundContainer = page.locator('[data-testid="background-container"]')
const initialBackground = await backgroundContainer.evaluate(el => getComputedStyle(el).backgroundColor);
console.log("Initial background color:", initialBackground);

// 1. Send message to change background to blue
await chat.sendMessage("Hi change the background color to blue");
await chat.assertUserMessageVisible(
"Hi change the background color to blue"
);
await waitForAIResponse(page);

await expect(backgroundContainer).not.toHaveCSS('background-color', initialBackground, { timeout: 7000 });
const backgroundBlue = await backgroundContainer.evaluate(el => getComputedStyle(el).backgroundColor);
// Check if background is blue (string color name or contains blue)
expect(backgroundBlue.toLowerCase()).toMatch(/blue|rgb\(.*,.*,.*\)|#[0-9a-f]{6}/);

// 2. Change to pink
await chat.sendMessage("Hi change the background color to pink");
await chat.assertUserMessageVisible(
"Hi change the background color to pink"
);
await waitForAIResponse(page);

await expect(backgroundContainer).not.toHaveCSS('background-color', backgroundBlue, { timeout: 7000 });
const backgroundPink = await backgroundContainer.evaluate(el => getComputedStyle(el).backgroundColor);
// Check if background is pink (string color name or contains pink)
expect(backgroundPink.toLowerCase()).toMatch(/pink|rgb\(.*,.*,.*\)|#[0-9a-f]{6}/);
});
});

test("[LangChain] Agentic Chat retains memory of user messages during a conversation", async ({
page,
}) => {
await retryOnAIFailure(async () => {
await page.goto(
"/langchain/feature/agentic_chat"
);

const chat = new AgenticChatPage(page);
await chat.openChat();
await chat.agentGreeting.click();

await chat.sendMessage("Hey there");
await chat.assertUserMessageVisible("Hey there");
await waitForAIResponse(page);
await chat.assertAgentReplyVisible(/how can I assist you/i);

const favFruit = "Mango";
await chat.sendMessage(`My favorite fruit is ${favFruit}`);
await chat.assertUserMessageVisible(`My favorite fruit is ${favFruit}`);
await waitForAIResponse(page);
await chat.assertAgentReplyVisible(new RegExp(favFruit, "i"));

await chat.sendMessage("and I love listening to Kaavish");
await chat.assertUserMessageVisible("and I love listening to Kaavish");
await waitForAIResponse(page);
await chat.assertAgentReplyVisible(/Kaavish/i);

await chat.sendMessage("tell me an interesting fact about Moon");
await chat.assertUserMessageVisible(
"tell me an interesting fact about Moon"
);
await waitForAIResponse(page);
await chat.assertAgentReplyVisible(/Moon/i);

await chat.sendMessage("Can you remind me what my favorite fruit is?");
await chat.assertUserMessageVisible(
"Can you remind me what my favorite fruit is?"
);
await waitForAIResponse(page);
await chat.assertAgentReplyVisible(new RegExp(favFruit, "i"));
});
});
38 changes: 38 additions & 0 deletions apps/dojo/e2e/tests/langchainTests/toolBasedGenUIPage.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { test, expect } from "@playwright/test";
import { ToolBaseGenUIPage } from "../../featurePages/ToolBaseGenUIPage";

const pageURL =
"/langchain/feature/tool_based_generative_ui";

test('[LangChain] Haiku generation and display verification', async ({
page,
}) => {
await page.goto(pageURL);

const genAIAgent = new ToolBaseGenUIPage(page);

await expect(genAIAgent.haikuAgentIntro).toBeVisible();
await genAIAgent.generateHaiku('Generate Haiku for "I will always win"');
await genAIAgent.checkGeneratedHaiku();
await genAIAgent.checkHaikuDisplay(page);
});

test('[LangChain] Haiku generation and UI consistency for two different prompts', async ({
page,
}) => {
await page.goto(pageURL);

const genAIAgent = new ToolBaseGenUIPage(page);

await expect(genAIAgent.haikuAgentIntro).toBeVisible();

const prompt1 = 'Generate Haiku for "I will always win"';
await genAIAgent.generateHaiku(prompt1);
await genAIAgent.checkGeneratedHaiku();
await genAIAgent.checkHaikuDisplay(page);

const prompt2 = 'Generate Haiku for "The moon shines bright"';
await genAIAgent.generateHaiku(prompt2);
await genAIAgent.checkGeneratedHaiku();
await genAIAgent.checkHaikuDisplay(page);
});
1 change: 1 addition & 0 deletions apps/dojo/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"@ag-ui/agno": "workspace:*",
"@ag-ui/crewai": "workspace:*",
"@ag-ui/langgraph": "workspace:*",
"@ag-ui/langchain": "workspace:*",
"@ag-ui/llamaindex": "workspace:*",
"@ag-ui/mastra": "workspace:*",
"@ag-ui/middleware-starter": "workspace:*",
Expand Down
30 changes: 30 additions & 0 deletions apps/dojo/src/agents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { HttpAgent } from "@ag-ui/client";
import { A2AMiddlewareAgent } from "@ag-ui/a2a-middleware";
import { A2AAgent } from "@ag-ui/a2a";
import { A2AClient } from "@a2a-js/sdk/client";
import { LangChainAgent } from "@ag-ui/langchain";

const envVars = getEnvVars();
export const agentsIntegrations: AgentIntegrationConfig[] = [
Expand Down Expand Up @@ -260,6 +261,35 @@ export const agentsIntegrations: AgentIntegrationConfig[] = [
};
},
},
{
id: "langchain",
agents: async () => {
return {
agentic_chat: new LangChainAgent({
chainFn: async ({ messages, tools, threadId }) => {
// @ts-ignore
const { ChatOpenAI } = await import("@langchain/openai");
const chatOpenAI = new ChatOpenAI({ model: "gpt-4o" });
const model = chatOpenAI.bindTools(tools, {
strict: true,
});
return model.stream(messages, { tools, metadata: { conversation_id: threadId } });
},
}),
tool_based_generative_ui: new LangChainAgent({
chainFn: async ({ messages, tools, threadId }) => {
// @ts-ignore
const { ChatOpenAI } = await import("@langchain/openai");
const chatOpenAI = new ChatOpenAI({ model: "gpt-4o" });
const model = chatOpenAI.bindTools(tools, {
strict: true,
});
return model.stream(messages, { tools, metadata: { conversation_id: threadId } });
},
}),
}
},
},
{
id: "agno",
agents: async () => {
Expand Down
8 changes: 8 additions & 0 deletions apps/dojo/src/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,14 @@ export const menuIntegrations: MenuIntegrationConfig[] = [
"subgraphs",
],
},
{
id: "langchain",
name: "LangChain",
features: [
"agentic_chat",
"tool_based_generative_ui",
],
},
{
id: "mastra",
name: "Mastra",
Expand Down
141 changes: 141 additions & 0 deletions integrations/langchain/typescript/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*

# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json

# Runtime data
pids
*.pid
*.seed
*.pid.lock

# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov

# Coverage directory used by tools like istanbul
coverage
*.lcov

# nyc test coverage
.nyc_output

# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt

# Bower dependency directory (https://bower.io/)
bower_components

# node-waf configuration
.lock-wscript

# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release

# Dependency directories
node_modules/
jspm_packages/

# Snowpack dependency directory (https://snowpack.dev/)
web_modules/

# TypeScript cache
*.tsbuildinfo

# Optional npm cache directory
.npm

# Optional eslint cache
.eslintcache

# Optional stylelint cache
.stylelintcache

# Optional REPL history
.node_repl_history

# Output of 'npm pack'
*.tgz

# Yarn Integrity file
.yarn-integrity

# dotenv environment variable files
.env
.env.*
!.env.example

# parcel-bundler cache (https://parceljs.org/)
.cache
.parcel-cache

# Next.js build output
.next
out

# Nuxt.js build / generate output
.nuxt
dist
.output

# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public

# vuepress build output
.vuepress/dist

# vuepress v2.x temp and cache directory
.temp
.cache

# Sveltekit cache directory
.svelte-kit/

# vitepress build output
**/.vitepress/dist

# vitepress cache directory
**/.vitepress/cache

# Docusaurus cache and generated files
.docusaurus

# Serverless directories
.serverless/

# FuseBox cache
.fusebox/

# DynamoDB Local files
.dynamodb/

# Firebase cache directory
.firebase/

# TernJS port file
.tern-port

# Stores VSCode versions used for testing VSCode extensions
.vscode-test

# yarn v3
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Vite files
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
.vite/
13 changes: 13 additions & 0 deletions integrations/langchain/typescript/.npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.turbo
.DS_Store
.git
.gitignore
.idea
.vscode
.env
__tests__
src
tsup.config.ts
tsconfig.json
jest.config.js
example
Loading
Loading