hoi4-agent-tools 3.10.0 → 4.0.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 +131 -0
- package/README.md +91 -147
- package/dist/bin/http.js +10 -0
- package/dist/bin/setup.js +3 -2
- package/dist/bin/stdio.js +10 -0
- package/dist/hoi4_agent_tools/core/artifacts.js +40 -5
- package/dist/hoi4_agent_tools/core/canonical.js +18 -4
- package/dist/hoi4_agent_tools/core/condition-evaluator.js +18 -0
- package/dist/hoi4_agent_tools/core/configuration.js +7 -0
- package/dist/hoi4_agent_tools/core/domain-scan-patterns.js +12 -0
- package/dist/hoi4_agent_tools/core/domain-tools.js +65 -0
- package/dist/hoi4_agent_tools/core/domain-validation.js +5 -2
- package/dist/hoi4_agent_tools/core/engine.js +29 -2
- package/dist/hoi4_agent_tools/core/index.js +2 -2
- package/dist/hoi4_agent_tools/core/job-executor.js +14 -1
- package/dist/hoi4_agent_tools/core/job-operation-registration.js +15 -7
- package/dist/hoi4_agent_tools/core/job-store.js +78 -5
- package/dist/hoi4_agent_tools/core/job-transactions.js +31 -2
- package/dist/hoi4_agent_tools/core/job-worker-host.js +314 -127
- package/dist/hoi4_agent_tools/core/job-worker.js +96 -37
- package/dist/hoi4_agent_tools/core/operation-result.js +123 -10
- package/dist/hoi4_agent_tools/core/operation-tasks.js +49 -89
- package/dist/hoi4_agent_tools/core/persistent-analysis-cache.js +25 -21
- package/dist/hoi4_agent_tools/core/server-registry.js +22 -5
- package/dist/hoi4_agent_tools/core/shared-request-capacity.js +26 -1
- package/dist/hoi4_agent_tools/core/source/cache.js +20 -10
- package/dist/hoi4_agent_tools/core/source/lexer.js +11 -3
- package/dist/hoi4_agent_tools/core/temporary-directories.js +293 -0
- package/dist/hoi4_agent_tools/core/transactions.js +114 -23
- package/dist/hoi4_agent_tools/core/worker-exit.js +80 -0
- package/dist/hoi4_agent_tools/core/workspace.js +84 -8
- package/dist/hoi4_agent_tools/decision/ai.js +1 -1
- package/dist/hoi4_agent_tools/decision/service.js +28 -0
- package/dist/hoi4_agent_tools/decision/source-inventory.js +7 -5
- package/dist/hoi4_agent_tools/event/job-operations.js +9 -5
- package/dist/hoi4_agent_tools/event/operations.js +14 -1
- package/dist/hoi4_agent_tools/focus/job-operations.js +1 -2
- package/dist/hoi4_agent_tools/focus/tool-operations.js +1 -1
- package/dist/hoi4_agent_tools/gui/assets.js +3 -0
- package/dist/hoi4_agent_tools/gui/dds.js +8 -4
- package/dist/hoi4_agent_tools/gui/layout.js +45 -5
- package/dist/hoi4_agent_tools/gui/native-state.js +244 -0
- package/dist/hoi4_agent_tools/gui/renderer.js +12 -7
- package/dist/hoi4_agent_tools/gui/source-graph.js +17 -4
- package/dist/hoi4_agent_tools/gui/studio.js +33 -21
- package/dist/hoi4_agent_tools/gui/validators.js +8 -6
- package/dist/hoi4_agent_tools/map/bmp.js +1 -1
- package/dist/hoi4_agent_tools/map/derived.js +748 -0
- package/dist/hoi4_agent_tools/map/job-operations.js +7 -3
- package/dist/hoi4_agent_tools/map/model.js +103 -0
- package/dist/hoi4_agent_tools/map/operations.js +427 -58
- package/dist/hoi4_agent_tools/map/references.js +483 -0
- package/dist/hoi4_agent_tools/map/service.js +136 -61
- package/dist/hoi4_agent_tools/map/tool-operations.js +2 -1
- package/dist/hoi4_agent_tools/map/validation.js +3 -0
- package/dist/hoi4_agent_tools/map/world.js +1280 -0
- package/dist/hoi4_agent_tools/mcp/prompts/probability.js +2 -2
- package/dist/hoi4_agent_tools/mcp/server/argument-errors.js +72 -0
- package/dist/hoi4_agent_tools/mcp/server/create-modern-operations.js +23 -5
- package/dist/hoi4_agent_tools/mcp/server/create.js +7 -0
- package/dist/hoi4_agent_tools/mcp/server/instructions.js +1 -1
- package/dist/hoi4_agent_tools/mcp/server/request-lifecycle.js +24 -30
- package/dist/hoi4_agent_tools/mcp/server/tool-listing.js +45 -0
- package/dist/hoi4_agent_tools/mcp/tools/analysis.js +28 -8
- package/dist/hoi4_agent_tools/mcp/tools/event.js +19 -30
- package/dist/hoi4_agent_tools/mcp/tools/focus.js +5 -13
- package/dist/hoi4_agent_tools/mcp/tools/gui.js +6 -6
- package/dist/hoi4_agent_tools/mcp/tools/job.js +4 -4
- package/dist/hoi4_agent_tools/mcp/tools/map.js +15 -18
- package/dist/hoi4_agent_tools/mcp/tools/probability.js +42 -48
- package/dist/hoi4_agent_tools/mcp/tools/reference.js +26 -9
- package/dist/hoi4_agent_tools/mcp/tools/technology.js +17 -30
- package/dist/hoi4_agent_tools/mcp/transports/http.js +28 -4
- package/dist/hoi4_agent_tools/mcp/transports/stdio-lifetime.js +31 -8
- package/dist/hoi4_agent_tools/probability/job-operations.js +4 -9
- package/dist/hoi4_agent_tools/probability/operations.js +175 -13
- package/dist/hoi4_agent_tools/probability/source-analysis.js +24 -1
- package/dist/hoi4_agent_tools/reference/error-log.js +359 -0
- package/dist/hoi4_agent_tools/reference/known-mistakes.js +307 -0
- package/dist/hoi4_agent_tools/reference/known-mistakes.json +154 -0
- package/dist/hoi4_agent_tools/reference/mod-index.js +101 -0
- package/dist/hoi4_agent_tools/reference/operations.js +88 -19
- package/dist/hoi4_agent_tools/reference/player-text.js +4 -3
- package/dist/hoi4_agent_tools/reference/script-validation.js +19 -1
- package/dist/hoi4_agent_tools/reference/service.js +6 -0
- package/dist/hoi4_agent_tools/runtime.js +14 -1
- package/dist/hoi4_agent_tools/schemas/event.js +78 -19
- package/dist/hoi4_agent_tools/schemas/focus-requests.js +10 -0
- package/dist/hoi4_agent_tools/schemas/lenient-arguments.js +266 -0
- package/dist/hoi4_agent_tools/schemas/map-requests.js +63 -20
- package/dist/hoi4_agent_tools/schemas/map.js +122 -3
- package/dist/hoi4_agent_tools/schemas/mod-tools.js +181 -0
- package/dist/hoi4_agent_tools/schemas/probability-requests.js +119 -9
- package/dist/hoi4_agent_tools/schemas/reference.js +13 -0
- package/dist/hoi4_agent_tools/schemas/scenarios.js +1 -3
- package/dist/hoi4_agent_tools/schemas/script-validation.js +13 -6
- package/dist/hoi4_agent_tools/schemas/technology.js +79 -21
- package/dist/hoi4_agent_tools/technology/job-operations.js +3 -4
- package/dist/hoi4_agent_tools/technology/operations.js +14 -1
- package/dist/hoi4_agent_tools/version.js +1 -1
- package/docs/README.md +7 -4
- package/docs/analysis.md +15 -2
- package/docs/configuration.md +281 -0
- package/docs/development.md +26 -2
- package/docs/events.md +29 -6
- package/docs/examples.md +13 -28
- package/docs/focus.md +127 -5
- package/docs/gui.md +105 -21
- package/docs/helper-expansion.md +9 -9
- package/docs/http.md +3 -1
- package/docs/jobs.md +23 -14
- package/docs/map.md +199 -7
- package/docs/mechanics.md +6 -2
- package/docs/probability.md +46 -16
- package/docs/reference.md +73 -5
- package/docs/setup.md +45 -14
- package/docs/technology.md +28 -4
- package/docs/third-party-notices.md +11 -0
- package/docs/tools.md +150 -42
- package/docs/troubleshooting.md +61 -0
- package/examples/clients/codex-config.toml +5 -2
- package/examples/clients/generic.json +2 -2
- package/examples/config/config.json +7 -0
- package/npm-shrinkwrap.json +151 -156
- package/package.json +13 -8
- package/schemas/configuration.schema.json +144 -128
- 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/error-log-input.schema.json +55 -0
- 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 +597 -126
- package/schemas/mechanic-test-input.schema.json +1 -1
- package/schemas/mod-index-input.schema.json +51 -0
- package/schemas/operation-result.schema.json +2 -2
- 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/reference-context-input.schema.json +1 -1
- package/schemas/reference-read-input.schema.json +1 -1
- package/schemas/reference-search-input.schema.json +1 -1
- package/schemas/scenario-suite.schema.json +3 -5
- package/schemas/scenario-test-input.schema.json +3 -5
- package/schemas/script-validate-input.schema.json +1 -1
- package/schemas/shared-scenario.schema.json +1 -1
- package/schemas/source-lookup-input.schema.json +1 -1
- package/server.json +3 -3
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
import { workspaceIdSchema } from './common.js';
|
|
3
|
+
export const errorLogCategorySchema = z.enum([
|
|
4
|
+
'syntax',
|
|
5
|
+
'duplicate',
|
|
6
|
+
'localisation',
|
|
7
|
+
'effect',
|
|
8
|
+
'trigger',
|
|
9
|
+
'scope',
|
|
10
|
+
'graphics',
|
|
11
|
+
'interface',
|
|
12
|
+
'map',
|
|
13
|
+
'missing_reference',
|
|
14
|
+
'other',
|
|
15
|
+
]);
|
|
16
|
+
export const errorLogRequestSchema = z
|
|
17
|
+
.object({
|
|
18
|
+
workspaceId: workspaceIdSchema,
|
|
19
|
+
/** mod: entries located in the mod's own files; unlocated: entries naming no file. */
|
|
20
|
+
scope: z.enum(['all', 'mod', 'unlocated']).default('all'),
|
|
21
|
+
category: errorLogCategorySchema.optional(),
|
|
22
|
+
query: z.string().min(1).max(200).optional(),
|
|
23
|
+
limit: z.number().int().min(1).max(50).default(20),
|
|
24
|
+
offset: z.number().int().min(0).max(1_000_000).default(0),
|
|
25
|
+
})
|
|
26
|
+
.strict();
|
|
27
|
+
export const errorLogDataSchema = z
|
|
28
|
+
.object({
|
|
29
|
+
log: z
|
|
30
|
+
.object({
|
|
31
|
+
path: z.string().max(64),
|
|
32
|
+
modifiedAt: z.string().max(64),
|
|
33
|
+
bytes: z.number().int().min(0),
|
|
34
|
+
truncated: z.boolean(),
|
|
35
|
+
entries: z.number().int().min(0),
|
|
36
|
+
})
|
|
37
|
+
.strict(),
|
|
38
|
+
scope: z.enum(['all', 'mod', 'unlocated']),
|
|
39
|
+
totalEntries: z.number().int().min(0),
|
|
40
|
+
distinctEntries: z.number().int().min(0),
|
|
41
|
+
modEntries: z.number().int().min(0),
|
|
42
|
+
changedSinceLog: z.number().int().min(0),
|
|
43
|
+
categories: z.array(z
|
|
44
|
+
.object({
|
|
45
|
+
category: errorLogCategorySchema,
|
|
46
|
+
entries: z.number().int().min(0),
|
|
47
|
+
distinct: z.number().int().min(0),
|
|
48
|
+
hint: z.string().max(300),
|
|
49
|
+
})
|
|
50
|
+
.strict()),
|
|
51
|
+
/** Messages that differ only in names, numbers and paths, grouped by their shape. */
|
|
52
|
+
patterns: z
|
|
53
|
+
.array(z
|
|
54
|
+
.object({
|
|
55
|
+
pattern: z.string().max(300),
|
|
56
|
+
category: errorLogCategorySchema,
|
|
57
|
+
distinct: z.number().int().min(0),
|
|
58
|
+
entries: z.number().int().min(0),
|
|
59
|
+
example: z.string().max(600),
|
|
60
|
+
})
|
|
61
|
+
.strict())
|
|
62
|
+
.max(8),
|
|
63
|
+
/** Compared with the previous launch's log this server read, when there was one. */
|
|
64
|
+
sinceLastLaunch: z
|
|
65
|
+
.object({
|
|
66
|
+
previousLogAt: z.string().max(64),
|
|
67
|
+
newEntries: z.number().int().min(0),
|
|
68
|
+
persistingEntries: z.number().int().min(0),
|
|
69
|
+
resolvedEntries: z.number().int().min(0),
|
|
70
|
+
resolvedExamples: z
|
|
71
|
+
.array(z
|
|
72
|
+
.object({
|
|
73
|
+
category: errorLogCategorySchema,
|
|
74
|
+
message: z.string().max(300),
|
|
75
|
+
relativePath: z.string().max(1024).optional(),
|
|
76
|
+
})
|
|
77
|
+
.strict())
|
|
78
|
+
.max(5),
|
|
79
|
+
})
|
|
80
|
+
.strict()
|
|
81
|
+
.optional(),
|
|
82
|
+
entries: z
|
|
83
|
+
.array(z
|
|
84
|
+
.object({
|
|
85
|
+
category: errorLogCategorySchema,
|
|
86
|
+
module: z.string().max(128),
|
|
87
|
+
message: z.string().max(600),
|
|
88
|
+
count: z.number().int().min(1),
|
|
89
|
+
firstLogLine: z.number().int().min(1),
|
|
90
|
+
time: z.string().max(16).optional(),
|
|
91
|
+
/** Absent from the previous launch's log. */
|
|
92
|
+
new: z.boolean().optional(),
|
|
93
|
+
/** A reviewed known mistake this message reports, with its documented fix. */
|
|
94
|
+
knownMistake: z
|
|
95
|
+
.object({ id: z.string().max(64), fix: z.string().max(300) })
|
|
96
|
+
.strict()
|
|
97
|
+
.optional(),
|
|
98
|
+
source: z
|
|
99
|
+
.object({
|
|
100
|
+
relativePath: z.string().max(1024),
|
|
101
|
+
line: z.number().int().min(0).optional(),
|
|
102
|
+
layer: z.enum(['mod', 'dependency', 'game', 'unknown']),
|
|
103
|
+
changedSinceLog: z.boolean(),
|
|
104
|
+
})
|
|
105
|
+
.strict()
|
|
106
|
+
.optional(),
|
|
107
|
+
})
|
|
108
|
+
.strict())
|
|
109
|
+
.max(50),
|
|
110
|
+
offset: z.number().int().min(0),
|
|
111
|
+
nextOffset: z.number().int().min(0).optional(),
|
|
112
|
+
})
|
|
113
|
+
.strict();
|
|
114
|
+
export const modIndexRequestSchema = z
|
|
115
|
+
.object({
|
|
116
|
+
workspaceId: workspaceIdSchema,
|
|
117
|
+
mode: z.enum(['overview', 'next_id']).default('overview'),
|
|
118
|
+
/** overview: the mod's own files, or every layer. */
|
|
119
|
+
layer: z.enum(['mod', 'all']).default('mod'),
|
|
120
|
+
/** next_id: the symbol kind whose numbered identifiers are counted. */
|
|
121
|
+
kind: z.enum(['event', 'focus', 'decision', 'idea', 'leader', 'technology']).default('event'),
|
|
122
|
+
prefix: z.string().min(1).max(256).optional(),
|
|
123
|
+
namespace: z.string().min(1).max(256).optional(),
|
|
124
|
+
})
|
|
125
|
+
.strict();
|
|
126
|
+
export const modIndexDataSchema = z
|
|
127
|
+
.object({
|
|
128
|
+
mode: z.enum(['overview', 'next_id']),
|
|
129
|
+
complete: z.boolean(),
|
|
130
|
+
layer: z.enum(['mod', 'all']).optional(),
|
|
131
|
+
/** The mod's descriptor.mod metadata. */
|
|
132
|
+
descriptor: z
|
|
133
|
+
.object({
|
|
134
|
+
name: z.string().max(256).optional(),
|
|
135
|
+
version: z.string().max(256).optional(),
|
|
136
|
+
supportedVersion: z.string().max(256).optional(),
|
|
137
|
+
remoteFileId: z.string().max(256).optional(),
|
|
138
|
+
tags: z.array(z.string().max(256)).max(64),
|
|
139
|
+
dependencies: z.array(z.string().max(256)).max(64),
|
|
140
|
+
replacePaths: z.array(z.string().max(256)).max(64),
|
|
141
|
+
})
|
|
142
|
+
.strict()
|
|
143
|
+
.optional(),
|
|
144
|
+
files: z.number().int().min(0).optional(),
|
|
145
|
+
kinds: z
|
|
146
|
+
.array(z.object({ kind: z.string().max(64), count: z.number().int().min(0) }).strict())
|
|
147
|
+
.optional(),
|
|
148
|
+
folders: z
|
|
149
|
+
.array(z
|
|
150
|
+
.object({
|
|
151
|
+
folder: z.string().max(256),
|
|
152
|
+
files: z.number().int().min(0),
|
|
153
|
+
bytes: z.number().int().min(0),
|
|
154
|
+
})
|
|
155
|
+
.strict())
|
|
156
|
+
.optional(),
|
|
157
|
+
namespaces: z
|
|
158
|
+
.array(z
|
|
159
|
+
.object({
|
|
160
|
+
namespace: z.string().max(256),
|
|
161
|
+
events: z.number().int().min(0),
|
|
162
|
+
lowest: z.number().int().min(0),
|
|
163
|
+
highest: z.number().int().min(0),
|
|
164
|
+
files: z.number().int().min(0),
|
|
165
|
+
})
|
|
166
|
+
.strict())
|
|
167
|
+
.optional(),
|
|
168
|
+
omittedNamespaces: z.number().int().min(0).optional(),
|
|
169
|
+
next: z
|
|
170
|
+
.object({
|
|
171
|
+
kind: z.string().max(64),
|
|
172
|
+
prefix: z.string().max(256),
|
|
173
|
+
used: z.number().int().min(0),
|
|
174
|
+
highest: z.number().int().min(0).optional(),
|
|
175
|
+
nextId: z.string().max(300),
|
|
176
|
+
firstGapId: z.string().max(300).optional(),
|
|
177
|
+
})
|
|
178
|
+
.strict()
|
|
179
|
+
.optional(),
|
|
180
|
+
})
|
|
181
|
+
.strict();
|
|
@@ -5,7 +5,7 @@ function compact(schema, description) {
|
|
|
5
5
|
return z.unknown().describe(description).pipe(schema);
|
|
6
6
|
}
|
|
7
7
|
const nestedSource = compact(probabilitySourceSchema, 'Source selector; snapshotPath binds frozen bytes to path with expectedSourceHash.');
|
|
8
|
-
const nestedScenarios = compact(probabilityScenarioSetSchema, '
|
|
8
|
+
const nestedScenarios = compact(probabilityScenarioSetSchema, 'World-state facts: { id, scenarios: [{ id, actor?, date?, state: { "path": value }, flags?: [names] }] }. Missing ids get defaults; a bare scenario array is accepted.');
|
|
9
9
|
const nestedManifest = compact(customWeightedPoolManifestSchema, 'Declared custom weighted pool and state transitions.');
|
|
10
10
|
const nestedRenderFilter = compact(probabilityRenderFilterSchema, 'Optional scenario, candidate, metric, diagnostic, source, and page filter.');
|
|
11
11
|
const nestedAcceptanceBands = compact(z.array(probabilityAcceptanceBandSchema).max(100_000), 'Optional named metric acceptance bands.');
|
|
@@ -24,26 +24,37 @@ const commonShape = {
|
|
|
24
24
|
outputs,
|
|
25
25
|
refresh: z.boolean().optional(),
|
|
26
26
|
};
|
|
27
|
+
const evaluationShape = {
|
|
28
|
+
scenarioSet: nestedScenarios.optional(),
|
|
29
|
+
horizonDays: z.number().positive().max(1_000_000).optional(),
|
|
30
|
+
metrics: z.array(probabilityMetricSchema).min(1).max(4).optional(),
|
|
31
|
+
acceptanceBands: nestedAcceptanceBands.optional(),
|
|
32
|
+
diagnosticThresholds: nestedDiagnosticThresholds.optional(),
|
|
33
|
+
outputs,
|
|
34
|
+
};
|
|
35
|
+
/**
|
|
36
|
+
* One call finds the weighted source and, when a single surface matches, evaluates it.
|
|
37
|
+
* Without a scenarioSet the evaluation uses one fact-free scenario, so the result shows base
|
|
38
|
+
* weights and the facts each condition still needs.
|
|
39
|
+
*/
|
|
27
40
|
export const probabilityInspectRequestSchema = z
|
|
28
41
|
.object({
|
|
29
42
|
workspaceId: workspaceIdSchema,
|
|
30
43
|
adapter: probabilityAdapterIdSchema.optional(),
|
|
31
44
|
source: nestedSource.optional(),
|
|
32
45
|
customPoolManifest: nestedManifest.optional(),
|
|
33
|
-
candidatePool,
|
|
46
|
+
candidatePool: candidatePool.describe('Candidate IDs; an event ID selects all of its options, a decision ID finds its file.'),
|
|
47
|
+
evaluate: z
|
|
48
|
+
.boolean()
|
|
49
|
+
.optional()
|
|
50
|
+
.describe('Default true: evaluate the matched surface. False returns only the inventory.'),
|
|
51
|
+
...evaluationShape,
|
|
34
52
|
refresh: z.boolean().optional(),
|
|
35
53
|
})
|
|
36
54
|
.strict()
|
|
37
55
|
.superRefine((value, context) => {
|
|
38
56
|
if (value.source !== undefined && value.customPoolManifest !== undefined)
|
|
39
57
|
context.addIssue({ code: 'custom', message: 'Provide either source or customPoolManifest' });
|
|
40
|
-
if (value.adapter !== undefined &&
|
|
41
|
-
value.source === undefined &&
|
|
42
|
-
value.customPoolManifest === undefined)
|
|
43
|
-
context.addIssue({
|
|
44
|
-
code: 'custom',
|
|
45
|
-
message: 'An adapter requires a source; provide a source alone to discover compatible adapters',
|
|
46
|
-
});
|
|
47
58
|
if (value.customPoolManifest !== undefined &&
|
|
48
59
|
value.adapter !== undefined &&
|
|
49
60
|
value.adapter !== 'custom_weighted_pool')
|
|
@@ -52,6 +63,15 @@ export const probabilityInspectRequestSchema = z
|
|
|
52
63
|
path: ['adapter'],
|
|
53
64
|
message: 'customPoolManifest requires adapter custom_weighted_pool',
|
|
54
65
|
});
|
|
66
|
+
if (value.source === undefined &&
|
|
67
|
+
value.customPoolManifest === undefined &&
|
|
68
|
+
(value.candidatePool?.length ?? 0) === 0 &&
|
|
69
|
+
value.adapter !== undefined)
|
|
70
|
+
context.addIssue({
|
|
71
|
+
code: 'custom',
|
|
72
|
+
path: ['source'],
|
|
73
|
+
message: 'Name what to inspect: source.path, source.identifier, or candidatePool IDs such as a decision or event ID',
|
|
74
|
+
});
|
|
55
75
|
});
|
|
56
76
|
export const probabilityEvaluateRequestSchema = z
|
|
57
77
|
.object({
|
|
@@ -166,3 +186,93 @@ export const probabilityRenderRequestSchema = z
|
|
|
166
186
|
filter: nestedRenderFilter.optional(),
|
|
167
187
|
})
|
|
168
188
|
.strict();
|
|
189
|
+
export const probabilityAnalysisKindSchema = z.enum([
|
|
190
|
+
'compare',
|
|
191
|
+
'sweep',
|
|
192
|
+
'simulate',
|
|
193
|
+
'sequence',
|
|
194
|
+
'render',
|
|
195
|
+
]);
|
|
196
|
+
const analysisVariants = {
|
|
197
|
+
compare: probabilityCompareRequestSchema,
|
|
198
|
+
sweep: probabilitySweepRequestSchema,
|
|
199
|
+
simulate: probabilitySimulateRequestSchema,
|
|
200
|
+
sequence: probabilitySequenceRequestSchema,
|
|
201
|
+
render: probabilityRenderRequestSchema,
|
|
202
|
+
};
|
|
203
|
+
/**
|
|
204
|
+
* Deeper weighted analysis behind one tool. The listed schema is the flat union of every
|
|
205
|
+
* analysis's fields; each request is validated against the schema of its own analysis.
|
|
206
|
+
*/
|
|
207
|
+
export const probabilityAnalyzeRequestSchema = z
|
|
208
|
+
.object({
|
|
209
|
+
workspaceId: workspaceIdSchema,
|
|
210
|
+
analysis: probabilityAnalysisKindSchema.describe('compare: before/after source or manifests; sweep: input ranges; simulate: sampled uncertainty; sequence: declared pool over time; render: images for a retained analysisId.'),
|
|
211
|
+
adapter: probabilityAdapterIdSchema.optional(),
|
|
212
|
+
source: nestedSource.optional(),
|
|
213
|
+
before: nestedSource.optional(),
|
|
214
|
+
after: nestedSource.optional(),
|
|
215
|
+
beforeManifest: nestedManifest.optional(),
|
|
216
|
+
afterManifest: nestedManifest.optional(),
|
|
217
|
+
customPoolManifest: nestedManifest.optional(),
|
|
218
|
+
scenarioSet: nestedScenarios.optional(),
|
|
219
|
+
candidatePool,
|
|
220
|
+
horizonDays: z.number().positive().max(1_000_000).optional(),
|
|
221
|
+
metrics: z.array(probabilityMetricSchema).min(1).max(4).optional(),
|
|
222
|
+
acceptanceBands: nestedAcceptanceBands.optional(),
|
|
223
|
+
diagnosticThresholds: nestedDiagnosticThresholds.optional(),
|
|
224
|
+
outputs,
|
|
225
|
+
sweep: z
|
|
226
|
+
.object({
|
|
227
|
+
paths: z.array(z.string().min(1).max(1024)).min(1).max(32),
|
|
228
|
+
steps: z.number().int().min(2).max(10_000).optional(),
|
|
229
|
+
pairwise: z.boolean().optional(),
|
|
230
|
+
findRankReversals: z.boolean().optional(),
|
|
231
|
+
})
|
|
232
|
+
.strict()
|
|
233
|
+
.optional(),
|
|
234
|
+
samples: z.number().int().min(100).max(10_000_000).optional(),
|
|
235
|
+
seed: z.number().int().min(-2_147_483_648).max(2_147_483_647).optional(),
|
|
236
|
+
confidenceLevel: z.number().min(0.5).max(0.9999).optional(),
|
|
237
|
+
samplingMethod: probabilitySamplingMethodSchema.optional(),
|
|
238
|
+
maxSteps: z.number().int().min(1).max(100_000).optional(),
|
|
239
|
+
analysisId: z.string().min(1).max(256).optional(),
|
|
240
|
+
expectedScenarioHash: z
|
|
241
|
+
.string()
|
|
242
|
+
.regex(/^[a-f0-9]{64}$/u)
|
|
243
|
+
.optional(),
|
|
244
|
+
includeHtml: z.boolean().optional(),
|
|
245
|
+
filter: nestedRenderFilter.optional(),
|
|
246
|
+
refresh: z.boolean().optional(),
|
|
247
|
+
})
|
|
248
|
+
.strict()
|
|
249
|
+
.superRefine((value, context) => {
|
|
250
|
+
const { analysis, ...rest } = value;
|
|
251
|
+
const parsed = analysisVariants[analysis].safeParse(rest);
|
|
252
|
+
if (parsed.success)
|
|
253
|
+
return;
|
|
254
|
+
for (const issue of parsed.error.issues)
|
|
255
|
+
context.addIssue({
|
|
256
|
+
code: 'custom',
|
|
257
|
+
path: issue.path,
|
|
258
|
+
message: issue.code === 'unrecognized_keys'
|
|
259
|
+
? `${issue.message} (not used by analysis ${analysis})`
|
|
260
|
+
: issue.message,
|
|
261
|
+
});
|
|
262
|
+
});
|
|
263
|
+
/** Split one analyze request into its analysis kind and that analysis's own request. */
|
|
264
|
+
export function splitProbabilityAnalyzeRequest(input) {
|
|
265
|
+
const { analysis, ...rest } = probabilityAnalyzeRequestSchema.parse(input);
|
|
266
|
+
switch (analysis) {
|
|
267
|
+
case 'compare':
|
|
268
|
+
return { analysis, request: probabilityCompareRequestSchema.parse(rest) };
|
|
269
|
+
case 'sweep':
|
|
270
|
+
return { analysis, request: probabilitySweepRequestSchema.parse(rest) };
|
|
271
|
+
case 'simulate':
|
|
272
|
+
return { analysis, request: probabilitySimulateRequestSchema.parse(rest) };
|
|
273
|
+
case 'sequence':
|
|
274
|
+
return { analysis, request: probabilitySequenceRequestSchema.parse(rest) };
|
|
275
|
+
case 'render':
|
|
276
|
+
return { analysis, request: probabilityRenderRequestSchema.parse(rest) };
|
|
277
|
+
}
|
|
278
|
+
}
|
|
@@ -171,6 +171,19 @@ export const referenceContextDataSchema = z
|
|
|
171
171
|
missing: z.array(z.string().max(256)).max(32),
|
|
172
172
|
coverage: coverageBySource,
|
|
173
173
|
skipped: count,
|
|
174
|
+
/**
|
|
175
|
+
* Reviewed mistakes for this surface that `hoi4.script_validate` flags in a checked file,
|
|
176
|
+
* each with its fix; the cited wiki heading is in the rule list the server ships.
|
|
177
|
+
*/
|
|
178
|
+
knownMistakes: z
|
|
179
|
+
.array(z
|
|
180
|
+
.object({
|
|
181
|
+
id: z.string().max(64),
|
|
182
|
+
title: z.string().max(120),
|
|
183
|
+
fix: z.string().max(300),
|
|
184
|
+
})
|
|
185
|
+
.strict())
|
|
186
|
+
.max(16),
|
|
174
187
|
})
|
|
175
188
|
.strict();
|
|
176
189
|
export const sourceLookupDataSchema = z
|
|
@@ -167,14 +167,12 @@ const readOnlySuiteTool = z.enum([
|
|
|
167
167
|
'hoi4.tech_inspect',
|
|
168
168
|
'hoi4.tech_render',
|
|
169
169
|
'hoi4.probability_inspect',
|
|
170
|
-
'hoi4.
|
|
171
|
-
'hoi4.probability_render',
|
|
170
|
+
'hoi4.probability_analyze',
|
|
172
171
|
'hoi4.focus_inspect',
|
|
173
172
|
'hoi4.focus_render',
|
|
174
173
|
'hoi4.gui_inspect',
|
|
175
174
|
'hoi4.gui_render',
|
|
176
175
|
'hoi4.map_inspect',
|
|
177
|
-
'hoi4.map_render',
|
|
178
176
|
]);
|
|
179
177
|
const suiteCaseMetadata = {
|
|
180
178
|
sourceSelectors: z.array(manifestItem).max(64).default([]),
|
|
@@ -18,7 +18,7 @@ const scope = z.enum([
|
|
|
18
18
|
export const scriptValidateRequestSchema = z
|
|
19
19
|
.object({
|
|
20
20
|
workspaceId: workspaceIdSchema,
|
|
21
|
-
/** Snippet mode: an effect or trigger body checked under `kind`
|
|
21
|
+
/** Snippet mode: an effect or trigger body checked under `scope`; a missing `kind` is inferred. */
|
|
22
22
|
source: z.string().min(1).max(64_000).optional(),
|
|
23
23
|
/** File mode: a scanned mod file whose blocks are checked under the scope its structure fixes. */
|
|
24
24
|
path: z.string().trim().min(1).max(4096).optional(),
|
|
@@ -39,11 +39,11 @@ export const scriptValidateRequestSchema = z
|
|
|
39
39
|
path: ['source'],
|
|
40
40
|
message: 'Provide either source with kind and scope, or a mod file path',
|
|
41
41
|
});
|
|
42
|
-
if (value.source !== undefined &&
|
|
42
|
+
if (value.source !== undefined && value.scope === undefined)
|
|
43
43
|
context.addIssue({
|
|
44
44
|
code: 'custom',
|
|
45
|
-
path: ['
|
|
46
|
-
message: 'A snippet check requires
|
|
45
|
+
path: ['scope'],
|
|
46
|
+
message: 'A snippet check requires a scope, such as country or state',
|
|
47
47
|
});
|
|
48
48
|
if (value.path !== undefined &&
|
|
49
49
|
(value.kind !== undefined || value.scope !== undefined || value.bindings.length > 0))
|
|
@@ -56,7 +56,14 @@ export const scriptValidateRequestSchema = z
|
|
|
56
56
|
export const scriptValidateDataSchema = z
|
|
57
57
|
.object({
|
|
58
58
|
valid: z.boolean().nullable(),
|
|
59
|
-
checksPerformed: z.array(z.enum([
|
|
59
|
+
checksPerformed: z.array(z.enum([
|
|
60
|
+
'syntax',
|
|
61
|
+
'command_kind',
|
|
62
|
+
'declared_scope',
|
|
63
|
+
'player_text',
|
|
64
|
+
'event_popups',
|
|
65
|
+
'known_mistakes',
|
|
66
|
+
])),
|
|
60
67
|
parametersChecked: z.literal(false),
|
|
61
68
|
documentation: z
|
|
62
69
|
.object({
|
|
@@ -73,7 +80,7 @@ export const scriptValidateDataSchema = z
|
|
|
73
80
|
code: z.string().max(80),
|
|
74
81
|
status: z.enum(['supported', 'error', 'unresolved', 'warning']),
|
|
75
82
|
command: z.string().max(256),
|
|
76
|
-
kind: z.enum(['effect', 'trigger', 'text']),
|
|
83
|
+
kind: z.enum(['effect', 'trigger', 'text', 'definition']),
|
|
77
84
|
scope: z.string().max(64),
|
|
78
85
|
line: z.number().int().min(1),
|
|
79
86
|
column: z.number().int().min(1),
|
|
@@ -102,27 +102,6 @@ export function validateTechnologyInspectRequest(value, context) {
|
|
|
102
102
|
message: 'Impact mode requires impact',
|
|
103
103
|
});
|
|
104
104
|
}
|
|
105
|
-
export const technologyInspectRequestSchema = z
|
|
106
|
-
.object({
|
|
107
|
-
workspaceId: workspaceIdSchema,
|
|
108
|
-
mode: technologyAnalysisModeSchema,
|
|
109
|
-
folderId: technologyIdSchema.optional(),
|
|
110
|
-
technologyId: technologyIdSchema.optional(),
|
|
111
|
-
categoryId: technologyIdSchema.optional(),
|
|
112
|
-
targetKind: technologyUnlockKindSchema.optional(),
|
|
113
|
-
targetId: technologyIdSchema.optional(),
|
|
114
|
-
direction: technologyDirectionSchema.optional(),
|
|
115
|
-
maxDepth: z.number().int().min(1).max(256).optional(),
|
|
116
|
-
maxNodes: z.number().int().min(1).max(25_000).optional(),
|
|
117
|
-
includeSubTechnologies: z.boolean().optional(),
|
|
118
|
-
classifications: z.array(technologyDefectClassSchema).max(4).optional(),
|
|
119
|
-
codes: z.array(z.string().min(1).max(256)).max(100).optional(),
|
|
120
|
-
impact: technologyImpactSchema.optional(),
|
|
121
|
-
helperExpansion: helperExpansionRequestSchema.optional(),
|
|
122
|
-
refresh: z.boolean().optional(),
|
|
123
|
-
})
|
|
124
|
-
.strict()
|
|
125
|
-
.superRefine(validateTechnologyInspectRequest);
|
|
126
105
|
export const technologyRenderRequestSchema = z
|
|
127
106
|
.object({
|
|
128
107
|
workspaceId: workspaceIdSchema,
|
|
@@ -173,3 +152,82 @@ export const technologyCompareRequestSchema = z
|
|
|
173
152
|
})
|
|
174
153
|
.strict()
|
|
175
154
|
.superRefine(validateTechnologyCompareRequest);
|
|
155
|
+
export const technologyInspectToolModeSchema = z.enum([
|
|
156
|
+
...technologyAnalysisModeSchema.options,
|
|
157
|
+
'compare',
|
|
158
|
+
]);
|
|
159
|
+
const technologyCompareOnlyFields = [
|
|
160
|
+
'before',
|
|
161
|
+
'after',
|
|
162
|
+
'proposedSources',
|
|
163
|
+
'render',
|
|
164
|
+
'maxRenderNodes',
|
|
165
|
+
];
|
|
166
|
+
const technologyInspectOnlyFields = [
|
|
167
|
+
'folderId',
|
|
168
|
+
'technologyId',
|
|
169
|
+
'categoryId',
|
|
170
|
+
'targetKind',
|
|
171
|
+
'targetId',
|
|
172
|
+
'direction',
|
|
173
|
+
'maxDepth',
|
|
174
|
+
'maxNodes',
|
|
175
|
+
'includeSubTechnologies',
|
|
176
|
+
'classifications',
|
|
177
|
+
'codes',
|
|
178
|
+
'impact',
|
|
179
|
+
'helperExpansion',
|
|
180
|
+
];
|
|
181
|
+
/** Inspection and graph comparison share one tool; mode compare selects the comparison. */
|
|
182
|
+
export const technologyInspectRequestSchema = z
|
|
183
|
+
.object({
|
|
184
|
+
workspaceId: workspaceIdSchema,
|
|
185
|
+
mode: technologyInspectToolModeSchema,
|
|
186
|
+
folderId: technologyIdSchema.optional(),
|
|
187
|
+
technologyId: technologyIdSchema.optional(),
|
|
188
|
+
categoryId: technologyIdSchema.optional(),
|
|
189
|
+
targetKind: technologyUnlockKindSchema.optional(),
|
|
190
|
+
targetId: technologyIdSchema.optional(),
|
|
191
|
+
direction: technologyDirectionSchema.optional(),
|
|
192
|
+
maxDepth: z.number().int().min(1).max(256).optional(),
|
|
193
|
+
maxNodes: z.number().int().min(1).max(25_000).optional(),
|
|
194
|
+
includeSubTechnologies: z.boolean().optional(),
|
|
195
|
+
classifications: z.array(technologyDefectClassSchema).max(4).optional(),
|
|
196
|
+
codes: z.array(z.string().min(1).max(256)).max(100).optional(),
|
|
197
|
+
impact: technologyImpactSchema.optional(),
|
|
198
|
+
helperExpansion: helperExpansionRequestSchema.optional(),
|
|
199
|
+
before: technologyGraphReferenceSchema.optional(),
|
|
200
|
+
after: technologyGraphReferenceSchema.optional(),
|
|
201
|
+
proposedSources: z.array(technologyProposedSourceSchema).min(1).max(128).optional(),
|
|
202
|
+
render: z.boolean().optional(),
|
|
203
|
+
maxRenderNodes: z.number().int().min(1).max(2_000).optional(),
|
|
204
|
+
refresh: z.boolean().optional(),
|
|
205
|
+
})
|
|
206
|
+
.strict()
|
|
207
|
+
.superRefine(validateTechnologyInspectToolRequest);
|
|
208
|
+
export function validateTechnologyInspectToolRequest(value, context) {
|
|
209
|
+
const compare = value.mode === 'compare';
|
|
210
|
+
for (const field of compare ? technologyInspectOnlyFields : technologyCompareOnlyFields)
|
|
211
|
+
if (value[field] !== undefined)
|
|
212
|
+
context.addIssue({
|
|
213
|
+
code: 'custom',
|
|
214
|
+
path: [field],
|
|
215
|
+
message: compare
|
|
216
|
+
? `${field} is not used by mode compare`
|
|
217
|
+
: `${field} is used only by mode compare`,
|
|
218
|
+
});
|
|
219
|
+
if (compare)
|
|
220
|
+
validateTechnologyCompareRequest(value, context);
|
|
221
|
+
else
|
|
222
|
+
validateTechnologyInspectRequest(value, context);
|
|
223
|
+
}
|
|
224
|
+
/** Split an inspect request into a comparison or an analysis of the current graph. */
|
|
225
|
+
export function splitTechnologyInspectRequest(input) {
|
|
226
|
+
if (input.mode !== 'compare')
|
|
227
|
+
return { compare: false, request: input };
|
|
228
|
+
const request = { workspaceId: input.workspaceId };
|
|
229
|
+
for (const field of [...technologyCompareOnlyFields, 'refresh'])
|
|
230
|
+
if (input[field] !== undefined)
|
|
231
|
+
request[field] = input[field];
|
|
232
|
+
return { compare: true, request: technologyCompareRequestSchema.parse(request) };
|
|
233
|
+
}
|
|
@@ -2,8 +2,8 @@ import { z } from 'zod/v4';
|
|
|
2
2
|
import { IdleCacheLifetime } from '../core/idle-cache-lifetime.js';
|
|
3
3
|
import { errorResult, toolResult } from '../core/operation-result.js';
|
|
4
4
|
import { ServiceError } from '../core/result.js';
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
5
|
+
import { technologyInspectRequestSchema, technologyRenderRequestSchema, } from '../schemas/technology.js';
|
|
6
|
+
import { inspectOrCompareTechnologies, normalizeTechnologyInspectionRequest, normalizeTechnologyRenderRequest, renderTechnologies, } from './operations.js';
|
|
7
7
|
import { TechnologyTreeViewer } from './service.js';
|
|
8
8
|
const wireResult = z.record(z.string(), z.json());
|
|
9
9
|
/** Registers typed technology operations without invoking transport handlers. */
|
|
@@ -54,7 +54,6 @@ export function registerTechnologyJobs(operations, engine) {
|
|
|
54
54
|
}
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
|
-
register('hoi4.tech_inspect', technologyInspectRequestSchema, normalizeTechnologyInspectionRequest,
|
|
57
|
+
register('hoi4.tech_inspect', technologyInspectRequestSchema, normalizeTechnologyInspectionRequest, inspectOrCompareTechnologies, 'Analyzing technology trees');
|
|
58
58
|
register('hoi4.tech_render', technologyRenderRequestSchema, normalizeTechnologyRenderRequest, renderTechnologies, 'Rendering technology-tree view');
|
|
59
|
-
register('hoi4.tech_compare', technologyCompareRequestSchema, normalizeTechnologyCompareRequest, compareTechnologies, 'Comparing technology-tree graphs');
|
|
60
59
|
}
|
|
@@ -3,11 +3,24 @@ import { helperExpansionValidation } from '../core/helper-expansion.js';
|
|
|
3
3
|
import { compareCodeUnits, hashCanonical } from '../core/canonical.js';
|
|
4
4
|
import { emptyServiceResult } from '../core/result.js';
|
|
5
5
|
import { setInlineFilesScanned } from '../core/operation-result.js';
|
|
6
|
-
import { technologyCompareRequestSchema, technologyInspectRequestSchema, technologyRenderRequestSchema, } from '../schemas/technology.js';
|
|
6
|
+
import { technologyCompareRequestSchema, technologyInspectRequestSchema, splitTechnologyInspectRequest, technologyRenderRequestSchema, } from '../schemas/technology.js';
|
|
7
7
|
import { technologyDiagnostics } from './service.js';
|
|
8
8
|
export function normalizeTechnologyInspectionRequest(input) {
|
|
9
9
|
return JSON.parse(JSON.stringify(technologyInspectRequestSchema.parse(input)));
|
|
10
10
|
}
|
|
11
|
+
/** Route mode compare to the graph comparison and every other mode to analysis. */
|
|
12
|
+
export function inspectOrCompareTechnologies(viewer, input) {
|
|
13
|
+
const split = splitTechnologyInspectRequest(input);
|
|
14
|
+
if (!split.compare)
|
|
15
|
+
return inspectTechnologies(viewer, input);
|
|
16
|
+
const { signal, principal } = input;
|
|
17
|
+
return compareTechnologies(viewer, {
|
|
18
|
+
...JSON.parse(JSON.stringify(split.request)),
|
|
19
|
+
workspaceId: input.workspaceId,
|
|
20
|
+
...(principal === undefined ? {} : { principal }),
|
|
21
|
+
...(signal === undefined ? {} : { signal }),
|
|
22
|
+
});
|
|
23
|
+
}
|
|
11
24
|
export function normalizeTechnologyRenderRequest(input) {
|
|
12
25
|
return JSON.parse(JSON.stringify(technologyRenderRequestSchema.parse(input)));
|
|
13
26
|
}
|
|
@@ -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
|
+
export const PACKAGE_VERSION = '4.0.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/README.md
CHANGED
|
@@ -16,21 +16,24 @@ You can ask your coding agent for these tasks in ordinary language; you do not n
|
|
|
16
16
|
| Inspect or edit the map | [Maps](map.md) |
|
|
17
17
|
| Compare weights, chances or timing | [AI and probability](probability.md) |
|
|
18
18
|
| Test a mechanic or check a content package | [Mechanic tests](mechanics.md) |
|
|
19
|
+
| Read the game's error log or pick a free event ID | [Local references](reference.md) |
|
|
19
20
|
|
|
20
21
|
## See the results
|
|
21
22
|
|
|
22
23
|
- [Examples](examples.md): practical prompts with real renders.
|
|
23
24
|
- [Latest release](https://github.com/klimPaskov/hoi4-agent-tools/releases/latest): a short introduction to the published server.
|
|
24
|
-
- [Focus and technology comparisons](visual-comparisons.md): supplied game captures beside source renders.
|
|
25
|
-
- [Interface comparisons](gui-comparisons.md): vanilla and
|
|
25
|
+
- [Focus and technology comparisons](https://github.com/klimPaskov/hoi4-agent-tools/blob/main/docs/visual-comparisons.md): supplied game captures beside source renders.
|
|
26
|
+
- [Interface comparisons](https://github.com/klimPaskov/hoi4-agent-tools/blob/main/docs/gui-comparisons.md): vanilla and mod windows.
|
|
26
27
|
|
|
27
28
|
## Detailed reference
|
|
28
29
|
|
|
29
|
-
- [Tool reference](tools.md): tool names
|
|
30
|
+
- [Tool reference](tools.md): tool names, what each one does, and an example call for each.
|
|
31
|
+
- [Troubleshooting](troubleshooting.md): error codes and what to do about them.
|
|
32
|
+
- [Configuration](configuration.md): every setting, default location and environment variable.
|
|
30
33
|
- [Background jobs](jobs.md): inspect, cancel or retrieve long operations.
|
|
31
34
|
- [Large event and technology queries](helper-expansion.md): follow bounded results without losing coverage.
|
|
32
35
|
- [Remote hosting](http.md): share the server over HTTP.
|
|
33
36
|
- [Development](development.md): build, test and contribute.
|
|
34
|
-
- [Architecture decisions](adr/README.md): implementation rationale for contributors.
|
|
37
|
+
- [Architecture decisions](https://github.com/klimPaskov/hoi4-agent-tools/blob/main/docs/adr/README.md): implementation rationale for contributors.
|
|
35
38
|
|
|
36
39
|
For vulnerability reporting, use the [security policy](../SECURITY.md).
|
package/docs/analysis.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Cross-system impact and decisions
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Find out why a decision is hidden or unavailable, and see what a script change affects elsewhere in the mod.
|
|
4
|
+
`hoi4.impact_inspect` and `hoi4.decision_inspect` return a summary and a linked JSON report with source locations, hashes and unresolved cases.
|
|
5
5
|
They support ordinary calls and persistent MCP tasks through stdio and HTTP.
|
|
6
6
|
|
|
7
7
|
## Cross-system impact
|
|
@@ -18,6 +18,19 @@ Use a symbol when you know the definition you plan to change:
|
|
|
18
18
|
|
|
19
19
|
Use `changedFiles` with scanned display paths such as `mod:common/ideas/rationing.txt` to seed every active definition in a file.
|
|
20
20
|
Use `proposedSources` to add, replace, or remove files in memory under the authorized mod root; a `null` content removes a source from the proposed snapshot.
|
|
21
|
+
Each entry is an object with `relativePath` and `content`, and a request takes between 1 and 64 entries of at most 8 MiB each:
|
|
22
|
+
|
|
23
|
+
```json
|
|
24
|
+
{
|
|
25
|
+
"proposedSources": [
|
|
26
|
+
{ "relativePath": "common/ideas/my_ideas.txt", "content": "ideas = { ... }" },
|
|
27
|
+
{ "relativePath": "common/ideas/my_old_ideas.txt", "content": null }
|
|
28
|
+
]
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Impact and decision proposals name the text field `content`.
|
|
33
|
+
Event and technology proposals for `hoi4.event_inspect` and `hoi4.tech_inspect` with `mode: compare` name the same field `source` and also accept an optional `expectedSourceHash`.
|
|
21
34
|
When `changedFiles` is omitted, each proposed file seeds all its active definitions alongside any selected symbols.
|
|
22
35
|
The report compares the original and proposed consumer graph, including added and removed consumers and affected files.
|
|
23
36
|
Moving a source location within one file does not count an unchanged reference as a new or removed consumer.
|