mirror of
https://github.com/mauriceboe/TREK.git
synced 2026-10-22 23:16:46 +00:00
66 lines
2.6 KiB
TypeScript
66 lines
2.6 KiB
TypeScript
import type { AssistantMessage } from '@trek/shared';
|
|
|
|
import { messageBlocks } from './assistantParts';
|
|
import { CARD_LOOKS } from './cards/cardLooks';
|
|
|
|
/**
|
|
* The next questions an answer suggests, as one tap each: read from what the
|
|
* answer holds, not asked from the model, so they cost nothing and come at
|
|
* once. Cards ask what their kind offers, places found ask to narrow them, a
|
|
* plan asks to go on, a forecast asks for the other weather. Three at most;
|
|
* the first kind the answer holds wins.
|
|
*/
|
|
|
|
export interface FollowUp {
|
|
id: string;
|
|
labelKey: string;
|
|
/** Asks for a change, so only someone who may edit the trip is offered it. */
|
|
edits?: boolean;
|
|
}
|
|
|
|
const PLACES: readonly FollowUp[] = [
|
|
{ id: 'cheaper', labelKey: 'assistant.followUp.cheaper' },
|
|
{ id: 'closer', labelKey: 'assistant.followUp.closer' },
|
|
{ id: 'openNow', labelKey: 'assistant.followUp.openNow' },
|
|
];
|
|
|
|
const PLAN: readonly FollowUp[] = [
|
|
{ id: 'nextDay', labelKey: 'assistant.followUp.nextDay' },
|
|
{ id: 'relaxed', labelKey: 'assistant.followUp.relaxed' },
|
|
{ id: 'dinners', labelKey: 'assistant.followUp.dinners' },
|
|
];
|
|
|
|
const WEATHER: readonly FollowUp[] = [
|
|
{ id: 'rain', labelKey: 'assistant.followUp.rain' },
|
|
{ id: 'sun', labelKey: 'assistant.followUp.sun' },
|
|
];
|
|
|
|
const GENERAL: readonly FollowUp[] = [
|
|
{ id: 'more', labelKey: 'assistant.followUp.more' },
|
|
{ id: 'next', labelKey: 'assistant.followUp.next' },
|
|
];
|
|
|
|
/**
|
|
* The follow-ups of the cards an answer ends on (past its closing words): what
|
|
* the first card's kind offers, laid out as the chat lays it out, without the
|
|
* ones that ask for a change when the user may not make one.
|
|
*/
|
|
function cardFollowUps(message: AssistantMessage, canEdit: boolean): readonly FollowUp[] {
|
|
const blocks = messageBlocks(message, false).filter((block) => block.kind !== 'text');
|
|
const last = blocks[blocks.length - 1];
|
|
const kind = last?.kind === 'cards' ? last.entries[0]?.card.kind : undefined;
|
|
const offered = kind ? (CARD_LOOKS[kind].followUps ?? []) : [];
|
|
return canEdit ? offered : offered.filter((followUp) => !followUp.edits);
|
|
}
|
|
|
|
/** What an answer offers to ask next; changes are offered only to someone who may make them. */
|
|
export function followUpsFor(message: AssistantMessage, canEdit: boolean): readonly FollowUp[] {
|
|
const fromCards = cardFollowUps(message, canEdit);
|
|
if (fromCards.length > 0) return fromCards;
|
|
const types = new Set(message.parts.map((part) => part.type));
|
|
if (canEdit && (types.has('data-trek-change') || types.has('data-trek-applied'))) return PLAN;
|
|
if (types.has('data-trek-places')) return PLACES;
|
|
if (types.has('data-trek-weather')) return WEATHER;
|
|
return types.has('text') ? GENERAL : [];
|
|
}
|