mirror of
https://github.com/langchain-ai/agents-from-scratch-ts.git
synced 2026-06-30 21:37:54 -04:00
Tests
This commit is contained in:
+4
-6
@@ -1,8 +1,7 @@
|
||||
/** @type {import('jest').Config} */
|
||||
/** @type {import('ts-jest').JestConfigWithTsJest} **/
|
||||
export default {
|
||||
preset: "ts-jest/presets/js-with-ts-esm",
|
||||
testEnvironment: "node",
|
||||
testMatch: ["**/tests-ts/**/*.test.ts"],
|
||||
testMatch: ["**/tests/**/*.test.ts"],
|
||||
extensionsToTreatAsEsm: [".ts"],
|
||||
transform: {
|
||||
"^.+\\.tsx?$": [
|
||||
@@ -17,10 +16,9 @@ export default {
|
||||
"^@/(.*)$": "<rootDir>/$1",
|
||||
"^(\\.{1,2}/.*)\\.js$": "$1",
|
||||
},
|
||||
|
||||
transformIgnorePatterns: ["node_modules/(?!(@langchain|langchain|@jest)/)"],
|
||||
rootDir: "../",
|
||||
setupFilesAfterEnv: ["<rootDir>/tests-ts/setup.mjs"],
|
||||
setupFilesAfterEnv: ["<rootDir>/tests/setup.mjs"],
|
||||
testTimeout: 30000, // For LLM calls
|
||||
moduleDirectories: ["node_modules", "src"],
|
||||
resolver: "jest-ts-webcompat-resolver",
|
||||
};
|
||||
|
||||
+4
-4
@@ -9,10 +9,10 @@
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
||||
"format": "prettier --write .",
|
||||
"agent": "langgraphjs dev",
|
||||
"test": "NODE_OPTIONS=--experimental-vm-modules jest --config=tests-ts/jest.config.mjs",
|
||||
"test:hitl": "cross-env NODE_OPTIONS=--experimental-vm-modules AGENT_MODULE=email_assistant_hitl jest --config=tests-ts/jest.config.mjs hitl_testing",
|
||||
"test:memory": "cross-env NODE_OPTIONS=--experimental-vm-modules AGENT_MODULE=email_assistant_hitl_memory jest --config=tests-ts/jest.config.mjs memory_testing",
|
||||
"test:base": "cross-env NODE_OPTIONS=--experimental-vm-modules AGENT_MODULE=email_assistant jest --config=tests-ts/jest.config.mjs test_response"
|
||||
"test": "NODE_OPTIONS=--experimental-vm-modules jest --config=jest.config.mjs",
|
||||
"test:hitl": "cross-env NODE_OPTIONS=--experimental-vm-modules AGENT_MODULE=email_assistant_hitl jest --config=jest.config.mjs hitl.test.ts",
|
||||
"test:memory": "cross-env NODE_OPTIONS=--experimental-vm-modules AGENT_MODULE=email_assistant_hitl_memory jest --config=jest.config.mjs memory.test.ts",
|
||||
"test:base": "cross-env NODE_OPTIONS=--experimental-vm-modules AGENT_MODULE=email_assistant jest --config=jest.config.mjs response.test.ts"
|
||||
},
|
||||
"dependencies": {
|
||||
"@jest/globals": "^29.7.0",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { z } from "zod";
|
||||
import { DynamicStructuredTool, tool } from "@langchain/core/tools";
|
||||
import { tool } from "@langchain/core/tools";
|
||||
|
||||
/**
|
||||
* Schema for writing an email
|
||||
@@ -32,7 +32,7 @@ ${content}
|
||||
description:
|
||||
"Write an email draft based on provided information. Use this when the user wants to compose a new email message.",
|
||||
schema: emailSchema,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -76,7 +76,7 @@ Recommended action: ${priority === "High" ? "Respond immediately" : "Review when
|
||||
description:
|
||||
"Analyze and categorize an email by importance and type. Use this when evaluating how to handle incoming messages.",
|
||||
schema: triageSchema,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -99,5 +99,5 @@ export const Done = tool(
|
||||
description:
|
||||
"Signal that you've completed the current task and no further actions are needed.",
|
||||
schema: doneSchema,
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
@@ -20,7 +20,7 @@ export const backgroundTool = tool(
|
||||
name: "background",
|
||||
description: "Get background information about the user",
|
||||
schema: z.object({}).describe("This tool doesn't take any arguments"),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -36,7 +36,7 @@ export const calPreferencesTool = tool(
|
||||
name: "cal_preferences",
|
||||
description: "Get the user's calendar preferences",
|
||||
schema: z.object({}).describe("This tool doesn't take any arguments"),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -52,14 +52,14 @@ export const responsePreferencesTool = tool(
|
||||
name: "response_preferences",
|
||||
description: "Get the user's response style preferences",
|
||||
schema: z.object({}).describe("This tool doesn't take any arguments"),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Tool to ask a question to the user
|
||||
*/
|
||||
export const questionTool = tool(
|
||||
async ({ content }: { content: string }) => {
|
||||
async ({ content }) => {
|
||||
return `The user will see and can answer this question: ${content}`;
|
||||
},
|
||||
{
|
||||
@@ -68,5 +68,5 @@ export const questionTool = tool(
|
||||
schema: z.object({
|
||||
content: z.string().describe("The question to ask the user"),
|
||||
}),
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
+15
-9
@@ -1,6 +1,11 @@
|
||||
import { EmailData } from "./schemas.js";
|
||||
|
||||
import { AIMessage, type BaseMessage } from "@langchain/core/messages";
|
||||
import {
|
||||
AIMessage,
|
||||
isAIMessage,
|
||||
coerceMessageLikeToMessage,
|
||||
type BaseMessage,
|
||||
} from "@langchain/core/messages";
|
||||
import type { ToolCall } from "@langchain/core/messages/tool";
|
||||
|
||||
/**
|
||||
@@ -53,7 +58,7 @@ export function formatEmailMarkdown(
|
||||
subject: string,
|
||||
author: string,
|
||||
to: string,
|
||||
emailThread: string,
|
||||
emailThread: string
|
||||
): string {
|
||||
return `## Email: ${subject}
|
||||
|
||||
@@ -201,13 +206,13 @@ export function extractToolCalls(messages: any[]): string[] {
|
||||
// Handle plain objects
|
||||
if (message.tool_calls && Array.isArray(message.tool_calls)) {
|
||||
toolCallNames.push(
|
||||
...message.tool_calls.map((call: any) => call.name.toLowerCase()),
|
||||
...message.tool_calls.map((call: any) => call.name.toLowerCase())
|
||||
);
|
||||
}
|
||||
// Handle class instances with toolCalls property
|
||||
else if ("toolCalls" in message && Array.isArray(message.toolCalls)) {
|
||||
toolCallNames.push(
|
||||
...message.toolCalls.map((call: any) => call.name.toLowerCase()),
|
||||
...message.toolCalls.map((call: any) => call.name.toLowerCase())
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -222,8 +227,9 @@ export function extractToolCalls(messages: any[]): string[] {
|
||||
*/
|
||||
export function formatMessagesString(messages: BaseMessage[]): string {
|
||||
return messages
|
||||
.map((message) => {
|
||||
.map((messageLike) => {
|
||||
let prefix = "";
|
||||
const message = coerceMessageLikeToMessage(messageLike);
|
||||
|
||||
// Determine prefix based on role
|
||||
if ("role" in message && message.role) {
|
||||
@@ -252,13 +258,13 @@ export function formatMessagesString(messages: BaseMessage[]): string {
|
||||
: JSON.stringify(message.content);
|
||||
|
||||
// Only AIMessage can have tool_calls
|
||||
if (message._getType() === "ai") {
|
||||
if (isAIMessage(message)) {
|
||||
const aiMessage = message as AIMessage; // Cast to AIMessage from @langchain/core/messages
|
||||
if (aiMessage.tool_calls && aiMessage.tool_calls.length > 0) {
|
||||
const toolCallsStr = aiMessage.tool_calls
|
||||
.map(
|
||||
(tc: ToolCall) =>
|
||||
`\n Tool: ${tc.name}\n Args: ${JSON.stringify(tc.args, null, 2)}`,
|
||||
`\n Tool: ${tc.name}\n Args: ${JSON.stringify(tc.args, null, 2)}`
|
||||
)
|
||||
.join("\n");
|
||||
content += `\n[Tool Calls: ${toolCallsStr}]`;
|
||||
@@ -277,12 +283,12 @@ export function formatEmailOptional(
|
||||
subject?: string,
|
||||
author?: string,
|
||||
to?: string,
|
||||
emailThread?: string,
|
||||
emailThread?: string
|
||||
): string {
|
||||
return formatEmailMarkdown(
|
||||
subject ?? "No Subject",
|
||||
author ?? "Unknown Sender",
|
||||
to ?? "Unknown Recipient",
|
||||
emailThread ?? "",
|
||||
emailThread ?? ""
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user