fix(schedule): close fixed-rate delivery review gaps

This commit is contained in:
pku-xht
2026-08-08 02:54:36 +08:00
committed by Tianyi Cui
parent d2be9a634f
commit 9a0bfc143b
3 changed files with 29 additions and 21 deletions

View File

@@ -28,11 +28,9 @@ import {
ScheduleId, ScheduleId,
createAfterScheduleRecord, createAfterScheduleRecord,
foldScheduleEvents, foldScheduleEvents,
scheduleReminderPresentation,
} from '@deepseek-ai/dsh-tool-schedule' } from '@deepseek-ai/dsh-tool-schedule'
import { import type { EveryScheduleRecord } from '@deepseek-ai/dsh-tool-schedule'
createEveryScheduleRecord,
resolveEveryOccurrence,
} from '../../../packages/schedule/tool-schedule/src/domain.ts'
const MODE = webSnapshotMode() const MODE = webSnapshotMode()
const OVERLAY = fileURLToPath(new URL('../../../examples/web-schedule/cordis.yml', import.meta.url)) const OVERLAY = fileURLToPath(new URL('../../../examples/web-schedule/cordis.yml', import.meta.url))
@@ -394,22 +392,23 @@ describe.skipIf(MODE === 'record')('web e2e: fixed-rate restart and batch receip
title: 'Every restart session', messageSeqs: [], source: { kind: 'user' }, title: 'Every restart session', messageSeqs: [], source: { kind: 'user' },
}) })
const seededAt = Date.now() const seededAt = Date.now()
const records = [ const records: readonly [EveryScheduleRecord, EveryScheduleRecord] = [
createEveryScheduleRecord( {
ScheduleId('schedule-every-primary'), id: ScheduleId('schedule-every-primary'),
EVERY_PROMPTS[0], kind: 'every',
300, prompt: EVERY_PROMPTS[0],
seededAt - 1_200_000, everySeconds: 300,
), scheduledAt: new Date(seededAt - 900_000).toISOString(),
createEveryScheduleRecord( },
ScheduleId('schedule-every-secondary'), {
EVERY_PROMPTS[1], id: ScheduleId('schedule-every-secondary'),
300, kind: 'every',
seededAt - 1_140_000, prompt: EVERY_PROMPTS[1],
), everySeconds: 300,
scheduledAt: new Date(seededAt - 840_000).toISOString(),
},
] ]
const [primary, secondary] = records const [primary, secondary] = records
if (primary === undefined || secondary === undefined) throw new Error('missing every fixtures')
const recordIds = new Set(records.map(record => record.id)) const recordIds = new Set(records.map(record => record.id))
for (const record of records) { for (const record of records) {
seeded.append('schedule/change', { version: 1, operation: 'create', schedule: record }) seeded.append('schedule/change', { version: 1, operation: 'create', schedule: record })
@@ -470,7 +469,16 @@ describe.skipIf(MODE === 'record')('web e2e: fixed-rate restart and batch receip
let batchSnapshot = batchBlock.text let batchSnapshot = batchBlock.text
const occurrencePlaceholders = ['{{primaryOccurrenceAt}}', '{{secondaryOccurrenceAt}}'] as const const occurrencePlaceholders = ['{{primaryOccurrenceAt}}', '{{secondaryOccurrenceAt}}'] as const
for (const [index, record] of records.entries()) { for (const [index, record] of records.entries()) {
const occurrenceAt = resolveEveryOccurrence(record, Date.parse(acceptedAt)).occurrenceAt const dispatch = dispatches.find(event => event.type === 'schedule/change'
&& event.data.operation === 'dispatch'
&& event.data.id === record.id)
if (dispatch?.type !== 'schedule/change') throw new Error(`missing dispatch for ${record.id}`)
const occurrenceAt = scheduleReminderPresentation(
agent.session.events,
dispatch.seq,
agent.session.header.seedLength ?? 0,
)?.occurrenceAt
if (occurrenceAt === undefined) throw new Error(`missing receipt occurrence for ${record.id}`)
batchSnapshot = batchSnapshot.split(occurrenceAt).join(occurrencePlaceholders[index]) batchSnapshot = batchSnapshot.split(occurrenceAt).join(occurrencePlaceholders[index])
} }
await compareOrRefreshGolden(EVERY_BATCH_EXPECTED, batchSnapshot, MODE) await compareOrRefreshGolden(EVERY_BATCH_EXPECTED, batchSnapshot, MODE)

View File

@@ -471,7 +471,7 @@ export function registerScheduleTools(
&& isRecurringGateExhausted(folded.lastRecurringAcceptedAt)) { && isRecurringGateExhausted(folded.lastRecurringAcceptedAt)) {
return { return {
code: 'time_out_of_range', code: 'time_out_of_range',
message: 'The scheduled time must be representable as a four-digit-year RFC 3339 UTC instant.', message: 'No compliant recurring delivery time remains representable within the four-digit-year range.',
} }
} }
const id = allocateScheduleId(folded) const id = allocateScheduleId(folded)

View File

@@ -327,7 +327,7 @@ describe('Schedule tool protocol', () => {
prompt: 'rolled back', every_seconds: 300, prompt: 'rolled back', every_seconds: 300,
}))).toEqual({ }))).toEqual({
code: 'time_out_of_range', code: 'time_out_of_range',
message: 'The scheduled time must be representable as a four-digit-year RFC 3339 UTC instant.', message: 'No compliant recurring delivery time remains representable within the four-digit-year range.',
}) })
expect(test.agent.session.events.filter(event => event.type === 'schedule/change')).toHaveLength(2) expect(test.agent.session.events.filter(event => event.type === 'schedule/change')).toHaveLength(2)
expect(value(await execute(test, 'schedule_list', {}))).toEqual([]) expect(value(await execute(test, 'schedule_list', {}))).toEqual([])