hoi4-agent-tools 4.2.0 → 4.4.0

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.
Files changed (124) hide show
  1. package/CHANGELOG.md +30 -1
  2. package/dist/hoi4_agent_tools/core/bounded-source.js +31 -9
  3. package/dist/hoi4_agent_tools/core/configuration.js +11 -0
  4. package/dist/hoi4_agent_tools/core/domain-validation.js +6 -1
  5. package/dist/hoi4_agent_tools/core/engine.js +3 -0
  6. package/dist/hoi4_agent_tools/core/game-documentation.js +24 -0
  7. package/dist/hoi4_agent_tools/core/operation-context.js +17 -1
  8. package/dist/hoi4_agent_tools/core/temporary-directories.js +7 -2
  9. package/dist/hoi4_agent_tools/core/transaction-limits.js +18 -4
  10. package/dist/hoi4_agent_tools/core/transactions.js +23 -4
  11. package/dist/hoi4_agent_tools/core/workspace-json.js +54 -0
  12. package/dist/hoi4_agent_tools/core/workspace.js +42 -6
  13. package/dist/hoi4_agent_tools/decision/service.js +1 -22
  14. package/dist/hoi4_agent_tools/event/graph.js +8 -1
  15. package/dist/hoi4_agent_tools/event/service.js +8 -0
  16. package/dist/hoi4_agent_tools/event/source-analysis.js +10 -6
  17. package/dist/hoi4_agent_tools/focus/importer.js +8 -6
  18. package/dist/hoi4_agent_tools/focus/native-effects.js +3 -1
  19. package/dist/hoi4_agent_tools/focus/tool-support.js +10 -1
  20. package/dist/hoi4_agent_tools/map/appearance-validation.js +1110 -0
  21. package/dist/hoi4_agent_tools/map/bmp.js +9 -1
  22. package/dist/hoi4_agent_tools/map/border-quality-input.js +209 -0
  23. package/dist/hoi4_agent_tools/map/border-quality.js +1180 -0
  24. package/dist/hoi4_agent_tools/map/colormap.js +128 -0
  25. package/dist/hoi4_agent_tools/map/geography/geometry.js +284 -0
  26. package/dist/hoi4_agent_tools/map/geography/index.js +6 -0
  27. package/dist/hoi4_agent_tools/map/geography/model.js +196 -0
  28. package/dist/hoi4_agent_tools/map/geography/preparation.js +120 -0
  29. package/dist/hoi4_agent_tools/map/geography/preview.js +647 -0
  30. package/dist/hoi4_agent_tools/map/geography/raster.js +253 -0
  31. package/dist/hoi4_agent_tools/map/geography/resolve.js +1467 -0
  32. package/dist/hoi4_agent_tools/map/model.js +15 -2
  33. package/dist/hoi4_agent_tools/map/operations.js +111 -8
  34. package/dist/hoi4_agent_tools/map/partition-fields.js +398 -0
  35. package/dist/hoi4_agent_tools/map/partition-geography.js +113 -0
  36. package/dist/hoi4_agent_tools/map/partition-graph.js +165 -0
  37. package/dist/hoi4_agent_tools/map/partition-groups.js +164 -0
  38. package/dist/hoi4_agent_tools/map/partition-provinces.js +727 -0
  39. package/dist/hoi4_agent_tools/map/partition-tuning.js +101 -0
  40. package/dist/hoi4_agent_tools/map/partition-watershed.js +252 -0
  41. package/dist/hoi4_agent_tools/map/partition.js +163 -0
  42. package/dist/hoi4_agent_tools/map/reference-import.js +333 -0
  43. package/dist/hoi4_agent_tools/map/reference-preparation.js +138 -5
  44. package/dist/hoi4_agent_tools/map/reference-sheets.js +231 -0
  45. package/dist/hoi4_agent_tools/map/reference-world.js +104 -13
  46. package/dist/hoi4_agent_tools/map/relief/checks.js +281 -0
  47. package/dist/hoi4_agent_tools/map/relief/fields.js +15 -0
  48. package/dist/hoi4_agent_tools/map/relief/full-resolution.js +133 -0
  49. package/dist/hoi4_agent_tools/map/relief/grid.js +190 -0
  50. package/dist/hoi4_agent_tools/map/relief/hydrology.js +1315 -0
  51. package/dist/hoi4_agent_tools/map/relief/index.js +27 -0
  52. package/dist/hoi4_agent_tools/map/relief/land.js +110 -0
  53. package/dist/hoi4_agent_tools/map/relief/macro-relief.js +535 -0
  54. package/dist/hoi4_agent_tools/map/relief/math.js +93 -0
  55. package/dist/hoi4_agent_tools/map/relief/river-raster.js +680 -0
  56. package/dist/hoi4_agent_tools/map/relief/terrain-synthesis.js +304 -0
  57. package/dist/hoi4_agent_tools/map/render.js +36 -0
  58. package/dist/hoi4_agent_tools/map/service.js +191 -16
  59. package/dist/hoi4_agent_tools/map/tool-operations.js +208 -2
  60. package/dist/hoi4_agent_tools/map/validation.js +9 -0
  61. package/dist/hoi4_agent_tools/map/water.js +227 -0
  62. package/dist/hoi4_agent_tools/map/world-context.js +24 -1
  63. package/dist/hoi4_agent_tools/map/world-edge.js +335 -0
  64. package/dist/hoi4_agent_tools/map/world-noise.js +34 -0
  65. package/dist/hoi4_agent_tools/map/world-partition.js +119 -0
  66. package/dist/hoi4_agent_tools/map/world-provinces.js +131 -56
  67. package/dist/hoi4_agent_tools/map/world.js +462 -124
  68. package/dist/hoi4_agent_tools/mcp/tools/map.js +69 -1
  69. package/dist/hoi4_agent_tools/probability/service.js +18 -18
  70. package/dist/hoi4_agent_tools/reference/operations.js +3 -2
  71. package/dist/hoi4_agent_tools/schemas/geography.js +325 -0
  72. package/dist/hoi4_agent_tools/schemas/map-requests.js +20 -2
  73. package/dist/hoi4_agent_tools/schemas/map.js +209 -2
  74. package/dist/hoi4_agent_tools/schemas/probability.js +7 -1
  75. package/dist/hoi4_agent_tools/schemas/reference-sheets.js +92 -0
  76. package/dist/hoi4_agent_tools/version.js +1 -1
  77. package/docs/analysis.md +1 -1
  78. package/docs/configuration.md +17 -14
  79. package/docs/map.md +258 -15
  80. package/docs/probability.md +1 -1
  81. package/docs/tools.md +4 -4
  82. package/docs/troubleshooting.md +11 -11
  83. package/npm-shrinkwrap.json +109 -91
  84. package/package.json +3 -3
  85. package/schemas/configuration.schema.json +65 -58
  86. package/schemas/continuous-focus-palette.schema.json +1 -1
  87. package/schemas/custom-weighted-pool.schema.json +1 -1
  88. package/schemas/decision-inspect-input.schema.json +1 -1
  89. package/schemas/error-log-input.schema.json +1 -1
  90. package/schemas/event-feature-manifest.schema.json +1 -1
  91. package/schemas/focus-plan.schema.json +1 -1
  92. package/schemas/focus-planning-sidecar.schema.json +1 -1
  93. package/schemas/geography-model.schema.json +1148 -0
  94. package/schemas/gui-animation-source.schema.json +1 -1
  95. package/schemas/gui-helper.schema.json +5 -11
  96. package/schemas/gui-scenario.schema.json +1 -1
  97. package/schemas/helper-expansion-request.schema.json +1 -1
  98. package/schemas/helper-expansion-summary.schema.json +1 -1
  99. package/schemas/impact-inspect-input.schema.json +1 -1
  100. package/schemas/map-operation.schema.json +2156 -259
  101. package/schemas/mechanic-test-input.schema.json +1 -1
  102. package/schemas/mod-index-input.schema.json +1 -1
  103. package/schemas/operation-result.schema.json +1 -1
  104. package/schemas/package-check-input.schema.json +1 -1
  105. package/schemas/package-manifest.schema.json +1 -1
  106. package/schemas/probability-analysis-result.schema.json +31 -7
  107. package/schemas/probability-compare-input.schema.json +1 -1
  108. package/schemas/probability-evaluate-input.schema.json +1 -1
  109. package/schemas/probability-inspect-input.schema.json +1 -1
  110. package/schemas/probability-render-input.schema.json +1 -1
  111. package/schemas/probability-scenario-set.schema.json +1 -1
  112. package/schemas/probability-sequence-input.schema.json +1 -1
  113. package/schemas/probability-simulate-input.schema.json +1 -1
  114. package/schemas/probability-sweep-input.schema.json +1 -1
  115. package/schemas/reference-context-input.schema.json +1 -1
  116. package/schemas/reference-read-input.schema.json +1 -1
  117. package/schemas/reference-search-input.schema.json +1 -1
  118. package/schemas/reference-sheets.schema.json +267 -0
  119. package/schemas/scenario-suite.schema.json +1 -1
  120. package/schemas/scenario-test-input.schema.json +1 -1
  121. package/schemas/script-validate-input.schema.json +1 -1
  122. package/schemas/shared-scenario.schema.json +1 -1
  123. package/schemas/source-lookup-input.schema.json +1 -1
  124. package/server.json +2 -2
