fix(agent): restore active-task routing and active-mode validation observation
Memind CI / Test, build, and release guards (push) Successful in 5m23s
Memind CI / Test, build, and release guards (push) Successful in 5m23s
Keep correction follow-ups on Agent using session transcript and active task context, and let Page Data validation reach Orchestrator when mode is active instead of requiring shadowEngine. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -11,6 +11,9 @@ import {
|
||||
coercePageGenerationSkill,
|
||||
createChatIntentRouter,
|
||||
createManagedChatIntentRouter,
|
||||
formatRouterTranscript,
|
||||
shouldDeferActiveTaskRoutingToLlm,
|
||||
shouldForceActiveAgentTaskContinuation,
|
||||
isNormalizedRouterDecisionEnabled,
|
||||
isNormalizedRouterDecisionShadow,
|
||||
resolveGatewayAgentSessionId,
|
||||
@@ -469,6 +472,141 @@ test('classifyWithRules keeps agent session confirmation on agent path', () => {
|
||||
assert.match(fresh.reason, /记忆/);
|
||||
});
|
||||
|
||||
test('classifyWithRules continues agent task after failed run in same session', () => {
|
||||
const activeTaskContext = {
|
||||
hasRecentAgentTask: true,
|
||||
lastRunFailed: true,
|
||||
lastSuggestedSkill: 'page-data-collect',
|
||||
lastRunStatus: 'failed',
|
||||
lastRoute: 'agent_orchestration',
|
||||
};
|
||||
const result = classifyWithRules({
|
||||
text: '还是没有按照我的逻辑更正',
|
||||
sessionId: '20260827_3',
|
||||
sessionMessageCount: 50,
|
||||
activeTaskContext,
|
||||
grantedSkills: ['page-data-collect'],
|
||||
});
|
||||
assert.equal(result.route, CHAT_INTENT_ROUTE.AGENT);
|
||||
assert.equal(result.suggestedSkill, 'page-data-collect');
|
||||
assert.match(result.reason, /上一轮任务未完成/);
|
||||
});
|
||||
|
||||
test('classifyWithRules routes correction follow-up to agent when recent agent task exists', () => {
|
||||
const activeTaskContext = {
|
||||
hasRecentAgentTask: true,
|
||||
lastRunFailed: false,
|
||||
lastSuggestedSkill: 'page-data-collect',
|
||||
lastRunStatus: 'succeeded',
|
||||
lastRoute: 'agent_orchestration',
|
||||
};
|
||||
const result = classifyWithRules({
|
||||
text: '不听指令了吗',
|
||||
sessionId: '20260827_3',
|
||||
sessionMessageCount: 51,
|
||||
activeTaskContext,
|
||||
grantedSkills: ['page-data-collect'],
|
||||
});
|
||||
assert.equal(result.route, CHAT_INTENT_ROUTE.AGENT);
|
||||
assert.equal(result.suggestedSkill, 'page-data-collect');
|
||||
assert.match(result.reason, /纠正或补充/);
|
||||
});
|
||||
|
||||
test('classifyWithRules defers ambiguous active-task follow-up to LLM router', () => {
|
||||
const activeTaskContext = {
|
||||
hasRecentAgentTask: true,
|
||||
lastRunFailed: false,
|
||||
lastSuggestedSkill: 'page-data-collect',
|
||||
lastRunStatus: 'succeeded',
|
||||
lastRoute: 'agent_orchestration',
|
||||
};
|
||||
const result = classifyWithRules({
|
||||
text: '招商管理端可以展开招商漏斗,明确准入门槛',
|
||||
sessionId: '20260827_3',
|
||||
sessionMessageCount: 52,
|
||||
activeTaskContext,
|
||||
grantedSkills: ['page-data-collect'],
|
||||
});
|
||||
assert.equal(result, null);
|
||||
});
|
||||
|
||||
test('formatRouterTranscript keeps recent turns and strips skill prefixes from user text', () => {
|
||||
const transcript = formatRouterTranscript([
|
||||
{
|
||||
role: 'user',
|
||||
metadata: { displayText: '帮我做商户沟通台账' },
|
||||
content: [{ type: 'text', text: '请使用 page-data-collect 技能:帮我做商户沟通台账' }],
|
||||
},
|
||||
{
|
||||
role: 'assistant',
|
||||
content: [{ type: 'text', text: '好的,我先创建问卷页面。' }],
|
||||
},
|
||||
], {
|
||||
excludeLatestUserText: '招商管理端展开漏斗',
|
||||
});
|
||||
assert.match(transcript, /用户:帮我做商户沟通台账/);
|
||||
assert.match(transcript, /助手:好的,我先创建问卷页面/);
|
||||
assert.doesNotMatch(transcript, /page-data-collect 技能/);
|
||||
});
|
||||
|
||||
test('createChatIntentRouter uses active-task fallback when LLM router is unavailable', async () => {
|
||||
const router = createChatIntentRouter({
|
||||
llmProviderService: {
|
||||
async createChatCompletion() {
|
||||
return null;
|
||||
},
|
||||
},
|
||||
env: {
|
||||
...process.env,
|
||||
MEMIND_CHAT_LLM_ROUTER_ENABLED: '1',
|
||||
MEMIND_CHAT_LLM_ROUTER_SHADOW: '0',
|
||||
MEMIND_CHAT_ROUTER_CANARY_USER_IDS: '',
|
||||
},
|
||||
});
|
||||
const result = await router.classify({
|
||||
userId: 'user-1',
|
||||
sessionId: '20260827_3',
|
||||
sessionMessageCount: 40,
|
||||
grantedSkills: ['page-data-collect'],
|
||||
activeTaskContext: {
|
||||
hasRecentAgentTask: true,
|
||||
lastRunFailed: true,
|
||||
lastSuggestedSkill: 'page-data-collect',
|
||||
lastRunStatus: 'failed',
|
||||
lastRoute: 'agent_orchestration',
|
||||
},
|
||||
userMessage: {
|
||||
role: 'user',
|
||||
content: [{ type: 'text', text: '还是没有按照我的逻辑更正' }],
|
||||
metadata: { displayText: '还是没有按照我的逻辑更正' },
|
||||
},
|
||||
});
|
||||
assert.equal(result.route, CHAT_INTENT_ROUTE.AGENT);
|
||||
assert.equal(result.suggestedSkill, 'page-data-collect');
|
||||
});
|
||||
|
||||
test('classifyWithRules keeps memory recall on direct chat even with failed agent task context', () => {
|
||||
const activeTaskContext = {
|
||||
hasRecentAgentTask: true,
|
||||
lastRunFailed: true,
|
||||
lastSuggestedSkill: 'page-data-collect',
|
||||
lastRunStatus: 'failed',
|
||||
};
|
||||
const result = classifyWithRules({
|
||||
text: '你记得我说想去哪儿吗',
|
||||
sessionId: '20260827_3',
|
||||
sessionMessageCount: 50,
|
||||
activeTaskContext,
|
||||
userMessage: {
|
||||
role: 'user',
|
||||
content: [{ type: 'text', text: '你记得我说想去哪儿吗' }],
|
||||
metadata: { displayText: '你记得我说想去哪儿吗' },
|
||||
},
|
||||
});
|
||||
assert.equal(result.route, CHAT_INTENT_ROUTE.DIRECT_CHAT);
|
||||
assert.match(result.reason, /记忆|历史对话/);
|
||||
});
|
||||
|
||||
test('classifyWithRules keeps memory recall on direct chat even when session already active', () => {
|
||||
const result = classifyWithRules({
|
||||
text: '你记得我说想去哪儿吗',
|
||||
|
||||
Reference in New Issue
Block a user