hoi4-agent-tools 3.3.0 → 3.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.
- package/CHANGELOG.md +12 -0
- package/dist/hoi4_agent_tools/core/condition-evaluator.js +13 -8
- package/dist/hoi4_agent_tools/core/helper-expansion.js +3 -0
- package/dist/hoi4_agent_tools/event/comparison-selection.js +78 -0
- package/dist/hoi4_agent_tools/event/helper-expansion.js +48 -0
- package/dist/hoi4_agent_tools/event/operations.js +16 -0
- package/dist/hoi4_agent_tools/event/service.js +21 -2
- package/dist/hoi4_agent_tools/focus/compact.js +241 -27
- package/dist/hoi4_agent_tools/focus/layout.js +119 -8
- package/dist/hoi4_agent_tools/focus/render.js +62 -0
- package/dist/hoi4_agent_tools/focus/scenario.js +99 -0
- package/dist/hoi4_agent_tools/focus/tool-operations.js +30 -4
- package/dist/hoi4_agent_tools/gui/assets.js +54 -4
- package/dist/hoi4_agent_tools/gui/layout.js +935 -104
- package/dist/hoi4_agent_tools/gui/renderer.js +47 -17
- package/dist/hoi4_agent_tools/gui/shader.js +515 -0
- package/dist/hoi4_agent_tools/gui/source-graph.js +166 -6
- package/dist/hoi4_agent_tools/gui/studio.js +245 -19
- package/dist/hoi4_agent_tools/gui/tool-operations.js +9 -0
- package/dist/hoi4_agent_tools/gui/validators.js +38 -12
- package/dist/hoi4_agent_tools/map/operations.js +70 -1
- package/dist/hoi4_agent_tools/map/render.js +70 -1
- package/dist/hoi4_agent_tools/map/service.js +30 -6
- package/dist/hoi4_agent_tools/map/tool-operations.js +67 -1
- package/dist/hoi4_agent_tools/mcp/tools/event.js +10 -1
- package/dist/hoi4_agent_tools/mcp/tools/focus.js +14 -4
- package/dist/hoi4_agent_tools/mcp/tools/gui.js +5 -1
- package/dist/hoi4_agent_tools/mcp/tools/map.js +12 -2
- package/dist/hoi4_agent_tools/mcp/tools/probability.js +5 -0
- package/dist/hoi4_agent_tools/probability/evaluation.js +3 -0
- package/dist/hoi4_agent_tools/probability/operations.js +8 -0
- package/dist/hoi4_agent_tools/probability/service.js +33 -12
- package/dist/hoi4_agent_tools/probability/source-analysis.js +1 -0
- package/dist/hoi4_agent_tools/schemas/event.js +8 -0
- package/dist/hoi4_agent_tools/schemas/focus-requests.js +40 -1
- package/dist/hoi4_agent_tools/schemas/gui-requests.js +8 -0
- package/dist/hoi4_agent_tools/schemas/map-requests.js +22 -1
- package/dist/hoi4_agent_tools/schemas/technology.js +7 -0
- package/dist/hoi4_agent_tools/technology/graph.js +25 -10
- package/dist/hoi4_agent_tools/technology/render.js +286 -31
- package/dist/hoi4_agent_tools/technology/service.js +55 -8
- package/dist/hoi4_agent_tools/technology/source-analysis.js +166 -3
- package/dist/hoi4_agent_tools/version.js +1 -1
- package/docs/events.md +3 -1
- package/docs/focus.md +10 -0
- package/docs/gui.md +49 -3
- package/docs/map.md +8 -0
- package/docs/probability.md +3 -1
- package/docs/technology.md +7 -2
- 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
|
@@ -17,6 +17,10 @@ export const focusInspectRequestSchema = z
|
|
|
17
17
|
previous: compactFocusLayoutSchema.optional(),
|
|
18
18
|
laneSpacing: z.number().int().min(1).max(100).optional(),
|
|
19
19
|
nodeSpacing: z.number().int().min(1).max(100).optional(),
|
|
20
|
+
scenario: z
|
|
21
|
+
.object({ completedFocusIds: z.array(z.string().min(1).max(256)).max(10_000) })
|
|
22
|
+
.strict()
|
|
23
|
+
.optional(),
|
|
20
24
|
})
|
|
21
25
|
.strict()
|
|
22
26
|
.superRefine((value, context) => {
|
|
@@ -34,7 +38,7 @@ export const focusInspectRequestSchema = z
|
|
|
34
38
|
message: 'treeId is only valid in national mode',
|
|
35
39
|
});
|
|
36
40
|
if (mode === 'continuous') {
|
|
37
|
-
for (const field of ['previous', 'laneSpacing', 'nodeSpacing']) {
|
|
41
|
+
for (const field of ['previous', 'laneSpacing', 'nodeSpacing', 'scenario']) {
|
|
38
42
|
if (value[field] !== undefined)
|
|
39
43
|
context.addIssue({
|
|
40
44
|
code: 'custom',
|
|
@@ -49,6 +53,12 @@ export const focusInspectRequestSchema = z
|
|
|
49
53
|
path: ['previous'],
|
|
50
54
|
message: 'previous requires treeId so it applies to exactly one tree',
|
|
51
55
|
});
|
|
56
|
+
if (value.scenario !== undefined && value.treeId === undefined)
|
|
57
|
+
context.addIssue({
|
|
58
|
+
code: 'custom',
|
|
59
|
+
path: ['scenario'],
|
|
60
|
+
message: 'scenario requires treeId so it applies to exactly one tree',
|
|
61
|
+
});
|
|
52
62
|
});
|
|
53
63
|
export const focusRenderRequestSchema = z
|
|
54
64
|
.object({
|
|
@@ -64,6 +74,7 @@ export const focusRenderRequestSchema = z
|
|
|
64
74
|
.min(FOCUS_RENDER_MIN_OUTPUT_SCALE)
|
|
65
75
|
.max(FOCUS_RENDER_MAX_OUTPUT_SCALE)
|
|
66
76
|
.optional(),
|
|
77
|
+
cropFocusIds: z.array(z.string().min(1).max(256)).max(16).optional(),
|
|
67
78
|
columns: z.number().int().min(1).max(12).optional(),
|
|
68
79
|
padding: z.number().int().min(0).max(1000).optional(),
|
|
69
80
|
})
|
|
@@ -80,6 +91,7 @@ export const focusRenderRequestSchema = z
|
|
|
80
91
|
['horizontalSpacing', value.horizontalSpacing],
|
|
81
92
|
['verticalSpacing', value.verticalSpacing],
|
|
82
93
|
['reviewScale', value.reviewScale],
|
|
94
|
+
['cropFocusIds', value.cropFocusIds],
|
|
83
95
|
];
|
|
84
96
|
for (const [field, fieldValue] of invalid) {
|
|
85
97
|
if (fieldValue !== undefined)
|
|
@@ -103,6 +115,25 @@ export const focusRewriteRequestSchema = z
|
|
|
103
115
|
relativePath: workspaceRelativePathSchema,
|
|
104
116
|
treeId: z.string().min(1).max(256).optional(),
|
|
105
117
|
layoutMode: z.enum(['authored', 'compact']).default('authored'),
|
|
118
|
+
compactFocusIds: z.array(z.string().min(1).max(256)).min(1).max(10_000).optional(),
|
|
119
|
+
pinnedFocusIds: z.array(z.string().min(1).max(256)).max(10_000).optional(),
|
|
120
|
+
symmetryGroups: z
|
|
121
|
+
.array(z
|
|
122
|
+
.object({
|
|
123
|
+
centerFocusId: z.string().min(1).max(256),
|
|
124
|
+
pairs: z
|
|
125
|
+
.array(z
|
|
126
|
+
.object({
|
|
127
|
+
leftFocusId: z.string().min(1).max(256),
|
|
128
|
+
rightFocusId: z.string().min(1).max(256),
|
|
129
|
+
})
|
|
130
|
+
.strict())
|
|
131
|
+
.min(1)
|
|
132
|
+
.max(10_000),
|
|
133
|
+
})
|
|
134
|
+
.strict())
|
|
135
|
+
.max(64)
|
|
136
|
+
.optional(),
|
|
106
137
|
plan: compactFocusPlanSchema.optional(),
|
|
107
138
|
createIfMissing: z.boolean().default(false),
|
|
108
139
|
horizontalSpacing: z.number().int().min(80).max(1000).optional(),
|
|
@@ -117,6 +148,14 @@ export const focusRewriteRequestSchema = z
|
|
|
117
148
|
})
|
|
118
149
|
.strict()
|
|
119
150
|
.superRefine((value, context) => {
|
|
151
|
+
if (value.layoutMode !== 'compact')
|
|
152
|
+
for (const field of ['compactFocusIds', 'pinnedFocusIds', 'symmetryGroups'])
|
|
153
|
+
if (value[field] !== undefined)
|
|
154
|
+
context.addIssue({
|
|
155
|
+
code: 'custom',
|
|
156
|
+
path: [field],
|
|
157
|
+
message: `${field} requires compact layout mode`,
|
|
158
|
+
});
|
|
120
159
|
const mode = value.mode ?? 'national';
|
|
121
160
|
const schema = mode === 'continuous' ? continuousFocusPaletteSchema : focusTreePlanSchema;
|
|
122
161
|
if (value.plan !== undefined && !schema.safeParse(value.plan).success)
|
|
@@ -82,6 +82,14 @@ export const guiRenderRequestSchema = z
|
|
|
82
82
|
relatedScenarios: z.array(compactGuiScenarioSchema).max(32).optional(),
|
|
83
83
|
generatedScenarios: compactGeneratedScenarioOptionsSchema.optional(),
|
|
84
84
|
comparisonScenario: compactGuiScenarioSchema.optional(),
|
|
85
|
+
sourceBaseline: z
|
|
86
|
+
.object({
|
|
87
|
+
relativePath: workspaceRelativePathSchema,
|
|
88
|
+
source: z.string().max(SOURCE_MAX_BYTES),
|
|
89
|
+
})
|
|
90
|
+
.strict()
|
|
91
|
+
.optional()
|
|
92
|
+
.describe('Previous mod-owned .gui source for a matched source comparison using the requested scenario.'),
|
|
85
93
|
})
|
|
86
94
|
.strict()
|
|
87
95
|
.superRefine(({ scenario, states, resolutions, relatedScenarios, generatedScenarios }, context) => {
|
|
@@ -63,6 +63,7 @@ export const mapInspectRequestSchema = z
|
|
|
63
63
|
]))
|
|
64
64
|
.max(100)
|
|
65
65
|
.default([]),
|
|
66
|
+
lookupOnly: z.boolean().default(false),
|
|
66
67
|
includeOverview: z.boolean().default(true),
|
|
67
68
|
allocationRequests: z.array(mapAllocationRequestSchema).max(100).default([]),
|
|
68
69
|
})
|
|
@@ -73,8 +74,28 @@ export const mapRenderRequestSchema = z
|
|
|
73
74
|
layer: mapLayerSchema.optional(),
|
|
74
75
|
overlays: z.array(mapOverlaySchema).max(12).optional(),
|
|
75
76
|
scale: z.number().int().min(1).max(16).optional(),
|
|
77
|
+
tile: z
|
|
78
|
+
.object({
|
|
79
|
+
x: z.number().int().min(0),
|
|
80
|
+
y: z.number().int().min(0),
|
|
81
|
+
width: z.number().int().min(1).max(2_048),
|
|
82
|
+
height: z.number().int().min(1).max(2_048),
|
|
83
|
+
})
|
|
84
|
+
.strict()
|
|
85
|
+
.optional(),
|
|
86
|
+
area: z
|
|
87
|
+
.object({
|
|
88
|
+
provinceIds: z.array(z.number().int().nonnegative()).max(256).optional(),
|
|
89
|
+
stateIds: z.array(z.number().int().nonnegative()).max(64).optional(),
|
|
90
|
+
regionIds: z.array(z.number().int().nonnegative()).max(64).optional(),
|
|
91
|
+
padding: z.number().int().min(0).max(256).optional(),
|
|
92
|
+
})
|
|
93
|
+
.strict()
|
|
94
|
+
.refine(({ provinceIds, stateIds, regionIds }) => (provinceIds?.length ?? 0) + (stateIds?.length ?? 0) + (regionIds?.length ?? 0) > 0, 'Map area requires at least one province, state, or region ID')
|
|
95
|
+
.optional(),
|
|
76
96
|
})
|
|
77
|
-
.strict()
|
|
97
|
+
.strict()
|
|
98
|
+
.refine(({ tile, area }) => tile === undefined || area === undefined, 'Choose tile or area, not both');
|
|
78
99
|
export const mapRewriteRequestSchema = z
|
|
79
100
|
.object({
|
|
80
101
|
workspaceId: workspaceIdSchema,
|
|
@@ -132,6 +132,13 @@ export const technologyRenderRequestSchema = z
|
|
|
132
132
|
categoryId: technologyIdSchema.optional(),
|
|
133
133
|
targetId: technologyIdSchema.optional(),
|
|
134
134
|
maxNodes: z.number().int().min(1).max(2_000).optional(),
|
|
135
|
+
scenario: z
|
|
136
|
+
.object({
|
|
137
|
+
year: z.number().int().min(1).max(9999),
|
|
138
|
+
researchedTechnologyIds: z.array(technologyIdSchema).max(25_000),
|
|
139
|
+
})
|
|
140
|
+
.strict()
|
|
141
|
+
.optional(),
|
|
135
142
|
includeHtml: z.boolean().optional(),
|
|
136
143
|
refresh: z.boolean().optional(),
|
|
137
144
|
})
|
|
@@ -11,6 +11,7 @@ const MAX_EXTERNAL_REFERENCES = 1_000_000;
|
|
|
11
11
|
const MAX_ISSUES = 100_000;
|
|
12
12
|
const MAX_HELPER_DEPTH = 64;
|
|
13
13
|
const MAX_HELPER_PROJECTIONS = 500_000;
|
|
14
|
+
const MAX_FULL_HELPER_CALLS = 4_096;
|
|
14
15
|
const confidenceRank = {
|
|
15
16
|
confirmed: 0,
|
|
16
17
|
high: 1,
|
|
@@ -188,6 +189,20 @@ function activeYearMarkers(values) {
|
|
|
188
189
|
left.year - right.year ||
|
|
189
190
|
compareCodeUnits(left.name, right.name));
|
|
190
191
|
}
|
|
192
|
+
function activeBackgrounds(values) {
|
|
193
|
+
const groups = new Map();
|
|
194
|
+
for (const background of values) {
|
|
195
|
+
const key = `${background.folderId}\0${background.name}`;
|
|
196
|
+
const group = groups.get(key) ?? [];
|
|
197
|
+
group.push(background);
|
|
198
|
+
groups.set(key, group);
|
|
199
|
+
}
|
|
200
|
+
return [...groups.values()]
|
|
201
|
+
.map((group) => group.sort((left, right) => right.loadOrder - left.loadOrder ||
|
|
202
|
+
compareCodeUnits(left.sourcePath, right.sourcePath) ||
|
|
203
|
+
left.location.start.offset - right.location.start.offset)[0])
|
|
204
|
+
.sort((left, right) => compareCodeUnits(left.folderId, right.folderId) || compareCodeUnits(left.name, right.name));
|
|
205
|
+
}
|
|
191
206
|
function enrichPlacements(placements, edges, gridboxes, technologies, unlocks, itemLayouts, signal) {
|
|
192
207
|
const technologyById = new Map(technologies.map((technology) => [technology.id, technology]));
|
|
193
208
|
const unlockKindsByTechnology = new Map();
|
|
@@ -238,11 +253,8 @@ function enrichPlacements(placements, edges, gridboxes, technologies, unlocks, i
|
|
|
238
253
|
return placements.map((placement) => {
|
|
239
254
|
const roots = rootsFor(placement.technologyId, placement.folderId);
|
|
240
255
|
const branchRootId = roots.length === 1 ? roots[0] : undefined;
|
|
241
|
-
const expectedGridbox = branchRootId
|
|
242
|
-
const candidates = expectedGridbox === undefined
|
|
243
|
-
? []
|
|
244
|
-
: gridboxes.filter(({ name, folderId }) => name === expectedGridbox &&
|
|
245
|
-
(folderId === undefined || folderId === placement.folderId));
|
|
256
|
+
const expectedGridbox = `${branchRootId ?? placement.technologyId}_tree`;
|
|
257
|
+
const candidates = gridboxes.filter(({ name, folderId }) => name === expectedGridbox && (folderId === undefined || folderId === placement.folderId));
|
|
246
258
|
const gridbox = candidates[0];
|
|
247
259
|
const technology = technologyById.get(placement.technologyId);
|
|
248
260
|
const folderLayouts = layoutsByFolder.get(placement.folderId);
|
|
@@ -1155,6 +1167,7 @@ function* technologyGraphAnalysis(snapshot, options) {
|
|
|
1155
1167
|
const gridboxes = activeGridboxes(fragments.flatMap(({ gridboxes }) => gridboxes));
|
|
1156
1168
|
const itemLayouts = activeItemLayouts(fragments.flatMap(({ itemLayouts }) => itemLayouts));
|
|
1157
1169
|
const yearMarkers = activeYearMarkers(fragments.flatMap(({ yearMarkers }) => yearMarkers));
|
|
1170
|
+
const backgrounds = activeBackgrounds(fragments.flatMap(({ backgrounds }) => backgrounds ?? []));
|
|
1158
1171
|
const categories = activeCategories(fragments.flatMap(({ categories }) => categories));
|
|
1159
1172
|
const selectedDoctrines = activeDefinitions(fragments.flatMap(({ doctrineDefinitions }) => doctrineDefinitions));
|
|
1160
1173
|
const doctrineDefinitions = localiseDoctrines(selectedDoctrines.active, snapshot.index, assets);
|
|
@@ -1168,10 +1181,11 @@ function* technologyGraphAnalysis(snapshot, options) {
|
|
|
1168
1181
|
const placements = enrichPlacements(basePlacements, edges, gridboxes, technologies, unlocks, itemLayouts, options.signal);
|
|
1169
1182
|
const unresolved = fragments.flatMap(({ unresolved }) => unresolved);
|
|
1170
1183
|
const helperCalls = fragments.flatMap(({ helperCalls }) => helperCalls);
|
|
1171
|
-
const
|
|
1184
|
+
const analysisMode = options.analysisMode ?? (helperCalls.length > MAX_FULL_HELPER_CALLS ? 'focused' : 'full');
|
|
1185
|
+
const walk = analysisMode === 'focused'
|
|
1172
1186
|
? undefined
|
|
1173
1187
|
: yield technologyHelperWalk(helperCalls, snapshot.revision);
|
|
1174
|
-
const externalReferences = expandHelperReferences(fragments.flatMap(({ externalReferences }) => externalReferences), helperCalls, unresolved,
|
|
1188
|
+
const externalReferences = expandHelperReferences(fragments.flatMap(({ externalReferences }) => externalReferences), helperCalls, unresolved, analysisMode, walk, options.signal);
|
|
1175
1189
|
const issues = diagnose(technologies, folders, placements, gridboxes, edges, categories, doctrineDefinitions, unlocks, externalReferences, selectedTechnologies.duplicates.map((group) => group.map(({ iconSprite, effectSignatureFields, ...technology }) => ({
|
|
1176
1190
|
...technology,
|
|
1177
1191
|
icon: iconStatus(iconSprite, snapshot.index, assets),
|
|
@@ -1197,14 +1211,14 @@ function* technologyGraphAnalysis(snapshot, options) {
|
|
|
1197
1211
|
const graph = {
|
|
1198
1212
|
schemaVersion: TECHNOLOGY_GRAPH_SCHEMA_VERSION,
|
|
1199
1213
|
parserVersion: TECHNOLOGY_PARSER_VERSION,
|
|
1200
|
-
analysisMode
|
|
1214
|
+
analysisMode,
|
|
1201
1215
|
workspaceId: snapshot.workspaceId,
|
|
1202
1216
|
workspaceIdentity: options.workspaceIdentity,
|
|
1203
1217
|
revision,
|
|
1204
1218
|
complete: snapshot.complete &&
|
|
1205
1219
|
unresolved.every(({ kind }) => kind !== 'partial_source') &&
|
|
1206
1220
|
!unresolved.some(({ blockers }) => blockers.some(({ code }) => code === 'TECH_HELPER_DEPTH_BLOCKED' || code === 'TECH_HELPER_PROJECTION_LIMIT')) &&
|
|
1207
|
-
!(
|
|
1221
|
+
!(analysisMode === 'focused' && helperCalls.length > 0),
|
|
1208
1222
|
analysisBoundary: {
|
|
1209
1223
|
staticAnalysis: true,
|
|
1210
1224
|
language: 'l_english',
|
|
@@ -1215,7 +1229,7 @@ function* technologyGraphAnalysis(snapshot, options) {
|
|
|
1215
1229
|
'meta-generated or variable technology identifiers',
|
|
1216
1230
|
'exact AI research choice and runtime research time',
|
|
1217
1231
|
'dynamic scripted localisation without supplied runtime values',
|
|
1218
|
-
...(
|
|
1232
|
+
...(analysisMode === 'focused' && helperCalls.length > 0
|
|
1219
1233
|
? ['large-workspace scripted-effect helper projections are deferred']
|
|
1220
1234
|
: []),
|
|
1221
1235
|
],
|
|
@@ -1235,6 +1249,7 @@ function* technologyGraphAnalysis(snapshot, options) {
|
|
|
1235
1249
|
gridboxes,
|
|
1236
1250
|
itemLayouts,
|
|
1237
1251
|
yearMarkers,
|
|
1252
|
+
backgrounds,
|
|
1238
1253
|
edges,
|
|
1239
1254
|
categories,
|
|
1240
1255
|
doctrineDefinitions,
|