@@ -216,8 +216,11 @@ const NATIVE_EFFECT_CONTAINERS = new Set([
216
216
  'while_loop_effect',
217
217
  ]);
218
218
  /** Inside a native effect such as `add_building_construction`, `key = yes` is an argument. */
219
- function isNativeArgumentBlock(normalizedKey) {
220
- return (nativeEffectKeys.has(normalizedKey) &&
219
+ function isNativeEffect(normalizedKey, documented) {
220
+ return nativeEffectKeys.has(normalizedKey) || documented?.has(normalizedKey) === true;
221
+ }
222
+ function isNativeArgumentBlock(normalizedKey, documented) {
223
+ return (isNativeEffect(normalizedKey, documented) &&
221
224
  !NATIVE_EFFECT_CONTAINERS.has(normalizedKey) &&
222
225
  !CONTROL_BLOCKS.has(normalizedKey) &&
223
226
  SCOPE_BLOCKS[normalizedKey] === undefined &&
@@ -285,10 +288,10 @@ function localisationKeysFromValue(value) {
285
288
  }
286
289
  return [...new Set(keys)].sort(compareCodeUnits);
287
290
  }
288
- function missingHelperCandidate(key, value, effectContext) {
291
+ function missingHelperCandidate(key, value, effectContext, documented) {
289
292
  const normalizedKey = key.toLowerCase();
290
293
  if (!effectContext ||
291
- nativeEffectKeys.has(normalizedKey) ||
294
+ isNativeEffect(normalizedKey, documented) ||
292
295
  NON_HELPER_BLOCKS.has(normalizedKey) ||
293
296
  SCOPE_BLOCKS[normalizedKey] !== undefined ||
294
297
  STATE_RULES[normalizedKey] !== undefined ||
@@ -993,7 +996,7 @@ class FragmentAnalyzer {
993
996
  if (this.context.inventoryComplete !== false &&
994
997
  context.nativeArguments !== true &&
995
998
  context.inferMissingHelpers !== false &&
996
- missingHelperCandidate(key, entry.value, effectContext)) {
999
+ missingHelperCandidate(key, entry.value, effectContext, this.context.documentedEffectKeys)) {
997
1000
  const target = this.unresolvedNode('missing_helper', key, entry, context.ownerId, semanticPath);
998
1001
  this.addEdge(context.ownerId, target, 'scripted_effect_call', entry, context.conditions, {
999
1002
  phase: context.phase,
@@ -1122,7 +1125,8 @@ class FragmentAnalyzer {
1122
1125
  effectContext: NON_EXECUTING_BLOCKS.has(normalizedKey) || isTriggerIterator(normalizedKey)
1123
1126
  ? false
1124
1127
  : effectContext,
1125
- nativeArguments: context.nativeArguments === true || isNativeArgumentBlock(normalizedKey),
1128
+ nativeArguments: context.nativeArguments === true ||
1129
+ isNativeArgumentBlock(normalizedKey, this.context.documentedEffectKeys),
1126
1130
  ...(context.inferMissingHelpers === false && isConventionalEffectBlock(normalizedKey)
1127
1131
  ? { inferMissingHelpers: true }
1128
1132
  : {}),
@@ -135,9 +135,9 @@ function isFormableDecision(target, options) {
135
135
  return false;
136
136
  return /(?:^form_|formable|form_country)/iu.test(target);
137
137
  }
138
- function isEffectContainer(key) {
138
+ function isEffectContainer(key, nativeEffects) {
139
139
  return (effectContainerKeys.has(key) ||
140
- (nativeFocusEffectKeys.has(key) &&
140
+ ((nativeFocusEffectKeys.has(key) || nativeEffects?.has(key) === true) &&
141
141
  /^(?:(?:global_)?every|ordered|random)_[a-z0-9_]+$/u.test(key)));
142
142
  }
143
143
  function isScopeKey(key, knownLeaders) {
@@ -342,6 +342,7 @@ function referenceLinks(document, block, options) {
342
342
  const links = [];
343
343
  const knownHelpers = catalogValues(options, 'helper');
344
344
  const knownLeaders = catalogValues(options, 'leader');
345
+ const isNative = (key) => nativeFocusEffectKeys.has(key) || options.nativeEffects?.has(key) === true;
345
346
  function recordReference(assignment, specification) {
346
347
  for (const target of referenceTargets(assignment, specification)) {
347
348
  const kind = specification.kind === 'decision' && isFormableDecision(target, options)
@@ -364,7 +365,8 @@ function referenceLinks(document, block, options) {
364
365
  recordReference(assignment, reference);
365
366
  if (assignment.value.type === 'block') {
366
367
  for (const nested of assignments(assignment.value)) {
367
- if (nested.value.type === 'block' && isEffectContainer(nested.key.value.toLowerCase())) {
368
+ if (nested.value.type === 'block' &&
369
+ isEffectContainer(nested.key.value.toLowerCase(), options.nativeEffects)) {
368
370
  effectAssignment(nested, new Set());
369
371
  }
370
372
  }
@@ -373,7 +375,7 @@ function referenceLinks(document, block, options) {
373
375
  }
374
376
  if (knownHelpers.has(key) &&
375
377
  !effectContainerKeys.has(normalizedKey) &&
376
- !nativeFocusEffectKeys.has(normalizedKey)) {
378
+ !isNative(normalizedKey)) {
377
379
  links.push({
378
380
  kind: 'helper',
379
381
  target: key,
@@ -381,7 +383,7 @@ function referenceLinks(document, block, options) {
381
383
  });
382
384
  return;
383
385
  }
384
- if (isEffectContainer(normalizedKey)) {
386
+ if (isEffectContainer(normalizedKey, options.nativeEffects)) {
385
387
  if (assignment.value.type !== 'block')
386
388
  return;
387
389
  if (normalizedKey === 'random_list') {
@@ -397,7 +399,7 @@ function referenceLinks(document, block, options) {
397
399
  }
398
400
  return;
399
401
  }
400
- if (nativeFocusEffectKeys.has(normalizedKey))
402
+ if (isNative(normalizedKey))
401
403
  return;
402
404
  if (assignment.value.type === 'block' && isScopeKey(key, knownLeaders)) {
403
405
  effectWalk(assignment.value, new Set());
@@ -2,7 +2,9 @@
2
2
  * Native effect identifiers used to distinguish direct scripted-effect calls
3
3
  * from engine effects while importing focus completion rewards.
4
4
  *
5
- * Source: the official HOI4 1.19.2 effects documentation reviewed 2026-07-10.
5
+ * Source: the official HOI4 1.19.2 effects documentation reviewed 2026-07-10. This is the
6
+ * fallback list; analysis also accepts every effect the installed game documents in
7
+ * documentation/effects_documentation.md, so effects added by later patches are recognized.
6
8
  * Keep this list synchronized during compatibility reviews.
7
9
  */
8
10
  export const nativeEffectKeys = new Set([
@@ -40,7 +40,7 @@ export function activeSidecar(snapshot, focusFile) {
40
40
  }
41
41
  export function importFocusFile(snapshot, file, palettes) {
42
42
  const document = parseClausewitz(file.bytes, file.displayPath);
43
- const imported = importFocusTrees(document, { references: referenceCatalog(snapshot) });
43
+ const imported = importFocusTrees(document, focusImportOptions(snapshot));
44
44
  const sidecar = activeSidecar(snapshot, file);
45
45
  imported.plans = imported.plans.map((plan) => {
46
46
  const enriched = sidecar === undefined
@@ -89,6 +89,15 @@ export function selectContinuousPlan(result, paletteId) {
89
89
  throw new ServiceError('CONTINUOUS_FOCUS_PALETTE_NOT_FOUND', `Continuous focus palette was not found: ${paletteId}`);
90
90
  return plan;
91
91
  }
92
+ /** Import options from a scan: its reference catalog and the installed game's documented effects. */
93
+ export function focusImportOptions(snapshot) {
94
+ return {
95
+ references: referenceCatalog(snapshot),
96
+ ...(snapshot.documentedEffects === undefined
97
+ ? {}
98
+ : { nativeEffects: snapshot.documentedEffects.names }),
99
+ };
100
+ }
92
101
  export function referenceCatalog(snapshot) {
93
102
  const identifiers = (kind) => [
94
103
  ...new Set(snapshot.index