You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

229 lines
6.8 KiB

import { AiAgentToolName } from './ai-agent.interfaces';
import {
applyToolExecutionPolicy,
createPolicyRouteResponse
} from './ai-agent.policy.utils';
import { determineToolPlan } from './ai-agent.utils';
const GREETING_QUERIES = [
'hi',
'Hi!',
'hello',
'hello.',
'hey?',
'thanks',
'thanks!',
'thank you',
'thank you.',
'good morning',
'Good morning!',
'good afternoon',
'good afternoon.',
'good evening',
'good evening?',
' hi ',
'HELLO',
'Hey!',
'hi!!!',
'hello??',
'good morning.',
'good afternoon?',
'good evening!',
'THANK YOU',
'Thanks.'
];
const IDENTITY_AND_USAGE_QUERIES = [
'who are you',
'who are you?',
'Who are you?',
'what are you',
'what are you?',
'what can you do',
'what can you do?',
'What can you do?',
'how do you work',
'how do you work?',
'how can i use this',
'how can i use this?',
'help',
'Help',
'help?',
'assist me',
'assist me?',
'what can you help with',
'what can you help with?',
'What can you help with?'
];
const ARITHMETIC_CASES: Array<{ expected: string; query: string }> = [
{ expected: '2+2 = 4', query: '2+2' },
{ expected: '5*3 = 15', query: '5*3' },
{ expected: '10 / 4 = 2.5', query: '10 / 4' },
{ expected: '7-10 = -3', query: '7-10' },
{ expected: '(2+3)*4 = 20', query: '(2+3)*4' },
{ expected: '3.5 + 1.25 = 4.75', query: '3.5 + 1.25' },
{ expected: '2 + (3 * (4 - 1)) = 11', query: '2 + (3 * (4 - 1))' },
{ expected: '8/2 = 4', query: 'what is 8/2' },
{ expected: '14 - 6 = 8', query: 'what is 14 - 6' },
{ expected: '100-25*2 = 50', query: '100-25*2' },
{ expected: '9+9 = 18', query: '9+9' },
{ expected: '12 / 3 = 4', query: '12 / 3' },
{ expected: '6*7 = 42', query: '6*7' },
{ expected: '(5+5)/2 = 5', query: '(5+5)/2' },
{ expected: '4*(2+1) = 12', query: '4*(2+1)' },
{ expected: '50 - 7 = 43', query: '50 - 7' },
{ expected: '1.2 + 3.4 = 4.6', query: '1.2 + 3.4' },
{ expected: '18/6+2 = 5', query: '18/6+2' },
{ expected: '2*(2*(2+1)) = 12', query: '2*(2*(2+1))' },
{ expected: '99-9 = 90', query: '99-9' }
];
const PORTFOLIO_VALUE_QUERIES = [
'How much money do I have?',
'how much money i have?',
'how much.i ahve money?',
'how much cash do i have?',
'how much value do i have?',
'what is my account balance?',
'what is my balance?',
'what is my portfolio value?',
'what is my portfolio worth?',
'what is my net worth?',
'tell me my account balance',
'tell me my portfolio value',
'show my account balance',
'show my portfolio value',
'show my portfolio worth',
'show my net worth',
'total portfolio value',
'total account value',
'what is the total value of my portfolio?',
'what is the total value in my account?',
'how much assets do i have?',
'how much equity do i have?',
'do i have enough money in my portfolio?',
'do i have money in my account?',
'tell me how much value my portfolio has'
];
const INVESTMENT_QUERIES = [
'where should i invest',
'where should i invest next',
'where i should invest',
'what should i invest in',
'what should i do to invest',
'what should i do with my portfolio',
'what can i do to improve my portfolio',
'how do i invest new money',
'how do i rebalance',
'invest 1000 usd',
'allocate 2000 usd',
'buy more diversified holdings',
'sell overweight positions and rebalance',
'trim my top holding and rebalance',
'rebalance my portfolio',
'rebalance and invest new cash',
'where should i allocate new money',
'how should i allocate this month',
'invest and rebalance for lower risk',
'buy and rebalance based on risk',
'sell and rotate into diversified assets',
'what should i do next with this portfolio',
'how do i add money without increasing concentration',
'invest next contribution into safer mix',
'allocate next cash to lower risk positions'
];
const ACTION_CONFIRMATION_PATTERN = /\b(?:allocat|buy|invest|rebalanc|sell|trim)\b/i;
describe('AiAgentSimpleInteractions', () => {
it('supports 100+ simple user commands with expected routing behavior', () => {
let evaluatedQueries = 0;
for (const query of GREETING_QUERIES) {
const plannedTools = determineToolPlan({ query });
const decision = applyToolExecutionPolicy({ plannedTools, query });
const response = createPolicyRouteResponse({
policyDecision: decision,
query
});
expect(decision.route).toBe('direct');
expect(decision.toolsToExecute).toEqual([]);
expect(response).toContain('Ghostfolio AI');
evaluatedQueries += 1;
}
for (const query of IDENTITY_AND_USAGE_QUERIES) {
const plannedTools = determineToolPlan({ query });
const decision = applyToolExecutionPolicy({ plannedTools, query });
const response = createPolicyRouteResponse({
policyDecision: decision,
query
});
expect(decision.route).toBe('direct');
expect(decision.toolsToExecute).toEqual([]);
expect(response).toContain('Ghostfolio AI');
evaluatedQueries += 1;
}
for (const { expected, query } of ARITHMETIC_CASES) {
const plannedTools = determineToolPlan({ query });
const decision = applyToolExecutionPolicy({ plannedTools, query });
const response = createPolicyRouteResponse({
policyDecision: decision,
query
});
expect(decision.route).toBe('direct');
expect(decision.toolsToExecute).toEqual([]);
expect(response).toBe(expected);
evaluatedQueries += 1;
}
for (const query of PORTFOLIO_VALUE_QUERIES) {
const plannedTools = determineToolPlan({ query });
const decision = applyToolExecutionPolicy({ plannedTools, query });
expect(plannedTools).toContain('portfolio_analysis');
expect(decision.route).toBe('tools');
expect(decision.toolsToExecute).toContain(
'portfolio_analysis' as AiAgentToolName
);
evaluatedQueries += 1;
}
for (const query of INVESTMENT_QUERIES) {
const plannedTools = determineToolPlan({ query });
const decision = applyToolExecutionPolicy({ plannedTools, query });
const hasActionConfirmationSignal = ACTION_CONFIRMATION_PATTERN.test(
query.toLowerCase()
);
expect(plannedTools).toEqual(
expect.arrayContaining([
'portfolio_analysis' as AiAgentToolName,
'risk_assessment' as AiAgentToolName,
'rebalance_plan' as AiAgentToolName
])
);
expect(decision.route).toBe('tools');
expect(decision.toolsToExecute).toEqual(
expect.arrayContaining([
'portfolio_analysis' as AiAgentToolName,
'risk_assessment' as AiAgentToolName
])
);
if (hasActionConfirmationSignal) {
expect(decision.toolsToExecute).toContain(
'rebalance_plan' as AiAgentToolName
);
}
evaluatedQueries += 1;
}
expect(evaluatedQueries).toBeGreaterThanOrEqual(100);
});
});