Files
memind/rain-service.test.mjs
T
john d2d463b1db
Memind CI / Test, build, and release guards (push) Successful in 5m5s
feat(rain): add date preset picker and reduce time clarification prompts.
Default to last 3 days in UI and backend, only ask when time is truly ambiguous, and treat「做成页面」as HTML report pages without follow-up questions.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-07 16:54:11 +08:00

116 lines
4.6 KiB
JavaScript

import test from 'node:test';
import assert from 'node:assert/strict';
import { resolveRainTimeRange, RAIN_DEFAULT_DAYS, resolveRainTimeRangeFromPreset } from './rain-service/time-range.mjs';
import { formatMeinputFullBlock } from './rain-service/meinput-full.mjs';
import { buildRainGooseHandoffText, stripRainSkillPrefix } from './rain-service/llm-analysis.mjs';
import {
RAIN_SKILL_NAME,
isRainModeMessage,
filterChatSkills,
CHAT_SKILL_DEFINITIONS,
} from './chat-skills.mjs';
test('resolveRainTimeRange defaults to 3 days when no time hint', () => {
const now = new Date('2026-09-04T12:00:00+08:00');
const result = resolveRainTimeRange('帮我总结最近的输入', now);
assert.equal(result.needsClarification, false);
assert.equal(result.source, 'default_3d');
assert.ok(result.range?.start);
assert.ok(result.range?.end);
const spanMs =
new Date(result.range.end).getTime() - new Date(result.range.start).getTime();
assert.ok(spanMs >= RAIN_DEFAULT_DAYS * 24 * 60 * 60 * 1000 - 60_000);
});
test('resolveRainTimeRange defaults to 3 days for fuzzy phrases like 前几天', () => {
const now = new Date('2026-09-04T12:00:00+08:00');
const result = resolveRainTimeRange('前几天我在做什么', now);
assert.equal(result.needsClarification, false);
assert.equal(result.source, 'default_3d');
});
test('resolveRainTimeRange asks clarification only for strictly ambiguous phrases', () => {
const result = resolveRainTimeRange('不太确定那段时间我在做什么', new Date('2026-09-04T12:00:00+08:00'));
assert.equal(result.needsClarification, true);
assert.match(result.clarificationQuestion ?? '', /起止时间/);
});
test('resolveRainTimeRangeFromPreset resolves UI presets', () => {
const now = new Date('2026-09-06T12:00:00+08:00');
const today = resolveRainTimeRangeFromPreset('today', now);
assert.equal(today.label, '今天');
assert.ok(today.range?.start);
const threeDays = resolveRainTimeRangeFromPreset('3d', now);
assert.equal(threeDays.label, '近3天');
});
test('resolveRainTimeRange parses yesterday explicitly', () => {
const now = new Date('2026-09-04T12:00:00+08:00');
const result = resolveRainTimeRange('我昨天输入了什么', now);
assert.equal(result.needsClarification, false);
assert.equal(result.source, 'user_explicit');
assert.equal(result.label, 'yesterday');
});
test('formatMeinputFullBlock lists every record with timestamp', () => {
const block = formatMeinputFullBlock(
[
{
created_at: '2026-09-02T19:42:16.541Z',
text: '项目',
app_name: 'Cursor',
app_bundle_id: 'com.cursor',
},
{
created_at: '2026-09-02T19:46:15.181Z',
text: '手机',
app_name: null,
app_bundle_id: 'com.apple.mobile',
},
],
{
range: { start: '2026-09-01T00:00:00.000Z', end: '2026-09-04T00:00:00.000Z' },
label: '近3天',
},
);
assert.match(block, /MeInput 原始输入 · Rain/);
assert.match(block, /项目/);
assert.match(block, /手机/);
assert.match(block, /2026-09-02 19:42:16/);
assert.doesNotMatch(block, /0\.2795/);
});
test('buildRainGooseHandoffText carries analysis to agent', () => {
const text = buildRainGooseHandoffText({
userQuery: '最近我输入了什么',
timeRangeLabel: '近3天',
recordCount: 12,
analysis: '用户在 Cursor 中输入了项目相关词',
userGoal: '回顾输入',
suggestedNextSteps: ['给用户时间线总结'],
});
assert.match(text, /Rain · MeInput 分析简报/);
assert.match(text, /用户在 Cursor 中输入了项目相关词/);
assert.match(text, /最近我输入了什么/);
});
test('isRainModeMessage detects selected rain skill', () => {
assert.equal(
isRainModeMessage({ metadata: { memindRun: { selectedChatSkill: RAIN_SKILL_NAME } } }),
true,
);
assert.equal(isRainModeMessage({ metadata: { memindRun: { selectedChatSkill: 'web' } } }), false);
});
test('filterChatSkills hides page templates by default', () => {
const options = CHAT_SKILL_DEFINITIONS.map((def) => ({ ...def, buildPrompt: () => '' }));
const filtered = filterChatSkills(options, { grantedSkills: ['page-template-travel'], canPublish: true });
assert.ok(filtered.some((item) => item.id === RAIN_SKILL_NAME));
assert.equal(filtered.some((item) => item.id === 'page-template-travel'), false);
});
test('stripRainSkillPrefix removes rain prompt header', () => {
const text = stripRainSkillPrefix('【Rain · MeInput 输入分析】在下方选择时间范围(默认近3天),描述你的诉求(例如「总结输入活动」或「做成页面报告」)。我的问题是:总结输入');
assert.equal(text, '总结输入');
});