Skip to content

optional AI-based name generation for map entities#1358

Open
Lupus7477 wants to merge 1 commit intoAzgaar:masterfrom
Lupus7477:feature/ai-name-generation
Open

optional AI-based name generation for map entities#1358
Lupus7477 wants to merge 1 commit intoAzgaar:masterfrom
Lupus7477:feature/ai-name-generation

Conversation

@Lupus7477
Copy link
Copy Markdown

Description

Adds optional AI-based name generation for map entities (zones, rivers, lakes, routes, burgs, states, map names).

Motivation: improve naming variety/context while keeping current behavior unchanged (opt-in only).

Closes #1357

Copilot AI review requested due to automatic review settings March 15, 2026 01:29
@netlify
Copy link
Copy Markdown

netlify bot commented Mar 15, 2026

Deploy Preview for afmg ready!

Name Link
🔨 Latest commit 5b98f55
🔍 Latest deploy log https://app.netlify.com/projects/afmg/deploys/69b60b8798e2ab00080c213d
😎 Deploy Preview https://deploy-preview-1358--afmg.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in AI-backed naming workflow across multiple map entity editors while keeping existing procedural naming as default behavior.

Changes:

  • Introduces new TS modules for AI provider access + prompt-based name generation exposed via window.AiNames
  • Adds UI controls (icons/buttons) to generate AI names for map entities and bulk “AI Names” regeneration
  • Adds Options UI for configuring model/provider, key, temperature, language override, custom prompt, and Ollama host

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
src/modules/index.ts Registers new AI modules in the TS module bootstrap.
src/modules/ai-providers.ts Implements provider-backed streaming text generation + localStorage-backed settings.
src/modules/ai-name-generator.ts Builds prompts for entity naming/translation and exposes window.AiNames API.
src/index.html Adds AI name generation UI elements and an Options section for AI naming configuration.
public/modules/ui/options.js Wires Options inputs to localStorage and initializes AI naming settings UI.
public/modules/ui/tools.js Adds “AI Names” bulk regeneration across many entity types.
public/modules/ui/editors/overviews.js Adds per-entity AI naming triggers in multiple editors/overviews.
public/modules/ui/ai-generator.js Updates Ollama host usage to be configurable (shared localStorage key).
package-lock.json Lockfile metadata normalization (removes peer: true entries).

