hoi4-agent-tools 3.0.9 → 3.2.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.
Files changed (145) hide show
  1. package/CHANGELOG.md +32 -1
  2. package/README.md +10 -2
  3. package/dist/bin/stdio.js +23 -12
  4. package/dist/hoi4_agent_tools/core/analysis-checkpoints.js +82 -0
  5. package/dist/hoi4_agent_tools/core/analysis-evidence.js +9 -0
  6. package/dist/hoi4_agent_tools/core/analysis-job-operations.js +38 -0
  7. package/dist/hoi4_agent_tools/core/artifact-resource.js +173 -0
  8. package/dist/hoi4_agent_tools/core/artifacts.js +84 -2
  9. package/dist/hoi4_agent_tools/core/condition-evaluator.js +16 -0
  10. package/dist/hoi4_agent_tools/core/dependency-pages.js +216 -0
  11. package/dist/hoi4_agent_tools/core/dependency-walk.js +266 -0
  12. package/dist/hoi4_agent_tools/core/domain-validation.js +188 -0
  13. package/dist/hoi4_agent_tools/core/engine.js +48 -5
  14. package/dist/hoi4_agent_tools/core/helper-expansion.js +186 -0
  15. package/dist/hoi4_agent_tools/core/impact-comparison.js +49 -0
  16. package/dist/hoi4_agent_tools/core/impact-graph.js +301 -0
  17. package/dist/hoi4_agent_tools/core/impact-semantic.js +256 -0
  18. package/dist/hoi4_agent_tools/core/index-segments.js +137 -0
  19. package/dist/hoi4_agent_tools/core/index.js +47 -4
  20. package/dist/hoi4_agent_tools/core/job-controls.js +109 -0
  21. package/dist/hoi4_agent_tools/core/job-executor.js +190 -0
  22. package/dist/hoi4_agent_tools/core/job-service.js +112 -0
  23. package/dist/hoi4_agent_tools/core/job-store.js +641 -0
  24. package/dist/hoi4_agent_tools/core/job-transactions.js +126 -0
  25. package/dist/hoi4_agent_tools/core/job-worker-host.js +202 -0
  26. package/dist/hoi4_agent_tools/core/job-worker.js +64 -0
  27. package/dist/hoi4_agent_tools/core/operation-context.js +31 -0
  28. package/dist/hoi4_agent_tools/core/operation-result.js +412 -0
  29. package/dist/hoi4_agent_tools/core/operation-tasks.js +387 -0
  30. package/dist/hoi4_agent_tools/core/persistent-analysis-cache.js +383 -0
  31. package/dist/hoi4_agent_tools/core/result.js +1 -0
  32. package/dist/hoi4_agent_tools/core/scanner.js +15 -75
  33. package/dist/hoi4_agent_tools/core/semantic-dependencies.js +233 -0
  34. package/dist/hoi4_agent_tools/core/shared-request-capacity.js +43 -11
  35. package/dist/hoi4_agent_tools/core/source/cache.js +107 -0
  36. package/dist/hoi4_agent_tools/core/source/parser.js +11 -1
  37. package/dist/hoi4_agent_tools/core/source-overlay.js +125 -0
  38. package/dist/hoi4_agent_tools/core/transaction-execution.js +134 -0
  39. package/dist/hoi4_agent_tools/core/transactions.js +80 -27
  40. package/dist/hoi4_agent_tools/decision/ai.js +104 -0
  41. package/dist/hoi4_agent_tools/decision/comparison.js +106 -0
  42. package/dist/hoi4_agent_tools/decision/cost.js +177 -0
  43. package/dist/hoi4_agent_tools/decision/evaluation.js +256 -0
  44. package/dist/hoi4_agent_tools/decision/lifecycle.js +114 -0
  45. package/dist/hoi4_agent_tools/decision/service.js +172 -0
  46. package/dist/hoi4_agent_tools/decision/source-inventory.js +182 -0
  47. package/dist/hoi4_agent_tools/event/graph.js +214 -290
  48. package/dist/hoi4_agent_tools/event/helper-expansion.js +33 -0
  49. package/dist/hoi4_agent_tools/event/job-operations.js +51 -0
  50. package/dist/hoi4_agent_tools/event/operations.js +179 -0
  51. package/dist/hoi4_agent_tools/event/service.js +67 -15
  52. package/dist/hoi4_agent_tools/event/source-analysis.js +5 -4
  53. package/dist/hoi4_agent_tools/focus/job-operations.js +77 -0
  54. package/dist/hoi4_agent_tools/focus/tool-operations.js +669 -0
  55. package/dist/hoi4_agent_tools/focus/tool-support.js +123 -0
  56. package/dist/hoi4_agent_tools/gui/job-operations.js +81 -0
  57. package/dist/hoi4_agent_tools/gui/tool-operations.js +270 -0
  58. package/dist/hoi4_agent_tools/impact/scenario-suites.js +74 -0
  59. package/dist/hoi4_agent_tools/impact/service.js +127 -0
  60. package/dist/hoi4_agent_tools/map/job-operations.js +76 -0
  61. package/dist/hoi4_agent_tools/map/tool-operations.js +493 -0
  62. package/dist/hoi4_agent_tools/mcp/prompts/probability.js +25 -0
  63. package/dist/hoi4_agent_tools/mcp/prompts/register-modern.js +29 -0
  64. package/dist/hoi4_agent_tools/mcp/resources/register-modern.js +34 -0
  65. package/dist/hoi4_agent_tools/mcp/resources/register.js +4 -150
  66. package/dist/hoi4_agent_tools/mcp/server/base-tools.js +3 -219
  67. package/dist/hoi4_agent_tools/mcp/server/create-modern-operations.js +188 -0
  68. package/dist/hoi4_agent_tools/mcp/server/create.js +18 -6
  69. package/dist/hoi4_agent_tools/mcp/server/instructions.js +2 -0
  70. package/dist/hoi4_agent_tools/mcp/server/job-task-store.js +67 -0
  71. package/dist/hoi4_agent_tools/mcp/server/legacy-task-tools.js +20 -0
  72. package/dist/hoi4_agent_tools/mcp/server/modern-tasks.js +168 -0
  73. package/dist/hoi4_agent_tools/mcp/server/progress.js +17 -15
  74. package/dist/hoi4_agent_tools/mcp/server/request-lifecycle.js +45 -0
  75. package/dist/hoi4_agent_tools/mcp/server/result.js +2 -412
  76. package/dist/hoi4_agent_tools/mcp/server/task-request-context.js +9 -0
  77. package/dist/hoi4_agent_tools/mcp/server/task-tool-catalog.js +16 -0
  78. package/dist/hoi4_agent_tools/mcp/server/task-tool-definition.js +1 -0
  79. package/dist/hoi4_agent_tools/mcp/server/transaction-execution.js +1 -123
  80. package/dist/hoi4_agent_tools/mcp/tools/analysis.js +65 -0
  81. package/dist/hoi4_agent_tools/mcp/tools/chaosx.js +38 -21
  82. package/dist/hoi4_agent_tools/mcp/tools/event.js +24 -315
  83. package/dist/hoi4_agent_tools/mcp/tools/focus.js +34 -1039
  84. package/dist/hoi4_agent_tools/mcp/tools/gui.js +19 -504
  85. package/dist/hoi4_agent_tools/mcp/tools/job.js +46 -0
  86. package/dist/hoi4_agent_tools/mcp/tools/map.js +21 -600
  87. package/dist/hoi4_agent_tools/mcp/tools/probability.js +39 -463
  88. package/dist/hoi4_agent_tools/mcp/tools/technology.js +40 -304
  89. package/dist/hoi4_agent_tools/mcp/transports/http.js +58 -1
  90. package/dist/hoi4_agent_tools/mcp/transports/modern-task-routing.js +109 -0
  91. package/dist/hoi4_agent_tools/mcp/transports/negotiated-stdio.js +121 -0
  92. package/dist/hoi4_agent_tools/probability/job-operations.js +58 -0
  93. package/dist/hoi4_agent_tools/probability/operations.js +183 -0
  94. package/dist/hoi4_agent_tools/probability/service.js +24 -3
  95. package/dist/hoi4_agent_tools/schemas/analysis.js +228 -0
  96. package/dist/hoi4_agent_tools/schemas/common.js +2 -0
  97. package/dist/hoi4_agent_tools/schemas/event.js +72 -1
  98. package/dist/hoi4_agent_tools/schemas/focus-requests.js +189 -0
  99. package/dist/hoi4_agent_tools/schemas/gui-requests.js +193 -0
  100. package/dist/hoi4_agent_tools/schemas/helper-expansion.js +58 -0
  101. package/dist/hoi4_agent_tools/schemas/map-requests.js +85 -0
  102. package/dist/hoi4_agent_tools/schemas/probability-requests.js +168 -0
  103. package/dist/hoi4_agent_tools/schemas/technology.js +90 -1
  104. package/dist/hoi4_agent_tools/schemas/transaction.js +1 -0
  105. package/dist/hoi4_agent_tools/technology/graph.js +83 -78
  106. package/dist/hoi4_agent_tools/technology/helper-expansion.js +33 -0
  107. package/dist/hoi4_agent_tools/technology/job-operations.js +60 -0
  108. package/dist/hoi4_agent_tools/technology/operations.js +125 -0
  109. package/dist/hoi4_agent_tools/technology/service.js +89 -15
  110. package/dist/hoi4_agent_tools/technology/source-analysis.js +2 -1
  111. package/dist/hoi4_agent_tools/version.js +1 -1
  112. package/docs/README.md +3 -0
  113. package/docs/analysis.md +100 -0
  114. package/docs/development.md +2 -0
  115. package/docs/events.md +7 -2
  116. package/docs/helper-expansion.md +78 -0
  117. package/docs/http.md +2 -0
  118. package/docs/jobs.md +86 -0
  119. package/docs/technology.md +6 -2
  120. package/package.json +15 -6
  121. package/schemas/configuration.schema.json +1 -1
  122. package/schemas/continuous-focus-palette.schema.json +1 -1
  123. package/schemas/custom-weighted-pool.schema.json +1 -1
  124. package/schemas/decision-inspect-input.schema.json +290 -0
  125. package/schemas/event-feature-manifest.schema.json +1 -1
  126. package/schemas/focus-plan.schema.json +1 -1
  127. package/schemas/focus-planning-sidecar.schema.json +1 -1
  128. package/schemas/gui-animation-source.schema.json +1 -1
  129. package/schemas/gui-helper.schema.json +1 -1
  130. package/schemas/gui-scenario.schema.json +1 -1
  131. package/schemas/helper-expansion-request.schema.json +44 -0
  132. package/schemas/helper-expansion-summary.schema.json +70 -0
  133. package/schemas/impact-inspect-input.schema.json +203 -0
  134. package/schemas/map-operation.schema.json +1 -1
  135. package/schemas/operation-result.schema.json +1 -1
  136. package/schemas/probability-analysis-result.schema.json +1 -1
  137. package/schemas/probability-compare-input.schema.json +1 -1
  138. package/schemas/probability-evaluate-input.schema.json +1 -1
  139. package/schemas/probability-inspect-input.schema.json +1 -1
  140. package/schemas/probability-render-input.schema.json +1 -1
  141. package/schemas/probability-scenario-set.schema.json +1 -1
  142. package/schemas/probability-sequence-input.schema.json +1 -1
  143. package/schemas/probability-simulate-input.schema.json +1 -1
  144. package/schemas/probability-sweep-input.schema.json +1 -1
  145. package/server.json +3 -3
