e13df82021
Memind CI / Test, build, and release guards (push) Failing after 14m19s
Stop ITL regex from intercepting new messages before Agent execution; move scheduled task and schedule write confirmation to MCP tool calls with draft commit on 确认. Co-authored-by: Cursor <cursoragent@cursor.com>
97 lines
2.9 KiB
JavaScript
97 lines
2.9 KiB
JavaScript
import assert from 'node:assert/strict';
|
|
import test from 'node:test';
|
|
import { commitIntentDraft } from './intent-transaction-commit.mjs';
|
|
import { requireUserConfirmForSideEffectTool } from './intent-tool-confirm-gate.mjs';
|
|
|
|
function createDraftStore() {
|
|
let pending = null;
|
|
return {
|
|
async getPendingDraft(userId) {
|
|
return pending?.userId === userId ? pending : null;
|
|
},
|
|
async createDraft(payload) {
|
|
pending = {
|
|
id: 'draft-tool-1',
|
|
status: 'draft',
|
|
...payload,
|
|
};
|
|
return pending;
|
|
},
|
|
async cancelDraft(id, userId) {
|
|
if (pending?.id === id && pending.userId === userId) pending = null;
|
|
return { id, status: 'cancelled' };
|
|
},
|
|
async markDraftCommitted(id, userId, committedRef) {
|
|
pending = { ...pending, id, userId, status: 'committed', committedRef };
|
|
return pending;
|
|
},
|
|
};
|
|
}
|
|
|
|
test('requireUserConfirmForSideEffectTool creates draft instead of writing', async () => {
|
|
const drafts = createDraftStore();
|
|
const gate = await requireUserConfirmForSideEffectTool({
|
|
userId: 'user-1',
|
|
toolName: 'scheduled_task_create',
|
|
toolArgs: {
|
|
taskSpec: '做今日新闻页面',
|
|
recurrence: 'daily',
|
|
hour: 6,
|
|
minute: 0,
|
|
},
|
|
intentDraftService: drafts,
|
|
env: { H5_INTENT_TRANSACTION_ENABLED: '1' },
|
|
});
|
|
assert.equal(gate.proceed, false);
|
|
assert.equal(gate.response.status, 'needs_user_confirmation');
|
|
assert.match(gate.response.cardText, /确认/u);
|
|
const pending = await drafts.getPendingDraft('user-1');
|
|
assert.equal(pending.draftType, 'agent_tool');
|
|
assert.equal(pending.payload.toolName, 'scheduled_task_create');
|
|
});
|
|
|
|
test('requireUserConfirmForSideEffectTool proceeds when feature disabled', async () => {
|
|
const gate = await requireUserConfirmForSideEffectTool({
|
|
userId: 'user-1',
|
|
toolName: 'scheduled_task_create',
|
|
toolArgs: { taskSpec: '做新闻页面', hour: 6 },
|
|
intentDraftService: createDraftStore(),
|
|
env: { H5_INTENT_TRANSACTION_ENABLED: '0' },
|
|
});
|
|
assert.equal(gate.proceed, true);
|
|
});
|
|
|
|
test('commitIntentDraft commits agent_tool scheduled task draft', async () => {
|
|
const created = [];
|
|
const committed = await commitIntentDraft({
|
|
draft: {
|
|
status: 'draft',
|
|
draftType: 'agent_tool',
|
|
title: '新闻页面',
|
|
payload: {
|
|
toolName: 'scheduled_task_create',
|
|
toolArgs: {
|
|
taskSpec: '做今日新闻页面',
|
|
recurrence: 'daily',
|
|
hour: 6,
|
|
minute: 0,
|
|
timezone: 'Asia/Shanghai',
|
|
},
|
|
},
|
|
},
|
|
userId: 'user-1',
|
|
scheduledTaskService: {
|
|
async createTask(input) {
|
|
created.push(input);
|
|
return { id: 'task-1', ...input };
|
|
},
|
|
},
|
|
scheduleService: null,
|
|
timezone: 'Asia/Shanghai',
|
|
env: { H5_INTENT_TRANSACTION_ENABLED: '1' },
|
|
});
|
|
assert.equal(committed.kind, 'scheduled_task');
|
|
assert.equal(created.length, 1);
|
|
assert.equal(created[0].hour, 6);
|
|
});
|