hoi4-agent-tools 3.2.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 +19 -0
- package/README.md +4 -0
- package/dist/hoi4_agent_tools/core/analysis-job-operations.js +11 -1
- package/dist/hoi4_agent_tools/core/condition-evaluator.js +18 -9
- package/dist/hoi4_agent_tools/core/helper-expansion.js +3 -0
- package/dist/hoi4_agent_tools/core/job-worker-host.js +3 -0
- package/dist/hoi4_agent_tools/core/operation-tasks.js +7 -0
- package/dist/hoi4_agent_tools/core/scenario-model.js +85 -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/scenario-conditions.js +2 -23
- 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/server/instructions.js +1 -1
- package/dist/hoi4_agent_tools/mcp/server/request-lifecycle.js +3 -0
- package/dist/hoi4_agent_tools/mcp/tools/analysis.js +90 -0
- 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/mechanic/assertions.js +112 -0
- package/dist/hoi4_agent_tools/mechanic/interpreter.js +619 -0
- package/dist/hoi4_agent_tools/mechanic/service.js +145 -0
- package/dist/hoi4_agent_tools/mechanic/source.js +89 -0
- package/dist/hoi4_agent_tools/package-check/service.js +231 -0
- package/dist/hoi4_agent_tools/probability/evaluation.js +6 -1
- 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/scenario-suite/service.js +341 -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/scenarios.js +264 -0
- 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/README.md +1 -0
- 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/mechanics.md +70 -0
- package/docs/probability.md +3 -1
- package/docs/technology.md +7 -2
- package/package.json +2 -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 +650 -0
- package/schemas/operation-result.schema.json +1 -1
- package/schemas/package-check-input.schema.json +164 -0
- package/schemas/package-manifest.schema.json +142 -0
- 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 +1004 -0
- package/schemas/scenario-test-input.schema.json +1057 -0
- package/schemas/shared-scenario.schema.json +237 -0
- package/server.json +2 -2
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
import { declaredConditionScenarioSchema } from './analysis.js';
|
|
3
|
+
import { workspaceIdSchema, workspaceRelativePathSchema } from './common.js';
|
|
4
|
+
const identifier = z.string().min(1).max(512);
|
|
5
|
+
const manifestToken = z.string().regex(/^[A-Za-z0-9_.:-]{1,512}$/u);
|
|
6
|
+
const sourceSelector = z
|
|
7
|
+
.object({
|
|
8
|
+
kind: z.enum(['scripted_effect', 'event_option', 'decision', 'focus_reward']),
|
|
9
|
+
id: identifier,
|
|
10
|
+
option: identifier.optional(),
|
|
11
|
+
})
|
|
12
|
+
.strict();
|
|
13
|
+
export const sharedScenarioSchema = declaredConditionScenarioSchema.safeExtend({
|
|
14
|
+
schemaVersion: z.literal('1.0'),
|
|
15
|
+
globalFlags: z.array(identifier).max(10_000).optional(),
|
|
16
|
+
scopeCatalogs: z
|
|
17
|
+
.record(identifier, z
|
|
18
|
+
.object({
|
|
19
|
+
complete: z.boolean(),
|
|
20
|
+
members: z.array(identifier).max(2_048),
|
|
21
|
+
})
|
|
22
|
+
.strict())
|
|
23
|
+
.optional(),
|
|
24
|
+
});
|
|
25
|
+
const assertionPath = z
|
|
26
|
+
.object({
|
|
27
|
+
scope: identifier.default('ROOT'),
|
|
28
|
+
key: identifier,
|
|
29
|
+
})
|
|
30
|
+
.strict();
|
|
31
|
+
const scalar = z.union([z.string().max(4_096), z.number(), z.boolean(), z.null()]);
|
|
32
|
+
export const mechanicAssertionSchema = z.discriminatedUnion('kind', [
|
|
33
|
+
z
|
|
34
|
+
.object({ id: identifier, kind: z.literal('equals'), path: assertionPath, expected: scalar })
|
|
35
|
+
.strict(),
|
|
36
|
+
z
|
|
37
|
+
.object({
|
|
38
|
+
id: identifier,
|
|
39
|
+
kind: z.literal('conservation'),
|
|
40
|
+
paths: z.array(assertionPath).min(2).max(64),
|
|
41
|
+
tolerance: z.number().nonnegative().default(0),
|
|
42
|
+
})
|
|
43
|
+
.strict(),
|
|
44
|
+
z
|
|
45
|
+
.object({
|
|
46
|
+
id: identifier,
|
|
47
|
+
kind: z.literal('array_alignment'),
|
|
48
|
+
paths: z.array(assertionPath).min(2).max(32),
|
|
49
|
+
})
|
|
50
|
+
.strict(),
|
|
51
|
+
z
|
|
52
|
+
.object({
|
|
53
|
+
id: identifier,
|
|
54
|
+
kind: z.literal('affordability'),
|
|
55
|
+
balance: assertionPath,
|
|
56
|
+
cost: z.number().nonnegative(),
|
|
57
|
+
})
|
|
58
|
+
.strict(),
|
|
59
|
+
z
|
|
60
|
+
.object({
|
|
61
|
+
id: identifier,
|
|
62
|
+
kind: z.literal('single_payment'),
|
|
63
|
+
balance: assertionPath,
|
|
64
|
+
cost: z.number().nonnegative(),
|
|
65
|
+
})
|
|
66
|
+
.strict(),
|
|
67
|
+
z
|
|
68
|
+
.object({
|
|
69
|
+
id: identifier,
|
|
70
|
+
kind: z.literal('repeated_setup'),
|
|
71
|
+
firstStep: z.number().int().nonnegative(),
|
|
72
|
+
secondStep: z.number().int().nonnegative(),
|
|
73
|
+
})
|
|
74
|
+
.strict(),
|
|
75
|
+
z
|
|
76
|
+
.object({
|
|
77
|
+
id: identifier,
|
|
78
|
+
kind: z.literal('exclusive_flags'),
|
|
79
|
+
scope: identifier.default('ROOT'),
|
|
80
|
+
flags: z.array(identifier).min(2).max(64),
|
|
81
|
+
})
|
|
82
|
+
.strict(),
|
|
83
|
+
z
|
|
84
|
+
.object({
|
|
85
|
+
id: identifier,
|
|
86
|
+
kind: z.literal('cleanup'),
|
|
87
|
+
scope: identifier.default('ROOT'),
|
|
88
|
+
flags: z.array(identifier).max(64).default([]),
|
|
89
|
+
targets: z.array(identifier).max(64).default([]),
|
|
90
|
+
})
|
|
91
|
+
.strict(),
|
|
92
|
+
z
|
|
93
|
+
.object({ id: identifier, kind: z.literal('end_state'), path: assertionPath, expected: scalar })
|
|
94
|
+
.strict(),
|
|
95
|
+
]);
|
|
96
|
+
export const mechanicCaseSchema = z
|
|
97
|
+
.object({
|
|
98
|
+
id: identifier,
|
|
99
|
+
scenario: sharedScenarioSchema,
|
|
100
|
+
steps: z
|
|
101
|
+
.array(z.discriminatedUnion('kind', [
|
|
102
|
+
z
|
|
103
|
+
.object({
|
|
104
|
+
kind: z.literal('effect'),
|
|
105
|
+
source: sourceSelector,
|
|
106
|
+
repeat: z.number().int().min(1).max(8).default(1),
|
|
107
|
+
})
|
|
108
|
+
.strict(),
|
|
109
|
+
z
|
|
110
|
+
.object({ kind: z.literal('advance_days'), days: z.number().int().min(0).max(36_500) })
|
|
111
|
+
.strict(),
|
|
112
|
+
]))
|
|
113
|
+
.min(1)
|
|
114
|
+
.max(128),
|
|
115
|
+
assertions: z.array(mechanicAssertionSchema).min(1).max(256),
|
|
116
|
+
})
|
|
117
|
+
.strict();
|
|
118
|
+
export const mechanicTestRequestSchema = z
|
|
119
|
+
.object({
|
|
120
|
+
workspaceId: workspaceIdSchema,
|
|
121
|
+
test: mechanicCaseSchema,
|
|
122
|
+
expectedRevision: z
|
|
123
|
+
.string()
|
|
124
|
+
.regex(/^[a-f0-9]{64}$/u)
|
|
125
|
+
.optional(),
|
|
126
|
+
refresh: z.boolean().default(false),
|
|
127
|
+
})
|
|
128
|
+
.strict();
|
|
129
|
+
const manifestItem = z.object({ kind: manifestToken, id: manifestToken }).strict();
|
|
130
|
+
export const packageManifestSchema = z
|
|
131
|
+
.object({
|
|
132
|
+
schemaVersion: z.literal('1.0'),
|
|
133
|
+
id: manifestToken,
|
|
134
|
+
definitions: z.array(manifestItem).max(2_048).default([]),
|
|
135
|
+
calls: z
|
|
136
|
+
.array(z.object({ from: manifestItem, to: manifestItem }).strict())
|
|
137
|
+
.max(2_048)
|
|
138
|
+
.default([]),
|
|
139
|
+
registrations: z
|
|
140
|
+
.array(z.object({ path: workspaceRelativePathSchema, token: manifestToken }).strict())
|
|
141
|
+
.max(2_048)
|
|
142
|
+
.default([]),
|
|
143
|
+
localisation: z.array(manifestToken).max(2_048).default([]),
|
|
144
|
+
assets: z.array(workspaceRelativePathSchema).max(2_048).default([]),
|
|
145
|
+
requiredCases: z
|
|
146
|
+
.array(z.object({ suite: workspaceRelativePathSchema, caseId: manifestToken }).strict())
|
|
147
|
+
.max(512)
|
|
148
|
+
.default([]),
|
|
149
|
+
})
|
|
150
|
+
.strict();
|
|
151
|
+
export const packageCheckRequestSchema = z
|
|
152
|
+
.object({
|
|
153
|
+
workspaceId: workspaceIdSchema,
|
|
154
|
+
manifest: packageManifestSchema,
|
|
155
|
+
expectedRevision: z
|
|
156
|
+
.string()
|
|
157
|
+
.regex(/^[a-f0-9]{64}$/u)
|
|
158
|
+
.optional(),
|
|
159
|
+
refresh: z.boolean().default(false),
|
|
160
|
+
})
|
|
161
|
+
.strict();
|
|
162
|
+
const readOnlySuiteTool = z.enum([
|
|
163
|
+
'hoi4.impact_inspect',
|
|
164
|
+
'hoi4.decision_inspect',
|
|
165
|
+
'hoi4.event_inspect',
|
|
166
|
+
'hoi4.event_render',
|
|
167
|
+
'hoi4.tech_inspect',
|
|
168
|
+
'hoi4.tech_render',
|
|
169
|
+
'hoi4.probability_inspect',
|
|
170
|
+
'hoi4.probability_evaluate',
|
|
171
|
+
'hoi4.probability_render',
|
|
172
|
+
'hoi4.focus_inspect',
|
|
173
|
+
'hoi4.focus_render',
|
|
174
|
+
'hoi4.gui_inspect',
|
|
175
|
+
'hoi4.gui_render',
|
|
176
|
+
'hoi4.map_inspect',
|
|
177
|
+
'hoi4.map_render',
|
|
178
|
+
]);
|
|
179
|
+
const suiteCaseMetadata = {
|
|
180
|
+
sourceSelectors: z.array(manifestItem).max(64).default([]),
|
|
181
|
+
assertions: z
|
|
182
|
+
.array(z
|
|
183
|
+
.object({
|
|
184
|
+
id: identifier,
|
|
185
|
+
path: z.array(identifier).min(1).max(16),
|
|
186
|
+
expected: scalar,
|
|
187
|
+
})
|
|
188
|
+
.strict())
|
|
189
|
+
.max(64)
|
|
190
|
+
.default([]),
|
|
191
|
+
views: z
|
|
192
|
+
.array(z.enum(['summary', 'artifacts', 'diagnostics']))
|
|
193
|
+
.max(3)
|
|
194
|
+
.default(['summary']),
|
|
195
|
+
};
|
|
196
|
+
export const scenarioSuiteSchema = z
|
|
197
|
+
.object({
|
|
198
|
+
schemaVersion: z.literal('1.0'),
|
|
199
|
+
id: identifier,
|
|
200
|
+
cases: z
|
|
201
|
+
.array(z.discriminatedUnion('domain', [
|
|
202
|
+
z
|
|
203
|
+
.object({
|
|
204
|
+
domain: z.literal('mechanic'),
|
|
205
|
+
id: identifier,
|
|
206
|
+
test: mechanicCaseSchema,
|
|
207
|
+
...suiteCaseMetadata,
|
|
208
|
+
})
|
|
209
|
+
.strict(),
|
|
210
|
+
z
|
|
211
|
+
.object({
|
|
212
|
+
domain: z.literal('package'),
|
|
213
|
+
id: identifier,
|
|
214
|
+
manifest: packageManifestSchema,
|
|
215
|
+
...suiteCaseMetadata,
|
|
216
|
+
})
|
|
217
|
+
.strict(),
|
|
218
|
+
z
|
|
219
|
+
.object({
|
|
220
|
+
domain: z.literal('tool'),
|
|
221
|
+
id: identifier,
|
|
222
|
+
tool: readOnlySuiteTool,
|
|
223
|
+
arguments: z.record(z.string().max(256), z.json()),
|
|
224
|
+
...suiteCaseMetadata,
|
|
225
|
+
})
|
|
226
|
+
.strict(),
|
|
227
|
+
]))
|
|
228
|
+
.min(1)
|
|
229
|
+
.max(10_000),
|
|
230
|
+
})
|
|
231
|
+
.strict()
|
|
232
|
+
.superRefine((suite, context) => {
|
|
233
|
+
const ids = new Set();
|
|
234
|
+
for (const [index, item] of suite.cases.entries()) {
|
|
235
|
+
if (ids.has(item.id))
|
|
236
|
+
context.addIssue({
|
|
237
|
+
code: 'custom',
|
|
238
|
+
path: ['cases', index, 'id'],
|
|
239
|
+
message: 'Suite case ids must be unique',
|
|
240
|
+
});
|
|
241
|
+
ids.add(item.id);
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
export const scenarioTestRequestSchema = z
|
|
245
|
+
.object({
|
|
246
|
+
workspaceId: workspaceIdSchema,
|
|
247
|
+
suite: scenarioSuiteSchema.optional(),
|
|
248
|
+
suitePath: workspaceRelativePathSchema.optional(),
|
|
249
|
+
continuation: z.string().max(4_096).optional(),
|
|
250
|
+
maxCases: z.number().int().min(1).max(256).default(32),
|
|
251
|
+
expectedRevision: z
|
|
252
|
+
.string()
|
|
253
|
+
.regex(/^[a-f0-9]{64}$/u)
|
|
254
|
+
.optional(),
|
|
255
|
+
refresh: z.boolean().default(false),
|
|
256
|
+
})
|
|
257
|
+
.strict()
|
|
258
|
+
.superRefine((input, context) => {
|
|
259
|
+
if ((input.suite === undefined) === (input.suitePath === undefined))
|
|
260
|
+
context.addIssue({
|
|
261
|
+
code: 'custom',
|
|
262
|
+
message: 'Specify exactly one inline suite or suitePath',
|
|
263
|
+
});
|
|
264
|
+
});
|
|
@@ -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,
|