( apps: AppEntry[], character: CharacterInfo, )
| 792 | } |
| 793 | |
| 794 | export async function consolidateApps( |
| 795 | apps: AppEntry[], |
| 796 | character: CharacterInfo, |
| 797 | ): Promise<AppEntry[]> { |
| 798 | logger.info( |
| 799 | 'consolidateApps', |
| 800 | 'Starting with', |
| 801 | apps.length, |
| 802 | 'apps:', |
| 803 | apps.map((a) => a.id), |
| 804 | ); |
| 805 | const { loadConfig, chat } = await import('./llmClient'); |
| 806 | const config = await loadConfig(); |
| 807 | if (!config) { |
| 808 | logger.warn('consolidateApps', 'No LLM config found, skipping consolidation'); |
| 809 | return apps; |
| 810 | } |
| 811 | logger.info('consolidateApps', 'Using LLM provider:', config.provider, 'model:', config.model); |
| 812 | |
| 813 | const appSummaries = apps.map((a) => ({ |
| 814 | id: a.id, |
| 815 | name: a.name, |
| 816 | keywords: a.keywords, |
| 817 | tags: a.tags.map((t) => ({ name: t.name, description: t.description })), |
| 818 | })); |
| 819 | |
| 820 | const prompt = `You are analyzing a list of apps extracted from a character card. |
| 821 | |
| 822 | Some of these apps are too small or fragmented to function as standalone apps. They need to be merged with related apps to form complete, functional applications. |
| 823 | |
| 824 | ## NPC Information (for filtering only — do NOT include in output) |
| 825 | |
| 826 | Character Name: ${character.name} |
| 827 | Description: ${character.description.slice(0, 500)} |
| 828 | |
| 829 | Any reference to this character (name, nicknames, account names, traits, etc.) must be stripped from all output fields. |
| 830 | |
| 831 | ## Extracted Apps |
| 832 | |
| 833 | ${JSON.stringify(appSummaries, null, 2)} |
| 834 | |
| 835 | ## Task |
| 836 | |
| 837 | Analyze each app and decide: |
| 838 | 1. Which apps can stand alone as complete, functional apps — keep them as-is |
| 839 | 2. Which apps are too small/fragmented and should be merged with other related apps |
| 840 | 3. How to group the fragmented apps with related apps |
| 841 | |
| 842 | Return a JSON array of consolidated apps. Each entry has: |
| 843 | - "name": the display name for the consolidated app (use the most representative name from the group, or create a new descriptive name) |
| 844 | - "memberIds": array of original app ids that should be merged into this group |
| 845 | - "keywords": the curated, deduplicated list of keywords for the consolidated app (merge from members, remove redundant/overlapping ones) |
| 846 | - "tags": the curated list of tags for the consolidated app. Each tag is { "name": string, "description": string }. Merge tags from all members, deduplicate by name, and keep the most descriptive description. |
| 847 | |
| 848 | ## Rules |
| 849 | |
| 850 | - Every original app id must appear in exactly one group |
| 851 | - A standalone app is a group with a single memberIds entry — still include its full keywords and tags |
nothing calls this directly
no test coverage detected