fix(schedule): close fixed-rate delivery review gaps
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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([])
|
||||||
|
|||||||
Reference in New Issue
Block a user