hoi4-agent-tools 2.8.5 → 2.8.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +11 -0
- package/dist/hoi4_agent_tools/core/artifacts.js +113 -44
- package/dist/hoi4_agent_tools/gui/assets.js +0 -5
- package/dist/hoi4_agent_tools/gui/layout.js +4 -1
- package/dist/hoi4_agent_tools/gui/renderer.js +12 -1
- package/dist/hoi4_agent_tools/gui/scenario-generator.js +402 -69
- package/dist/hoi4_agent_tools/gui/scenario.js +1 -1
- package/dist/hoi4_agent_tools/gui/source-graph.js +61 -9
- package/dist/hoi4_agent_tools/gui/studio.js +45 -4
- package/dist/hoi4_agent_tools/gui/validators.js +6 -1
- package/dist/hoi4_agent_tools/probability/service.js +3 -2
- package/dist/hoi4_agent_tools/version.js +1 -1
- package/docs/gui.md +4 -4
- package/package.json +1 -1
- package/schemas/configuration.schema.json +1 -1
- package/schemas/continuous-focus-palette.schema.json +1 -1
- package/schemas/custom-weighted-pool.schema.json +1 -1
- package/schemas/event-feature-manifest.schema.json +1 -1
- package/schemas/focus-plan.schema.json +1 -1
- package/schemas/focus-planning-sidecar.schema.json +1 -1
- package/schemas/gui-animation-source.schema.json +1 -1
- package/schemas/gui-helper.schema.json +1 -1
- package/schemas/gui-scenario.schema.json +1 -1
- package/schemas/map-operation.schema.json +1 -1
- package/schemas/operation-result.schema.json +1 -1
- package/schemas/probability-analysis-result.schema.json +1 -1
- package/schemas/probability-compare-input.schema.json +1 -1
- package/schemas/probability-evaluate-input.schema.json +1 -1
- package/schemas/probability-inspect-input.schema.json +1 -1
- package/schemas/probability-render-input.schema.json +1 -1
- package/schemas/probability-scenario-set.schema.json +1 -1
- package/schemas/probability-sequence-input.schema.json +1 -1
- package/schemas/probability-simulate-input.schema.json +1 -1
- package/schemas/probability-sweep-input.schema.json +1 -1
- package/server.json +2 -2
|
@@ -117,7 +117,27 @@ export function guiElementAttributeFidelity(key) {
|
|
|
117
117
|
return 'unsupported';
|
|
118
118
|
}
|
|
119
119
|
function normalizeAssetPath(value) {
|
|
120
|
-
return value
|
|
120
|
+
return value
|
|
121
|
+
.replaceAll('\\', '/')
|
|
122
|
+
.replace(/^\/+|^\.\//u, '')
|
|
123
|
+
.replace(/\/+/gu, '/')
|
|
124
|
+
.toLowerCase();
|
|
125
|
+
}
|
|
126
|
+
function textureNodeFor(textureNodes, texturePath) {
|
|
127
|
+
const normalized = normalizeAssetPath(texturePath);
|
|
128
|
+
const extension = path.posix.extname(normalized);
|
|
129
|
+
const rasterExtensions = ['.png', '.bmp', '.tga', '.dds'];
|
|
130
|
+
const candidates = rasterExtensions.includes(extension)
|
|
131
|
+
? [
|
|
132
|
+
normalized,
|
|
133
|
+
...rasterExtensions
|
|
134
|
+
.filter((candidate) => candidate !== extension)
|
|
135
|
+
.map((candidate) => `${normalized.slice(0, -extension.length)}${candidate}`),
|
|
136
|
+
]
|
|
137
|
+
: [normalized];
|
|
138
|
+
return candidates
|
|
139
|
+
.map((candidate) => textureNodes.get(candidate))
|
|
140
|
+
.find((value) => value !== undefined);
|
|
121
141
|
}
|
|
122
142
|
function scalarValue(value, constants) {
|
|
123
143
|
const expanded = constants.get(value) ?? value;
|
|
@@ -363,7 +383,7 @@ function indexGuiElements(document, file, fileNodeId, nodes, edges, elements) {
|
|
|
363
383
|
}
|
|
364
384
|
}
|
|
365
385
|
}
|
|
366
|
-
function indexSpritesAndFonts(document, file, fileNodeId, nodes, edges, sprites, fonts) {
|
|
386
|
+
function indexSpritesAndFonts(document, file, fileNodeId, nodes, edges, sprites, fonts, globalTextColours) {
|
|
367
387
|
const walk = (block) => {
|
|
368
388
|
for (const assignment of assignments(block)) {
|
|
369
389
|
if (assignment.value.type !== 'block')
|
|
@@ -457,14 +477,21 @@ function indexSpritesAndFonts(document, file, fileNodeId, nodes, edges, sprites,
|
|
|
457
477
|
const colour = paradoxColour(firstScalarInsensitive(child, 'color', 'colour'));
|
|
458
478
|
const borderColour = paradoxColour(firstScalarInsensitive(child, 'border_color', 'borderColor', 'border_colour'));
|
|
459
479
|
const textColours = textColoursFrom(child);
|
|
460
|
-
const
|
|
480
|
+
const override = assignment.key.value === 'bitmapfont_override';
|
|
481
|
+
const id = deterministicId('gui_font', {
|
|
482
|
+
path: file.displayPath,
|
|
483
|
+
name,
|
|
484
|
+
override,
|
|
485
|
+
languages,
|
|
486
|
+
assetPaths,
|
|
487
|
+
});
|
|
461
488
|
const font = {
|
|
462
489
|
id,
|
|
463
490
|
name,
|
|
464
491
|
sourcePath: file.displayPath,
|
|
465
492
|
location: nodeLocation(document, assignment, name),
|
|
466
493
|
kind: 'bitmapfont',
|
|
467
|
-
override
|
|
494
|
+
override,
|
|
468
495
|
languages,
|
|
469
496
|
assetPaths,
|
|
470
497
|
...(colour === undefined ? {} : { colour }),
|
|
@@ -492,6 +519,9 @@ function indexSpritesAndFonts(document, file, fileNodeId, nodes, edges, sprites,
|
|
|
492
519
|
addEdge(edges, 'contains', fileNodeId, id, true, {}, font.location);
|
|
493
520
|
}
|
|
494
521
|
}
|
|
522
|
+
if (assignment.key.value === 'bitmapfonts') {
|
|
523
|
+
Object.assign(globalTextColours, textColoursFrom(child));
|
|
524
|
+
}
|
|
495
525
|
walk(child);
|
|
496
526
|
}
|
|
497
527
|
};
|
|
@@ -773,8 +803,21 @@ function indexScriptedLocalisation(document, file, fileNodeId, nodes, edges, def
|
|
|
773
803
|
const name = firstScalar(assignment.value, 'name')?.value;
|
|
774
804
|
if (name === undefined)
|
|
775
805
|
continue;
|
|
776
|
-
const
|
|
777
|
-
|
|
806
|
+
const choices = childBlocks(assignment.value, 'text').flatMap((textBlock) => {
|
|
807
|
+
const localisationKey = firstScalarInsensitive(textBlock, 'localisation_key', 'localization_key');
|
|
808
|
+
if (localisationKey === undefined)
|
|
809
|
+
return [];
|
|
810
|
+
const trigger = childBlocks(textBlock, 'trigger')[0];
|
|
811
|
+
return [
|
|
812
|
+
{
|
|
813
|
+
localisationKey,
|
|
814
|
+
...(trigger === undefined ? {} : { triggerExpression: raw(document, trigger) }),
|
|
815
|
+
rawSource: raw(document, textBlock),
|
|
816
|
+
},
|
|
817
|
+
];
|
|
818
|
+
});
|
|
819
|
+
const localisationKeys = choices
|
|
820
|
+
.map(({ localisationKey }) => localisationKey)
|
|
778
821
|
.sort((left, right) => compareCodeUnits(left, right));
|
|
779
822
|
const id = deterministicId('scripted_localisation', { path: file.displayPath, name });
|
|
780
823
|
const location = nodeLocation(document, assignment, name);
|
|
@@ -784,6 +827,7 @@ function indexScriptedLocalisation(document, file, fileNodeId, nodes, edges, def
|
|
|
784
827
|
sourcePath: file.displayPath,
|
|
785
828
|
location,
|
|
786
829
|
localisationKeys,
|
|
830
|
+
choices,
|
|
787
831
|
rawSource: raw(document, assignment),
|
|
788
832
|
}, 'scripted localisation');
|
|
789
833
|
addNode(nodes, {
|
|
@@ -792,7 +836,13 @@ function indexScriptedLocalisation(document, file, fileNodeId, nodes, edges, def
|
|
|
792
836
|
name,
|
|
793
837
|
path: file.displayPath,
|
|
794
838
|
location,
|
|
795
|
-
metadata: {
|
|
839
|
+
metadata: {
|
|
840
|
+
localisationKeys,
|
|
841
|
+
choices: choices.map(({ localisationKey, triggerExpression }) => ({
|
|
842
|
+
localisationKey,
|
|
843
|
+
...(triggerExpression === undefined ? {} : { triggerExpression }),
|
|
844
|
+
})),
|
|
845
|
+
},
|
|
796
846
|
});
|
|
797
847
|
addEdge(edges, 'contains', fileNodeId, id, true, {}, location);
|
|
798
848
|
}
|
|
@@ -864,7 +914,7 @@ function linkGraph(nodes, edges, elements, sprites, fonts, scriptedGuis, scripte
|
|
|
864
914
|
for (const [index, texturePath] of [sprite.texturePath, sprite.texturePath2].entries()) {
|
|
865
915
|
if (texturePath === undefined)
|
|
866
916
|
continue;
|
|
867
|
-
const textureId = textureNodes
|
|
917
|
+
const textureId = textureNodeFor(textureNodes, texturePath);
|
|
868
918
|
addEdge(edges, 'uses_texture', sprite.id, textureId ?? `texture:${normalizeAssetPath(texturePath)}`, textureId !== undefined, { texturePath, slot: index + 1 }, sprite.location);
|
|
869
919
|
}
|
|
870
920
|
const candidates = [
|
|
@@ -1069,6 +1119,7 @@ export function buildGuiSourceGraph(files, sharedIndex) {
|
|
|
1069
1119
|
const elements = [];
|
|
1070
1120
|
const sprites = [];
|
|
1071
1121
|
const fonts = [];
|
|
1122
|
+
const textColours = {};
|
|
1072
1123
|
const scriptedGuis = [];
|
|
1073
1124
|
const animationSources = [];
|
|
1074
1125
|
const scriptedLocalisation = [];
|
|
@@ -1190,7 +1241,7 @@ export function buildGuiSourceGraph(files, sharedIndex) {
|
|
|
1190
1241
|
if (kind === 'gui_file')
|
|
1191
1242
|
indexGuiElements(document, file, fileNodeId, nodes, edges, elements);
|
|
1192
1243
|
if (kind === 'gfx_file') {
|
|
1193
|
-
indexSpritesAndFonts(document, file, fileNodeId, nodes, edges, sprites, fonts);
|
|
1244
|
+
indexSpritesAndFonts(document, file, fileNodeId, nodes, edges, sprites, fonts, textColours);
|
|
1194
1245
|
}
|
|
1195
1246
|
if (kind === 'scripted_gui_file') {
|
|
1196
1247
|
indexScriptedGuis(document, file, fileNodeId, nodes, edges, scriptedGuis);
|
|
@@ -1270,6 +1321,7 @@ export function buildGuiSourceGraph(files, sharedIndex) {
|
|
|
1270
1321
|
elements,
|
|
1271
1322
|
sprites,
|
|
1272
1323
|
fonts,
|
|
1324
|
+
textColours: Object.fromEntries(Object.entries(textColours).sort(([left], [right]) => compareCodeUnits(left, right))),
|
|
1273
1325
|
scriptedGuis,
|
|
1274
1326
|
animationSources,
|
|
1275
1327
|
scriptedLocalisation,
|
|
@@ -328,7 +328,7 @@ function localisationIconSpriteCandidates(token) {
|
|
|
328
328
|
const normalized = token.startsWith('GFX_') ? token : `GFX_${token}`;
|
|
329
329
|
return [...new Set([normalized, `${normalized}_texticon`, `${normalized}_text_icon`])];
|
|
330
330
|
}
|
|
331
|
-
function referencedAssetPatternsForWindow(graph, windowName, additionalSpriteNames = []) {
|
|
331
|
+
export function referencedAssetPatternsForWindow(graph, windowName, additionalSpriteNames = [], languages = ['l_english']) {
|
|
332
332
|
const spriteNames = new Set(additionalSpriteNames);
|
|
333
333
|
const fontNames = new Set();
|
|
334
334
|
const textValues = new Set();
|
|
@@ -347,6 +347,37 @@ function referencedAssetPatternsForWindow(graph, windowName, additionalSpriteNam
|
|
|
347
347
|
spriteNames.add(candidate);
|
|
348
348
|
}
|
|
349
349
|
}
|
|
350
|
+
const relatedScriptedGuiNames = new Set(graph.scriptedGuis
|
|
351
|
+
.filter((definition) => definition.windowName === windowName || definition.parentWindowName === windowName)
|
|
352
|
+
.map(({ name }) => name));
|
|
353
|
+
let addedRelatedScriptedGui = true;
|
|
354
|
+
while (addedRelatedScriptedGui) {
|
|
355
|
+
addedRelatedScriptedGui = false;
|
|
356
|
+
for (const definition of graph.scriptedGuis) {
|
|
357
|
+
if (definition.parentScriptedGui === undefined ||
|
|
358
|
+
!relatedScriptedGuiNames.has(definition.parentScriptedGui) ||
|
|
359
|
+
relatedScriptedGuiNames.has(definition.name))
|
|
360
|
+
continue;
|
|
361
|
+
relatedScriptedGuiNames.add(definition.name);
|
|
362
|
+
addedRelatedScriptedGui = true;
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
const dynamicImageTokens = new Set(graph.scriptedGuis
|
|
366
|
+
.filter(({ name }) => relatedScriptedGuiNames.has(name))
|
|
367
|
+
.flatMap(({ propertyDefinitions }) => propertyDefinitions)
|
|
368
|
+
.flatMap(({ attributes }) => {
|
|
369
|
+
const image = Object.entries(attributes).find(([key]) => key.toLocaleLowerCase('en-US') === 'image')?.[1];
|
|
370
|
+
if (typeof image !== 'string')
|
|
371
|
+
return [];
|
|
372
|
+
const match = /^\[([^\]]+)\]$/u.exec(image);
|
|
373
|
+
return match?.[1] === undefined ? [] : [match[1]];
|
|
374
|
+
}));
|
|
375
|
+
for (const definition of graph.scriptedLocalisation) {
|
|
376
|
+
if (!dynamicImageTokens.has(definition.name))
|
|
377
|
+
continue;
|
|
378
|
+
for (const candidate of definition.localisationKeys)
|
|
379
|
+
spriteNames.add(candidate);
|
|
380
|
+
}
|
|
350
381
|
const spritesByName = new Map(graph.sprites.map((sprite) => [sprite.name.toLocaleLowerCase('en-US'), sprite]));
|
|
351
382
|
const selectedSprites = new Map();
|
|
352
383
|
const pendingSprites = [...spriteNames];
|
|
@@ -366,7 +397,17 @@ function referencedAssetPatternsForWindow(graph, windowName, additionalSpriteNam
|
|
|
366
397
|
}
|
|
367
398
|
const selectedManifests = graph.animationSources.filter(({ sprite }) => selectedSprites.has(sprite.toLocaleLowerCase('en-US')));
|
|
368
399
|
const selectedFontNames = new Set([...fontNames].map((name) => name.toLocaleLowerCase('en-US')));
|
|
369
|
-
const
|
|
400
|
+
const normalizedLanguages = new Set(languages.flatMap((language) => {
|
|
401
|
+
const normalized = language.toLocaleLowerCase('en-US');
|
|
402
|
+
return [normalized, normalized.replace(/^l_/u, '')];
|
|
403
|
+
}));
|
|
404
|
+
const selectedFonts = graph.fonts.filter(({ name, languages: fontLanguages }) => selectedFontNames.has(name.toLocaleLowerCase('en-US')) &&
|
|
405
|
+
(fontLanguages.length === 0 ||
|
|
406
|
+
fontLanguages.some((language) => {
|
|
407
|
+
const normalized = language.toLocaleLowerCase('en-US');
|
|
408
|
+
return (normalizedLanguages.has(normalized) ||
|
|
409
|
+
normalizedLanguages.has(normalized.replace(/^l_/u, '')));
|
|
410
|
+
})));
|
|
370
411
|
const references = [
|
|
371
412
|
...[...selectedSprites.values()].flatMap(({ texturePath, texturePath2 }) => [texturePath, texturePath2].filter((value) => value !== undefined)),
|
|
372
413
|
...selectedFonts.flatMap(({ assetPaths }) => assetPaths),
|
|
@@ -665,7 +706,7 @@ export class ScriptedGuiStudio {
|
|
|
665
706
|
const definitionFiles = mergeScannedFiles(layoutFiles, linkedDefinitions.files, localisation.files);
|
|
666
707
|
const definitions = this.graphForFiles(definitionFiles, `definitions:${workspaceId}`);
|
|
667
708
|
assertTargetWindowAvailable(definitions.graph, windowName);
|
|
668
|
-
const referencedPatterns = referencedAssetPatternsForWindow(definitions.graph, windowName, additionalSpriteNames);
|
|
709
|
+
const referencedPatterns = referencedAssetPatternsForWindow(definitions.graph, windowName, additionalSpriteNames, languages);
|
|
669
710
|
const exactReferenced = referencedPatterns.length === 0
|
|
670
711
|
? []
|
|
671
712
|
: await this.scanner.scan(workspace, {
|
|
@@ -1100,7 +1141,7 @@ export class ScriptedGuiStudio {
|
|
|
1100
1141
|
const scenario = parsePreviewScenario(input.scenario);
|
|
1101
1142
|
const renderBudget = new RenderBudget();
|
|
1102
1143
|
let proposedGraph = buildGuiSourceGraph(proposedFiles, this.engine.indexFiles(proposedFiles));
|
|
1103
|
-
const proposedAssetPatterns = referencedAssetPatternsForWindow(proposedGraph, input.windowName);
|
|
1144
|
+
const proposedAssetPatterns = referencedAssetPatternsForWindow(proposedGraph, input.windowName, [], [scenario.language]);
|
|
1104
1145
|
const exactProposedAssets = proposedAssetPatterns.length === 0
|
|
1105
1146
|
? []
|
|
1106
1147
|
: await this.scanner.scan(workspace, {
|
|
@@ -509,7 +509,12 @@ function validateReferencesAndScript(graph, scene, diagnostics) {
|
|
|
509
509
|
const selectedSpriteNames = new Set(scene.elements.flatMap(({ sprite }) => (sprite === undefined ? [] : [sprite.spriteName])));
|
|
510
510
|
const selectedSpriteIds = new Set(graph.sprites.filter(({ name }) => selectedSpriteNames.has(name)).map(({ id }) => id));
|
|
511
511
|
const selectedFontNames = new Set(scene.elements.flatMap(({ text }) => (text?.fontName === undefined ? [] : [text.fontName])));
|
|
512
|
-
const
|
|
512
|
+
const sceneLanguage = scene.scenario.language.toLocaleLowerCase('en-US');
|
|
513
|
+
const selectedFontIds = new Set(graph.fonts
|
|
514
|
+
.filter(({ name, languages }) => selectedFontNames.has(name) &&
|
|
515
|
+
(languages.length === 0 ||
|
|
516
|
+
languages.some((language) => language.toLocaleLowerCase('en-US') === sceneLanguage)))
|
|
517
|
+
.map(({ id }) => id));
|
|
513
518
|
const selectedManifestIds = new Set(graph.animationSources
|
|
514
519
|
.filter(({ sprite }) => selectedSpriteNames.has(sprite))
|
|
515
520
|
.map(({ id }) => id));
|
|
@@ -735,11 +735,12 @@ export class ProbabilityAnalyzer {
|
|
|
735
735
|
}
|
|
736
736
|
async store(result, outputs, includeHtml = false, signal, principal) {
|
|
737
737
|
const cached = this.state.byCacheKey.get(result.metadata.cacheKey);
|
|
738
|
+
const workspace = this.engine.resolver.get(result.metadata.workspaceId, principal);
|
|
738
739
|
if (cached?.operation === result.operation &&
|
|
739
740
|
cached.status === result.status &&
|
|
740
|
-
visualOutputs(outputs).length === 0
|
|
741
|
+
visualOutputs(outputs).length === 0 &&
|
|
742
|
+
(await this.engine.artifacts.available(workspace, cached.resources, signal)))
|
|
741
743
|
return cached;
|
|
742
|
-
const workspace = this.engine.resolver.get(result.metadata.workspaceId, principal);
|
|
743
744
|
const provenance = {
|
|
744
745
|
kind: 'probability-analysis',
|
|
745
746
|
toolVersion: PACKAGE_VERSION,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { LATEST_PROTOCOL_VERSION } from '@modelcontextprotocol/sdk/types.js';
|
|
2
2
|
export const PACKAGE_NAME = 'hoi4-agent-tools';
|
|
3
|
-
export const PACKAGE_VERSION = '2.8.
|
|
3
|
+
export const PACKAGE_VERSION = '2.8.7';
|
|
4
4
|
export const MCP_PROTOCOL_VERSION = LATEST_PROTOCOL_VERSION;
|
|
5
5
|
export const CONFIG_VERSION = 1;
|
|
6
6
|
export const TRANSACTION_VERSION = 1;
|
package/docs/gui.md
CHANGED
|
@@ -33,15 +33,15 @@ Inspection checks missing assets and localisation, invalid sizes, overlap, clipp
|
|
|
33
33
|
|
|
34
34
|
The renderer resolves sprites and fonts through the complete mod, dependency, and installed-game load order. Mod windows therefore render ordinary vanilla sprites, tiled vanilla panels, progress bars, masked shields, button frames, and localisation icons such as `£command_power` without copying game assets into the mod. Case differences in GFX and font identifiers do not prevent a valid asset from resolving.
|
|
35
35
|
|
|
36
|
-
Bitmap text uses the language-appropriate HOI4 font definition and its real glyph atlas. Header, serif, compact, typewriter, black, inverted, and other declared faces keep their own glyph shapes, native metrics, face colour, border colour, language override, and font-specific `textcolors` palette. HOI4 localisation colour runs such as `§Y` and `§R`
|
|
36
|
+
Bitmap text uses the language-appropriate HOI4 font definition and its real glyph atlas. Header, serif, compact, typewriter, black, inverted, and other declared faces keep their own glyph shapes, native metrics, face colour, border colour, language override, and font-specific `textcolors` palette. HOI4 localisation colour runs such as `§Y` and `§R` multiply the selected palette colour into the native glyph pixels, preserving the atlas's sharp antialiasing and dark shadow pixels instead of flattening the glyph into a blurred monochrome mask or switching to the tool font. The default language uses the base font rather than an unrelated language override, and the renderer recognizes installed-game atlases whose filename omits a page suffix declared by the matching `.fnt` file.
|
|
37
37
|
|
|
38
38
|
Layout follows Clausewitz orientation and element-origin anchors, including `CENTER_LEFT`, `CENTER_RIGHT`, `CENTER_UP`, `CENTER_DOWN`, `origo`, `centerposition`, inherited container coordinate origins, local scale, and both `%` and `%%` relative dimensions. Text boxes use native font metrics together with `maxWidth`, `maxHeight`, alignment, wrapping, and `fixedsize` clipping. Cornered tile sprites use fixed nine-slice borders and optional center tiling; progress bars composite their filled and background textures; masked shields composite their background and mask textures.
|
|
39
39
|
|
|
40
40
|
Scripted-GUI composition follows `parent_scripted_gui` chains even when the linked child window is a top-level sibling in the `.gui` file. Literal `always = yes` and `always = no` visibility and click-enabled blocks are applied automatically. A scenario's `values` object supplies concrete runtime values in one place: variable names resolve numeric text, scripted-localisation names resolve dynamic labels, a progress-bar element name sets its fill value, and element keys ending in `.image`, `.frame`, `.x`, `.y`, `.visible`, or `.enabled` update that visual property. Scripted-GUI property expressions such as `image = "[GetMeterSprite]"` or `x = meter_fill_width` consume matching scenario values automatically. Dynamic lists instantiate their declared `entry_container` or `country_scope_entry_container`; each scenario row can select the country template with `countryScope`, choose an explicit `entryContainer`, and provide row-scoped text, image, frame, position, visibility, and enabled values.
|
|
41
41
|
|
|
42
|
-
`hoi4.gui_inspect` and `hoi4.gui_render` generate a plausible seeded runtime scenario by default. The generator discovers numeric and text tokens in
|
|
42
|
+
`hoi4.gui_inspect` and `hoi4.gui_render` generate a plausible seeded runtime scenario by default. The generator follows the complete `parent_scripted_gui` surface, discovers numeric and text tokens in GUI localisation and scripted-GUI properties, chooses real scripted-localisation text and sprite candidates, applies simple source thresholds, fills meters within their declared ranges, populates dynamic lists with coherent rows, selects one overlapping tab pane, keeps active and idle controls mutually exclusive, and leaves values explicitly supplied by the caller unchanged. Normal controls and animation frames remain stable unless variation is explicitly requested. Every explicit `relatedScenarios` entry is rendered beside the generated view.
|
|
43
43
|
|
|
44
|
-
Generation is reproducible. Set `generatedScenarios.seed` to any stable string for an exact rerun, use `count` for several plausible versions, or configure numeric bounds, integer or decimal values, list row bounds, text samples, visibility probability, and state variation. Set `enabled` to `false` when only the supplied scenario should render,
|
|
44
|
+
Generation is reproducible. Set `generatedScenarios.seed` to any stable string for an exact rerun, use `count` for several plausible versions, or configure numeric bounds, integer or decimal values, list row bounds, text samples, visibility probability, and state variation. The generated view is the default. Set `enabled` to `false` when only the supplied placeholder scenario should render, or set `preservePlaceholder` to `true` to include the placeholder beside generated scenarios.
|
|
45
45
|
|
|
46
46
|
```json
|
|
47
47
|
{
|
|
@@ -93,6 +93,6 @@ Large inspections, renders, and rewrites send periodic MCP progress heartbeats w
|
|
|
93
93
|
|
|
94
94
|
The renderer does not run the game engine. Each render includes a fidelity report that separates fields it models from fields it approximates, ignores, cannot resolve, or does not support. Treat that report as part of the review.
|
|
95
95
|
|
|
96
|
-
The generated primary view replaces discovered numeric and text runtime tokens with plausible values.
|
|
96
|
+
The generated primary view replaces discovered numeric and text runtime tokens with plausible values. Set `generatedScenarios.preservePlaceholder` to `true`, or disable generation, when the same run should also show unresolved numeric values such as `[?variable|format]` as `[X]` and unresolved text-returning scripted or scoped localisation such as `[GetStatusText]`, `[FROM.GetName]`, and `[?leader_scope.GetName]` as `[dynamic_loc]`. Put `variable` or `GetStatusText` in the supplied scenario's `values` object when an exact value matters; explicit values always take precedence over generated ones and can drive the related meter or state-dependent controls. Supported HOI4 `§` localisation colour controls use the active font's palette and `§!` restores the face colour.
|
|
97
97
|
|
|
98
98
|
A rewrite stops if malformed or unsupported GUI script makes the requested change ambiguous. Frame-sheet animation, nine-slice tiling, progress composition, masking, and the primary and secondary textures referenced by vanilla GFX definitions render offline. Engine shader programs, hardcoded controls, and dynamic values that are not supplied by a scenario remain fidelity-report entries; an unexecuted shader never hides its resolved base texture.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hoi4-agent-tools",
|
|
3
3
|
"mcpName": "io.github.klimPaskov/hoi4-agent-tools",
|
|
4
|
-
"version": "2.8.
|
|
4
|
+
"version": "2.8.7",
|
|
5
5
|
"description": "Analyze HOI4 events, tech trees, AI weights, and MTTH; build focus trees, GUIs, and maps.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/configuration.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/continuous-focus-palette.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/custom-weighted-pool.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/event-feature-manifest.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/focus-plan.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/focus-planning-sidecar.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/gui-animation-source.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/gui-helper.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/gui-scenario.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/map-operation.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"oneOf": [
|
|
5
5
|
{
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/operation-result.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/probability-analysis-result.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/probability-compare-input.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/probability-evaluate-input.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/probability-inspect-input.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/probability-render-input.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/probability-scenario-set.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/probability-sequence-input.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/probability-simulate-input.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
{
|
|
2
|
-
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v2.8.7/schemas/probability-sweep-input.schema.json",
|
|
3
3
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
4
4
|
"type": "object",
|
|
5
5
|
"properties": {
|
package/server.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"name": "io.github.klimPaskov/hoi4-agent-tools",
|
|
4
4
|
"title": "HOI4 Agent Tools",
|
|
5
5
|
"description": "Analyze HOI4 events, tech trees, AI weights, and MTTH; build focus trees, GUIs, and maps.",
|
|
6
|
-
"version": "2.8.
|
|
6
|
+
"version": "2.8.7",
|
|
7
7
|
"repository": {
|
|
8
8
|
"url": "https://github.com/klimPaskov/hoi4-agent-tools",
|
|
9
9
|
"source": "github"
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
{
|
|
14
14
|
"registryType": "npm",
|
|
15
15
|
"identifier": "hoi4-agent-tools",
|
|
16
|
-
"version": "2.8.
|
|
16
|
+
"version": "2.8.7",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
}
|