hoi4-agent-tools 3.4.0 → 3.4.1
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 +10 -0
- package/dist/hoi4_agent_tools/core/condition-evaluator.js +7 -0
- package/dist/hoi4_agent_tools/core/index.js +1 -0
- package/dist/hoi4_agent_tools/core/job-worker-host.js +19 -1
- package/dist/hoi4_agent_tools/core/operation-result.js +4 -1
- package/dist/hoi4_agent_tools/event/operations.js +16 -10
- package/dist/hoi4_agent_tools/gui/validators.js +3 -0
- package/dist/hoi4_agent_tools/mechanic/interpreter.js +91 -30
- package/dist/hoi4_agent_tools/mechanic/source.js +19 -4
- package/dist/hoi4_agent_tools/technology/operations.js +29 -1
- package/dist/hoi4_agent_tools/technology/render.js +2 -1
- package/dist/hoi4_agent_tools/technology/service.js +1 -0
- package/dist/hoi4_agent_tools/version.js +1 -1
- package/docs/events.md +1 -1
- package/docs/gui.md +1 -0
- package/docs/jobs.md +1 -0
- package/docs/mechanics.md +2 -1
- package/docs/technology.md +5 -1
- 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/decision-inspect-input.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/helper-expansion-request.schema.json +1 -1
- package/schemas/helper-expansion-summary.schema.json +1 -1
- package/schemas/impact-inspect-input.schema.json +1 -1
- package/schemas/map-operation.schema.json +1 -1
- package/schemas/mechanic-test-input.schema.json +1 -1
- package/schemas/operation-result.schema.json +1 -1
- package/schemas/package-check-input.schema.json +1 -1
- package/schemas/package-manifest.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/schemas/scenario-suite.schema.json +1 -1
- package/schemas/scenario-test-input.schema.json +1 -1
- package/schemas/shared-scenario.schema.json +1 -1
- package/server.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
## 3.4.1 - 2026-09-25
|
|
6
|
+
|
|
7
|
+
- Validate technology renders against the requested view's source placement, node coverage, and sprite resolution without inheriting unrelated graph-wide diagnostics, while reporting deferred whole-workspace helper projection as a separate analysis boundary; resolve subtechnology art from the source GUI slot before using a technology-id fallback and include every referenced slot texture in the asset scan.
|
|
8
|
+
- Accept focused event inspection and render evidence when every event source was scanned and no blocking diagnostics remain, while retaining deferred workspace-wide helper and lifecycle projections as an explicit boundary.
|
|
9
|
+
- Keep repeated window-local GUI control names additive in the shared index, exclude engine-owned compound-control roles from scripted click-effect requirements, and preserve compact operation summaries when linked evidence exceeds the MCP wire budget.
|
|
10
|
+
- Parse each active scripted-effect source document once when building mechanic helper inventories so bounded real-workspace scenarios do not multiply parser state by the number of helpers in a file.
|
|
11
|
+
- Interpret declared temporary-variable assignment, arithmetic, rounding, clamping, and scope-valued inputs with chain-wide unscoped semantics in bounded mechanic scenarios.
|
|
12
|
+
- Evaluate `has_variable` against declared scenario state so guarded defaults and subsequent temporary-variable arithmetic remain deterministic.
|
|
13
|
+
- Follow a live replacement worker through its terminal publication instead of returning a nonterminal job record during concurrent checkpoint recovery.
|
|
14
|
+
|
|
5
15
|
## 3.4.0 - 2026-09-20
|
|
6
16
|
|
|
7
17
|
- Add branch-local focus cleanup with pinned anchors and symmetry groups, connector measurements, source-linked crops, and scenario-backed structural route diagnostics.
|
|
@@ -278,6 +278,13 @@ function evaluateAssignmentCore(assignment, scenario, candidate, definitions, he
|
|
|
278
278
|
unresolved: [],
|
|
279
279
|
};
|
|
280
280
|
}
|
|
281
|
+
if (key === 'has_variable') {
|
|
282
|
+
const state = scopeContext.expression === 'ROOT' ? scenario.state : scopeContext.binding.state;
|
|
283
|
+
return {
|
|
284
|
+
state: Object.hasOwn(state, right) || Object.hasOwn(state, `variable.${right}`) ? 'true' : 'false',
|
|
285
|
+
unresolved: [],
|
|
286
|
+
};
|
|
287
|
+
}
|
|
281
288
|
if (key === 'tag' || key === 'original_tag') {
|
|
282
289
|
const actor = scopeContext.expression === 'ROOT'
|
|
283
290
|
? scenario.actor
|
|
@@ -1369,6 +1369,7 @@ export class SymbolIndex {
|
|
|
1369
1369
|
this.#active.set(key, active);
|
|
1370
1370
|
const additiveCategory = active.kind === 'decision_category' ||
|
|
1371
1371
|
active.kind === 'technology_category' ||
|
|
1372
|
+
active.kind === 'gui_element' ||
|
|
1372
1373
|
active.kind === 'texture';
|
|
1373
1374
|
for (const candidate of group) {
|
|
1374
1375
|
candidate.overridden = additiveCategory ? candidate.sourceShadowed : candidate !== active;
|
|
@@ -73,7 +73,12 @@ export class JobWorkerHost {
|
|
|
73
73
|
for (;;) {
|
|
74
74
|
try {
|
|
75
75
|
await this.scheduler.run(this.owner, 1024, signal, () => this.capacity.run(signal, (lease) => this.launch(workspaceId, id, lease, principal)));
|
|
76
|
-
|
|
76
|
+
const current = await this.jobs.get(workspaceId, id, principal);
|
|
77
|
+
if (['completed', 'cancelled', 'failed'].includes(current.status))
|
|
78
|
+
return current;
|
|
79
|
+
if (current.owner !== undefined && jobOwnerLiveness(current.owner) === 'alive')
|
|
80
|
+
return await this.followOwner(workspaceId, id, principal);
|
|
81
|
+
throw new ServiceError('JOB_WORKER_EXIT', 'The worker stopped without publishing a terminal job outcome');
|
|
77
82
|
}
|
|
78
83
|
catch (error) {
|
|
79
84
|
const current = await this.jobs.get(workspaceId, id, principal);
|
|
@@ -108,6 +113,19 @@ export class JobWorkerHost {
|
|
|
108
113
|
}
|
|
109
114
|
}
|
|
110
115
|
}
|
|
116
|
+
async followOwner(workspaceId, id, principal) {
|
|
117
|
+
for (;;) {
|
|
118
|
+
const record = await this.jobs.get(workspaceId, id, principal);
|
|
119
|
+
if (['completed', 'failed', 'cancelled'].includes(record.status))
|
|
120
|
+
return record;
|
|
121
|
+
const liveness = record.owner === undefined ? 'dead' : jobOwnerLiveness(record.owner);
|
|
122
|
+
if (liveness !== 'alive')
|
|
123
|
+
throw new ServiceError(liveness === 'unknown' ? 'JOB_OWNER_UNRESOLVED' : 'JOB_WORKER_EXIT', liveness === 'unknown'
|
|
124
|
+
? 'The replacement execution owner cannot be verified on this host'
|
|
125
|
+
: 'The replacement worker stopped without publishing a terminal job outcome');
|
|
126
|
+
await delay(100);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
111
129
|
async launch(workspaceId, id, lease, principal) {
|
|
112
130
|
// Resolve the same configured workspace and grants again immediately before dispatch.
|
|
113
131
|
await this.jobs.get(workspaceId, id, principal);
|
|
@@ -114,6 +114,9 @@ function boundedResult(result, actualBytes) {
|
|
|
114
114
|
: 'Tool output exceeded the wire budget; nonessential inline details were omitted',
|
|
115
115
|
details: { actualBytes, maxBytes: MAX_TOOL_RESULT_BYTES },
|
|
116
116
|
};
|
|
117
|
+
const compactData = result.data !== null && typeof result.data === 'object' && !Array.isArray(result.data)
|
|
118
|
+
? result.data
|
|
119
|
+
: {};
|
|
117
120
|
return {
|
|
118
121
|
status: result.status,
|
|
119
122
|
code: result.code.slice(0, 256),
|
|
@@ -141,7 +144,7 @@ function boundedResult(result, actualBytes) {
|
|
|
141
144
|
},
|
|
142
145
|
},
|
|
143
146
|
],
|
|
144
|
-
data: {},
|
|
147
|
+
data: jsonBytesWithin(compactData, 2_048) ? compactData : {},
|
|
145
148
|
};
|
|
146
149
|
}
|
|
147
150
|
function jsonStringBytes(value) {
|
|
@@ -37,21 +37,27 @@ export function eventGraphCounts(graph, artifacts) {
|
|
|
37
37
|
}
|
|
38
38
|
export function eventGraphValidation(graph) {
|
|
39
39
|
const counts = eventGraphCounts(graph, 0);
|
|
40
|
+
const analysisBoundaryPassed = graph.complete || (graph.analysisMode === 'focused' && graph.skippedSourceCount === 0);
|
|
41
|
+
const passed = analysisBoundaryPassed && counts.blockingDiagnostics === 0;
|
|
40
42
|
return {
|
|
41
|
-
passed
|
|
43
|
+
passed,
|
|
42
44
|
checks: [
|
|
43
45
|
{
|
|
44
46
|
id: 'event-analysis',
|
|
45
|
-
passed
|
|
46
|
-
message:
|
|
47
|
-
?
|
|
47
|
+
passed,
|
|
48
|
+
message: counts.blockingDiagnostics > 0
|
|
49
|
+
? `${counts.blockingDiagnostics} blocking event-chain diagnostics; full evidence is linked`
|
|
48
50
|
: graph.complete
|
|
49
|
-
?
|
|
50
|
-
: graph.
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
51
|
+
? 'The event-chain analysis is complete and has no blocking diagnostics'
|
|
52
|
+
: graph.analysisMode === 'focused' && graph.skippedSourceCount === 0
|
|
53
|
+
? 'Whole-workspace helper projections and lifecycle passes were deferred; the requested event analysis retains direct source evidence'
|
|
54
|
+
: graph.analysisMode === 'focused'
|
|
55
|
+
? `${graph.skippedSourceCount} event-analysis source(s) were skipped; linked evidence records the partial boundary`
|
|
56
|
+
: graph.issues.some(({ code }) => code === 'EVENT_HELPER_DEPTH_LIMIT' ||
|
|
57
|
+
code === 'EVENT_HELPER_PROJECTION_LIMIT' ||
|
|
58
|
+
code === 'EVENT_HELPER_STATE_PROJECTION_LIMIT')
|
|
59
|
+
? 'Helper expansion reached a depth or materialization boundary; helper_expansion mode provides bounded source-linked continuation'
|
|
60
|
+
: `${graph.skippedSourceCount} event-analysis source(s) were skipped; full evidence is linked`,
|
|
55
61
|
},
|
|
56
62
|
],
|
|
57
63
|
};
|
|
@@ -655,6 +655,9 @@ function validateReferencesAndScript(graph, scene, diagnostics) {
|
|
|
655
655
|
const elementsById = new Map(graph.elements.map((element) => [element.id, element]));
|
|
656
656
|
for (const button of scene.elements.filter(({ elementType }) => /button/iu.test(elementType))) {
|
|
657
657
|
const source = elementsById.get(button.sourceId);
|
|
658
|
+
const referencedByScript = effects.has(button.name) || triggers.has(button.name);
|
|
659
|
+
if ((source === undefined || !/button/iu.test(source.elementType)) && !referencedByScript)
|
|
660
|
+
continue;
|
|
658
661
|
const tooltipOnly = !effects.has(button.name) &&
|
|
659
662
|
!triggers.has(button.name) &&
|
|
660
663
|
(typeof source?.attributes.pdx_tooltip === 'string' ||
|
|
@@ -13,6 +13,22 @@ const numericEffects = new Map([
|
|
|
13
13
|
['add_war_support', { key: 'war_support', mode: 'add', min: 0, max: 1 }],
|
|
14
14
|
]);
|
|
15
15
|
const harmlessEffects = new Set(['hidden_effect', 'custom_effect_tooltip', 'log', 'tooltip']);
|
|
16
|
+
const variableEffects = new Map([
|
|
17
|
+
['set_variable', 'set'],
|
|
18
|
+
['set_temp_variable', 'set'],
|
|
19
|
+
['add_to_variable', 'add'],
|
|
20
|
+
['add_to_temp_variable', 'add'],
|
|
21
|
+
['subtract_from_variable', 'subtract'],
|
|
22
|
+
['subtract_from_temp_variable', 'subtract'],
|
|
23
|
+
['multiply_variable', 'multiply'],
|
|
24
|
+
['multiply_temp_variable', 'multiply'],
|
|
25
|
+
['divide_variable', 'divide'],
|
|
26
|
+
['divide_temp_variable', 'divide'],
|
|
27
|
+
['clamp_variable', 'clamp'],
|
|
28
|
+
['clamp_temp_variable', 'clamp'],
|
|
29
|
+
['round_variable', 'round'],
|
|
30
|
+
['round_temp_variable', 'round'],
|
|
31
|
+
]);
|
|
16
32
|
function numeric(value) {
|
|
17
33
|
if (typeof value === 'number' && Number.isFinite(value))
|
|
18
34
|
return value;
|
|
@@ -175,6 +191,40 @@ export class MechanicInterpreter {
|
|
|
175
191
|
return (numeric(scenarioValue(this.state, key, targetScope)) ??
|
|
176
192
|
numeric(scenarioValue(this.state, `variable.${key}`, targetScope)));
|
|
177
193
|
}
|
|
194
|
+
scopeReference(expression, scope, stack) {
|
|
195
|
+
const scopeId = (name) => {
|
|
196
|
+
if (name === 'ROOT')
|
|
197
|
+
return this.state.scenario.actor ?? 'ROOT';
|
|
198
|
+
if (name === 'THIS')
|
|
199
|
+
return scope === 'ROOT'
|
|
200
|
+
? (this.state.scenario.actor ?? 'ROOT')
|
|
201
|
+
: this.state.scenario.scopes?.[scope]?.id;
|
|
202
|
+
if (name === 'PREV') {
|
|
203
|
+
const previous = stack.findLast((item) => item.startsWith('scope:'))?.slice(6);
|
|
204
|
+
return previous === undefined
|
|
205
|
+
? undefined
|
|
206
|
+
: previous === 'ROOT'
|
|
207
|
+
? (this.state.scenario.actor ?? 'ROOT')
|
|
208
|
+
: this.state.scenario.scopes?.[previous]?.id;
|
|
209
|
+
}
|
|
210
|
+
return this.state.scenario.scopes?.[name]?.id;
|
|
211
|
+
};
|
|
212
|
+
if (expression.startsWith('event_target:'))
|
|
213
|
+
return this.state.scenario.eventTargets?.[expression.slice(13)];
|
|
214
|
+
const identifier = /^([A-Za-z0-9_:]+)(?:\.id)?$/u.exec(expression)?.[1];
|
|
215
|
+
return identifier === undefined ? undefined : scopeId(identifier.toUpperCase());
|
|
216
|
+
}
|
|
217
|
+
value(expression, path, scope, stack) {
|
|
218
|
+
const numberValue = this.number(expression, path, scope);
|
|
219
|
+
if (numberValue !== undefined)
|
|
220
|
+
return numberValue;
|
|
221
|
+
const dotted = /^(ROOT|THIS|FROM|PREV)\.(.+)$/iu.exec(expression);
|
|
222
|
+
const targetScope = dotted?.[1]?.toUpperCase() === 'THIS' ? scope : (dotted?.[1]?.toUpperCase() ?? scope);
|
|
223
|
+
const key = dotted?.[2] ?? expression;
|
|
224
|
+
const existing = scenarioValue(this.state, key, targetScope) ??
|
|
225
|
+
scenarioValue(this.state, `variable.${key}`, targetScope);
|
|
226
|
+
return existing ?? this.scopeReference(expression, scope, stack);
|
|
227
|
+
}
|
|
178
228
|
mathExpression(block, path, scope) {
|
|
179
229
|
const entries = entriesOnly(block);
|
|
180
230
|
if (entries === undefined || entries[0]?.key.value !== 'value')
|
|
@@ -410,42 +460,53 @@ export class MechanicInterpreter {
|
|
|
410
460
|
}
|
|
411
461
|
return;
|
|
412
462
|
}
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
'
|
|
416
|
-
|
|
417
|
-
'
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
463
|
+
const variableMode = variableEffects.get(key);
|
|
464
|
+
if (variableMode !== undefined) {
|
|
465
|
+
const variableScope = key.includes('temp_variable') ? 'ROOT' : scope;
|
|
466
|
+
const scalarVariable = asText(entry.value);
|
|
467
|
+
if (variableMode === 'round') {
|
|
468
|
+
const variable = scalarVariable ?? (child === undefined ? undefined : firstScalar(child, 'var')?.value);
|
|
469
|
+
const before = variable === undefined
|
|
470
|
+
? undefined
|
|
471
|
+
: numeric(scenarioValue(this.state, variable, variableScope));
|
|
472
|
+
const after = before === undefined ? undefined : Math.round(before);
|
|
473
|
+
if (variable === undefined) {
|
|
474
|
+
this.unknown(key, path, scope, 'Variable must resolve');
|
|
475
|
+
return;
|
|
476
|
+
}
|
|
477
|
+
setScenarioValue(this.state, variable, after, variableScope);
|
|
478
|
+
this.note(key, path, scope, after === undefined ? 'unresolved' : 'applied', before, after, after === undefined ? 'Variable value is not numeric' : undefined, variable);
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
421
481
|
if (child === undefined) {
|
|
422
482
|
this.unknown(key, path, scope, 'Variable effect requires a block');
|
|
423
483
|
return;
|
|
424
484
|
}
|
|
425
485
|
const short = assignments(child).find((item) => !['var', 'value', 'min', 'max', 'tooltip'].includes(item.key.value));
|
|
426
486
|
const variable = firstScalar(child, 'var')?.value ?? short?.key.value;
|
|
487
|
+
if (variable === undefined) {
|
|
488
|
+
this.unknown(key, path, scope, 'Variable must resolve');
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
427
491
|
const expression = firstScalar(child, 'value')?.value ??
|
|
428
492
|
(short === undefined ? undefined : asText(short.value));
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
this.
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
const
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
if (value !== undefined && key === 'divide_variable')
|
|
447
|
-
after = value === 0 ? undefined : before / value;
|
|
448
|
-
if (value !== undefined && key === 'clamp_variable') {
|
|
493
|
+
const operand = expression === undefined
|
|
494
|
+
? variableMode === 'set' && short?.value.type === 'block'
|
|
495
|
+
? this.mathExpression(short.value, path, scope)
|
|
496
|
+
: undefined
|
|
497
|
+
: this.value(expression, path, scope, stack);
|
|
498
|
+
const previous = scenarioValue(this.state, variable, variableScope);
|
|
499
|
+
const before = numeric(previous) ?? 0;
|
|
500
|
+
let after = variableMode === 'set' ? operand : numeric(operand);
|
|
501
|
+
if (variableMode === 'add' && typeof after === 'number')
|
|
502
|
+
after = before + after;
|
|
503
|
+
if (variableMode === 'subtract' && typeof after === 'number')
|
|
504
|
+
after = before - after;
|
|
505
|
+
if (variableMode === 'multiply' && typeof after === 'number')
|
|
506
|
+
after = before * after;
|
|
507
|
+
if (variableMode === 'divide' && typeof after === 'number')
|
|
508
|
+
after = after === 0 ? undefined : before / after;
|
|
509
|
+
if (variableMode === 'clamp') {
|
|
449
510
|
const minimum = firstScalar(child, 'min')?.value;
|
|
450
511
|
const maximum = firstScalar(child, 'max')?.value;
|
|
451
512
|
const min = minimum === undefined ? -Infinity : this.number(minimum, path, scope);
|
|
@@ -453,8 +514,8 @@ export class MechanicInterpreter {
|
|
|
453
514
|
after =
|
|
454
515
|
min === undefined || max === undefined ? undefined : Math.max(min, Math.min(max, before));
|
|
455
516
|
}
|
|
456
|
-
setScenarioValue(this.state, variable, after,
|
|
457
|
-
this.note(key, path, scope, after === undefined ? 'unresolved' : 'applied',
|
|
517
|
+
setScenarioValue(this.state, variable, after, variableScope);
|
|
518
|
+
this.note(key, path, scope, after === undefined ? 'unresolved' : 'applied', previous, after, after === undefined ? 'Numeric operand is unknown or division by zero' : undefined, variable);
|
|
458
519
|
return;
|
|
459
520
|
}
|
|
460
521
|
if (key === 'set_country_flag' ||
|
|
@@ -77,13 +77,28 @@ export function selectMechanicSource(snapshot, selector) {
|
|
|
77
77
|
}
|
|
78
78
|
export function scriptedEffectSources(snapshot) {
|
|
79
79
|
const result = new Map();
|
|
80
|
+
const symbolsByPath = new Map();
|
|
80
81
|
for (const symbol of snapshot.index.symbols) {
|
|
81
82
|
if (symbol.kind !== 'scripted_effect' || symbol.overridden || symbol.sourceShadowed)
|
|
82
83
|
continue;
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
84
|
+
const symbols = symbolsByPath.get(symbol.path) ?? [];
|
|
85
|
+
symbols.push(symbol);
|
|
86
|
+
symbolsByPath.set(symbol.path, symbols);
|
|
87
|
+
}
|
|
88
|
+
for (const [sourcePath, symbols] of symbolsByPath) {
|
|
89
|
+
const document = activeDocument(snapshot, sourcePath);
|
|
90
|
+
if (document === undefined)
|
|
91
|
+
continue;
|
|
92
|
+
const blocks = new Map();
|
|
93
|
+
for (const definition of assignments(document.root)) {
|
|
94
|
+
if (definition.value.type === 'block' && !blocks.has(definition.key.value))
|
|
95
|
+
blocks.set(definition.key.value, definition.value);
|
|
96
|
+
}
|
|
97
|
+
for (const symbol of symbols) {
|
|
98
|
+
const block = blocks.get(symbol.id);
|
|
99
|
+
if (block !== undefined)
|
|
100
|
+
result.set(symbol.id, { id: symbol.id, path: symbol.path, block });
|
|
101
|
+
}
|
|
87
102
|
}
|
|
88
103
|
return result;
|
|
89
104
|
}
|
|
@@ -58,6 +58,34 @@ export function technologyValidation(graph) {
|
|
|
58
58
|
],
|
|
59
59
|
};
|
|
60
60
|
}
|
|
61
|
+
export function technologyRenderValidation(graph, render) {
|
|
62
|
+
const omitted = render.omittedNodeCount;
|
|
63
|
+
const unresolvedSprites = render.unresolvedIconSprites.length;
|
|
64
|
+
const sourcePlacementPassed = render.view !== 'folder' || render.sourceAccurate;
|
|
65
|
+
const analysisBoundaryPassed = graph.complete || (graph.analysisMode === 'focused' && graph.skippedSourceCount === 0);
|
|
66
|
+
const renderPassed = sourcePlacementPassed && omitted === 0 && unresolvedSprites === 0;
|
|
67
|
+
return {
|
|
68
|
+
passed: renderPassed && analysisBoundaryPassed,
|
|
69
|
+
checks: [
|
|
70
|
+
{
|
|
71
|
+
id: 'technology-render',
|
|
72
|
+
passed: renderPassed,
|
|
73
|
+
message: renderPassed
|
|
74
|
+
? 'The requested technology view rendered with complete node and sprite coverage'
|
|
75
|
+
: `${sourcePlacementPassed ? 0 : 1} source-placement failure(s), ${omitted} omitted node(s), and ${unresolvedSprites} unresolved sprite(s) affect the requested technology view`,
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
id: 'technology-analysis-boundary',
|
|
79
|
+
passed: analysisBoundaryPassed,
|
|
80
|
+
message: graph.complete
|
|
81
|
+
? 'The supporting technology analysis is complete'
|
|
82
|
+
: analysisBoundaryPassed
|
|
83
|
+
? 'Whole-workspace helper projections were deferred; the requested render retains direct source evidence'
|
|
84
|
+
: `${graph.skippedSourceCount} technology source(s) were skipped; linked evidence records the partial analysis boundary`,
|
|
85
|
+
},
|
|
86
|
+
],
|
|
87
|
+
};
|
|
88
|
+
}
|
|
61
89
|
export async function inspectTechnologies(viewer, input) {
|
|
62
90
|
const output = await viewer.analyze(input);
|
|
63
91
|
const result = emptyServiceResult(input.workspaceId, {
|
|
@@ -93,7 +121,7 @@ export async function renderTechnologies(viewer, input) {
|
|
|
93
121
|
result.code = output.graph.complete ? 'TECH_RENDERED' : 'TECH_RENDERED_PARTIAL';
|
|
94
122
|
setInlineFilesScanned(result, output.graph.filesScanned);
|
|
95
123
|
result.artifacts = output.artifacts.map(publicArtifactLink);
|
|
96
|
-
result.validation =
|
|
124
|
+
result.validation = technologyRenderValidation(output.graph, output.render);
|
|
97
125
|
return result;
|
|
98
126
|
}
|
|
99
127
|
export async function compareTechnologies(viewer, input) {
|
|
@@ -72,9 +72,10 @@ function technologyNode(graph, technologyId, placement) {
|
|
|
72
72
|
subTechnologies: technology.subTechnologies.map((id, index) => {
|
|
73
73
|
const definition = graph.technologies.find((candidate) => candidate.id === id);
|
|
74
74
|
const slot = itemLayout?.subTechnologySlots?.find((candidate) => candidate.index === index);
|
|
75
|
+
const iconSprite = slot?.sprite ?? definition?.icon.sprite;
|
|
75
76
|
return {
|
|
76
77
|
id,
|
|
77
|
-
...(
|
|
78
|
+
...(iconSprite === undefined ? {} : { iconSprite }),
|
|
78
79
|
placementStatus: slot === undefined ? 'missing_source_slot' : 'source_slot',
|
|
79
80
|
...(slot === undefined ? {} : { slot }),
|
|
80
81
|
};
|
|
@@ -487,6 +487,7 @@ export class TechnologyTreeViewer {
|
|
|
487
487
|
});
|
|
488
488
|
const guiSprites = [
|
|
489
489
|
...preliminary.itemLayouts.flatMap(({ designTeamIcon }) => designTeamIcon === undefined ? [] : [designTeamIcon.sprite]),
|
|
490
|
+
...preliminary.itemLayouts.flatMap(({ subTechnologySlots }) => (subTechnologySlots ?? []).flatMap(({ sprite }) => (sprite === undefined ? [] : [sprite]))),
|
|
490
491
|
...preliminary.itemLayouts.flatMap(({ backgroundSprite }) => backgroundSprite === undefined
|
|
491
492
|
? []
|
|
492
493
|
: [
|
|
@@ -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 = '3.4.
|
|
3
|
+
export const PACKAGE_VERSION = '3.4.1';
|
|
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/events.md
CHANGED
|
@@ -19,7 +19,7 @@ Use the three event tools directly from the target mod.
|
|
|
19
19
|
|
|
20
20
|
Use narrow identifiers, direction, and depth limits when the task concerns one chain.
|
|
21
21
|
Broad scans build the structural event graph without expanding every scripted helper into duplicate paths.
|
|
22
|
-
Focused trace, path, and selector-based inventory requests may defer workspace-wide helper projections and lifecycle passes
|
|
22
|
+
Focused trace, path, and selector-based inventory requests may defer workspace-wide helper projections and lifecycle passes. When every event source was scanned and no blocking diagnostics remain, validation accepts the requested direct-source evidence while the linked artifacts continue to record that deferred boundary.
|
|
23
23
|
Focused trace and path calls collapse only the selected bounded route.
|
|
24
24
|
For a large helper closure, use [bounded helper expansion](helper-expansion.md) to receive resumable pages without first materializing every projection.
|
|
25
25
|
|
package/docs/gui.md
CHANGED
|
@@ -51,6 +51,7 @@ The scene records the selected shader source, hash and entry point.
|
|
|
51
51
|
Additional shader operations, including animated end-cap sampling, remain explicit unsupported findings rather than accepted pixel-parity evidence.
|
|
52
52
|
|
|
53
53
|
Container scrollbars use referenced or inline `extendedScrollbarType` templates, including their backgrounds, inline track, thumb and end-button artwork.
|
|
54
|
+
The template's slider and end-button roles are engine-owned compound controls, so scripted click-effect checks apply to authored source buttons and explicitly referenced role names rather than requiring effects for the native scrollbar internals.
|
|
54
55
|
Each attachment has independent instance IDs and source provenance even when multiple containers reuse one template.
|
|
55
56
|
The renderer measures direct content bounds and populated grid/list rows, retaining declared list bounds as a minimum, clamps scroll offsets, and applies `autohide_scrollbars`.
|
|
56
57
|
A nested container contributes its declared bounds rather than the overflowing artwork of its descendants.
|
package/docs/jobs.md
CHANGED
|
@@ -57,6 +57,7 @@ Event and technology helper expansion also saves an authenticated intermediate f
|
|
|
57
57
|
A replacement validates the saved paths, adjacency cursor, graph identity, and checkpoint bytes before continuing.
|
|
58
58
|
Source changes before intermediate-frontier recovery cause a fresh analysis of the current revision; old and new graph evidence are never combined.
|
|
59
59
|
An active host allows at most two replacement attempts after proven worker death, and never retries the same unchanged frontier twice.
|
|
60
|
+
If another bounded host has already claimed an interrupted job, the initiating host follows that live replacement until it publishes a terminal outcome; it does not expose the replacement's intermediate `running` record as the synchronous result.
|
|
60
61
|
Checkpoint recovery never overrides cancellation or live/unverifiable ownership, and never replays a rewrite.
|
|
61
62
|
Event and technology scan artifacts retain revision-addressed graphs for later comparisons, and bounded responses state their requested depth, node, edge, render, helper-expansion, or candidate coverage.
|
|
62
63
|
Their opt-in `helper_expansion` mode also returns [bounded continuation pages](helper-expansion.md) through both ordinary calls and persistent jobs.
|
package/docs/mechanics.md
CHANGED
|
@@ -41,7 +41,8 @@ An `advance_days` step only expires modeled timed flags; it never runs on action
|
|
|
41
41
|
|
|
42
42
|
The linked trace records applied, skipped, and unresolved source operations with before and after values.
|
|
43
43
|
The `single_payment` assertion checks the named balance's final change and the number and size of its traced deductions, so a compensating grant cannot hide a second charge.
|
|
44
|
-
Supported operations include documented variable arithmetic, flags, event targets, arrays, conditionals, finite declared scope iteration, scripted helpers, safe meta substitutions, and selected balance effects.
|
|
44
|
+
Supported operations include documented persistent and unscoped temporary-variable arithmetic, exact `has_variable` presence checks, flags, event targets, arrays, conditionals, finite declared scope iteration, scripted helpers, safe meta substitutions, and selected balance effects.
|
|
45
|
+
Active scripted-effect documents are parsed once per source file and their helper blocks share that bounded source model.
|
|
45
46
|
Decision engine political-power costs are applied once before `complete_effect`; custom cost triggers check affordability and their payment remains in `complete_effect`.
|
|
46
47
|
Unresolved eligibility, unsupported effects, dynamic names that cannot be resolved, missing finite scope catalogs, and bounded-work limits remain unresolved rather than guessed.
|
|
47
48
|
An effect with an unknown write set conservatively makes state assertions unresolved.
|
package/docs/technology.md
CHANGED
|
@@ -56,10 +56,14 @@ It preserves separate conditional call sites and identifies source, cycle, and d
|
|
|
56
56
|
|
|
57
57
|
`hoi4.tech_render` returns authoritative JSON with deterministic SVG and PNG resources; set `includeHtml` when a bundled static report is useful. Folder renders read the actual `techtree_<folder>_item` and `techtree_<folder>_small_item` geometry, choose the small item for technologies that do not unlock equipment or explicitly force it, and place the source GUI's year labels. Available views are `summary`, `folder`, `dependencies`, `technology`, `doctrine`, `exclusive`, `memberships`, `bonuses`, `grants`, `unlocks`, `metadata`, `assets`, and `unresolved`.
|
|
58
58
|
|
|
59
|
-
Folder renders use folder assignments, gridbox geometry, technology coordinates, and item dimensions found in source. File-local `@` constants in technology coordinates are resolved before placement. A technology with multiple prerequisite roots can use its own declared gridbox. The item template supplies its unavailable, available, or researched skin, icon center, name position, and design-team icon position when the corresponding sprites resolve. `sub_technology_slot_<index>` geometry
|
|
59
|
+
Folder renders use folder assignments, gridbox geometry, technology coordinates, and item dimensions found in source. File-local `@` constants in technology coordinates are resolved before placement. A technology with multiple prerequisite roots can use its own declared gridbox. The item template supplies its unavailable, available, or researched skin, icon center, name position, and design-team icon position when the corresponding sprites resolve. `sub_technology_slot_<index>` geometry and its source `picture` sprite position each declared subtechnology icon; the technology-id icon is a fallback when the slot does not declare art, and a missing slot stays visible as unresolved placement metadata. The folder's tiled panel sprite fills the canvas, and source `*_techtree_bg` sprites render behind technology nodes at their declared GUI positions; when the GUI omits a sprite size, the decoded dimensions supply it. Year labels retain their source font, box dimensions, alignment, orientation, and colour declarations in the graph. Sprite declarations and texture files resolve through the active load order across the mod, configured dependencies, and the detected or configured game installation. The authoritative JSON and SVG expose `layoutSize`, rendered sprite coverage, and unresolved sprite names without embedding image data in JSON. `sourceAccurate` describes source pixel placement only; it is not a percentage of visual agreement with a game screenshot. The game may change the visibility of design-team icons and status corners at runtime. Dependency and other semantic views are labelled as generated analysis layouts.
|
|
60
60
|
|
|
61
61
|
A `small` 72-pixel item can still display its source `GFX_*_medium` artwork at full card size; the layout name does not select smaller icon art.
|
|
62
62
|
|
|
63
|
+
Render validation is scoped to the requested view: folder source placement, omitted nodes, and unresolved sprites determine whether that render passes. Graph-wide semantic diagnostics remain available through technology inspection and do not falsely invalidate an otherwise complete source-backed folder render. Deferred whole-workspace helper projection remains an explicit analysis boundary and does not by itself invalidate a complete direct-source render.
|
|
64
|
+
|
|
65
|
+
Subtechnology cards use the sprite declared by their source GUI slot before any technology-id fallback. Slot-declared textures are included in the bounded asset scan even when no ordinary technology icon references the same file.
|
|
66
|
+
|
|
63
67
|
Example folder render:
|
|
64
68
|
|
|
65
69
|
```json
|
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": "3.4.
|
|
4
|
+
"version": "3.4.1",
|
|
5
5
|
"description": "Analyze HOI4 events, decisions, impact, tech, AI, 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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/decision-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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/helper-expansion-request.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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/helper-expansion-summary.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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/impact-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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/mechanic-test-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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/package-check-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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/package-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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/probability-sweep-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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/scenario-suite.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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/scenario-test-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/v3.4.
|
|
2
|
+
"$id": "https://github.com/klimPaskov/hoi4-agent-tools/blob/v3.4.1/schemas/shared-scenario.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, decisions, impact, tech, AI, and MTTH; build focus trees, GUIs, and maps.",
|
|
6
|
-
"version": "3.4.
|
|
6
|
+
"version": "3.4.1",
|
|
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": "3.4.
|
|
16
|
+
"version": "3.4.1",
|
|
17
17
|
"transport": {
|
|
18
18
|
"type": "stdio"
|
|
19
19
|
}
|