fix(bridge): 漏调 collect_info 时补抽线索
This commit is contained in:
@@ -321,3 +321,39 @@ test('agent: does not auto-create when the LLM already created the opportunity',
|
||||
await agent.run(conv, { uuid: 'msg-once', text_content: 'We are Acme GmbH, contact John Doe, we want 500 pieces.', content: '...' });
|
||||
assert.equal(twenty.calls.filter((c) => c[0] === 'createOpportunity').length, 1);
|
||||
});
|
||||
|
||||
test('agent: extracts lead fields when the LLM skips collect_info (company mentioned, unit-less quantity)', async () => {
|
||||
const twenty = leadTwenty();
|
||||
const tools = leadTools(twenty);
|
||||
let sent = '';
|
||||
let llmCalls = 0;
|
||||
const deps = {
|
||||
llm: {
|
||||
enabled: true,
|
||||
model: 'fake',
|
||||
chat: async () => {
|
||||
llmCalls += 1;
|
||||
if (llmCalls === 1) {
|
||||
return { content: 'Could you share your contact details so we can follow up?', toolCalls: [], usage: null };
|
||||
}
|
||||
// extractLeadFields 的调用:返回 JSON
|
||||
return { content: JSON.stringify({ company: 'Leadfix GmbH', contactName: 'Anna Klein', productNeed: '500 stainless steel rings', quantity: '500' }), toolCalls: [], usage: null };
|
||||
},
|
||||
},
|
||||
client: {
|
||||
getMessages: async () => [{ id: 1, text_content: 'We are Leadfix GmbH, contact Anna Klein. We need 500 stainless steel rings.', sender_type: 'contact', private: false }],
|
||||
sendMessage: async (_uuid, content) => { sent = content; },
|
||||
sendPrivateNote: async () => {},
|
||||
},
|
||||
tools,
|
||||
verification: { getVerifiedEmail: async () => null, sendCode: async () => ({}), verifyCode: async () => ({}) },
|
||||
metrics: { record: async () => {}, enabled: false },
|
||||
contextManager: { compressHistory: async (_c, h) => h },
|
||||
};
|
||||
const conv = { uuid: 'conv-lead-extract', inbox_id: '1', channel: 'livechat', contact: { type: 'visitor' } };
|
||||
const agent = createAgent({ sites: [], defaultSite: 'www' }, deps);
|
||||
await agent.run(conv, { uuid: 'msg-lead-extract', text_content: 'We are Leadfix GmbH, contact Anna Klein. We need 500 stainless steel rings.', content: '...' });
|
||||
assert.equal(llmCalls >= 2, true);
|
||||
assert.equal(twenty.calls.filter((c) => c[0] === 'createOpportunity').length, 1);
|
||||
assert.ok(twenty.calls.some((c) => c[0] === 'createCompany' && c[1] === 'Leadfix GmbH'));
|
||||
});
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
const test = require('node:test');
|
||||
const assert = require('node:assert/strict');
|
||||
const { hasBuyingIntent, missingLeadContacts, detectLanguage, appendLeadFollowup, alreadyAsksForLead } = require('../src/lead-intent');
|
||||
const { hasBuyingIntent, looksLikeLead, missingLeadContacts, detectLanguage, appendLeadFollowup, alreadyAsksForLead } = require('../src/lead-intent');
|
||||
|
||||
test('lead-intent: product + quantity is buying intent', () => {
|
||||
assert.equal(hasBuyingIntent('I want 500 pieces of stainless steel rings'), true);
|
||||
@@ -26,3 +26,11 @@ test('lead-intent: detects existing ask in reply', () => {
|
||||
assert.equal(alreadyAsksForLead('Could you share your company name and email?'), true);
|
||||
assert.equal(alreadyAsksForLead('Here are some rings.'), false);
|
||||
});
|
||||
|
||||
test('lead-intent: company/contact signal counts as a lead even without unit-quantity', () => {
|
||||
// 单位不规整(500 stainless steel rings)时 hasBuyingIntent 为 false,但已是明确线索
|
||||
assert.equal(hasBuyingIntent('We are Acme GmbH, contact Anna Klein. We need 500 stainless steel rings.'), false);
|
||||
assert.equal(looksLikeLead('We are Acme GmbH, contact Anna Klein. We need 500 stainless steel rings.'), true);
|
||||
assert.equal(looksLikeLead('Our company is Test Buyer BV, contact name Jan Jansen.'), false); // 没有商品词
|
||||
assert.equal(looksLikeLead('Do you have rings?'), false); // 没有公司/联系人信号
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user