MAJOR: introduce split providers per LLM call and config system

This commit is contained in:
2026-07-09 12:24:15 +05:30
parent 907c3b8ed7
commit 13f6dd424e
3 changed files with 46 additions and 7 deletions

View File

@@ -186,6 +186,40 @@ async function main() {
process.exit(1);
}
// Resolve playEntityId to actual entity UUID if name/ID substring matches
let resolvedPlayEntityId: string | undefined = undefined;
if (playEntityId) {
let matched = worldState.getEntity(playEntityId);
if (!matched) {
for (const ent of worldState.entities.values()) {
const nameAttr = ent.attributes.get("name")?.getValue();
if (nameAttr && nameAttr.toLowerCase() === playEntityId.toLowerCase()) {
matched = ent;
break;
}
}
}
if (!matched) {
for (const ent of worldState.entities.values()) {
const nameAttr = ent.attributes.get("name")?.getValue();
if (
(nameAttr && nameAttr.toLowerCase().includes(playEntityId.toLowerCase())) ||
ent.id.toLowerCase().includes(playEntityId.toLowerCase())
) {
matched = ent;
break;
}
}
}
if (matched) {
resolvedPlayEntityId = matched.id;
console.log(`Resolved player character "${playEntityId}" to entity ID "${matched.id}" (Name: ${matched.attributes.get("name")?.getValue() || "Unnamed"})`);
} else {
console.warn(`Warning: Could not find any entity matching "${playEntityId}". Running in observer mode.`);
}
}
// 3. Ensure API Key exists if we are running LLMs
const apiKey = process.env.GOOGLE_API_KEY;
if (!apiKey) {
@@ -205,8 +239,9 @@ async function main() {
);
console.log(`SIMULATION STARTED: "${scenarioJson.name}"`);
console.log(`Description: ${scenarioJson.description}`);
if (playEntityId) {
console.log(`Player Role: Controlling entity "${playEntityId}"`);
if (resolvedPlayEntityId) {
const matched = worldState.getEntity(resolvedPlayEntityId);
console.log(`Player Role: Controlling entity "${resolvedPlayEntityId}" (Name: ${matched?.attributes.get("name")?.getValue() || "Unnamed"})`);
} else {
console.log("Player Role: Observing fully autonomous NPC run");
}
@@ -238,7 +273,7 @@ async function main() {
for (const entity of entities) {
// 1. Determine the ActorAgent generator: CLI input for player, LLM for NPCs
const isPlayer = playEntityId && entity.id === playEntityId;
const isPlayer = resolvedPlayEntityId && entity.id === resolvedPlayEntityId;
const generator = isPlayer ? new CLIProseGenerator() : undefined;
const agent = new ActorAgent(llmProvider, bufferRepo, 20, generator);

View File

@@ -209,7 +209,7 @@ export function serializeSubjectiveWorldState(
lines.push(" Entities present with you:");
for (const e of coLocated) {
const alias = resolveAliasViewer(viewer, e.id);
lines.push(` - ${alias} (ID: ${e.id}):`);
lines.push(` - ${alias}:`);
const eVisible = e.getVisibleAttributesFor(viewerId);
lines.push(serializeVisibleAttributes(eVisible).split("\n").map((l) => " " + l).join("\n"));
}
@@ -221,7 +221,7 @@ export function serializeSubjectiveWorldState(
lines.push(" Other presences you are aware of (elsewhere):");
for (const e of elsewhere) {
const alias = resolveAliasViewer(viewer, e.id);
lines.push(` - ${alias} (ID: ${e.id}) [elsewhere]`);
lines.push(` - ${alias} [elsewhere]`);
}
}

View File

@@ -32,10 +32,14 @@ export function serializeSubjectiveBufferEntry(
);
let details: string;
const content = entry.intent.description.trim() || entry.intent.originalText.trim();
if (entry.intent.type === "dialogue") {
details = `spoke to ${targetAliases.join(", ") || "someone"}: "${entry.intent.description}"`;
details = `spoke to ${targetAliases.join(", ") || "someone"}: "${content}"`;
} else if (entry.intent.type === "monologue") {
details = `thought: "${content}"`;
} else {
details = `${entry.intent.description}`;
details = content;
if (entry.outcome) {
details += ` (Outcome: ${entry.outcome.isValid ? "Succeeded" : `Failed - ${entry.outcome.reason}`})`;
}