mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-24 16:03:02 +00:00
feat(tours): save_tour_change saves a confirmed change to a city walk whole or not at all
An assistant can now save the change prepare_tour_change prepared, once the traveller said yes to it exactly as shown. Until now a proposal could only be looked at; the traveller had to redo it by hand in the planner. - The save names the proposal: the same changes, the revision it was prepared on, the proposal_id the preparation answered and confirmed true. Anything else, a change altered on the way or no yes, is refused and nothing is saved. - Place editing on the trip and the tour are checked again before anything is written. A tour changed since the proposal was prepared is a conflict on the tour's one revision (no second one), telling the assistant to prepare the change anew instead of writing over newer edits. The changes are laid on the saved tour once more inside the write, so a station visited or skipped meanwhile, or a place of the trip gone, refuses the save with every reason. - The change goes through the write the planner's save uses, in one transaction: line, stations, keys, measures and visits together or not at all, and the trip is told only after the commit. Stations kept keep their keys and visits. Where the router gives no way on foot the walk keeps its stations only and waits for the planner, as a created one does. - Every save is kept as a step of the tour (tour_change_steps): the proposal, the revision it was prepared on and the one it raised the tour to, the changes and the tour as it was before them, so the step can be followed and taken back later. Nothing of the conversation is kept. - A new walk has no revision to name and stays with create_city_walk; both tool descriptions and the wiki say which is which.
This commit is contained in:
@@ -1,4 +1,10 @@
|
||||
import { TOUR_CHANGE_MAX, TOUR_CHANGE_OPS, tourChangeRequestSchema, tourChangeSchema } from './tour-change.schema';
|
||||
import {
|
||||
TOUR_CHANGE_MAX,
|
||||
TOUR_CHANGE_OPS,
|
||||
tourChangeRequestSchema,
|
||||
tourChangeSaveRequestSchema,
|
||||
tourChangeSchema,
|
||||
} from './tour-change.schema';
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
@@ -34,3 +40,32 @@ describe('a change to a saved tour prepared for review (MCP-T02)', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('a prepared change the traveller confirmed, sent to be saved (MCP-T03)', () => {
|
||||
const save = {
|
||||
changes: [{ op: 'remove', key: 'stop-park' }],
|
||||
expected_revision: 3,
|
||||
proposal_id: '0123456789abcdef0123456789abcdef',
|
||||
confirmed: true,
|
||||
};
|
||||
|
||||
it('takes the changes with the revision and the proposal they were prepared as, and the yes', () => {
|
||||
expect(tourChangeSaveRequestSchema.parse(save)).toEqual(save);
|
||||
});
|
||||
|
||||
it('refuses a save without the yes, without the revision, of no proposal, or with anything more', () => {
|
||||
const refused = [
|
||||
{ ...save, confirmed: false },
|
||||
{ ...save, confirmed: undefined },
|
||||
{ ...save, expected_revision: undefined },
|
||||
{ ...save, expected_revision: 0 },
|
||||
{ ...save, proposal_id: 'not-a-proposal' },
|
||||
{ ...save, proposal_id: '0123456789ABCDEF0123456789ABCDEF' },
|
||||
{ ...save, note: 'the traveller said so in the chat' },
|
||||
{ ...save, changes: [] },
|
||||
];
|
||||
for (const body of refused) {
|
||||
expect(tourChangeSaveRequestSchema.safeParse(body).success, JSON.stringify(body)).toBe(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { cityWalkStationSchema } from './tour-walk-briefing.schema';
|
||||
import { stationKeySchema } from './tours.schema';
|
||||
import { stationKeySchema, tourRevisionSchema } from './tours.schema';
|
||||
|
||||
import { z } from 'zod';
|
||||
|
||||
@@ -46,3 +46,31 @@ export const tourChangeRequestSchema = z
|
||||
})
|
||||
.strict();
|
||||
export type TourChangeRequest = z.infer<typeof tourChangeRequestSchema>;
|
||||
|
||||
/**
|
||||
* MCP-T03: the proposal_id a preparation answers, binding a save to the very
|
||||
* proposal the traveller was shown: the same tour, revision and changes.
|
||||
*/
|
||||
export const tourChangeProposalIdSchema = z
|
||||
.string()
|
||||
.regex(/^[0-9a-f]{32}$/)
|
||||
.describe('The proposal_id prepare_tour_change answered with the proposal the traveller confirmed');
|
||||
|
||||
/**
|
||||
* MCP-T03: a prepared change the traveller confirmed, sent to be saved. It
|
||||
* repeats the changes and the revision of the proposal they were shown, names
|
||||
* that proposal and says yes in so many words: a save without the yes, or of
|
||||
* anything other than what was prepared, is refused.
|
||||
*/
|
||||
export const tourChangeSaveRequestSchema = tourChangeRequestSchema
|
||||
.extend({
|
||||
expected_revision: tourRevisionSchema.describe(
|
||||
'base.revision of the proposal: the revision of the tour it was prepared on',
|
||||
),
|
||||
proposal_id: tourChangeProposalIdSchema,
|
||||
confirmed: z
|
||||
.literal(true)
|
||||
.describe('true only once the traveller said yes to exactly this proposal as it was shown to them'),
|
||||
})
|
||||
.strict();
|
||||
export type TourChangeSaveRequest = z.infer<typeof tourChangeSaveRequestSchema>;
|
||||
|
||||
Reference in New Issue
Block a user