{
const optionsTab = byId("optionsTab");
if (optionsTab) {
const origClick = optionsTab.onclick;
class="icon-book pointer"
></span>
<span id="provinceNameEditorShortRandom" data-tip="Generate random name" class="icon-globe pointer"></span>
<span id="provinceNameEditorShortAi" data-tip="Generate name using AI" class="icon-fleur-de-lis pointer hiddenIcon"></span>
data-tip="Click to re-generate full name"
class="icon-arrows-cw pointer"
></span>
<span id="provinceNameEditorFullAi" data-tip="Generate full name using AI" class="icon-fleur-de-lis pointer hiddenIcon"></span>

export function getStoredTemperature(): number {
const stored = localStorage.getItem("fmg-ai-temperature");
return stored ? parseFloat(stored) : 1;
Comment on lines +112 to +118
if (line === "data: [DONE]") break;

try {
const parsed = line.startsWith("data: ") ? JSON.parse(line.slice(6)) : JSON.parse(line);
getContent(parsed);
} catch (error) {
ERROR && console.error("Failed to parse line:", line, error);
Comment on lines +159 to +166
function buildBatchNamePrompt(entityType: EntityType, language: string, count: number, ctx?: EntityContext): string {
const entity = ENTITY_DESCRIPTIONS[entityType];
const context = buildContextString(entityType, ctx);
const customPrompt = getCustomPrompt();

let prompt = `Generate ${count} unique fantasy names for ${entity}s in a ${language} linguistic style. All names MUST be unique — no duplicates allowed.`;
if (context) prompt += ` ${context}`;
prompt += ` Reply with ONLY the names, one per line. No numbering, no quotes, no explanation.`;
Comment on lines +202 to +222
const AI_MODELS = {
"gpt-4o-mini": "openai",
"chatgpt-4o-latest": "openai",
"gpt-4o": "openai",
"gpt-4-turbo": "openai",
o3: "openai",
"o3-mini": "openai",
"o3-pro": "openai",
"o4-mini": "openai",
"claude-opus-4-20250514": "anthropic",
"claude-sonnet-4-20250514": "anthropic",
"claude-3-5-haiku-latest": "anthropic",
"claude-3-5-sonnet-latest": "anthropic",
"claude-3-opus-latest": "anthropic",
"ollama (local models)": "ollama"
};

function initAiSettings() {
const modelSelect = byId("aiNamesModel");
if (!modelSelect) return;

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an opt-in AI-assisted naming feature to the Fantasy Map Generator UI and generation flow, allowing users to generate names for multiple entity types (map name, burgs, states/provinces, rivers/lakes, routes, zones, cultures, religions/deities) via configurable AI providers.

Changes:

  • Introduces new TS modules for AI provider integration and prompt-based name generation exposed via window.AiNames.
  • Adds UI controls (icons/buttons) across multiple editors + an Options section to configure model/provider/key/temperature/language override/custom prompt.
  • Adds bulk “AI Names” regeneration action in Tools plus per-entity “generate with AI” actions in editors/overviews.

Reviewed changes

Copilot reviewed 19 out of 20 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
src/modules/index.ts Loads new AI modules at startup.
src/modules/ai-providers.ts Implements provider streaming calls + localStorage-backed settings.
src/modules/ai-name-generator.ts Builds prompts and exposes window.AiNames helpers for entity naming.
src/index.html Adds AI buttons and Options UI for AI name generation settings.
public/modules/ui/options.js Persists AI settings to localStorage and initializes the Options UI.
public/modules/ui/tools.js Adds “regenerate all AI names” flow for unlocked entities.
public/modules/ui/zones-editor.js Adds per-zone + bulk AI zone naming.
public/modules/ui/routes-editor.js Adds AI route naming with contextual prompt inputs.
public/modules/ui/routes-overview.js Adds bulk AI route renaming in overview.
public/modules/ui/rivers-editor.js Adds AI naming for a river in the editor.
public/modules/ui/rivers-overview.js Adds bulk AI river renaming in overview.
public/modules/ui/lakes-editor.js Adds AI naming for a lake in the editor.
public/modules/ui/burg-editor.js Adds AI naming for a burg in the editor.
public/modules/ui/burgs-overview.js Adds bulk AI burg renaming in overview.
public/modules/ui/provinces-editor.js Adds AI short/full name generation in the province name editor dialog.
public/modules/dynamic/editors/states-editor.js Adds AI short/full name generation + bulk AI rename for states.
public/modules/dynamic/editors/cultures-editor.js Adds per-culture + bulk AI culture naming.
public/modules/dynamic/editors/religions-editor.js Adds per-religion AI naming + AI deity generation + bulk AI rename.
public/modules/ui/ai-generator.js Allows custom Ollama host for the existing generic AI text generator.
package-lock.json Lockfile metadata changes.

burgName.value = await AiNames.generateName("burg", culture);
changeName();
} catch (error) {
tip(error.message, true, "error", 4000);
const optionsTab = byId("optionsTab");
if (optionsTab) {
const origClick = optionsTab.onclick;
optionsTab.addEventListener("click", function () {
Comment on lines +202 to +217
const AI_MODELS = {
"gpt-4o-mini": "openai",
"chatgpt-4o-latest": "openai",
"gpt-4o": "openai",
"gpt-4-turbo": "openai",
o3: "openai",
"o3-mini": "openai",
"o3-pro": "openai",
"o4-mini": "openai",
"claude-opus-4-20250514": "anthropic",
"claude-sonnet-4-20250514": "anthropic",
"claude-3-5-haiku-latest": "anthropic",
"claude-3-5-sonnet-latest": "anthropic",
"claude-3-opus-latest": "anthropic",
"ollama (local models)": "ollama"
};
class="icon-book pointer"
></span>
<span id="provinceNameEditorShortRandom" data-tip="Generate random name" class="icon-globe pointer"></span>
<span id="provinceNameEditorShortAi" data-tip="Generate name using AI" class="icon-fleur-de-lis pointer hiddenIcon"></span>
data-tip="Click to re-generate full name"
class="icon-arrows-cw pointer"
></span>
<span id="provinceNameEditorFullAi" data-tip="Generate full name using AI" class="icon-fleur-de-lis pointer hiddenIcon"></span>
Comment on lines +2090 to +2098
<tr data-tip="Enter API key for selected AI provider. For Ollama enter the model name (e.g. llama3.2:3b)">
<td></td>
<td>API Key</td>
<td>
<input id="aiNamesKey" placeholder="Enter API key" class="long" type="text" />
</td>
<td>
<i id="aiNamesKeyHelp" data-tip="Click to see usage instructions" class="icon-help-circled pointer"></i>
</td>
<input data-tip="Religion form" class="religionForm" style="width: 6em"
value="${r.form}" autocorrect="off" spellcheck="false" />
<span data-tip="Click to re-generate supreme deity" class="icon-arrows-cw hide"></span>
<span data-tip="Generate deity name with AI" class="icon-robot-deity hiddenIcon hide" style="visibility: hidden"></span>
Comment on lines +109 to +120
for (let i = 0; i < lines.length - 1; i++) {
const line = lines[i].trim();
if (!line) continue;
if (line === "data: [DONE]") break;

try {
const parsed = line.startsWith("data: ") ? JSON.parse(line.slice(6)) : JSON.parse(line);
getContent(parsed);
} catch (error) {
ERROR && console.error("Failed to parse line:", line, error);
}
}
Comment on lines +159 to +168
function buildBatchNamePrompt(entityType: EntityType, language: string, count: number, ctx?: EntityContext): string {
const entity = ENTITY_DESCRIPTIONS[entityType];
const context = buildContextString(entityType, ctx);
const customPrompt = getCustomPrompt();

let prompt = `Generate ${count} unique fantasy names for ${entity}s in a ${language} linguistic style. All names MUST be unique — no duplicates allowed.`;
if (context) prompt += ` ${context}`;
prompt += ` Reply with ONLY the names, one per line. No numbering, no quotes, no explanation.`;
if (customPrompt) prompt += ` Additional instructions: ${customPrompt}`;
return prompt;
Comment on lines +179 to +183
export async function generateAiName(entityType: EntityType, cultureIndex: number, ctx?: EntityContext): Promise<string> {
if (!hasApiKey()) {
openAiSetupDialog();
throw new Error("No API key configured");
}
@Azgaar
Copy link
Copy Markdown
Owner

Azgaar commented Mar 15, 2026

Not sure I like the implementation. There is already an AI-generation dialog and we should we-use and globalize it, not add a global option, it's already very busy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: optional AI-based name generation for map entities

3 participants