mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-19 05:26:47 +00:00
fix(mcp): keep transit out of the transport create enum
The transport form's picker has nine entries, not ten: a transit booking carries a provider itinerary in metadata.transit and create_transit_journey is what writes one, so letting a caller hand-make a bare transit row produces a shape the transit UI does not expect. Splits the one list in two - what may be asked for, and what counts as a transport for the update gate - so a stored transit booking stays editable through update_transport, which is where it was already reachable. Also reports the ids set_reservation_travelers dropped instead of returning a plain success with a shorter list.
This commit is contained in:
@@ -592,6 +592,23 @@ describe('Tool: set_reservation_travelers', () => {
|
||||
});
|
||||
const data = parseToolResult(result) as any;
|
||||
expect(data.travelers.map((t: any) => t.user_id)).toEqual([owner.id]);
|
||||
// A caller that guessed an id for a name it could not resolve is told so
|
||||
// rather than getting a plain success with a shorter list.
|
||||
expect(data.ignored_user_ids).toEqual([outsider.id]);
|
||||
});
|
||||
});
|
||||
|
||||
it('says nothing about ignored ids when every id was on the trip', async () => {
|
||||
const { user: owner } = createUser(testDb);
|
||||
const trip = createTrip(testDb, owner.id);
|
||||
await withHarness(owner.id, async (h) => {
|
||||
const reservationId = await makeBooking(h, trip.id);
|
||||
const result = await h.client.callTool({
|
||||
name: 'set_reservation_travelers',
|
||||
arguments: { tripId: trip.id, reservationId, user_ids: [owner.id] },
|
||||
});
|
||||
const data = parseToolResult(result) as any;
|
||||
expect(data.ignored_user_ids).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -1052,11 +1052,11 @@ describe('Tool: update_transport (multi-leg)', () => {
|
||||
|
||||
/** client/src/components/Planner/TransportModal.tsx, in the picker's order. */
|
||||
const PICKER_TRANSPORT_TYPES = [
|
||||
'flight', 'train', 'bus', 'car', 'taxi', 'bicycle', 'cruise', 'ferry', 'transit', 'transport_other',
|
||||
'flight', 'train', 'bus', 'car', 'taxi', 'bicycle', 'cruise', 'ferry', 'transport_other',
|
||||
] as const;
|
||||
|
||||
/** The six the tools used to reject outright. */
|
||||
const NEWLY_ACCEPTED = ['bus', 'taxi', 'bicycle', 'ferry', 'transit', 'transport_other'] as const;
|
||||
/** The five the tools used to reject outright. */
|
||||
const NEWLY_ACCEPTED = ['bus', 'taxi', 'bicycle', 'ferry', 'transport_other'] as const;
|
||||
|
||||
describe('Transport tools: the full type list', () => {
|
||||
it.each(PICKER_TRANSPORT_TYPES)('create_transport accepts %s', async (type) => {
|
||||
@@ -1172,6 +1172,36 @@ describe('Transport tools: the full type list', () => {
|
||||
});
|
||||
});
|
||||
|
||||
it('refuses to hand-make a transit booking, which create_transit_journey owns', async () => {
|
||||
const { user } = createUser(testDb);
|
||||
const trip = createTrip(testDb, user.id);
|
||||
await withHarness(user.id, async (h) => {
|
||||
const result = await h.client.callTool({
|
||||
name: 'create_transport',
|
||||
arguments: { tripId: trip.id, type: 'transit', title: 'Tram 4' },
|
||||
});
|
||||
expect((result as { isError?: boolean }).isError).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
it('still lets update_transport reach a stored transit booking', async () => {
|
||||
const { user } = createUser(testDb);
|
||||
const trip = createTrip(testDb, user.id);
|
||||
// As create_transit_journey leaves it: a transport row carrying an itinerary.
|
||||
const reservationId = Number(testDb.prepare(
|
||||
"INSERT INTO reservations (trip_id, title, type, status) VALUES (?, 'Tram 4', 'transit', 'pending')"
|
||||
).run(trip.id).lastInsertRowid);
|
||||
await withHarness(user.id, async (h) => {
|
||||
const result = await h.client.callTool({
|
||||
name: 'update_transport',
|
||||
arguments: { tripId: trip.id, reservationId, status: 'confirmed' },
|
||||
});
|
||||
expect((result as { isError?: boolean }).isError).toBeFalsy();
|
||||
const row = testDb.prepare('SELECT status, type FROM reservations WHERE id = ?').get(reservationId) as any;
|
||||
expect(row).toMatchObject({ status: 'confirmed', type: 'transit' });
|
||||
});
|
||||
});
|
||||
|
||||
it('still refuses legs on a mode whose form never writes them', async () => {
|
||||
const { user } = createUser(testDb);
|
||||
const trip = createTrip(testDb, user.id);
|
||||
|
||||
Reference in New Issue
Block a user