Batch of LLM-assisted fixes/feature updates
This commit is contained in:
1 parent
7c6453160a
commit
05aaf394df
16 files changed
+5597
-912
No files matched your search
+58
-17
@@ -1,37 +1,78 @@
|
||||
const RandomBot = require('./RandomBot');
|
||||
const LLMBot = require('./LLMBot');
|
||||
'use strict';
|
||||
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const RandomBot = require('./RandomBot');
|
||||
const LLMBot = require('./LLMBot');
|
||||
|
||||
const NAMES_PATH = path.join(__dirname, 'bot_names.txt');
|
||||
const FALLBACK_NAMES = ['DefaultBot', 'BackupBot', 'SpareBot', 'ExtraBot'];
|
||||
|
||||
function readNames() {
|
||||
try {
|
||||
const names = fs
|
||||
.readFileSync(NAMES_PATH, 'utf8')
|
||||
.split('\n')
|
||||
.map((name) => name.trim())
|
||||
.filter((name) => name.length > 0);
|
||||
return names.length ? names : FALLBACK_NAMES;
|
||||
} catch (err) {
|
||||
console.warn(`[BotFactory] Could not read ${NAMES_PATH}: ${err.message}`);
|
||||
return FALLBACK_NAMES;
|
||||
}
|
||||
}
|
||||
|
||||
class BotFactory {
|
||||
static createBot(type) {
|
||||
switch (type.toLowerCase()) {
|
||||
/**
|
||||
* Create a bot instance. LLM bots fall back to RandomBot when the LLM
|
||||
* client cannot be constructed (missing API key/config) so a game can
|
||||
* always start.
|
||||
*/
|
||||
static createBot(type = 'llm') {
|
||||
switch (String(type).toLowerCase()) {
|
||||
case 'random':
|
||||
return new RandomBot();
|
||||
case 'llm':
|
||||
return new LLMBot();
|
||||
try {
|
||||
return new LLMBot();
|
||||
} catch (err) {
|
||||
console.warn(
|
||||
`[BotFactory] LLM bot unavailable (${err.message}); using RandomBot instead.`
|
||||
);
|
||||
return new RandomBot();
|
||||
}
|
||||
default:
|
||||
throw new Error(`Unknown bot type: ${type}`);
|
||||
}
|
||||
}
|
||||
|
||||
static generateBotName() {
|
||||
const names = fs.readFileSync(path.join(__dirname, 'bot_names.txt'), 'utf8')
|
||||
.split('\n')
|
||||
.map(name => name.trim())
|
||||
.filter(name => name.length > 0);
|
||||
/**
|
||||
* Pick a random bot name, avoiding names already used in the room.
|
||||
*/
|
||||
static generateBotName(exclude = []) {
|
||||
const names = readNames();
|
||||
const taken = new Set(
|
||||
(Array.isArray(exclude) ? exclude : [exclude])
|
||||
.filter(Boolean)
|
||||
.map((name) => String(name).toLowerCase())
|
||||
);
|
||||
|
||||
if (names.length === 0) {
|
||||
return 'DefaultBot'; // Fallback if no names are found
|
||||
}
|
||||
const available = names.filter((name) => !taken.has(name.toLowerCase()));
|
||||
const pool = available.length ? available : names;
|
||||
const pick = pool[Math.floor(Math.random() * pool.length)] || FALLBACK_NAMES[0];
|
||||
|
||||
const randomIndex = Math.floor(Math.random() * names.length);
|
||||
return names[randomIndex];
|
||||
// If every themed name is taken, disambiguate with a number.
|
||||
if (taken.has(pick.toLowerCase())) {
|
||||
let suffix = 2;
|
||||
while (taken.has(`${pick}${suffix}`.toLowerCase())) suffix += 1;
|
||||
return `${pick}${suffix}`;
|
||||
}
|
||||
return pick;
|
||||
}
|
||||
|
||||
static getAvailableBotTypes() {
|
||||
return ['random'];
|
||||
return ['llm', 'random'];
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = BotFactory;
|
||||
module.exports = BotFactory;
|
||||
Reference in new issue
Block a user