Skip to content
Merged
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
7 changes: 6 additions & 1 deletion frontend/internal-packages/agent/src/createGraph.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { AIMessage } from '@langchain/core/messages'
import { AIMessage, isHumanMessage } from '@langchain/core/messages'
import type { RunnableConfig } from '@langchain/core/runnables'
import { END, START, StateGraph } from '@langchain/langgraph'
import type { BaseCheckpointSaver } from '@langchain/langgraph-checkpoint'
Expand All @@ -24,8 +24,13 @@ export const createGraph = (checkpointer?: BaseCheckpointSaver) => {
const qaAgentSubgraph = createQaAgentGraph()

const callDbAgent = async (state: WorkflowState, config: RunnableConfig) => {
// Extract user input from the first HumanMessage
const userInput =
state.messages.find((msg) => isHumanMessage(msg))?.text || ''
Comment on lines +27 to +29
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Verify the .text property on HumanMessage.

The code uses .text to extract the message content from a HumanMessage. LangGraph messages typically expose a .content property instead. Please verify that .text is the correct property to use here.

Run the following script to check the property usage across the codebase:

Additionally, search the web to confirm the correct property:


🏁 Script executed:

#!/bin/bash
# Description: Check how HumanMessage content is accessed elsewhere in the codebase

# Search for other usages of HumanMessage content extraction
rg -n --type=ts -A2 -B2 'HumanMessage.*\.(text|content)' frontend/internal-packages/agent/

Length of output: 467


🌐 Web query:

What property should be used to access the text content of a HumanMessage in LangChain/LangGraph TypeScript? Is it .text or .content?

💡 Result:

Use the .content property. LangChain message classes (including HumanMessage) expose their payload as .content (which may be a string or structured content blocks); there is no top-level .text property on HumanMessage. [1][2]

Sources:
[1] LangChain JS Messages docs — "Messages have a content attribute...".
[2] LangChain concepts / message types — "All messages have a role, content, and response_metadata property."


Replace .text with .content on HumanMessage
In frontend/internal-packages/agent/src/createGraph.ts:29, change ?.text to ?.content when extracting userInput.

🤖 Prompt for AI Agents
In frontend/internal-packages/agent/src/createGraph.ts around lines 27 to 29,
the code extracts the user's input from the first HumanMessage using ?.text
which is incorrect; update the property access to ?.content so it reads the
message body correctly (i.e., find the first HumanMessage and use its content
field, falling back to an empty string).


const prompt = convertRequirementsToPrompt(
state.analyzedRequirements,
userInput,
state.schemaIssues,
)
const modifiedState = { ...state, messages: [], prompt }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,12 +56,23 @@ describe('convertAnalyzedRequirementsToPrompt', () => {
}

it('should convert analyzed requirements to formatted text prompt', () => {
const result = convertRequirementsToPrompt(sampleAnalyzedRequirements)
const userInput = 'Design a user management system with authentication'
const result = convertRequirementsToPrompt(
sampleAnalyzedRequirements,
userInput,
)

expect(result).toMatchInlineSnapshot(`
"Session Goal: Build a user management system
"## Session Goal

Build a user management system

## Original User Request

Design a user management system with authentication

## Test Cases

Test Cases:
- authentication: User login (SELECT), User logout (UPDATE), Password reset (UPDATE)
- userManagement: Create new user (INSERT), Update user info (UPDATE), Delete user (DELETE)"
`)
Expand All @@ -72,13 +83,20 @@ describe('convertAnalyzedRequirementsToPrompt', () => {
goal: 'Simple system',
testcases: {},
}
const userInput = 'Build a simple system'

const result = convertRequirementsToPrompt(analyzedRequirements)
const result = convertRequirementsToPrompt(analyzedRequirements, userInput)

expect(result).toMatchInlineSnapshot(`
"Session Goal: Simple system
"## Session Goal

Simple system

## Original User Request

Build a simple system

Test Cases:"
## Test Cases"
`)
})

Expand All @@ -97,76 +115,112 @@ describe('convertAnalyzedRequirementsToPrompt', () => {
],
},
}
const userInput = 'Add a basic feature'

const result = convertRequirementsToPrompt(analyzedRequirements)
const result = convertRequirementsToPrompt(analyzedRequirements, userInput)

expect(result).toMatchInlineSnapshot(`
"Session Goal:
"## Session Goal



## Original User Request

Add a basic feature

## Test Cases

Test Cases:
- basic: Basic feature test (INSERT)"
`)
})

describe('with schemaIssues filtering', () => {
it('should filter testcases based on schemaIssues without showing issue details', () => {
const userInput = 'Design a user management system with authentication'
const schemaIssues = [
{ testcaseId: '2', description: 'Missing logout table' },
]

const result = convertRequirementsToPrompt(
sampleAnalyzedRequirements,
userInput,
schemaIssues,
)

expect(result).toMatchInlineSnapshot(`
"Session Goal: Build a user management system
"## Session Goal

Build a user management system

## Original User Request

Design a user management system with authentication

## Test Cases

Test Cases:
- authentication: User logout (UPDATE)"
`)
})

it('should handle empty schemaIssues array', () => {
const userInput = 'Design a user management system with authentication'
const schemaIssues: Array<{
testcaseId: string
description: string
}> = []

const result = convertRequirementsToPrompt(
sampleAnalyzedRequirements,
userInput,
schemaIssues,
)

// Should behave like no schemaIssues parameter
expect(result).toMatchInlineSnapshot(`
"Session Goal: Build a user management system
"## Session Goal

Build a user management system

## Original User Request

Design a user management system with authentication

## Test Cases

Test Cases:
- authentication: User login (SELECT), User logout (UPDATE), Password reset (UPDATE)
- userManagement: Create new user (INSERT), Update user info (UPDATE), Delete user (DELETE)"
`)
})

it('should filter out entire categories when no testcases match schemaIssues', () => {
const userInput = 'Design a user management system with authentication'
const schemaIssues = [
{ testcaseId: '1', description: 'Login form missing' },
]

const result = convertRequirementsToPrompt(
sampleAnalyzedRequirements,
userInput,
schemaIssues,
)

expect(result).toMatchInlineSnapshot(`
"Session Goal: Build a user management system
"## Session Goal

Build a user management system

## Original User Request

Design a user management system with authentication

## Test Cases

Test Cases:
- authentication: User login (SELECT)"
`)
})

it('should handle schemaIssues with no matching testcases', () => {
const userInput = 'Design a user management system with authentication'
const schemaIssues = [
{
testcaseId: 'non-existent',
Expand All @@ -176,26 +230,39 @@ describe('convertAnalyzedRequirementsToPrompt', () => {

const result = convertRequirementsToPrompt(
sampleAnalyzedRequirements,
userInput,
schemaIssues,
)

expect(result).toMatchInlineSnapshot(`
"Session Goal: Build a user management system
"## Session Goal

Build a user management system

Test Cases:"
## Original User Request

Design a user management system with authentication

## Test Cases"
`)
})

it('should filter testcases without showing IDs or issue details', () => {
const userInput = 'Design a user management system with authentication'
const schemaIssues = [
{ testcaseId: '4', description: 'User table structure issue' },
]

const result = convertRequirementsToPrompt(
sampleAnalyzedRequirements,
userInput,
schemaIssues,
)

expect(result).toContain('## Original User Request')
expect(result).toContain(
'Design a user management system with authentication',
)
expect(result).toContain('Create new user')
expect(result).not.toContain('[4]')
expect(result).not.toContain('User table structure issue')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ type TestCases = AnalyzedRequirements['testcases']

export const convertRequirementsToPrompt = (
requirements: AnalyzedRequirements,
userInput: string,
schemaIssues?: Array<{ testcaseId: string; description: string }>,
): string => {
let testcasesToUse: TestCases = requirements.testcases
Expand All @@ -29,13 +30,22 @@ export const convertRequirementsToPrompt = (
testcasesToUse = filteredTestcases
}

return `Session Goal:${requirements.goal ? ` ${requirements.goal}` : ''}
const testCasesSection = Object.entries(testcasesToUse)
.map(
([category, testcases]) =>
`- ${category}: ${testcases.map((tc) => `${tc.title} (${tc.type})`).join(', ')}`,
)
.join('\n')

return `## Session Goal

${requirements.goal}

## Original User Request

${userInput}

## Test Cases

Test Cases:
${Object.entries(testcasesToUse)
.map(
([category, testcases]) =>
`- ${category}: ${testcases.map((tc) => `${tc.title} (${tc.type})`).join(', ')}`,
)
.join('\n')}`.trim()
${testCasesSection}`.trim()
}