@curless/hotel-storefront 0.48.0 → 0.49.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/backend.d.ts.map +1 -1
- package/dist/backend.js.map +1 -1
- package/dist/card.generated.d.ts +1 -1
- package/dist/card.generated.js +2 -2
- package/dist/card.generated.js.map +1 -1
- package/dist/demo-hotels.d.ts +7 -0
- package/dist/demo-hotels.d.ts.map +1 -1
- package/dist/demo-hotels.js +167 -79
- package/dist/demo-hotels.js.map +1 -1
- package/dist/fence.d.ts +10 -0
- package/dist/fence.d.ts.map +1 -1
- package/dist/fence.js +15 -0
- package/dist/fence.js.map +1 -1
- package/dist/huazhu/backend.d.ts.map +1 -1
- package/dist/huazhu/backend.js +11 -6
- package/dist/huazhu/backend.js.map +1 -1
- package/dist/listing.d.ts +5 -1
- package/dist/listing.d.ts.map +1 -1
- package/dist/listing.js +6 -2
- package/dist/listing.js.map +1 -1
- package/dist/present.d.ts +27 -0
- package/dist/present.d.ts.map +1 -1
- package/dist/present.js +40 -2
- package/dist/present.js.map +1 -1
- package/dist/same-booking.d.ts +33 -0
- package/dist/same-booking.d.ts.map +1 -0
- package/dist/same-booking.js +73 -0
- package/dist/same-booking.js.map +1 -0
- package/dist/server.d.ts +2 -2
- package/dist/server.js +3 -3
- package/dist/server.js.map +1 -1
- package/dist/tools.d.ts +3 -3
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +86 -40
- package/dist/tools.js.map +1 -1
- package/dist/trip.d.ts +0 -11
- package/dist/trip.d.ts.map +1 -1
- package/dist/trip.js +21 -6
- package/dist/trip.js.map +1 -1
- package/package.json +1 -1
package/dist/tools.d.ts
CHANGED
|
@@ -15,7 +15,7 @@ export declare const LOOK_UP_MAX = 6;
|
|
|
15
15
|
*/
|
|
16
16
|
export declare const buildTools: (n: ToolNames, v: Vocabulary, caps?: BackendCapabilities) => ({
|
|
17
17
|
readonly name: `list_${string}${string}`;
|
|
18
|
-
readonly description: `${string}, shown as a card for a guest to look through and pick one ${string} to book.
|
|
18
|
+
readonly description: `${string}, shown as a card for a guest to look through and pick one ${string} to book. It holds no plan of days: a day-by-day plan (\u884C\u7A0B, \u5B89\u6392, an itinerary) is a card of its own, laid out by the days, with a ${string} for each part of the trip read up as text. Asked with no place - or a country of many cities - it answers with the places to choose from: regions, countries and cities, each with how many ${string} it has; \`all\` lists the ${string} themselves. \`city\` (a city or a country) or \`query\` answers with the ${string}: a picture, the city and area, a rating where the ${string} publishes one, and a from-price, and a city usually holds several. With \`checkIn\` and \`checkOut\` every ${string} is priced for those nights - its cheapest room that takes the party, \`rooms\` of it, for the whole stay with taxes - or marked as having no room for them. \`sort\` and \`maxNightly\` order and cap by that price, or by the from-price without dates, where the matches share one currency. \`brand\`, \`facilities\`, \`freeCancellation\`, \`breakfast\` and \`bed\` narrow the list, and the answer counts what each would leave. A long list comes a page at a time: the answer says how many more there are and the \`offset\` of the next page. Words or a place that match nothing are widened once, and the answer names what it widened to.${string}`;
|
|
19
19
|
readonly annotations: {
|
|
20
20
|
readonly title: string;
|
|
21
21
|
readonly readOnlyHint: true;
|
|
@@ -178,7 +178,7 @@ export declare const buildTools: (n: ToolNames, v: Vocabulary, caps?: BackendCap
|
|
|
178
178
|
};
|
|
179
179
|
} | {
|
|
180
180
|
readonly name: `look_up_${string}${string}`;
|
|
181
|
-
readonly description: `Reads up to 6 ${string} - a \`city\`'s (or a country's), or the ones named in \`${string}\` - and returns them as text, with nothing drawn and nothing shown to the guest: each one's id, area, rating, description and amenities, its add-ons with their ids and prices, and, given \`checkIn\` and \`checkOut\`, its rooms priced for those nights with taxes in.
|
|
181
|
+
readonly description: `Reads up to 6 ${string} - a \`city\`'s (or a country's), or the ones named in \`${string}\` - and returns them as text, with nothing drawn and nothing shown to the guest: each one's id, area, rating, description and amenities, its add-ons with their ids and prices, and, given \`checkIn\` and \`checkOut\`, its rooms priced for those nights with taxes in. Nothing it reads is shown, so the ${string} of a day-by-day plan - for each part of the trip, those near where its days are spent - can be read up before the plan is drawn; its ids are the ones a comparison and a plan take.`;
|
|
182
182
|
readonly annotations: {
|
|
183
183
|
readonly title: string;
|
|
184
184
|
readonly readOnlyHint: true;
|
|
@@ -663,7 +663,7 @@ export declare const buildTools: (n: ToolNames, v: Vocabulary, caps?: BackendCap
|
|
|
663
663
|
};
|
|
664
664
|
} | {
|
|
665
665
|
readonly name: `show_${string}itinerary`;
|
|
666
|
-
readonly description: `A day-by-day plan (\u884C\u7A0B) as one card - the card for a trip of several days, or for a guest
|
|
666
|
+
readonly description: `A day-by-day plan (\u884C\u7A0B) as one card - the card for a trip of several days, or for days a guest asked to have planned (a city with a span of dates and \u884C\u7A0B is one): the days are laid out by where they are spent, and each part of the trip has a ${string} near those days, chosen from the ${string} read up as text. A week in a big city is usually two or three stays: its far-out sights fall on neighbouring days, and those nights have a ${string} near them, with the reason in that day's \`why\` (Beijing's Summer Palace, Yuanmingyuan, Fragrant Hills and the Peking and Tsinghua campuses - \u9890\u548C\u56ED, \u5706\u660E\u56ED, \u9999\u5C71, \u5317\u5927\u6E05\u534E - are days side by side in the north-west); a day out of town, such as the Great Wall, is a day of its own, there and back; one ${string} for the whole week suits days that are all within about 45 minutes of it. Nothing here knows a sight's opening days: each day is drawn as it is given, with its date (many museums close on Mondays, the Palace Museum - \u6545\u5BAB - among them). Each day carries its own label, an optional note, the moments of the day in order, and the ${string} and add-ons attached to it, with their details filled in from their own records - a ${string} with its photograph and, given dates, the price of its nights. Each stay is marked with whether it is booked, in the trip or only in the plan, and the card says how many of each. Nothing is added to the trip.`;
|
|
667
667
|
readonly annotations: {
|
|
668
668
|
readonly title: string;
|
|
669
669
|
readonly readOnlyHint: true;
|
package/dist/tools.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,mBAAmB,EASzB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAa,YAAY,EAAgB,MAAM,cAAc,CAAC;AAC1E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAK7C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AA+BhD,OAAO,EAGL,KAAK,SAAS,EAKf,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAEV,cAAc,EAkBd,eAAe,EAKhB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAa,KAAK,UAAU,EAAwC,MAAM,YAAY,CAAC;AAuF9F,+GAA+G;AAC/G,eAAO,MAAM,WAAW,IAAI,CAAC;AAE7B;;;;GAIG;AACH,eAAO,MAAM,UAAU,GACrB,GAAG,SAAS,EACZ,GAAG,UAAU,EACb,OAAM,mBAAuC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IACC,CAAC;AAEjD,mEAAmE;AACnE;;;;;GAKG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,EAC7E,GAAG,CAAC,EACJ,OAAO;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,UAAU,CAAA;CAAE,KAC7C,CAWF,CAAC;AAEF,eAAO,MAAM,aAAa,GAAI,GAAG,SAAS,EAAE,MAAM,mBAAmB,KAAG,GAAG,CAAC,MAAM,CAO9E,CAAC;
|
|
1
|
+
{"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"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"}
|
package/dist/tools.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DEFAULT_PAGE, FULL_CAPABILITIES, LASTING_REQUESTS, MAX_PAGE, REQUEST_KINDS, REQUEST_NOTE_MAX, guestTooLong, unitWords, } from './backend.js';
|
|
2
2
|
import { MAX_GUESTS, isDay, nights as nightsBetween } from './dates.js';
|
|
3
3
|
import { FACILITIES } from './facilities.js';
|
|
4
|
-
import { DESCRIPTION_MAX, POLICY_MAX, hotelText } from './fence.js';
|
|
4
|
+
import { DESCRIPTION_MAX, POLICY_MAX, hotelName, hotelText } from './fence.js';
|
|
5
5
|
import { clockOf, minutesOf, startProblem, stayWords, windowWords } from './hourly.js';
|
|
6
6
|
import { amountsIn, formatMoney, keepingAmounts, money, multiplyMoney, toMinor } from './money.js';
|
|
7
7
|
import { namedExactly, roomNamesOf, roomTypeNamed, withTraditional } from './names.js';
|
|
@@ -298,7 +298,7 @@ const allTools = (n, v) => {
|
|
|
298
298
|
// description says it too, as what the card is, never as an order: the
|
|
299
299
|
// directory rule (tool-descriptions.test.ts) holds, and "first" is one of
|
|
300
300
|
// its words, hence "the other way round".
|
|
301
|
-
description: `${upFirst(catalogue(v))}, shown as a card for a guest to look through and pick one ${v.noun} to book.
|
|
301
|
+
description: `${upFirst(catalogue(v))}, shown as a card for a guest to look through and pick one ${v.noun} to book. It holds no plan of days: a day-by-day plan (行程, 安排, an itinerary) is a card of its own, laid out by the days, with a ${v.noun} for each part of the trip read up as text. Asked with no place - or a country of many cities - it answers with the places to choose from: regions, countries and cities, each with how many ${v.nounPlural} it has; \`all\` lists the ${v.nounPlural} themselves. \`city\` (a city or a country) or \`query\` answers with the ${v.nounPlural}: a picture, the city and area, a rating where the ${v.noun} publishes one, and a from-price, and a city usually holds several. With \`checkIn\` and \`checkOut\` every ${v.noun} is priced for those nights - its cheapest room that takes the party, \`rooms\` of it, for the whole stay with taxes - or marked as having no room for them. \`sort\` and \`maxNightly\` order and cap by that price, or by the from-price without dates, where the matches share one currency. \`brand\`, \`facilities\`, \`freeCancellation\`, \`breakfast\` and \`bed\` narrow the list, and the answer counts what each would leave. A long list comes a page at a time: the answer says how many more there are and the \`offset\` of the next page. Words or a place that match nothing are widened once, and the answer names what it widened to.${v.hints.search ? ` ${v.hints.search}` : ''}`,
|
|
302
302
|
annotations: reads(`Browse ${catalogue(v)}`, open),
|
|
303
303
|
inputSchema: {
|
|
304
304
|
type: 'object',
|
|
@@ -431,7 +431,7 @@ const allTools = (n, v) => {
|
|
|
431
431
|
// the guest for one question (robin, 2026-09-29, Opus in Claude.ai). The
|
|
432
432
|
// reference apps do the same split: search without a card, present with
|
|
433
433
|
// one.
|
|
434
|
-
description: `Reads up to ${LOOK_UP_MAX} ${v.nounPlural} - a \`city\`'s (or a country's), or the ones named in \`${v.nounPlural}\` - and returns them as text, with nothing drawn and nothing shown to the guest: each one's id, area, rating, description and amenities, its add-ons with their ids and prices, and, given \`checkIn\` and \`checkOut\`, its rooms priced for those nights with taxes in.
|
|
434
|
+
description: `Reads up to ${LOOK_UP_MAX} ${v.nounPlural} - a \`city\`'s (or a country's), or the ones named in \`${v.nounPlural}\` - and returns them as text, with nothing drawn and nothing shown to the guest: each one's id, area, rating, description and amenities, its add-ons with their ids and prices, and, given \`checkIn\` and \`checkOut\`, its rooms priced for those nights with taxes in. Nothing it reads is shown, so the ${v.nounPlural} of a day-by-day plan - for each part of the trip, those near where its days are spent - can be read up before the plan is drawn; its ids are the ones a comparison and a plan take.`,
|
|
435
435
|
annotations: reads(`Look up ${catalogue(v)}`, open),
|
|
436
436
|
inputSchema: {
|
|
437
437
|
type: 'object',
|
|
@@ -740,7 +740,7 @@ const allTools = (n, v) => {
|
|
|
740
740
|
},
|
|
741
741
|
{
|
|
742
742
|
name: n.itinerary,
|
|
743
|
-
description: `A day-by-day plan (行程) as one card - the card for a trip of several days, or for a guest
|
|
743
|
+
description: `A day-by-day plan (行程) as one card - the card for a trip of several days, or for days a guest asked to have planned (a city with a span of dates and 行程 is one): the days are laid out by where they are spent, and each part of the trip has a ${v.noun} near those days, chosen from the ${v.nounPlural} read up as text. A week in a big city is usually two or three stays: its far-out sights fall on neighbouring days, and those nights have a ${v.noun} near them, with the reason in that day's \`why\` (Beijing's Summer Palace, Yuanmingyuan, Fragrant Hills and the Peking and Tsinghua campuses - 颐和园, 圆明园, 香山, 北大清华 - are days side by side in the north-west); a day out of town, such as the Great Wall, is a day of its own, there and back; one ${v.noun} for the whole week suits days that are all within about 45 minutes of it. Nothing here knows a sight's opening days: each day is drawn as it is given, with its date (many museums close on Mondays, the Palace Museum - 故宫 - among them). Each day carries its own label, an optional note, the moments of the day in order, and the ${v.nounPlural} and add-ons attached to it, with their details filled in from their own records - a ${v.noun} with its photograph and, given dates, the price of its nights. Each stay is marked with whether it is booked, in the trip or only in the plan, and the card says how many of each. Nothing is added to the trip.`,
|
|
744
744
|
annotations: reads(v.market ? `Lay out an itinerary on ${v.brand}` : `Lay out a ${v.brand} itinerary`, open),
|
|
745
745
|
inputSchema: {
|
|
746
746
|
type: 'object',
|
|
@@ -983,6 +983,8 @@ const TRIP_SCHEMA = {
|
|
|
983
983
|
subtotal: STR,
|
|
984
984
|
taxesAndFees: STR,
|
|
985
985
|
total: STR,
|
|
986
|
+
/** Which of a room type's rates a room named by its type was put in as - the text's first line. */
|
|
987
|
+
took: STR,
|
|
986
988
|
/** Who is signed in, on every payload. */
|
|
987
989
|
member: OBJ,
|
|
988
990
|
/** What the tier took off THIS trip, and what it earns. */
|
|
@@ -1373,6 +1375,10 @@ export const buildOutputSchemas = (n) => ({
|
|
|
1373
1375
|
inTrip: { type: 'number' },
|
|
1374
1376
|
planned: { type: 'number' },
|
|
1375
1377
|
dropped: ARR,
|
|
1378
|
+
/** The stays not booked yet, together - only when all are priced in one currency. */
|
|
1379
|
+
staysTotal: STR,
|
|
1380
|
+
/** What the text says of a long stay at one hotel, in the same words. */
|
|
1381
|
+
nudges: STRS,
|
|
1376
1382
|
},
|
|
1377
1383
|
required: ['view'],
|
|
1378
1384
|
},
|
|
@@ -2815,8 +2821,8 @@ const suggestionsFor = async (deps, d) => {
|
|
|
2815
2821
|
out.push({
|
|
2816
2822
|
// The label IS what is sent: a chip that sends more than it says is
|
|
2817
2823
|
// a chip that says something else in the guest's name.
|
|
2818
|
-
label: `Compare ${hotel.name} with the other ${hotel.city} hotels`,
|
|
2819
|
-
say: `Compare ${hotel.name} with the other ${hotel.city} hotels`,
|
|
2824
|
+
label: `Compare ${hotelName(hotel.name)} with the other ${hotelName(hotel.city)} hotels`,
|
|
2825
|
+
say: `Compare ${hotelName(hotel.name)} with the other ${hotelName(hotel.city)} hotels`,
|
|
2820
2826
|
});
|
|
2821
2827
|
}
|
|
2822
2828
|
// The price order is not a suggestion any more: it is the list's own sort
|
|
@@ -2825,12 +2831,12 @@ const suggestionsFor = async (deps, d) => {
|
|
|
2825
2831
|
const pick = (d.columns ?? []).find((c) => c.recommended);
|
|
2826
2832
|
if (pick) {
|
|
2827
2833
|
out.push({
|
|
2828
|
-
label: `Rooms at ${pick.hotel.name}`,
|
|
2834
|
+
label: `Rooms at ${hotelName(pick.hotel.name)}`,
|
|
2829
2835
|
ask: { tool: 'getHotel', args: { hotel: pick.hotel.id, ...on } },
|
|
2830
2836
|
});
|
|
2831
2837
|
out.push({
|
|
2832
|
-
label: `Plan the days at ${pick.hotel.name}`,
|
|
2833
|
-
say: `Plan the days at ${pick.hotel.name}`,
|
|
2838
|
+
label: `Plan the days at ${hotelName(pick.hotel.name)}`,
|
|
2839
|
+
say: `Plan the days at ${hotelName(pick.hotel.name)}`,
|
|
2834
2840
|
});
|
|
2835
2841
|
}
|
|
2836
2842
|
}
|
|
@@ -3072,7 +3078,7 @@ const longStayNudges = async (deps, stays, days) => {
|
|
|
3072
3078
|
const h = [...byArea.values()].find((o) => dayNames(day, areaWords(o)));
|
|
3073
3079
|
return h
|
|
3074
3080
|
? [
|
|
3075
|
-
`Day ${i + 1}${day.date ? ` (${day.date})` : ''} names ${h.area}, where ${h.name} (\`${h.id}\`) is.`,
|
|
3081
|
+
`Day ${i + 1}${day.date ? ` (${day.date})` : ''} names ${hotelName(h.area)}, where ${hotelName(h.name)} (\`${h.id}\`) is.`,
|
|
3076
3082
|
]
|
|
3077
3083
|
: [];
|
|
3078
3084
|
})
|
|
@@ -3081,14 +3087,18 @@ const longStayNudges = async (deps, stays, days) => {
|
|
|
3081
3087
|
continue;
|
|
3082
3088
|
const others = [...byArea.values()]
|
|
3083
3089
|
.slice(0, OTHER_AREAS_MAX)
|
|
3084
|
-
.map((h) => `${h.area} - ${h.name} (\`${h.id}\`)`);
|
|
3090
|
+
.map((h) => `${hotelName(h.area)} - ${hotelName(h.name)} (\`${h.id}\`)`);
|
|
3091
|
+
// The plan's own stay, in the same cleaned words.
|
|
3092
|
+
const at = hotelName(x.name);
|
|
3093
|
+
const area = hotelName(x.area);
|
|
3094
|
+
const city = hotelName(x.city);
|
|
3085
3095
|
out.push(whole
|
|
3086
3096
|
? [
|
|
3087
|
-
`All ${x.nights} nights are at ${
|
|
3097
|
+
`All ${x.nights} nights are at ${at} (${area}). ${city} also has: ${others.join('; ')}.`,
|
|
3088
3098
|
...elsewhere,
|
|
3089
|
-
`One hotel for the whole trip fits only when every day is within about 45 minutes of it. In your reply, name the days spent farther out than that and add one sentence on the other way - "it could also be two stays: ..." - those nights at the hotel here nearest them, and why; or say in one sentence why every day is within reach of ${
|
|
3099
|
+
`One hotel for the whole trip fits only when every day is within about 45 minutes of it. In your reply, name the days spent farther out than that and add one sentence on the other way - "it could also be two stays: ..." - those nights at the hotel here nearest them, and why; or say in one sentence why every day is within reach of ${area}.`,
|
|
3090
3100
|
].join(' ')
|
|
3091
|
-
: `${x.nights} nights are at ${
|
|
3101
|
+
: `${x.nights} nights are at ${at} (${area}). ${city} also has: ${others.join('; ')}. In your reply, name the planned days that are far from ${area} and offer moving those nights to the hotel here nearest them, with the reason in one sentence - or say why every day suits ${area}.`);
|
|
3092
3102
|
}
|
|
3093
3103
|
return out;
|
|
3094
3104
|
};
|
|
@@ -3191,6 +3201,31 @@ const putRoomLine = async (deps, t, ctx, key, store, args, detail) => {
|
|
|
3191
3201
|
// 2026-10-12).
|
|
3192
3202
|
const who = identity(deps, ctx, key);
|
|
3193
3203
|
const startTime = str(args.startTime);
|
|
3204
|
+
// ⚠️ TAKING A ROOM OUT NEEDS NO ROOM FOR SALE. The lookups below are of
|
|
3205
|
+
// what is for sale, so a room that had gone since it went into the trip -
|
|
3206
|
+
// the stay a booking could not make - could not be taken out of it
|
|
3207
|
+
// (2026-10-14). Nor could a room by the hour once its window had passed:
|
|
3208
|
+
// the start was checked against today's window first, and every line of a
|
|
3209
|
+
// trip must be removable (2026-10-27 audit, F6). The line in the trip is the
|
|
3210
|
+
// one asked about - by its nights, or a room by the hour by its start.
|
|
3211
|
+
if (args.rooms !== undefined && clampCount(args.rooms, MAX_ROOMS_PER_LINE) === 0) {
|
|
3212
|
+
const asked = asStay(args);
|
|
3213
|
+
const start = startTime ? minutesOf(startTime) : undefined;
|
|
3214
|
+
const held = deps.trips
|
|
3215
|
+
.read(store)
|
|
3216
|
+
.find((l) => l.kind === 'room' &&
|
|
3217
|
+
l.hotelId === hotelId &&
|
|
3218
|
+
l.roomId === roomRef &&
|
|
3219
|
+
(l.hourly
|
|
3220
|
+
? start !== undefined &&
|
|
3221
|
+
minutesOf(l.hourly.start) === start &&
|
|
3222
|
+
(!asked || l.stay.checkIn === asked.checkIn)
|
|
3223
|
+
: !!asked && l.stay.checkIn === asked.checkIn && l.stay.checkOut === asked.checkOut));
|
|
3224
|
+
if (held) {
|
|
3225
|
+
deps.trips.set(store, unset(held));
|
|
3226
|
+
return currentTrip(deps, key, who, store);
|
|
3227
|
+
}
|
|
3228
|
+
}
|
|
3194
3229
|
const today = (startTime || !asStay(args)
|
|
3195
3230
|
? deps.backend.hourlyRooms?.(hotelId, guestsOf(args), who)
|
|
3196
3231
|
: undefined);
|
|
@@ -3269,23 +3304,6 @@ const putRoomLine = async (deps, t, ctx, key, store, args, detail) => {
|
|
|
3269
3304
|
: 'Which nights? A room needs a check-in and a check-out date before it can go into the trip.',
|
|
3270
3305
|
};
|
|
3271
3306
|
}
|
|
3272
|
-
// ⚠️ TAKING A ROOM OUT NEEDS NO ROOM FOR SALE. The lookup below is of
|
|
3273
|
-
// what is for sale, so a room that had gone since it went into the trip -
|
|
3274
|
-
// the stay a booking could not make - could not be taken out of it
|
|
3275
|
-
// (2026-10-14). The line in the trip is the one asked about.
|
|
3276
|
-
if (args.rooms !== undefined && clampCount(args.rooms, MAX_ROOMS_PER_LINE) === 0) {
|
|
3277
|
-
const held = deps.trips
|
|
3278
|
-
.read(store)
|
|
3279
|
-
.find((l) => l.kind === 'room' &&
|
|
3280
|
-
l.hotelId === hotelId &&
|
|
3281
|
-
l.roomId === roomRef &&
|
|
3282
|
-
l.stay.checkIn === stay.checkIn &&
|
|
3283
|
-
l.stay.checkOut === stay.checkOut);
|
|
3284
|
-
if (held) {
|
|
3285
|
-
deps.trips.set(store, unset(held));
|
|
3286
|
-
return currentTrip(deps, key, identity(deps, ctx, key), store);
|
|
3287
|
-
}
|
|
3288
|
-
}
|
|
3289
3307
|
// The backend owns the calendar - it knows each hotel's own timezone, and a
|
|
3290
3308
|
// second opinion computed from this process's clock would disagree with it
|
|
3291
3309
|
// for eight hours a day.
|
|
@@ -3370,7 +3388,11 @@ const putRoomLine = async (deps, t, ctx, key, store, args, detail) => {
|
|
|
3370
3388
|
rooms: clampCount(args.rooms ?? 1, MAX_ROOMS_PER_LINE),
|
|
3371
3389
|
});
|
|
3372
3390
|
const now = await currentTrip(deps, key, identity(deps, ctx, key), store);
|
|
3373
|
-
|
|
3391
|
+
// Which rate was taken, in the structure too and in the same words - see
|
|
3392
|
+
// the itinerary's `nudges` (2026-10-27 audit, F11).
|
|
3393
|
+
return took
|
|
3394
|
+
? { ...now, structured: { ...now.structured, took }, text: `${took}\n${now.text}` }
|
|
3395
|
+
: now;
|
|
3374
3396
|
};
|
|
3375
3397
|
/**
|
|
3376
3398
|
* Books the rooms in one slot of the trip store for a named guest - THE ONE
|
|
@@ -4370,7 +4392,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
4370
4392
|
const extras = await deps.backend.extrasFor(h.id, stay);
|
|
4371
4393
|
const rooms = (detail.rooms ?? []).filter((r) => r.roomsLeft >= roomsWanted);
|
|
4372
4394
|
blocks.push([
|
|
4373
|
-
`### ${h.name} · id \`${h.id}\``,
|
|
4395
|
+
`### ${hotelName(h.name)} · id \`${h.id}\``,
|
|
4374
4396
|
[
|
|
4375
4397
|
[h.area, h.city, h.country].filter(Boolean).join(', '),
|
|
4376
4398
|
h.brand,
|
|
@@ -4386,7 +4408,7 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
4386
4408
|
: rooms.length
|
|
4387
4409
|
? [
|
|
4388
4410
|
`Rooms for ${stay.checkIn} to ${stay.checkOut}, ${stay.guests} guests${roomsWanted > 1 ? `, ${roomsWanted} rooms` : ''}:`,
|
|
4389
|
-
...rooms.map((r) => `- ${r.name} · sleeps ${r.sleeps}${r.breakfast ? ' · breakfast' : ''} · ${formatMoney(r.stayTotal)} for the stay incl. taxes and fees${r.freeCancellationUntil ? `, free to cancel until ${freeUntilText(r)}` : r.refundable ? '' : ', non-refundable'}`),
|
|
4411
|
+
...rooms.map((r) => `- ${r.name} · sleeps ${r.sleeps}${r.breakfast ? ' · breakfast' : ''} · ${formatMoney(r.stayTotal)} for the stay incl. taxes and fees${roomsWanted > 1 ? ` (${formatMoney(multiplyMoney(r.stayTotal, roomsWanted))} for ${roomsWanted} rooms)` : ''}${r.freeCancellationUntil ? `, free to cancel until ${freeUntilText(r)}` : r.refundable ? '' : ', non-refundable'}`),
|
|
4390
4412
|
].join('\n')
|
|
4391
4413
|
: (detail.noRooms ?? `No room type here has ${roomsWanted} left for those nights.`),
|
|
4392
4414
|
extras.length
|
|
@@ -4721,9 +4743,13 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
4721
4743
|
url: step.url,
|
|
4722
4744
|
...(step.kind === 'confirm' ? { booking: bookingForCard(step.booking) } : {}),
|
|
4723
4745
|
},
|
|
4746
|
+
// ⚠️ THE LINK STAYS ON THE CARD (2026-10-27 audit, F9). Only the card
|
|
4747
|
+
// calls this, and the card hands this text to the model as context - so
|
|
4748
|
+
// UnionPay's own page, a link nobody here knows the life of, went into
|
|
4749
|
+
// the conversation. `url` is in the structure, for the card alone.
|
|
4724
4750
|
text: step.kind === 'enroll'
|
|
4725
|
-
? `No UnionPay card is on file for that email yet. UnionPay's page to add one
|
|
4726
|
-
: `UnionPay's page to confirm ${step.booking.confirmationCode} on
|
|
4751
|
+
? `No UnionPay card is on file for that email yet. UnionPay's page to add one is on the card - once it is added, paying with UnionPay again opens the confirmation.`
|
|
4752
|
+
: `UnionPay's page to confirm ${step.booking.confirmationCode} on is on the card - the hotel is asked once UnionPay has confirmed it.`,
|
|
4727
4753
|
};
|
|
4728
4754
|
}
|
|
4729
4755
|
if (name === t.previewChange || name === t.changeBooking) {
|
|
@@ -5146,17 +5172,37 @@ const answerTool = async (deps, name, rawArgs, ctx) => {
|
|
|
5146
5172
|
const stayItems = plan.days
|
|
5147
5173
|
.flatMap((day) => day.items)
|
|
5148
5174
|
.filter((x) => x.kind === 'hotel' && (x.night ?? 1) === 1 && x.checkIn && x.roomId);
|
|
5149
|
-
|
|
5175
|
+
// Each stay's rate says its terms where they bind - see `ItineraryItem.refundable`.
|
|
5176
|
+
const termsOf = (x) => [
|
|
5177
|
+
x.refundable === false ? 'non-refundable' : '',
|
|
5178
|
+
x.payment === 'prepaid' ? 'paid in advance' : '',
|
|
5179
|
+
]
|
|
5180
|
+
.filter(Boolean)
|
|
5181
|
+
.join(', ');
|
|
5182
|
+
const stays = stayItems.map((x, i) => `Stay ${i + 1}: ${hotelName(x.name)} (\`${x.id}\`), room \`${x.roomId}\`${x.roomName ? ` (${hotelName(x.roomName)}${termsOf(x) ? `; ${termsOf(x)}` : ''})` : termsOf(x) ? ` (${termsOf(x)})` : ''}, ${x.checkIn} to ${x.checkOut}${x.nights ? ` (${x.nights} ${x.nights === 1 ? 'night' : 'nights'})` : ''}${x.booked ? ` - booked, ${x.booked}` : x.inTrip ? ' - in the trip' : ''}`);
|
|
5183
|
+
// ⚠️ IN BOTH, IN THE SAME WORDS (2026-10-27 audit, F11): a host that hands
|
|
5184
|
+
// the model `structuredContent` rather than the text never saw what the
|
|
5185
|
+
// text said of a long stay. The model's part of the answer is the same on
|
|
5186
|
+
// either side.
|
|
5187
|
+
const nudges = stays.length ? await longStayNudges(deps, stayItems, plan.days) : [];
|
|
5150
5188
|
return {
|
|
5151
|
-
structured: {
|
|
5189
|
+
structured: {
|
|
5190
|
+
view: 'itinerary',
|
|
5191
|
+
...common(deps, key),
|
|
5192
|
+
...plan,
|
|
5193
|
+
gap,
|
|
5194
|
+
...(nudges.length ? { nudges } : {}),
|
|
5195
|
+
},
|
|
5152
5196
|
text: [
|
|
5153
5197
|
`**${plan.title}** · ${plan.days.length} ${plan.days.length === 1 ? 'day' : 'days'}. ${gap}`,
|
|
5154
5198
|
...(stays.length
|
|
5155
5199
|
? [
|
|
5156
5200
|
`Priced stays (${plan.stay?.guests ?? 2} guests; ${t.addToTrip} takes each one's hotel id, room id and dates):`,
|
|
5157
5201
|
...stays,
|
|
5158
|
-
|
|
5159
|
-
|
|
5202
|
+
...(plan.staysTotal
|
|
5203
|
+
? [`Together, the stays not booked yet: ${plan.staysTotal}.`]
|
|
5204
|
+
: []),
|
|
5205
|
+
...nudges,
|
|
5160
5206
|
]
|
|
5161
5207
|
: []),
|
|
5162
5208
|
...plan.dropped.map((d) => `Left out: ${d.name} — ${d.why}`),
|