hoi4-agent-tools 2.2.0 → 2.3.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 +15 -0
- package/README.md +30 -21
- package/dist/bin/stdio.js +0 -4
- package/dist/hoi4_agent_tools/core/clausewitz-evaluation.js +90 -0
- package/dist/hoi4_agent_tools/core/engine.js +5 -0
- package/dist/hoi4_agent_tools/core/index.js +57 -1
- package/dist/hoi4_agent_tools/core/source/ast-path.js +41 -0
- package/dist/hoi4_agent_tools/core/source/index.js +1 -0
- package/dist/hoi4_agent_tools/event/limits.js +1 -1
- package/dist/hoi4_agent_tools/mcp/server/create.js +3 -1
- package/dist/hoi4_agent_tools/mcp/tools/probability.js +413 -0
- package/dist/hoi4_agent_tools/probability/adapters.js +344 -0
- package/dist/hoi4_agent_tools/probability/compare.js +178 -0
- package/dist/hoi4_agent_tools/probability/evaluation.js +649 -0
- package/dist/hoi4_agent_tools/probability/index.js +13 -0
- package/dist/hoi4_agent_tools/probability/model.js +5 -0
- package/dist/hoi4_agent_tools/probability/rational.js +145 -0
- package/dist/hoi4_agent_tools/probability/render.js +307 -0
- package/dist/hoi4_agent_tools/probability/sequence.js +858 -0
- package/dist/hoi4_agent_tools/probability/service.js +1168 -0
- package/dist/hoi4_agent_tools/probability/simulation.js +545 -0
- package/dist/hoi4_agent_tools/probability/source-analysis.js +458 -0
- package/dist/hoi4_agent_tools/probability/sweep.js +265 -0
- package/dist/hoi4_agent_tools/probability/trigger-evaluator.js +280 -0
- package/dist/hoi4_agent_tools/probability/value-evaluator.js +357 -0
- package/dist/hoi4_agent_tools/schemas/probability.js +930 -0
- package/dist/hoi4_agent_tools/version.js +1 -1
- package/docs/README.md +1 -0
- package/docs/development.md +2 -0
- package/docs/probability.md +80 -0
- package/docs/research/probability-adapter-evidence.md +64 -0
- package/examples/clients/codex-config.toml +3 -0
- package/examples/clients/generic.json +8 -0
- package/examples/probability/adaptive-event-pool.json +92 -0
- package/examples/probability/adaptive-event-sequence-input.json +57 -0
- package/examples/probability/event-mtth-scenarios.json +57 -0
- package/examples/probability/event-mtth-simulate-input.json +37 -0
- package/examples/probability/focus-route-scenarios.json +61 -0
- package/examples/probability/focus-route-sweep-input.json +36 -0
- package/package.json +17 -8
- package/schemas/configuration.schema.json +747 -0
- package/schemas/continuous-focus-palette.schema.json +325 -0
- package/schemas/custom-weighted-pool.schema.json +298 -0
- package/schemas/event-feature-manifest.schema.json +63 -0
- package/schemas/focus-plan.schema.json +927 -0
- package/schemas/focus-planning-sidecar.schema.json +407 -0
- package/schemas/gui-animation-source.schema.json +176 -0
- package/schemas/gui-helper.schema.json +301 -0
- package/schemas/gui-scenario.schema.json +298 -0
- package/schemas/map-operation.schema.json +2284 -0
- package/schemas/operation-result.schema.json +327 -0
- package/schemas/probability-analysis-result.schema.json +2211 -0
- package/schemas/probability-compare-input.schema.json +664 -0
- package/schemas/probability-evaluate-input.schema.json +665 -0
- package/schemas/probability-inspect-input.schema.json +97 -0
- package/schemas/probability-render-input.schema.json +141 -0
- package/schemas/probability-scenario-set.schema.json +430 -0
- package/schemas/probability-sequence-input.schema.json +886 -0
- package/schemas/probability-simulate-input.schema.json +691 -0
- package/schemas/probability-sweep-input.schema.json +702 -0
- package/server.json +3 -3
- package/dist/hoi4_agent_tools/mcp/tools/chaosx.js +0 -530
|
@@ -0,0 +1,413 @@
|
|
|
1
|
+
import { z } from 'zod/v4';
|
|
2
|
+
import { emptyServiceResult } from '../../core/result.js';
|
|
3
|
+
import { ProbabilityAnalyzer, } from '../../probability/service.js';
|
|
4
|
+
import { customWeightedPoolManifestSchema, probabilityAcceptanceBandSchema, probabilityAdapterIdSchema, probabilityDiagnosticThresholdsSchema, probabilityMetricSchema, probabilityOutputSchema, probabilityRenderFilterSchema, probabilityScenarioSetSchema, probabilitySamplingMethodSchema, probabilitySourceSchema, } from '../../schemas/probability.js';
|
|
5
|
+
import { workspaceIdSchema } from '../../schemas/common.js';
|
|
6
|
+
import { compactValidatedInputSchema } from '../server/context-schemas.js';
|
|
7
|
+
import { nonNegativeIntegerSchema, sha256Schema } from '../server/output-schemas.js';
|
|
8
|
+
import { progressReporter } from '../server/progress.js';
|
|
9
|
+
import { errorResult, setInlineFilesScanned, strictOperationResultSchema, toolResult, } from '../server/result.js';
|
|
10
|
+
const nestedSource = compactValidatedInputSchema(probabilitySourceSchema, 'Source selector or proposed source.');
|
|
11
|
+
const nestedScenarios = compactValidatedInputSchema(probabilityScenarioSetSchema, 'Explicit world-state scenarios.');
|
|
12
|
+
const nestedManifest = compactValidatedInputSchema(customWeightedPoolManifestSchema, 'Declared custom weighted pool and state transitions.');
|
|
13
|
+
const nestedRenderFilter = compactValidatedInputSchema(probabilityRenderFilterSchema, 'Optional scenario, candidate, metric, diagnostic, source, and page filter.');
|
|
14
|
+
const nestedAcceptanceBands = compactValidatedInputSchema(z.array(probabilityAcceptanceBandSchema).max(100_000), 'Optional named metric acceptance bands.');
|
|
15
|
+
const nestedDiagnosticThresholds = compactValidatedInputSchema(probabilityDiagnosticThresholdsSchema, 'Optional diagnostic thresholds.');
|
|
16
|
+
const candidatePool = z.array(z.string().min(1).max(512)).max(100_000).optional();
|
|
17
|
+
const outputs = z.array(probabilityOutputSchema).max(10).optional();
|
|
18
|
+
const commonShape = {
|
|
19
|
+
workspaceId: workspaceIdSchema,
|
|
20
|
+
adapter: probabilityAdapterIdSchema,
|
|
21
|
+
source: nestedSource,
|
|
22
|
+
scenarioSet: nestedScenarios,
|
|
23
|
+
candidatePool,
|
|
24
|
+
horizonDays: z.number().positive().max(1_000_000).optional(),
|
|
25
|
+
metrics: z.array(probabilityMetricSchema).min(1).max(4).optional(),
|
|
26
|
+
acceptanceBands: nestedAcceptanceBands.optional(),
|
|
27
|
+
diagnosticThresholds: nestedDiagnosticThresholds.optional(),
|
|
28
|
+
outputs,
|
|
29
|
+
refresh: z.boolean().optional(),
|
|
30
|
+
};
|
|
31
|
+
const inspectInput = z
|
|
32
|
+
.object({
|
|
33
|
+
workspaceId: workspaceIdSchema,
|
|
34
|
+
adapter: probabilityAdapterIdSchema.optional(),
|
|
35
|
+
source: nestedSource.optional(),
|
|
36
|
+
candidatePool,
|
|
37
|
+
refresh: z.boolean().optional(),
|
|
38
|
+
})
|
|
39
|
+
.strict()
|
|
40
|
+
.superRefine((value, context) => {
|
|
41
|
+
if ((value.adapter === undefined) !== (value.source === undefined))
|
|
42
|
+
context.addIssue({
|
|
43
|
+
code: 'custom',
|
|
44
|
+
message: 'Provide adapter and source together, or omit both to list adapters',
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
const evaluateInput = z.object(commonShape).strict();
|
|
48
|
+
const sweepInput = z
|
|
49
|
+
.object({
|
|
50
|
+
...commonShape,
|
|
51
|
+
sweep: z
|
|
52
|
+
.object({
|
|
53
|
+
paths: z.array(z.string().min(1).max(1024)).min(1).max(32),
|
|
54
|
+
steps: z.number().int().min(2).max(10_000).default(25),
|
|
55
|
+
pairwise: z.boolean().default(false),
|
|
56
|
+
findRankReversals: z.boolean().default(true),
|
|
57
|
+
})
|
|
58
|
+
.strict(),
|
|
59
|
+
})
|
|
60
|
+
.strict();
|
|
61
|
+
const simulateInput = z
|
|
62
|
+
.object({
|
|
63
|
+
...commonShape,
|
|
64
|
+
samples: z.number().int().min(100).max(10_000_000).default(100_000),
|
|
65
|
+
seed: z.number().int().min(-2_147_483_648).max(2_147_483_647).default(1),
|
|
66
|
+
confidenceLevel: z.number().min(0.5).max(0.9999).default(0.95),
|
|
67
|
+
samplingMethod: probabilitySamplingMethodSchema.default('latin_hypercube'),
|
|
68
|
+
})
|
|
69
|
+
.strict();
|
|
70
|
+
const sequenceInput = z
|
|
71
|
+
.object({
|
|
72
|
+
workspaceId: workspaceIdSchema,
|
|
73
|
+
scenarioSet: nestedScenarios,
|
|
74
|
+
customPoolManifest: nestedManifest,
|
|
75
|
+
horizonDays: z.number().positive().max(1_000_000),
|
|
76
|
+
maxSteps: z.number().int().min(1).max(100_000).default(1_000),
|
|
77
|
+
samples: z.number().int().min(100).max(10_000_000).default(100_000),
|
|
78
|
+
seed: z.number().int().min(-2_147_483_648).max(2_147_483_647).default(1),
|
|
79
|
+
confidenceLevel: z.number().min(0.5).max(0.9999).default(0.95),
|
|
80
|
+
acceptanceBands: nestedAcceptanceBands.optional(),
|
|
81
|
+
diagnosticThresholds: nestedDiagnosticThresholds.optional(),
|
|
82
|
+
outputs,
|
|
83
|
+
})
|
|
84
|
+
.strict();
|
|
85
|
+
const compareInput = z
|
|
86
|
+
.object({
|
|
87
|
+
workspaceId: workspaceIdSchema,
|
|
88
|
+
adapter: probabilityAdapterIdSchema,
|
|
89
|
+
before: nestedSource,
|
|
90
|
+
after: nestedSource,
|
|
91
|
+
scenarioSet: nestedScenarios,
|
|
92
|
+
candidatePool,
|
|
93
|
+
horizonDays: z.number().positive().max(1_000_000).optional(),
|
|
94
|
+
acceptanceBands: nestedAcceptanceBands.optional(),
|
|
95
|
+
diagnosticThresholds: nestedDiagnosticThresholds.optional(),
|
|
96
|
+
outputs,
|
|
97
|
+
refresh: z.boolean().optional(),
|
|
98
|
+
})
|
|
99
|
+
.strict();
|
|
100
|
+
const renderInput = z
|
|
101
|
+
.object({
|
|
102
|
+
workspaceId: workspaceIdSchema,
|
|
103
|
+
analysisId: z.string().min(1).max(256),
|
|
104
|
+
expectedScenarioHash: sha256Schema.optional(),
|
|
105
|
+
outputs: z.array(probabilityOutputSchema).min(1).max(10),
|
|
106
|
+
includeHtml: z.boolean().default(false),
|
|
107
|
+
filter: nestedRenderFilter.optional(),
|
|
108
|
+
})
|
|
109
|
+
.strict();
|
|
110
|
+
const analysisDataSchema = z
|
|
111
|
+
.object({
|
|
112
|
+
operation: z.enum(['evaluate', 'sweep', 'simulate', 'sequence', 'compare', 'render']),
|
|
113
|
+
analysisId: z.string().max(256),
|
|
114
|
+
analysisStatus: z.enum(['complete', 'partial', 'blocked', 'cancelled', 'stale']),
|
|
115
|
+
adapterId: z.string().max(256),
|
|
116
|
+
sourceRevision: sha256Schema,
|
|
117
|
+
sourceHash: sha256Schema,
|
|
118
|
+
scenarioHash: sha256Schema,
|
|
119
|
+
cacheKey: sha256Schema,
|
|
120
|
+
scenarios: nonNegativeIntegerSchema,
|
|
121
|
+
candidates: nonNegativeIntegerSchema,
|
|
122
|
+
unresolved: nonNegativeIntegerSchema,
|
|
123
|
+
diagnostics: nonNegativeIntegerSchema,
|
|
124
|
+
sweepPoints: nonNegativeIntegerSchema.optional(),
|
|
125
|
+
samples: nonNegativeIntegerSchema.optional(),
|
|
126
|
+
sequenceMethod: z
|
|
127
|
+
.enum(['exact_state_distribution', 'bounded_beam', 'seeded_monte_carlo'])
|
|
128
|
+
.optional(),
|
|
129
|
+
comparisonChanges: nonNegativeIntegerSchema.optional(),
|
|
130
|
+
visualResources: nonNegativeIntegerSchema.optional(),
|
|
131
|
+
})
|
|
132
|
+
.strict();
|
|
133
|
+
const inspectDataSchema = z
|
|
134
|
+
.object({
|
|
135
|
+
adapters: nonNegativeIntegerSchema,
|
|
136
|
+
adapterId: z.string().max(256).optional(),
|
|
137
|
+
sourceRevision: sha256Schema.optional(),
|
|
138
|
+
sourceHash: sha256Schema.optional(),
|
|
139
|
+
candidates: nonNegativeIntegerSchema,
|
|
140
|
+
poolComplete: z.boolean().optional(),
|
|
141
|
+
requiredInputs: nonNegativeIntegerSchema,
|
|
142
|
+
unresolved: nonNegativeIntegerSchema,
|
|
143
|
+
})
|
|
144
|
+
.strict();
|
|
145
|
+
const analysisOutput = strictOperationResultSchema(analysisDataSchema);
|
|
146
|
+
const inspectOutput = strictOperationResultSchema(inspectDataSchema);
|
|
147
|
+
const readOnly = {
|
|
148
|
+
readOnlyHint: true,
|
|
149
|
+
destructiveHint: false,
|
|
150
|
+
idempotentHint: true,
|
|
151
|
+
openWorldHint: false,
|
|
152
|
+
};
|
|
153
|
+
function requestContext(engine, context, workspaceId, refresh, signal) {
|
|
154
|
+
return {
|
|
155
|
+
workspaceId: engine.resolver.resolveWorkspaceId(workspaceId, context.principal),
|
|
156
|
+
...(context.principal === undefined ? {} : { principal: context.principal }),
|
|
157
|
+
...(refresh === undefined ? {} : { refresh }),
|
|
158
|
+
signal,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function analysisData(result) {
|
|
162
|
+
return {
|
|
163
|
+
operation: result.operation,
|
|
164
|
+
analysisId: result.analysisId,
|
|
165
|
+
analysisStatus: result.status,
|
|
166
|
+
adapterId: result.adapter.id,
|
|
167
|
+
sourceRevision: result.metadata.sourceRevision,
|
|
168
|
+
sourceHash: result.metadata.sourceHash,
|
|
169
|
+
scenarioHash: result.metadata.scenarioHash,
|
|
170
|
+
cacheKey: result.metadata.cacheKey,
|
|
171
|
+
scenarios: result.scenarios.length,
|
|
172
|
+
candidates: result.scenarios.reduce((sum, scenario) => sum + scenario.candidates.length, 0),
|
|
173
|
+
unresolved: result.unresolved.length,
|
|
174
|
+
diagnostics: result.diagnostics.length,
|
|
175
|
+
...(result.sweep === undefined ? {} : { sweepPoints: result.sweep.points.length }),
|
|
176
|
+
...(result.metadata.samples === undefined ? {} : { samples: result.metadata.samples }),
|
|
177
|
+
...(result.sequence === undefined ? {} : { sequenceMethod: result.sequence.method }),
|
|
178
|
+
...(result.comparison === undefined
|
|
179
|
+
? {}
|
|
180
|
+
: { comparisonChanges: result.comparison.scenarioChanges.length }),
|
|
181
|
+
visualResources: result.resources.filter(({ mimeType }) => mimeType.startsWith('image/'))
|
|
182
|
+
.length,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
function analysisServiceResult(workspaceId, result) {
|
|
186
|
+
const output = emptyServiceResult(workspaceId, analysisData(result));
|
|
187
|
+
output.code =
|
|
188
|
+
result.status === 'complete'
|
|
189
|
+
? 'PROBABILITY_ANALYZED'
|
|
190
|
+
: result.status === 'stale'
|
|
191
|
+
? result.diagnostics.some(({ code }) => code === 'PROBABILITY_SCENARIO_STALE')
|
|
192
|
+
? 'PROBABILITY_SCENARIO_STALE'
|
|
193
|
+
: 'PROBABILITY_ANALYSIS_STALE'
|
|
194
|
+
: 'PROBABILITY_ANALYZED_PARTIAL';
|
|
195
|
+
output.artifacts = result.resources;
|
|
196
|
+
output.diagnostics = result.diagnostics;
|
|
197
|
+
output.validation = {
|
|
198
|
+
passed: result.status !== 'blocked' && result.status !== 'cancelled',
|
|
199
|
+
checks: [
|
|
200
|
+
{
|
|
201
|
+
id: 'uncertainty-visible',
|
|
202
|
+
passed: true,
|
|
203
|
+
message: `${result.unresolved.length} unresolved or bounded analysis item(s) are explicit`,
|
|
204
|
+
},
|
|
205
|
+
],
|
|
206
|
+
};
|
|
207
|
+
return output;
|
|
208
|
+
}
|
|
209
|
+
export function registerProbabilityTools(server, engine, context) {
|
|
210
|
+
const analyzer = new ProbabilityAnalyzer(engine);
|
|
211
|
+
server.registerTool('hoi4.probability_inspect', {
|
|
212
|
+
title: 'Inspect AI and MTTH weighted logic',
|
|
213
|
+
description: 'List versioned adapters or discover weighted blocks, candidate pools, capabilities, provenance, and unsupported constructs.',
|
|
214
|
+
inputSchema: inspectInput,
|
|
215
|
+
outputSchema: inspectOutput,
|
|
216
|
+
annotations: readOnly,
|
|
217
|
+
}, async (input, extra) => {
|
|
218
|
+
const progress = progressReporter(extra);
|
|
219
|
+
const base = requestContext(engine, context, input.workspaceId, input.refresh, progress.signal);
|
|
220
|
+
try {
|
|
221
|
+
await progress.report(0, 2, 'Inspecting weighted source');
|
|
222
|
+
const inspected = await analyzer.inspect(base, input.adapter, input.source, input.candidatePool);
|
|
223
|
+
const result = emptyServiceResult(base.workspaceId, {
|
|
224
|
+
adapters: inspected.adapters.length,
|
|
225
|
+
...(inspected.surface === undefined
|
|
226
|
+
? {}
|
|
227
|
+
: {
|
|
228
|
+
adapterId: inspected.surface.adapter.id,
|
|
229
|
+
sourceRevision: inspected.surface.sourceRevision,
|
|
230
|
+
sourceHash: inspected.surface.sourceHash,
|
|
231
|
+
poolComplete: inspected.surface.poolComplete,
|
|
232
|
+
}),
|
|
233
|
+
candidates: inspected.surface?.candidateCount ?? 0,
|
|
234
|
+
requiredInputs: inspected.surface?.requiredInputs.length ?? 0,
|
|
235
|
+
unresolved: inspected.surface?.unsupported.length ?? 0,
|
|
236
|
+
});
|
|
237
|
+
result.code =
|
|
238
|
+
inspected.surface === undefined
|
|
239
|
+
? 'PROBABILITY_ADAPTERS_LISTED'
|
|
240
|
+
: 'PROBABILITY_SOURCE_INSPECTED';
|
|
241
|
+
result.artifacts = inspected.artifacts;
|
|
242
|
+
setInlineFilesScanned(result, inspected.filesScanned);
|
|
243
|
+
await progress.report(2, 2, 'Weighted source inspection complete');
|
|
244
|
+
return toolResult(result);
|
|
245
|
+
}
|
|
246
|
+
catch (error) {
|
|
247
|
+
return errorResult(error, base.workspaceId);
|
|
248
|
+
}
|
|
249
|
+
});
|
|
250
|
+
server.registerTool('hoi4.probability_evaluate', {
|
|
251
|
+
title: 'Evaluate AI and MTTH scenarios',
|
|
252
|
+
description: 'Evaluate eligibility, modifier traces, exact values, proven probabilities, MTTH timing, bounds, and unresolved inputs.',
|
|
253
|
+
inputSchema: evaluateInput,
|
|
254
|
+
outputSchema: analysisOutput,
|
|
255
|
+
annotations: readOnly,
|
|
256
|
+
}, async (input, extra) => {
|
|
257
|
+
const progress = progressReporter(extra);
|
|
258
|
+
const base = requestContext(engine, context, input.workspaceId, input.refresh, progress.signal);
|
|
259
|
+
try {
|
|
260
|
+
await progress.report(0, 3, 'Scanning and evaluating weighted source');
|
|
261
|
+
const request = {
|
|
262
|
+
...base,
|
|
263
|
+
...input,
|
|
264
|
+
workspaceId: base.workspaceId,
|
|
265
|
+
};
|
|
266
|
+
const analyzed = await analyzer.evaluate(request);
|
|
267
|
+
await progress.report(3, 3, 'Scenario evaluation complete');
|
|
268
|
+
return toolResult(analysisServiceResult(base.workspaceId, analyzed));
|
|
269
|
+
}
|
|
270
|
+
catch (error) {
|
|
271
|
+
return errorResult(error, base.workspaceId);
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
server.registerTool('hoi4.probability_sweep', {
|
|
275
|
+
title: 'Sweep AI and MTTH parameters',
|
|
276
|
+
description: 'Evaluate declared ranges, sensitivity, breakpoints, and rank reversals without inventing world state.',
|
|
277
|
+
inputSchema: sweepInput,
|
|
278
|
+
outputSchema: analysisOutput,
|
|
279
|
+
annotations: readOnly,
|
|
280
|
+
}, async (input, extra) => {
|
|
281
|
+
const progress = progressReporter(extra);
|
|
282
|
+
const base = requestContext(engine, context, input.workspaceId, input.refresh, progress.signal);
|
|
283
|
+
try {
|
|
284
|
+
await progress.report(0, 3, 'Evaluating parameter sweep');
|
|
285
|
+
const request = {
|
|
286
|
+
...base,
|
|
287
|
+
...input,
|
|
288
|
+
workspaceId: base.workspaceId,
|
|
289
|
+
};
|
|
290
|
+
const analyzed = await analyzer.sweep(request);
|
|
291
|
+
await progress.report(3, 3, 'Parameter sweep complete');
|
|
292
|
+
return toolResult(analysisServiceResult(base.workspaceId, analyzed));
|
|
293
|
+
}
|
|
294
|
+
catch (error) {
|
|
295
|
+
return errorResult(error, base.workspaceId);
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
server.registerTool('hoi4.probability_simulate', {
|
|
299
|
+
title: 'Simulate uncertain weighted scenarios',
|
|
300
|
+
description: 'Run reproducible seeded Monte Carlo analysis with distributions, supported correlations, and confidence intervals.',
|
|
301
|
+
inputSchema: simulateInput,
|
|
302
|
+
outputSchema: analysisOutput,
|
|
303
|
+
annotations: readOnly,
|
|
304
|
+
}, async (input, extra) => {
|
|
305
|
+
const progress = progressReporter(extra);
|
|
306
|
+
const base = requestContext(engine, context, input.workspaceId, input.refresh, progress.signal);
|
|
307
|
+
try {
|
|
308
|
+
await progress.report(0, input.samples, 'Sampling uncertain scenarios');
|
|
309
|
+
const request = {
|
|
310
|
+
...base,
|
|
311
|
+
...input,
|
|
312
|
+
workspaceId: base.workspaceId,
|
|
313
|
+
};
|
|
314
|
+
const analyzed = await analyzer.simulate(request);
|
|
315
|
+
await progress.report(input.samples, input.samples, 'Seeded simulation complete');
|
|
316
|
+
return toolResult(analysisServiceResult(base.workspaceId, analyzed));
|
|
317
|
+
}
|
|
318
|
+
catch (error) {
|
|
319
|
+
return errorResult(error, base.workspaceId);
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
server.registerTool('hoi4.probability_sequence', {
|
|
323
|
+
title: 'Analyze a declared weighted sequence',
|
|
324
|
+
description: 'Analyze only manifest-declared recovery, caps, cooldowns, removals, resets, timers, and terminal states.',
|
|
325
|
+
inputSchema: sequenceInput,
|
|
326
|
+
outputSchema: analysisOutput,
|
|
327
|
+
annotations: readOnly,
|
|
328
|
+
}, async (input, extra) => {
|
|
329
|
+
const progress = progressReporter(extra);
|
|
330
|
+
const base = requestContext(engine, context, input.workspaceId, undefined, progress.signal);
|
|
331
|
+
try {
|
|
332
|
+
await progress.report(0, input.maxSteps, 'Analyzing declared sequence');
|
|
333
|
+
const request = {
|
|
334
|
+
...base,
|
|
335
|
+
...input,
|
|
336
|
+
workspaceId: base.workspaceId,
|
|
337
|
+
};
|
|
338
|
+
const analyzed = await analyzer.sequence(request);
|
|
339
|
+
await progress.report(input.maxSteps, input.maxSteps, 'Sequence analysis complete');
|
|
340
|
+
return toolResult(analysisServiceResult(base.workspaceId, analyzed));
|
|
341
|
+
}
|
|
342
|
+
catch (error) {
|
|
343
|
+
return errorResult(error, base.workspaceId);
|
|
344
|
+
}
|
|
345
|
+
});
|
|
346
|
+
server.registerTool('hoi4.probability_compare', {
|
|
347
|
+
title: 'Compare weighted source patches',
|
|
348
|
+
description: 'Compare real or proposed source under identical scenarios with modifier, score, probability, timing, and rank attribution.',
|
|
349
|
+
inputSchema: compareInput,
|
|
350
|
+
outputSchema: analysisOutput,
|
|
351
|
+
annotations: readOnly,
|
|
352
|
+
}, async (input, extra) => {
|
|
353
|
+
const progress = progressReporter(extra);
|
|
354
|
+
const base = requestContext(engine, context, input.workspaceId, input.refresh, progress.signal);
|
|
355
|
+
try {
|
|
356
|
+
await progress.report(0, 4, 'Comparing weighted source');
|
|
357
|
+
const request = {
|
|
358
|
+
...base,
|
|
359
|
+
...input,
|
|
360
|
+
workspaceId: base.workspaceId,
|
|
361
|
+
};
|
|
362
|
+
const analyzed = await analyzer.compare(request);
|
|
363
|
+
await progress.report(4, 4, 'Weighted source comparison complete');
|
|
364
|
+
return toolResult(analysisServiceResult(base.workspaceId, analyzed));
|
|
365
|
+
}
|
|
366
|
+
catch (error) {
|
|
367
|
+
return errorResult(error, base.workspaceId);
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
server.registerTool('hoi4.probability_render', {
|
|
371
|
+
title: 'Render AI and MTTH analysis',
|
|
372
|
+
description: 'Render cached analysis data as deterministic ranking, matrix, waterfall, timing, sensitivity, sequence, comparison, or unresolved resources.',
|
|
373
|
+
inputSchema: renderInput,
|
|
374
|
+
outputSchema: analysisOutput,
|
|
375
|
+
annotations: readOnly,
|
|
376
|
+
}, async (input, extra) => {
|
|
377
|
+
const progress = progressReporter(extra);
|
|
378
|
+
const base = requestContext(engine, context, input.workspaceId, undefined, progress.signal);
|
|
379
|
+
try {
|
|
380
|
+
await progress.report(0, input.outputs.length, 'Rendering analysis resources');
|
|
381
|
+
const request = {
|
|
382
|
+
...base,
|
|
383
|
+
...input,
|
|
384
|
+
workspaceId: base.workspaceId,
|
|
385
|
+
outputs: input.outputs.filter((output) => output !== 'json'),
|
|
386
|
+
};
|
|
387
|
+
const analyzed = await analyzer.render(request);
|
|
388
|
+
await progress.report(input.outputs.length, input.outputs.length, 'Analysis rendering complete');
|
|
389
|
+
return toolResult(analysisServiceResult(base.workspaceId, analyzed));
|
|
390
|
+
}
|
|
391
|
+
catch (error) {
|
|
392
|
+
return errorResult(error, base.workspaceId);
|
|
393
|
+
}
|
|
394
|
+
});
|
|
395
|
+
server.registerPrompt('hoi4.probability_analysis', {
|
|
396
|
+
title: 'Analyze HOI4 weighted logic',
|
|
397
|
+
description: 'Plan one source-linked AI, MTTH, random, or declared-pool analysis and return to the owning modding workflow.',
|
|
398
|
+
argsSchema: {
|
|
399
|
+
objective: z.string().min(1).max(4096),
|
|
400
|
+
sourceHint: z.string().max(1024).optional(),
|
|
401
|
+
},
|
|
402
|
+
}, ({ objective, sourceHint }) => ({
|
|
403
|
+
messages: [
|
|
404
|
+
{
|
|
405
|
+
role: 'user',
|
|
406
|
+
content: {
|
|
407
|
+
type: 'text',
|
|
408
|
+
text: `Analyze this HOI4 weighted-logic task: ${objective}${sourceHint === undefined ? '' : `\nSource hint: ${sourceHint}`}\nIdentify the exact weighted surface and adapter, declare representative world-state scenarios and every required candidate or external factor, inspect first, run the narrowest useful evaluate/sweep/simulate/sequence/compare operation, review linked uncertainty and provenance, then return the findings to the normal owning modding workflow. Do not infer missing state, execute effects, or edit source through probability tools.`,
|
|
409
|
+
},
|
|
410
|
+
},
|
|
411
|
+
],
|
|
412
|
+
}));
|
|
413
|
+
}
|