From 1b5f90a495676985b341c90a8fc7b09debbdbeca Mon Sep 17 00:00:00 2001 From: Carlos Castillo Date: Sun, 12 Jan 2025 14:14:29 +0100 Subject: [PATCH] :zap: Enhance PersonalShopper to suggest augmentations based on remaining budget --- src/PersonalShopper.ts | 39 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/src/PersonalShopper.ts b/src/PersonalShopper.ts index bd66b39..16da31b 100644 --- a/src/PersonalShopper.ts +++ b/src/PersonalShopper.ts @@ -47,11 +47,28 @@ export class PersonalShopper { this.log('More than one armour suggested, taking the first one', armourSuggestions.map((a) => `${a.id}: ${a.name}`).join(', ')); } const armour = armourSuggestions[0]; + const remainingBudget = budget - creditsFromCrFormat(armour.price); + const suitableAugments = await this.getAvailableAugments(character, remainingBudget); + if (suitableAugments.length === 0) { + return { + found: true, + armour, + augments: [], + }; + } + + const whatDoIWantAugments = `I want you to suggest me up to three augmentations for my amour ${armour.name}`; + const augmentsSuggestions = await this.suggestEquipment(character, whatDoIWantAugments, suitableAugments, remainingBudget); + if ('error' in augmentsSuggestions) { + this.logError(`Error suggesting augments: ${augmentsSuggestions.error}`); + this.log('raw augments suggestion:', augmentsSuggestions.answer); + return {found: true, armour, augments: []}; + } return { found: true, armour, - augments: [], + augments: augmentsSuggestions, }; } @@ -69,6 +86,24 @@ export class PersonalShopper { return this.equipmentRepository.findByCriteria(armourCriteria, additionalArmourContext, 30); } + private async getAvailableAugments(character: Character, budget: number): Promise { + const armourCriteria: EquipmentCriteria = { + sections: { + type: 'sections-subsection', + sections: [ + { section: 'Armour', subsection: 'Armour Modifications' }, + { section: 'Armour', subsection: 'Armour Mods' }, + { section: 'Augments', subsection: 'Augment Options' }, + ], + }, + maxPrice: budget, + maxTL: 12, // TODO: infer from SOC and/or experience + }; + + const additionalArmourContext = `suitable for a ${character.role} with ${character.experience} experience.`; + return this.equipmentRepository.findByCriteria(armourCriteria, additionalArmourContext, 30); + } + private async suggestEquipment(character: Character, whatDoIWant: string, itemsAvailable: Equipment[], budget: number): Promise { const additionalShoppingContext = stripIndent`These are the available items in format "id: name [section/subsection] [tl] [price in credits] [weight in kg] [skill requirement if any]: ${itemsAvailable.map((i) => `${i.id}: ${i.name} [${i.section}/${i.subsection}] [${i.tl}] [${creditsFromCrFormat(i.price)}] [${i.mass}] [${i.skill}]`).join('\n')} @@ -119,7 +154,7 @@ export class PersonalShopper { return itemsSuggestion.data.itemIds.reduce((acc: Equipment[], itemId) => { const item = itemsAvailable.find((i) => i.id === itemId); if (!item) { - this.logError(`Item ID suggested does not exists ${itemId}`); + this.logError(`Item ID suggested does not exists ${itemId} [${itemsSuggestion.data.reasoning}]`); return acc; } return [...acc, item];