@@ -333,24 +333,17 @@ async function resolveGuiRevision(engine, context, studio, cache, workspaceId, s
333
333
  filesScanned: Object.keys(sourceHashes).sort(compareCodeUnits),
334
334
  };
335
335
  }
336
- export function registerChaosxTools(server, engine, context) {
336
+ export function createChaosxToolOperations(engine, context) {
337
337
  const guiStudio = new ScriptedGuiStudio(engine);
338
338
  const guiRevisionCache = new Map();
339
339
  const guiCacheLifetime = new IdleCacheLifetime(() => {
340
340
  guiStudio.clearCaches();
341
341
  guiRevisionCache.clear();
342
342
  });
343
- server.registerTool('chaosx.visual_revision', {
344
- title: 'Check ChaosX visual revisions',
345
- description: 'Private ChaosX cache-coherency endpoint. Computes exact scripted-GUI source revisions without rendering PNG artifacts.',
346
- inputSchema: chaosxVisualRevisionInput,
347
- outputSchema: chaosxVisualRevisionOutput,
348
- annotations: readOnly,
349
- }, async (input, extra) => {
350
- const workspaceId = await resolveServerWorkspaceId(engine, context, input.workspaceId, extra.signal);
343
+ const visualCall = async (input, progress) => {
344
+ const workspaceId = await resolveServerWorkspaceId(engine, context, input.workspaceId, progress.signal);
351
345
  const releaseCaches = guiCacheLifetime.begin();
352
346
  try {
353
- const progress = progressReporter(extra);
354
347
  await progress.report(0, 2, 'Checking ChaosX scripted-GUI sources');
355
348
  const resolvedGuiRevisions = [];
356
349
  for (const selector of input.guiWindows)
@@ -381,17 +374,10 @@ export function registerChaosxTools(server, engine, context) {
381
374
  finally {
382
375
  releaseCaches();
383
376
  }
384
- });
385
- server.registerTool('chaosx.focus_country_assets', {
386
- title: 'Render ChaosX focus country assets',
387
- description: 'Private ChaosX Discord integration endpoint. Returns country flags and leader portraits to accompany a focus-tree raster; it is not intended for coding-agent workflows.',
388
- inputSchema: chaosxCountryAssetsInput,
389
- outputSchema: chaosxCountryAssetsOutput,
390
- annotations: artifactProducing,
391
- }, async (input, extra) => {
392
- const workspaceId = await resolveServerWorkspaceId(engine, context, input.workspaceId, extra.signal);
377
+ };
378
+ const countryCall = async (input, progress) => {
379
+ const workspaceId = await resolveServerWorkspaceId(engine, context, input.workspaceId, progress.signal);
393
380
  try {
394
- const progress = progressReporter(extra);
395
381
  await progress.report(0, 3, 'Resolving ChaosX country assets');
396
382
  const discoveryWorkspace = engine.resolver.get(workspaceId, context.principal);
397
383
  const snapshot = await engine.scan(workspaceId, { patterns: countryAssetDiscoveryPatterns(discoveryWorkspace) }, context.principal, progress.signal);
@@ -488,5 +474,36 @@ export function registerChaosxTools(server, engine, context) {
488
474
  catch (error) {
489
475
  return errorResult(error, workspaceId);
490
476
  }
491
- });
477
+ };
478
+ return {
479
+ visual: {
480
+ definition: {
481
+ name: 'chaosx.visual_revision',
482
+ title: 'Check ChaosX visual revisions',
483
+ description: 'Private ChaosX cache-coherency endpoint. Computes exact scripted-GUI source revisions without rendering PNG artifacts.',
484
+ inputSchema: chaosxVisualRevisionInput,
485
+ outputSchema: chaosxVisualRevisionOutput,
486
+ annotations: readOnly,
487
+ },
488
+ call: visualCall,
489
+ },
490
+ country: {
491
+ definition: {
492
+ name: 'chaosx.focus_country_assets',
493
+ title: 'Render ChaosX focus country assets',
494
+ description: 'Private ChaosX Discord integration endpoint. Returns country flags and leader portraits to accompany a focus-tree raster; it is not intended for coding-agent workflows.',
495
+ inputSchema: chaosxCountryAssetsInput,
496
+ outputSchema: chaosxCountryAssetsOutput,
497
+ annotations: artifactProducing,
498
+ },
499
+ call: countryCall,
500
+ },
501
+ };
502
+ }
503
+ export function registerChaosxTools(server, engine, context) {
504
+ const operations = createChaosxToolOperations(engine, context);
505
+ const { name: visualName, ...visualDefinition } = operations.visual.definition;
506
+ const { name: countryName, ...countryDefinition } = operations.country.definition;
507
+ server.registerTool(visualName, visualDefinition, (input, extra) => operations.visual.call(input, progressReporter(extra)));
508
+ server.registerTool(countryName, countryDefinition, (input, extra) => operations.country.call(input, progressReporter(extra)));
492
509
  }
@@ -1,16 +1,10 @@
1
+ import { registerLegacyTaskTools } from '../server/legacy-task-tools.js';
1
2
  import { z } from 'zod/v4';
2
- import { publicArtifactLink } from '../../core/artifacts.js';
3
- import { compareCodeUnits } from '../../core/canonical.js';
4
- import { IdleCacheLifetime } from '../../core/idle-cache-lifetime.js';
5
- import { emptyServiceResult } from '../../core/result.js';
6
- import { EventChainViewer, eventDiagnostics, } from '../../event/service.js';
7
- import { eventDirectionSchema, eventGraphReferenceSchema, eventImpactSubjectSchema, eventInspectModeSchema, eventProposedSourceSchema, eventRenderViewSchema, eventSelectorSchema, eventStateSubjectSchema, } from '../../schemas/event.js';
8
- import { workspaceIdSchema } from '../../schemas/common.js';
3
+ import { helperExpansionRequestSchema, helperExpansionSummarySchema, } from '../../schemas/helper-expansion.js';
4
+ import { eventDirectionSchema, eventGraphReferenceSchema, eventImpactSubjectSchema, eventInspectModeSchema, eventProposedSourceSchema, eventRenderViewSchema, eventSelectorSchema, eventInspectRequestSchema, eventRenderRequestSchema, eventCompareRequestSchema, validateEventCompareRequest, validateEventInspectRequest, eventStateSubjectSchema, } from '../../schemas/event.js';
9
5
  import { compactValidatedInputSchema } from '../server/context-schemas.js';
10
6
  import { nonNegativeIntegerSchema, sha256Schema } from '../server/output-schemas.js';
11
- import { progressReporter } from '../server/progress.js';
12
- import { errorResult, setInlineFilesScanned, strictOperationResultSchema, toolResult, } from '../server/result.js';
13
- import { resolveServerWorkspaceId } from '../server/base-tools.js';
7
+ import { strictOperationResultSchema } from '../server/result.js';
14
8
  const nestedSelectorSchema = compactValidatedInputSchema(eventSelectorSchema, 'Event selector; see docs/events.md.');
15
9
  const nestedStateSubjectSchema = compactValidatedInputSchema(eventStateSubjectSchema, 'State kind and name.');
16
10
  const nestedImpactSubjectSchema = compactValidatedInputSchema(eventImpactSubjectSchema, 'Impact kind and name.');
@@ -18,73 +12,31 @@ const nestedGraphReferenceSchema = compactValidatedInputSchema(eventGraphReferen
18
12
  const nestedProposedSourceSchema = compactValidatedInputSchema(eventProposedSourceSchema, 'In-memory source overlay; never written.');
19
13
  const eventInspectInputSchema = z
20
14
  .object({
21
- workspaceId: workspaceIdSchema,
22
- mode: eventInspectModeSchema,
15
+ ...eventInspectRequestSchema.shape,
23
16
  selector: nestedSelectorSchema.optional(),
24
17
  from: nestedSelectorSchema.optional(),
25
18
  to: nestedSelectorSchema.optional(),
26
- direction: eventDirectionSchema.optional(),
27
- maxDepth: z.number().int().min(1).max(64).optional(),
28
- maxNodes: z.number().int().min(1).max(5_000).optional(),
29
- maxEdges: z.number().int().min(1).max(20_000).optional(),
30
- expandHelpers: z.boolean().optional(),
31
19
  stateSubject: nestedStateSubjectSchema.optional(),
32
20
  impactSubject: nestedImpactSubjectSchema.optional(),
33
- refresh: z.boolean().optional(),
21
+ helperExpansion: compactValidatedInputSchema(helperExpansionRequestSchema, 'Bounded helper paths; opaque continuationUri resumes the same source and roots. See docs/events.md.').optional(),
34
22
  })
35
23
  .strict()
36
- .superRefine((value, context) => {
37
- if (value.mode === 'trace' && value.selector === undefined) {
38
- context.addIssue({ code: 'custom', path: ['selector'], message: 'Trace requires selector' });
39
- }
40
- if (value.mode === 'explain_path' && (value.from === undefined || value.to === undefined)) {
41
- context.addIssue({
42
- code: 'custom',
43
- path: value.from === undefined ? ['from'] : ['to'],
44
- message: 'Path explanation requires from and to',
45
- });
46
- }
47
- if (value.mode === 'impact' && value.impactSubject === undefined) {
48
- context.addIssue({
49
- code: 'custom',
50
- path: ['impactSubject'],
51
- message: 'Impact analysis requires impactSubject',
52
- });
53
- }
54
- });
24
+ .superRefine(validateEventInspectRequest);
55
25
  const eventRenderInputSchema = z
56
26
  .object({
57
- workspaceId: workspaceIdSchema,
58
- view: eventRenderViewSchema,
27
+ ...eventRenderRequestSchema.shape,
59
28
  selector: nestedSelectorSchema.optional(),
60
- direction: eventDirectionSchema.optional(),
61
- maxDepth: z.number().int().min(1).max(64).optional(),
62
- maxNodes: z.number().int().min(1).max(240).optional(),
63
- expandHelpers: z.boolean().optional(),
64
- includeHtml: z.boolean().optional(),
65
- refresh: z.boolean().optional(),
66
29
  })
67
30
  .strict();
68
31
  const eventCompareInputSchema = z
69
32
  .object({
70
- workspaceId: workspaceIdSchema,
33
+ ...eventCompareRequestSchema.shape,
71
34
  before: nestedGraphReferenceSchema.optional(),
72
35
  after: nestedGraphReferenceSchema.optional(),
73
36
  proposedSources: z.array(nestedProposedSourceSchema).min(1).max(64).optional(),
74
- render: z.boolean().optional(),
75
- maxRenderNodes: z.number().int().min(1).max(240).optional(),
76
- refresh: z.boolean().optional(),
77
37
  })
78
38
  .strict()
79
- .superRefine((value, context) => {
80
- if (value.after !== undefined && value.proposedSources !== undefined) {
81
- context.addIssue({
82
- code: 'custom',
83
- path: ['after'],
84
- message: 'after and proposedSources are mutually exclusive',
85
- });
86
- }
87
- });
39
+ .superRefine(validateEventCompareRequest);
88
40
  const eventGraphCountsSchema = z
89
41
  .object({
90
42
  events: nonNegativeIntegerSchema,
@@ -128,6 +80,7 @@ const eventInspectOutputSchema = strictOperationResultSchema(z
128
80
  revision: sha256Schema,
129
81
  graphHash: sha256Schema,
130
82
  counts: eventGraphCountsSchema,
83
+ helperExpansion: helperExpansionSummarySchema.optional(),
131
84
  boundary: inspectBoundarySchema,
132
85
  })
133
86
  .strict());
@@ -206,276 +159,32 @@ const readOnlyEventTool = {
206
159
  idempotentHint: true,
207
160
  openWorldHint: false,
208
161
  };
209
- function graphCounts(graph, artifacts) {
210
- const diagnostics = eventDiagnostics(graph);
211
- return {
212
- events: graph.statistics.eventCount,
213
- options: graph.statistics.optionCount,
214
- entries: graph.statistics.entryCount,
215
- helpers: graph.statistics.helperCount,
216
- unresolvedNodes: graph.statistics.unresolvedNodeCount,
217
- terminals: graph.statistics.terminalCount,
218
- edges: graph.statistics.edgeCount,
219
- derivedEdges: graph.statistics.derivedEdgeCount,
220
- stateAccesses: graph.statistics.stateAccessCount,
221
- issues: graph.statistics.issueCount,
222
- diagnostics: diagnostics.length,
223
- blockingDiagnostics: diagnostics.filter(({ severity }) => severity === 'error' || severity === 'blocker').length,
224
- skippedSources: graph.skippedSourceCount,
225
- artifacts,
226
- };
227
- }
228
- function graphValidation(graph) {
229
- const counts = graphCounts(graph, 0);
230
- const focused = graph.analysisMode === 'focused';
231
- return {
232
- passed: graph.complete && counts.blockingDiagnostics === 0,
233
- checks: [
234
- {
235
- id: 'event-analysis',
236
- passed: graph.complete && counts.blockingDiagnostics === 0,
237
- message: focused
238
- ? 'Large workspace analysis deferred workspace-wide helper projections and lifecycle passes; direct evidence is linked'
239
- : graph.complete
240
- ? `${counts.blockingDiagnostics} blocking event-chain diagnostics; full evidence is linked`
241
- : `${graph.skippedSourceCount} event-analysis source(s) were skipped; full evidence is linked`,
242
- },
243
- ],
244
- };
245
- }
246
- function inspectRequest(input, context, signal) {
247
- return {
248
- workspaceId: input.workspaceId,
249
- mode: input.mode,
250
- ...(input.selector === undefined
251
- ? {}
252
- : { selector: input.selector }),
253
- ...(input.from === undefined
254
- ? {}
255
- : { from: input.from }),
256
- ...(input.to === undefined ? {} : { to: input.to }),
257
- ...(input.direction === undefined ? {} : { direction: input.direction }),
258
- ...(input.maxDepth === undefined ? {} : { maxDepth: input.maxDepth }),
259
- ...(input.maxNodes === undefined ? {} : { maxNodes: input.maxNodes }),
260
- ...(input.maxEdges === undefined ? {} : { maxEdges: input.maxEdges }),
261
- ...(input.expandHelpers === undefined ? {} : { expandHelpers: input.expandHelpers }),
262
- ...(input.stateSubject === undefined ? {} : { stateSubject: input.stateSubject }),
263
- ...(input.impactSubject === undefined ? {} : { impactSubject: input.impactSubject }),
264
- ...(input.refresh === undefined ? {} : { refresh: input.refresh }),
265
- ...(context.principal === undefined ? {} : { principal: context.principal }),
266
- signal,
267
- };
268
- }
269
- function renderRequest(input, context, signal) {
270
- return {
271
- workspaceId: input.workspaceId,
272
- view: input.view,
273
- ...(input.selector === undefined
274
- ? {}
275
- : { selector: input.selector }),
276
- ...(input.direction === undefined ? {} : { direction: input.direction }),
277
- ...(input.maxDepth === undefined ? {} : { maxDepth: input.maxDepth }),
278
- ...(input.maxNodes === undefined ? {} : { maxNodes: input.maxNodes }),
279
- ...(input.expandHelpers === undefined ? {} : { expandHelpers: input.expandHelpers }),
280
- ...(input.includeHtml === undefined ? {} : { includeHtml: input.includeHtml }),
281
- ...(input.refresh === undefined ? {} : { refresh: input.refresh }),
282
- ...(context.principal === undefined ? {} : { principal: context.principal }),
283
- signal,
284
- };
285
- }
286
- function compareRequest(input, context, signal) {
287
- return {
288
- workspaceId: input.workspaceId,
289
- ...(input.before === undefined
290
- ? {}
291
- : { before: input.before }),
292
- ...(input.after === undefined
293
- ? {}
294
- : { after: input.after }),
295
- ...(input.proposedSources === undefined
296
- ? {}
297
- : {
298
- proposedSources: input.proposedSources,
299
- }),
300
- ...(input.render === undefined ? {} : { render: input.render }),
301
- ...(input.maxRenderNodes === undefined ? {} : { maxRenderNodes: input.maxRenderNodes }),
302
- ...(input.refresh === undefined ? {} : { refresh: input.refresh }),
303
- ...(context.principal === undefined ? {} : { principal: context.principal }),
304
- signal,
305
- };
306
- }
307
- export function registerEventTools(server, engine, context) {
308
- const viewer = new EventChainViewer(engine);
309
- const cacheLifetime = new IdleCacheLifetime(() => viewer.clearCaches());
310
- server.registerTool('hoi4.event_inspect', {
162
+ export const eventTaskTools = [
163
+ {
164
+ name: 'hoi4.event_inspect',
311
165
  title: 'Inspect event chains',
312
166
  description: 'Scan, find roots, trace, explain paths, inspect state flow, lint, or assess impact. Full source-linked reports are resources.',
313
167
  inputSchema: eventInspectInputSchema,
314
168
  outputSchema: eventInspectOutputSchema,
315
169
  annotations: readOnlyEventTool,
316
- }, async (input, extra) => {
317
- const workspaceId = await resolveServerWorkspaceId(engine, context, input.workspaceId, extra.signal);
318
- const releaseCaches = cacheLifetime.begin();
319
- try {
320
- const progress = progressReporter(extra);
321
- await progress.report(0, 3, 'Analyzing event chain');
322
- const inspected = await viewer.inspect(inspectRequest({ ...input, workspaceId }, context, progress.signal));
323
- await progress.report(2, 3, 'Linking complete event analysis');
324
- const result = emptyServiceResult(workspaceId, {
325
- mode: inspected.mode,
326
- analysisMode: inspected.graph.analysisMode ?? 'full',
327
- revision: inspected.graph.revision,
328
- graphHash: inspected.graphHash,
329
- counts: graphCounts(inspected.graph, inspected.artifacts.length),
330
- boundary: {
331
- direction: input.direction ?? 'both',
332
- maxDepth: input.maxDepth ?? 8,
333
- maxNodes: input.maxNodes ?? 500,
334
- maxEdges: input.maxEdges ?? 2_000,
335
- expandHelpers: input.expandHelpers ?? (input.mode === 'explain_path' ? true : false),
336
- refresh: input.refresh ?? input.mode === 'scan',
337
- },
338
- });
339
- result.code = inspected.graph.complete ? 'EVENT_INSPECTED' : 'EVENT_INSPECTED_PARTIAL';
340
- setInlineFilesScanned(result, inspected.graph.filesScanned);
341
- result.artifacts = inspected.artifacts.map(publicArtifactLink);
342
- result.validation = graphValidation(inspected.graph);
343
- await progress.report(3, 3, 'Event inspection complete');
344
- return toolResult(result);
345
- }
346
- catch (error) {
347
- return errorResult(error, workspaceId);
348
- }
349
- finally {
350
- releaseCaches();
351
- }
352
- });
353
- server.registerTool('hoi4.event_render', {
170
+ },
171
+ {
172
+ name: 'hoi4.event_render',
354
173
  title: 'Render event chains',
355
174
  description: 'Render deterministic JSON, SVG, PNG, and optional HTML for an event-chain view. Complete artifacts retain source links.',
356
175
  inputSchema: eventRenderInputSchema,
357
176
  outputSchema: eventRenderOutputSchema,
358
177
  annotations: readOnlyEventTool,
359
- }, async (input, extra) => {
360
- const workspaceId = await resolveServerWorkspaceId(engine, context, input.workspaceId, extra.signal);
361
- const releaseCaches = cacheLifetime.begin();
362
- try {
363
- const progress = progressReporter(extra);
364
- await progress.report(0, 3, 'Rendering event-chain view');
365
- const rendered = await viewer.renderAndStore(renderRequest({ ...input, workspaceId }, context, progress.signal));
366
- await progress.report(2, 3, 'Linking complete event renders');
367
- const result = emptyServiceResult(workspaceId, {
368
- view: rendered.render.view,
369
- analysisMode: rendered.graph.analysisMode ?? 'full',
370
- revision: rendered.graph.revision,
371
- graphHash: rendered.graphHash,
372
- layoutHash: rendered.render.layout.layoutHash,
373
- hashes: rendered.render.hashes,
374
- counts: {
375
- ...graphCounts(rendered.graph, rendered.artifacts.length),
376
- selectedNodes: rendered.render.selectedNodeIds.length,
377
- omittedNodes: rendered.render.omittedNodeCount,
378
- branchRenders: rendered.branches.length,
379
- },
380
- boundary: {
381
- direction: input.direction ?? 'both',
382
- maxDepth: input.maxDepth ?? 4,
383
- maxNodes: input.maxNodes ?? 120,
384
- expandHelpers: input.expandHelpers ?? false,
385
- includeHtml: input.includeHtml ?? false,
386
- refresh: input.refresh ?? false,
387
- },
388
- });
389
- result.code = rendered.graph.complete ? 'EVENT_RENDERED' : 'EVENT_RENDERED_PARTIAL';
390
- setInlineFilesScanned(result, rendered.graph.filesScanned);
391
- result.artifacts = rendered.artifacts.map(publicArtifactLink);
392
- result.validation = graphValidation(rendered.graph);
393
- await progress.report(3, 3, 'Event render complete');
394
- return toolResult(result);
395
- }
396
- catch (error) {
397
- return errorResult(error, workspaceId);
398
- }
399
- finally {
400
- releaseCaches();
401
- }
402
- });
403
- server.registerTool('hoi4.event_compare', {
178
+ },
179
+ {
180
+ name: 'hoi4.event_compare',
404
181
  title: 'Compare event chains',
405
182
  description: 'Compare cached, artifact-backed, current, or in-memory proposed event graphs without writing source. Full changes are resources.',
406
183
  inputSchema: eventCompareInputSchema,
407
184
  outputSchema: eventCompareOutputSchema,
408
185
  annotations: readOnlyEventTool,
409
- }, async (input, extra) => {
410
- const workspaceId = await resolveServerWorkspaceId(engine, context, input.workspaceId, extra.signal);
411
- const releaseCaches = cacheLifetime.begin();
412
- try {
413
- const progress = progressReporter(extra);
414
- await progress.report(0, 3, 'Comparing event-chain graphs');
415
- const compared = await viewer.compareAndStore(compareRequest({ ...input, workspaceId }, context, progress.signal));
416
- await progress.report(2, 3, 'Linking complete event comparison');
417
- const { comparison } = compared;
418
- const result = emptyServiceResult(workspaceId, {
419
- beforeRevision: comparison.beforeRevision,
420
- afterRevision: comparison.afterRevision,
421
- beforeGraphHash: comparison.beforeGraphHash,
422
- afterGraphHash: comparison.afterGraphHash,
423
- ...(compared.render === undefined ? {} : { renderHashes: compared.render.hashes }),
424
- counts: {
425
- changes: comparison.changes.length,
426
- addedNodes: comparison.addedNodeIds.length,
427
- removedNodes: comparison.removedNodeIds.length,
428
- changedNodes: comparison.changedNodeIds.length,
429
- addedEdges: comparison.addedEdgeIds.length,
430
- removedEdges: comparison.removedEdgeIds.length,
431
- changedEdges: comparison.changedEdgeIds.length,
432
- addedStateAccesses: comparison.addedStateAccessIds.length,
433
- removedStateAccesses: comparison.removedStateAccessIds.length,
434
- changedStateAccesses: comparison.changedStateAccessIds.length,
435
- addedStateLinks: comparison.addedStateLinkIds.length,
436
- removedStateLinks: comparison.removedStateLinkIds.length,
437
- changedStateLinks: comparison.changedStateLinkIds.length,
438
- addedDiagnostics: comparison.addedIssueIds.length,
439
- resolvedDiagnostics: comparison.resolvedIssueIds.length,
440
- addedUnresolved: comparison.addedUnresolvedIds.length,
441
- resolvedUnresolved: comparison.resolvedUnresolvedIds.length,
442
- disconnectedRoots: comparison.newlyDisconnectedRootIds.length,
443
- disconnectedBranches: comparison.newlyDisconnectedBranchIds.length,
444
- disconnectedTerminals: comparison.newlyDisconnectedTerminalIds.length,
445
- beforeSkippedSources: compared.before.skippedSourceCount,
446
- afterSkippedSources: compared.after.skippedSourceCount,
447
- artifacts: compared.artifacts.length,
448
- },
449
- boundary: {
450
- proposedSources: input.proposedSources?.length ?? 0,
451
- render: input.render ?? true,
452
- maxRenderNodes: input.maxRenderNodes ?? 120,
453
- refresh: compared.refresh,
454
- },
455
- });
456
- result.code =
457
- compared.before.complete && compared.after.complete
458
- ? 'EVENT_COMPARED'
459
- : 'EVENT_COMPARED_PARTIAL';
460
- setInlineFilesScanned(result, [...new Set([...compared.before.filesScanned, ...compared.after.filesScanned])].sort(compareCodeUnits));
461
- result.artifacts = compared.artifacts.map(publicArtifactLink);
462
- const beforeValidation = graphValidation(compared.before);
463
- const afterValidation = graphValidation(compared.after);
464
- result.validation = {
465
- passed: beforeValidation.passed && afterValidation.passed,
466
- checks: [...beforeValidation.checks, ...afterValidation.checks].map((check, index) => ({
467
- ...check,
468
- id: `${index === 0 ? 'before' : 'after'}-${check.id}`,
469
- })),
470
- };
471
- await progress.report(3, 3, 'Event comparison complete');
472
- return toolResult(result);
473
- }
474
- catch (error) {
475
- return errorResult(error, workspaceId);
476
- }
477
- finally {
478
- releaseCaches();
479
- }
480
- });
186
+ },
187
+ ];
188
+ export function registerEventTools(server) {
189
+ registerLegacyTaskTools(server, eventTaskTools);
481
190
  }