@px-lsp/protocol 0.1.0 → 0.2.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.
@@ -1,3 +1,4 @@
1
+ import type { DefSource } from "./types";
1
2
  /** Resolved extension settings, computed client-side (path validation, Steam
2
3
  * detection fallbacks, workspace-folder default) and pushed to the server. */
3
4
  export interface ParadoxSettings {
@@ -17,6 +18,16 @@ export interface ParadoxSettings {
17
18
  locLanguage: string;
18
19
  /** Show inferred scope after scope-changing block openers (off by default). */
19
20
  scopeInlayHints: boolean;
21
+ /**
22
+ * How much a hover shows. `standard` applies every cap in the design;
23
+ * `compact` drops prose and examples; `full` lifts the example cap and shows
24
+ * every distinct meaning.
25
+ */
26
+ hoverDetail?: "compact" | "standard" | "full";
27
+ /** Custom era calendar (total-conversion mods): how script dates display in
28
+ * game. Absent = no calendar features. Shape: calendar.ts `CalendarSetting`;
29
+ * the server sanitizes it on intake, so clients may pass raw JSON. */
30
+ calendar?: import("./calendar").CalendarSetting;
20
31
  /** Our diagnostic codes to suppress everywhere. */
21
32
  diagnosticsIgnore: string[];
22
33
  /** Glob patterns (workspace-relative paths) whose diagnostics are suppressed. */
@@ -54,6 +65,25 @@ export interface ParadoxClientCapabilities {
54
65
  * registers one whenever the client supports dynamic registration.
55
66
  */
56
67
  ownFileWatcher?: boolean;
68
+ /**
69
+ * The client's hover renderer navigates `file:` links, so provenance lines
70
+ * ("where is this defined") may be markdown links. Default false: the same
71
+ * `file.txt:12` label is rendered as plain text, which reads correctly in a
72
+ * client that would otherwise show a dead link.
73
+ *
74
+ * Note that `textDocument.completion.completionItem.snippetSupport` — the
75
+ * other axis an embedder should declare — is a STANDARD LSP capability, not
76
+ * one of these: send it in the initialize params, not here.
77
+ */
78
+ fileLinks?: boolean;
79
+ /**
80
+ * The client renders `$(codicon)` theme icons in hover markdown, i.e. it sets
81
+ * `supportThemeIcons` on the MarkdownString. Default false, and the default
82
+ * matters: a client without it prints the literal text `$(symbol-method)`,
83
+ * which is worse than the plain `■` it would otherwise get. Implies
84
+ * {@link ParadoxClientCapabilities.hoverHtml} is respected for colour.
85
+ */
86
+ hoverIcons?: boolean;
57
87
  }
58
88
  /** initializationOptions passed at LanguageClient start. All fields optional:
59
89
  * the server has fail-soft fallbacks for bare clients. */
@@ -66,9 +96,9 @@ export interface ParadoxInitOptions {
66
96
  /**
67
97
  * @deprecated Send {@link ParadoxInitOptions.client} instead. `true` is an
68
98
  * alias for `{ hoverHtml: true, commands: <every id in clientCommands>,
69
- * ownFileWatcher: true }` (what the VSCode extension declared before the
70
- * capabilities object existed); false/absent means all-off. Ignored when
71
- * `client` is present.
99
+ * ownFileWatcher: true, fileLinks: true }` plus snippet support (what the
100
+ * VSCode extension declared before the capabilities object existed);
101
+ * false/absent means all-off. Ignored when `client` is present.
72
102
  */
73
103
  clientCommands?: boolean;
74
104
  /**
@@ -100,6 +130,7 @@ export declare const clientCommands: {
100
130
  readonly editLocalization: "px.editLocalization";
101
131
  readonly openLocalizationSideBySide: "px.openLocalizationSideBySide";
102
132
  readonly showReferences: "px.showReferences";
133
+ readonly showExamplesWiki: "px.showExamplesWiki";
103
134
  };
104
135
  /** Every id in {@link clientCommands}: what a fully capable client registers. */
105
136
  export declare const allClientCommandIds: string[];
@@ -134,6 +165,39 @@ export interface LocEntryInfo {
134
165
  source: "vanilla" | "parent" | "mod";
135
166
  value?: string;
136
167
  }
168
+ /**
169
+ * Request: a localization value as the PLAYER reads it;
170
+ * {@link LocTextParams} -> {@link LocTextResult}.
171
+ *
172
+ * {@link lookupLocRequest} answers the value verbatim, which is what an editor
173
+ * needs. A panel that SHOWS the value needs the sentence: the games write a
174
+ * culture parameter as `"The [GetTrait('rough_terrain_expert').GetName(
175
+ * GetNullCharacter )] Commander Trait is more common"` (145 of the 280
176
+ * parameter values with a real call take that one shape), and a modder reading
177
+ * a form must not be shown the brackets.
178
+ *
179
+ * Everything the renderer knows is DERIVED: the words come from the loc index
180
+ * (mod entries shadow the game's), the kind a `Get<Something>('name')` chain
181
+ * names comes from the definition index, and the loc key that kind's names take
182
+ * comes from the active profile's schema. No table of function names, so a
183
+ * workspace of any of the games gets the same behavior from its own schema.
184
+ */
185
+ export declare const locTextRequest = "paradox/locText";
186
+ export interface LocTextParams extends ModScopedParams {
187
+ keys: string[];
188
+ }
189
+ export interface LocTextValue {
190
+ /** The value verbatim, exactly as {@link lookupLocRequest} answers it. */
191
+ raw: string;
192
+ /** The same value as plain text: markup stripped, datafunctions resolved. */
193
+ text: string;
194
+ /** False when any part of the value stayed a word for something unresolved. */
195
+ resolved: boolean;
196
+ }
197
+ export interface LocTextResult {
198
+ /** Loc key -> its rendering. A key the loc index cannot find is ABSENT. */
199
+ values: Record<string, LocTextValue>;
200
+ }
137
201
  /** Notification: data health for the status bar; payload {@link StatusPayload}. */
138
202
  export declare const statusNotification = "paradox/status";
139
203
  export interface StatusPayload {
@@ -143,6 +207,10 @@ export interface StatusPayload {
143
207
  * (data/<gameId>/script_docs) rather than the user's own dump. */
144
208
  tokensFromBundledDumps?: boolean;
145
209
  definitions: number;
210
+ /** Tokens the bundled wiki added that script_docs did not have. The wiki is
211
+ * merged even when the user has their own dump, but its real contribution is
212
+ * usage examples; the extra NAMES are mostly deprecated API. */
213
+ tokensWikiOnly?: number;
146
214
  /** True while a (re)scan is running. */
147
215
  indexing: boolean;
148
216
  }
@@ -172,6 +240,20 @@ export interface OverviewDef {
172
240
  name: string;
173
241
  file: string;
174
242
  line: number;
243
+ /**
244
+ * The loc-resolved display name, when the kind's loc pattern resolves to one
245
+ * ({@link EventVocabularyItem.label}). Set by {@link definitionFormRequest}
246
+ * only, so a creator listing what the mod already has can show the player's
247
+ * word for it; absent everywhere else.
248
+ */
249
+ label?: string;
250
+ /**
251
+ * Where the definition comes from. Set by {@link definitionFormRequest} only,
252
+ * whose list includes the game's and a dependency's definitions (a creator
253
+ * opens one to duplicate or override it) and must say which is which; absent
254
+ * everywhere else, where every definition listed is the mod's own.
255
+ */
256
+ source?: "vanilla" | "parent" | "mod";
175
257
  }
176
258
  export interface OverviewKind {
177
259
  kind: string;
@@ -374,6 +456,148 @@ export interface EventDetail {
374
456
  options: EventOptionInfo[];
375
457
  refs: EventRefInfo[];
376
458
  }
459
+ /**
460
+ * Request: the searchable catalog behind the Examples Wiki;
461
+ * `null` -> {@link ExampleWikiIndex}.
462
+ *
463
+ * One compact row per name the server knows about, so a client can filter and
464
+ * rank the whole vocabulary without asking again. Everything expensive (the
465
+ * full documentation, the usage block, the vanilla sites) is left to
466
+ * {@link exampleWikiEntryRequest}.
467
+ */
468
+ export declare const exampleWikiRequest = "paradox/exampleWiki";
469
+ /**
470
+ * What an Examples Wiki row is. The first four are engine tokens from
471
+ * script_docs or the wiki tables; the next three are `[ ... ]` datafunctions:
472
+ * a global (`GetPlayer`), a member of a data type (`Character.GetName`), and
473
+ * a data type itself (`Character`). The next seven are the variable and list
474
+ * names the definition index found in the indexed script itself, one kind per
475
+ * storage class ({@link exampleWikiVariableKinds}). The last two are the script
476
+ * grammar the game documents nowhere ({@link exampleWikiVocabularyKinds}): the
477
+ * glue keywords (`limit`, `NOT`, `base`) and the scope words (`root`, `prev`).
478
+ */
479
+ export type ExampleWikiKind = "trigger" | "effect" | "event_target" | "modifier" | "datafn_global" | "datafn_member" | "data_type" | "keyword" | "scope_word" | "variable" | "local_variable" | "global_variable" | "variable_list" | "local_variable_list" | "global_variable_list" | "list";
480
+ /** The {@link ExampleWikiKind}s whose rows come from the definition index. */
481
+ export declare const exampleWikiVariableKinds: ExampleWikiKind[];
482
+ /**
483
+ * The {@link ExampleWikiKind}s whose rows are script grammar rather than a
484
+ * name from a dump or an index. One filter chip covers both.
485
+ */
486
+ export declare const exampleWikiVocabularyKinds: ExampleWikiKind[];
487
+ export interface ExampleWikiEntry {
488
+ /** Display and lookup name; a member carries its owner (`Character.GetName`). */
489
+ name: string;
490
+ kind: ExampleWikiKind;
491
+ /** Owning data type of a member row; absent on every other kind. */
492
+ owner?: string;
493
+ /** First sentence of the documentation, capped; empty when undocumented. */
494
+ shortDoc: string;
495
+ /** Times vanilla uses the name. 0 means "not counted", not "never used". */
496
+ count: number;
497
+ }
498
+ export interface ExampleWikiIndex {
499
+ /** Every row, most-used first. */
500
+ entries: ExampleWikiEntry[];
501
+ /** Plain sentences naming where the rows came from, for an About line. */
502
+ sources: string[];
503
+ /** True when the rows do NOT come from the user's own script_docs dump, so
504
+ * a client can suggest running `script_docs` in the game console. */
505
+ needsScriptDocs: boolean;
506
+ }
507
+ /**
508
+ * Request: everything the toolkit knows about ONE Examples Wiki row;
509
+ * {@link ExampleWikiEntryParams} -> {@link ExampleWikiDetail} | null.
510
+ *
511
+ * `null` means the name is not in the catalog. Vanilla example sites are
512
+ * searched on demand and come back as absolute paths, so a client can open
513
+ * the file at the line without resolving anything itself.
514
+ */
515
+ export declare const exampleWikiEntryRequest = "paradox/exampleWikiEntry";
516
+ export interface ExampleWikiEntryParams {
517
+ name: string;
518
+ kind: ExampleWikiKind;
519
+ }
520
+ /** One place in the game or mod files that uses the name. */
521
+ export interface ExampleWikiSite {
522
+ /** The line as written, trimmed and capped. */
523
+ text: string;
524
+ /** Absolute path. */
525
+ file: string;
526
+ /** 1-based line number. */
527
+ line: number;
528
+ /**
529
+ * The lines around the site as written, dedented and capped, with the `line`
530
+ * line among them. Absent when the file could not be read.
531
+ */
532
+ context?: string[];
533
+ /** 1-based line number of `context[0]`; absent with `context`. */
534
+ contextStart?: number;
535
+ /** What the site does with the name ("set", "read"); absent when it only uses it. */
536
+ label?: string;
537
+ }
538
+ export interface ExampleWikiDetail {
539
+ name: string;
540
+ kind: ExampleWikiKind;
541
+ owner?: string;
542
+ count: number;
543
+ /** Full documentation prose; empty when nothing documents the name. */
544
+ doc: string;
545
+ /** Scopes an engine token works in; empty when unknown. */
546
+ scopes: string[];
547
+ /** The token's remaining script_docs metadata lines, verbatim. */
548
+ traits?: string;
549
+ /** The `usage:` example block from script_docs or the wiki, verbatim. */
550
+ usage?: string;
551
+ /** Datafunction return type; absent when unknown. */
552
+ ret?: string;
553
+ /** Datafunction argument types, when the dump recorded them. */
554
+ args?: string[];
555
+ /** A datafunction is either read like a field or called with parentheses. */
556
+ callKind?: "promote" | "function";
557
+ /** Literal arguments vanilla passes, most used first. */
558
+ literals: string[];
559
+ /** Literals found before the list was capped. */
560
+ literalsTotal: number;
561
+ /** Members of a data type, or nothing on other kinds. */
562
+ members: string[];
563
+ membersTotal: number;
564
+ /** Datafunctions that return this data type. */
565
+ producers: string[];
566
+ producersTotal: number;
567
+ /** What a variable holds, in words ("character", "list of title", "unknown"). */
568
+ valueType?: string;
569
+ /** Top-level definitions a variable is set inside, most sites first. */
570
+ containers?: string[];
571
+ /** Containers found before the list was capped. */
572
+ containersTotal?: number;
573
+ /** Vanilla uses, capped; empty when the search found none. */
574
+ examples: ExampleWikiSite[];
575
+ /** Why the example list looks the way it does, in one sentence. */
576
+ examplesNote?: string;
577
+ /**
578
+ * What can be written FROM each scope this token produces, one entry per
579
+ * `output: S` scope. Present only on a token that declares one; every list
580
+ * is derived from the declared scopes of the other catalog rows.
581
+ */
582
+ fromScope?: ExampleWikiFromScope[];
583
+ /** Where the facts above come from, in one sentence. */
584
+ provenance: string;
585
+ }
586
+ /** Names usable once a token has moved the scope to {@link scope}, most used
587
+ * first. Each list is capped; the `*Total` is what was found before the cap. */
588
+ export interface ExampleWikiFromScope {
589
+ /** The produced scope word, as the game's own docs write it ("faith"). */
590
+ scope: string;
591
+ /** Triggers whose declared scopes include this one. */
592
+ triggers: string[];
593
+ triggersTotal: number;
594
+ /** Effects whose declared scopes include this one. */
595
+ effects: string[];
596
+ effectsTotal: number;
597
+ /** Event targets that take this scope as input. */
598
+ targets: string[];
599
+ targetsTotal: number;
600
+ }
377
601
  /** Request: GUI widget tree for a .gui document; {@link GuiTreeParams} -> {@link GuiTree}. */
378
602
  export declare const guiTreeRequest = "paradox/guiTree";
379
603
  export interface GuiTreeParams {
@@ -404,7 +628,7 @@ export interface GuiTree {
404
628
  /**
405
629
  * Request: rendered GUI layout for a .gui document;
406
630
  * {@link GuiLayoutParams} -> {@link GuiLayoutResult}. Rectangles come from
407
- * the measured layout engine (docs/gui-designer/calibration/spec.md), with
631
+ * the measured layout engine (docs/gui-designer/spec.md), with
408
632
  * templates/types resolved against the vanilla + mod gui tree.
409
633
  */
410
634
  export declare const guiLayoutRequest = "paradox/guiLayout";
@@ -1160,6 +1384,13 @@ export interface EventGraphParams {
1160
1384
  /** Also read each mod event's `theme`. Off by default: it costs one parse per
1161
1385
  * event file, and only a client that draws the theme's art needs it. */
1162
1386
  themes?: boolean;
1387
+ /**
1388
+ * Leave out every definition that has no edge in the answer. ON by default
1389
+ * (absent = true): the pruned definitions are dropped before their cards
1390
+ * are read, so a mod with hundreds of standalone events stays cheap. `root`
1391
+ * is always kept. Send `false` to see the whole namespace, edges or not.
1392
+ */
1393
+ connectedOnly?: boolean;
1163
1394
  }
1164
1395
  /**
1165
1396
  * One row of a mod event's card, in EXECUTION order (immediate, then the
@@ -1282,10 +1513,38 @@ export interface EventVocabularyItem {
1282
1513
  doc?: string;
1283
1514
  /** Dimmer right-hand label: where the value comes from (mod / vanilla / a kind). */
1284
1515
  hint?: string;
1516
+ /**
1517
+ * The name the PLAYER reads: the loc value of the kind's first loc pattern
1518
+ * with `$` replaced by the definition name (`trait_$` -> `trait_brave` ->
1519
+ * "Brave"). Set by {@link definitionFormRequest} only, and absent when
1520
+ * nothing resolves, so a client shows the key rather than an invented word.
1521
+ */
1522
+ label?: string;
1523
+ /**
1524
+ * The family this definition belongs to, when one folder holds several and
1525
+ * the schema entry names the key that says so (`type = ethos` in
1526
+ * common/culture/pillars). Set by {@link definitionFormRequest} only, so a
1527
+ * creator can draw one picker per family; absent everywhere else.
1528
+ */
1529
+ group?: string;
1285
1530
  }
1286
1531
  /** Caps: an editor lists a page at a time, and these ride on every open. */
1287
1532
  export declare const EVENT_VOCABULARY_MAX_TOKENS = 600;
1288
1533
  export declare const EVENT_VOCABULARY_MAX_VALUES = 400;
1534
+ /**
1535
+ * Most values {@link DefinitionFormKey.sampled} carries, and the point past
1536
+ * which a key is taken to have no value SET at all (a key whose value differs
1537
+ * per definition is a free field, not a list to offer).
1538
+ */
1539
+ export declare const DEFINITION_FORM_MAX_SAMPLED = 80;
1540
+ /**
1541
+ * How long a block body {@link DefinitionFormKey.example} may be. A placeholder
1542
+ * is read at a glance, and the shortest bodies a game writes for a block key
1543
+ * (a trait's `triggered_opinion`, a culture's `parameters`) fit well inside
1544
+ * this; a longer one is cut with an ellipsis rather than dropped, because half
1545
+ * a real body still says what the key wants.
1546
+ */
1547
+ export declare const DEFINITION_FORM_MAX_EXAMPLE = 120;
1289
1548
  /**
1290
1549
  * Request: the value set a VALUE belongs to, resolved through the definition
1291
1550
  * index; {@link EventValueOptionsParams} -> {@link EventValueOptionsResult} |
@@ -1404,6 +1663,59 @@ export interface GuiUseSite {
1404
1663
  */
1405
1664
  via: string[];
1406
1665
  }
1666
+ /**
1667
+ * Request: the code snippets a host can offer for one open script document;
1668
+ * {@link SnippetsParams} -> {@link SnippetsResult}. Answers for OPEN script
1669
+ * documents only (the server reads the client's text, not the disk); a document
1670
+ * it does not know answers with an EMPTY list, never an error.
1671
+ *
1672
+ * Two sources, neither hand-written. The definition and child-block skeletons
1673
+ * are the measured shape of the document folder's own definition kind (at least
1674
+ * half of the game's definitions of that kind carry each key, in the median
1675
+ * order they hold there). The token entries are the block form of the `usage:`
1676
+ * example the game's own script_docs dump ships for an engine trigger or effect,
1677
+ * filtered to the block the cursor sits in.
1678
+ *
1679
+ * Every entry carries BOTH insert forms, exactly like completion does: `snippet`
1680
+ * for a host that expands `${1:…}` tabstops, `plain` for one that does not.
1681
+ */
1682
+ export declare const snippetsRequest = "paradox/snippets";
1683
+ export interface SnippetsParams {
1684
+ uri: string;
1685
+ /** 0-based, as in LSP. Decides which engine block templates fit. */
1686
+ position: {
1687
+ line: number;
1688
+ character: number;
1689
+ };
1690
+ }
1691
+ /** One offer, ready to insert at the cursor. */
1692
+ export interface SnippetItem {
1693
+ /**
1694
+ * Stable id: the definition kind (`event`), the kind and its child block
1695
+ * (`event.option`), or the engine token (`if`) — plus `<token>.full` when the
1696
+ * token's example marks fields optional and an all-fields form follows it.
1697
+ * Suitable as a picker key.
1698
+ */
1699
+ id: string;
1700
+ /** Reads as what it inserts: "new event", "option block", "if". */
1701
+ label: string;
1702
+ /** Provenance, with the measurement behind it. */
1703
+ detail: string;
1704
+ /**
1705
+ * `definition` = a whole definition of the document's kind, including the
1706
+ * file header line when the document declares none; `block` = one child block
1707
+ * of that kind; `token` = an engine trigger/effect's own dumped example.
1708
+ */
1709
+ form: "definition" | "block" | "token";
1710
+ /** `${1:…}` tabstop form. */
1711
+ snippet: string;
1712
+ /** The same shape free of `${`, for hosts without snippet expansion. */
1713
+ plain: string;
1714
+ }
1715
+ export interface SnippetsResult {
1716
+ /** Skeletons first (definition, then its child blocks), then engine tokens. */
1717
+ snippets: SnippetItem[];
1718
+ }
1407
1719
  /**
1408
1720
  * Request: the inferred scope chain at a cursor position;
1409
1721
  * {@link ScopeAtParams} -> {@link ScopeAtResult} | null. Answers for OPEN
@@ -1460,3 +1772,348 @@ export interface ScopeAtResult {
1460
1772
  */
1461
1773
  savedScopes: SavedScopeInfo[];
1462
1774
  }
1775
+ /**
1776
+ * Request: everything a visual creator needs to draw a form for one definition
1777
+ * kind; {@link DefinitionFormParams} -> {@link DefinitionForm} | null (null =
1778
+ * the active game's schema has no such kind, which is the honest answer for a
1779
+ * client asking about content this game does not have).
1780
+ *
1781
+ * Nothing in the answer is hand-written for the creator: the folder, the loc
1782
+ * key patterns and the icon folder come from the schema table, the keys from
1783
+ * the harvested `_*.info` structures, the option lists from the definition
1784
+ * index (the same resolver {@link eventValueOptionsRequest} answers with) and
1785
+ * `existing` from the same index walk {@link modOverviewRequest} does. A game
1786
+ * patch that adds a key or a value changes the form without a release.
1787
+ */
1788
+ export declare const definitionFormRequest = "paradox/definitionForm";
1789
+ export interface DefinitionFormParams {
1790
+ /** Definition kind, as the schema table spells it ("trait"). */
1791
+ kind: string;
1792
+ /** Load this definition into `current` (edit rather than create). */
1793
+ name?: string;
1794
+ /** Restrict mod-side entries to one workspace mod (plus vanilla/parents). */
1795
+ modRoot?: string | null;
1796
+ }
1797
+ /** One key of a definition body, with what is known about the values it takes. */
1798
+ export interface DefinitionFormKey {
1799
+ key: string;
1800
+ /** The game's own one-line documentation, capped. Absent when it has none. */
1801
+ doc?: string;
1802
+ /** Coarse value hint from the schema: `loc`, `bool`, `block`, `enum:a|b|c`. */
1803
+ values?: string;
1804
+ /** Vanilla usage count from the harvest, the order the keys arrive in. */
1805
+ freq?: number;
1806
+ /**
1807
+ * Definition kinds this key's value names, when the profile says so. The
1808
+ * lists live in {@link DefinitionForm.options}, keyed by kind, so several
1809
+ * keys naming the same kind share one list.
1810
+ */
1811
+ refKinds?: string[];
1812
+ /**
1813
+ * The values the indexed definitions of this kind actually write for this
1814
+ * key, most used first, for keys no definition index can answer (a culture's
1815
+ * `clothing_gfx` names an art set, not a definition). Measured from the game
1816
+ * and mod files the server has indexed, at request time, so a patch changes
1817
+ * the list without a release; absent when the key has no refKinds-free value
1818
+ * set of at most {@link DEFINITION_FORM_MAX_SAMPLED} entries, which is the
1819
+ * honest answer for a key whose value is different in every definition.
1820
+ */
1821
+ sampled?: string[];
1822
+ /**
1823
+ * The literal the indexed definitions of this kind write most often for this
1824
+ * key: a real value, so a form can show it as the input's placeholder
1825
+ * instead of inventing one. Unlike {@link sampled} it counts numbers and
1826
+ * quoted text too (quotes stripped), and it survives the cap, so a key whose
1827
+ * value differs in every definition still has an example.
1828
+ *
1829
+ * A key whose value is a BLOCK gets the most written body instead, collapsed
1830
+ * onto one line and capped at {@link DEFINITION_FORM_MAX_EXAMPLE}
1831
+ * characters, so a script field has a placeholder too.
1832
+ *
1833
+ * A key whose value set is already stated (`bool`, `enum:`) carries an
1834
+ * example as well, though no {@link sampled}: a dropdown showing the value
1835
+ * the game itself writes says more than one reading "not set".
1836
+ */
1837
+ example?: string;
1838
+ }
1839
+ export interface DefinitionForm {
1840
+ kind: string;
1841
+ /** Schema path the definition is written into, e.g. `common/traits`. */
1842
+ folder: string;
1843
+ /**
1844
+ * Every loc key the game reads for this kind, `$` being the definition name
1845
+ * (`trait_$_desc`). The full set a form should offer, not the conservative
1846
+ * `requiredLoc` subset a diagnostic is allowed to demand.
1847
+ */
1848
+ locPatterns: string[];
1849
+ /** Where the game looks for this kind's icon, e.g. `gfx/interface/icons/traits`. */
1850
+ iconFolder?: string;
1851
+ /** Top-level keys, harvest order (most used first), curated keys ahead. */
1852
+ keys: DefinitionFormKey[];
1853
+ /** Named sub-blocks with their own keys, when the harvest has them. */
1854
+ blocks?: Record<string, DefinitionFormKey[]>;
1855
+ /** Ref kind -> every indexed definition of it, mod entries first, capped. */
1856
+ options: Record<string, EventVocabularyItem[]>;
1857
+ /**
1858
+ * Trigger name -> the values that trigger accepts, for the handful of
1859
+ * triggers a no-code condition builder offers rows for (`has_dlc_feature`,
1860
+ * `has_game_rule`, `scripted_trigger`). Which triggers those are, and where
1861
+ * each list comes from, is the game profile's own table; the values
1862
+ * themselves are read from what the server already holds (the trigger's own
1863
+ * script_docs entry, the definition index), never written for the creator.
1864
+ * A trigger with no resolvable list is ABSENT rather than empty, so a client
1865
+ * offers a free input instead of a picker with nothing in it.
1866
+ */
1867
+ conditions?: Record<string, EventVocabularyItem[]>;
1868
+ /** The modifier vocabulary, most used first: what a modifier row may offer. */
1869
+ modifiers: {
1870
+ name: string;
1871
+ doc?: string;
1872
+ }[];
1873
+ /** Definitions of this kind the mod already has (modRoot or every workspace mod). */
1874
+ existing: OverviewDef[];
1875
+ /** The definition `params.name` asked for, when it is indexed. */
1876
+ current?: {
1877
+ file: string;
1878
+ /** 0-based. */
1879
+ line: number;
1880
+ source: DefSource;
1881
+ /** The block verbatim, `name = { ... }`, exactly as the file has it. */
1882
+ text: string;
1883
+ };
1884
+ }
1885
+ /**
1886
+ * Request: text edits that write a definition into a script file;
1887
+ * {@link DefinitionEditParams} -> {@link DefinitionEditResult}. The script
1888
+ * sibling of {@link guiSourceEditRequest}, over the same span model, and with
1889
+ * the same division of labour: the server never writes, it returns offsets
1890
+ * into the text it was handed and the host applies them as ONE
1891
+ * `WorkspaceEdit`, which keeps undo and dirty state in the editor.
1892
+ *
1893
+ * Offsets are UTF-16 into `params.text` (the document text, with no BOM, the
1894
+ * way an editor delivers it), computed against that one text and applied
1895
+ * end-first. Every edit is surgical, so a file's other definitions, its
1896
+ * comments, its CRLF and its indentation stay byte-identical.
1897
+ */
1898
+ export declare const definitionEditRequest = "paradox/definitionEdit";
1899
+ export interface DefinitionEditParams {
1900
+ /** For display only; the text is authoritative. */
1901
+ uri: string;
1902
+ /** Authoritative document text every offset refers to. */
1903
+ text: string;
1904
+ /** Computed in order against the one text and answered as one edit set. */
1905
+ ops: DefinitionOp[];
1906
+ }
1907
+ export type DefinitionOp =
1908
+ /**
1909
+ * Set or (with a null value) remove keys on the top-level definition `name`.
1910
+ * `value` is raw script text: `2`, `{ craven }`, `"quoted"`.
1911
+ */
1912
+ {
1913
+ op: "setProperties";
1914
+ name: string;
1915
+ properties: {
1916
+ key: string;
1917
+ value: string | null;
1918
+ }[];
1919
+ }
1920
+ /**
1921
+ * Write the whole `name = { ... }` block: replaces the top-level block of
1922
+ * that name, or appends it after a blank separator line when the file has
1923
+ * none.
1924
+ */
1925
+ | {
1926
+ op: "upsertBlock";
1927
+ name: string;
1928
+ text: string;
1929
+ };
1930
+ export interface DefinitionEditResult {
1931
+ /** Every applied op's edits together. Apply the whole set as ONE change. */
1932
+ edits: GuiTextEdit[];
1933
+ /** One verdict per requested op, in request order; `refused` names why it wrote nothing. */
1934
+ ops: {
1935
+ refused?: string;
1936
+ }[];
1937
+ }
1938
+ /**
1939
+ * Request: how the GAME prints each modifier; {@link ModifierFormatsParams} ->
1940
+ * {@link ModifierFormatsResult} | null (null = the active profile names no
1941
+ * formats source, or the game folder is not configured).
1942
+ *
1943
+ * A creator that lets a modder add `monthly_income = 0.5` has to show what the
1944
+ * player will see, and the player sees "[gold_i] +0.50 Monthly Income" in
1945
+ * green. None of that is written here: the flags come from the game's own
1946
+ * `common/modifier_definition_formats/` (documented by `_definitions.info`
1947
+ * there), every word comes from the loc index, and every icon comes from the
1948
+ * `texticon` blocks of the game's `gui/texticons.gui`. A modifier no format
1949
+ * block names gets the file's documented defaults, so the answer covers every
1950
+ * modifier token the server knows rather than only the formatted ones.
1951
+ */
1952
+ export declare const modifierFormatsRequest = "paradox/modifierFormats";
1953
+ export interface ModifierFormatsParams extends ModScopedParams {
1954
+ /**
1955
+ * Loc keys to render as parts too, through the same texticon chain the
1956
+ * prefixes take. A client that prints a line of the game's own UI (a cost
1957
+ * line such as `"[prestige_i] $VALUE|0$"`) asks for the key and gets its
1958
+ * icon and text back; a key the loc index cannot resolve is absent.
1959
+ */
1960
+ lines?: string[];
1961
+ }
1962
+ /**
1963
+ * One piece of a prefix or suffix: a word, or a texticon. `[gold_i]` in a loc
1964
+ * value resolves through `game_concept_gold_i` = `"@gold_icon!"` to the
1965
+ * `texticon` block naming the sprite, which is what an icon part carries.
1966
+ */
1967
+ export type FormatPart = {
1968
+ text: string;
1969
+ } | {
1970
+ icon: {
1971
+ texture: string;
1972
+ uv?: [number, number, number, number];
1973
+ };
1974
+ };
1975
+ /** How one modifier is printed, straight out of the game's own format files. */
1976
+ export interface ModifierFormat {
1977
+ /** The player's word for the modifier, loc-resolved; the key title-cased when it has none. */
1978
+ label: string;
1979
+ /** Digits after the point. The file's documented default is 2. */
1980
+ decimals: number;
1981
+ /** Scale the value by 100 and print a `%`. */
1982
+ percent?: boolean;
1983
+ /** Print a `%` without scaling: the value already is one. */
1984
+ alreadyPercent?: boolean;
1985
+ /** Which direction is good for the player. The file's documented default is `bad`. */
1986
+ color: "good" | "neutral" | "bad";
1987
+ /** `no_difference_sign`: print the number without a leading `+`/`-`. */
1988
+ noSign?: boolean;
1989
+ /** The game does not show this modifier at all. */
1990
+ hidden?: boolean;
1991
+ /** Drawn before the number (`[gold_i]`). */
1992
+ prefix?: FormatPart[];
1993
+ /** Drawn after the number (`/month`). */
1994
+ suffix?: FormatPart[];
1995
+ /** Used in place of `suffix` for negative values, when the game defines one. */
1996
+ negativeSuffix?: FormatPart[];
1997
+ }
1998
+ export interface ModifierFormatsResult {
1999
+ /** Modifier name -> its format. Every modifier token the server knows. */
2000
+ formats: Record<string, ModifierFormat>;
2001
+ /** Loc key -> its parts, for each `lines` entry the loc index resolved. */
2002
+ lines?: Record<string, FormatPart[]>;
2003
+ }
2004
+ /**
2005
+ * Request: a dynasty as a family tree; {@link DynastyTreeParams} ->
2006
+ * {@link DynastyTreeResult}.
2007
+ *
2008
+ * Two answers behind one method. Without `dynasty` the result is the picker
2009
+ * list: every dynasty the index knows, mod entries first. With `dynasty` it is
2010
+ * that dynasty's houses and members, read out of the game's own
2011
+ * `history/characters` files.
2012
+ *
2013
+ * Everything is DERIVED: the folders come from the active profile's schema
2014
+ * (`dynasty`, `dynasty_house`, `character` kinds), the members from the
2015
+ * character blocks themselves, the display names from the loc index. A profile
2016
+ * whose schema has no `dynasty` kind answers `supported: false` and empty
2017
+ * lists, which is what a client shows instead of an empty tree.
2018
+ */
2019
+ export declare const dynastyTreeRequest = "paradox/dynastyTree";
2020
+ export interface DynastyTreeParams extends ModScopedParams {
2021
+ /** A dynasty id: answer that dynasty's houses and members instead of the list. */
2022
+ dynasty?: string;
2023
+ }
2024
+ /** One dynasty, as the picker lists it. */
2025
+ export interface DynastySummary {
2026
+ /** The block's own key, which is what a character's `dynasty = ` names. */
2027
+ id: string;
2028
+ /** The `name = ` value, a loc key (`dynn_Karling`). */
2029
+ nameKey: string;
2030
+ /** The loc text when the server can resolve it, else `nameKey` itself. */
2031
+ name: string;
2032
+ culture?: string;
2033
+ source: DefSource;
2034
+ file: string;
2035
+ /** 0-based. */
2036
+ line: number;
2037
+ /** Characters whose `dynasty`, or whose house's dynasty, is this one. */
2038
+ characterCount: number;
2039
+ houseCount: number;
2040
+ }
2041
+ /** One house of a dynasty (`house_karling = { name = … dynasty = 25061 }`). */
2042
+ export interface DynastyHouse {
2043
+ id: string;
2044
+ nameKey: string;
2045
+ name: string;
2046
+ /** The dynasty id the house belongs to. */
2047
+ dynasty: string;
2048
+ source: DefSource;
2049
+ file: string;
2050
+ /** 0-based. */
2051
+ line: number;
2052
+ }
2053
+ /**
2054
+ * The character-level skill keys, in the order a client shows them. MEASURED
2055
+ * over the vanilla `history/characters` corpus (2026-09-03): stewardship 8 964,
2056
+ * martial 8 940, diplomacy 8 908, intrigue 8 892, learning 495, prowess 150.
2057
+ */
2058
+ export declare const DYNASTY_SKILLS: readonly ["diplomacy", "martial", "stewardship", "intrigue", "learning", "prowess"];
2059
+ /**
2060
+ * One character of `history/characters`. Dates are the game's own
2061
+ * `Y.M.D` strings, taken from the dated block that carries the `birth`/`death`
2062
+ * statement.
2063
+ */
2064
+ export interface DynastyCharacter {
2065
+ /** The block's own key: numeric in vanilla, but `han_1234` shapes exist too. */
2066
+ id: string;
2067
+ /** The `name = ` value, a plain string in history, not a loc key. */
2068
+ name: string;
2069
+ female: boolean;
2070
+ dynasty?: string;
2071
+ /** `dynasty_house = `; a character carries the house OR the dynasty, not both. */
2072
+ house?: string;
2073
+ father?: string;
2074
+ mother?: string;
2075
+ culture?: string;
2076
+ religion?: string;
2077
+ /** `Y.M.D` of the dated block holding `birth`. */
2078
+ birth?: string;
2079
+ death?: string;
2080
+ /**
2081
+ * `dna = `, the portrait DNA name, without the quotes the file may put
2082
+ * around it (350 of 438 vanilla statements write it bare).
2083
+ */
2084
+ dna?: string;
2085
+ /**
2086
+ * The skills the block sets, keyed by {@link DYNASTY_SKILLS}. A skill the
2087
+ * block does not name is absent, which is not the same as zero: the game
2088
+ * rolls one it was not given.
2089
+ */
2090
+ skills?: Record<string, number>;
2091
+ traits: string[];
2092
+ /** Ids this character is married to (`add_spouse`), in file order. */
2093
+ spouses: string[];
2094
+ /**
2095
+ * Set when the character belongs to ANOTHER dynasty and is only in the
2096
+ * answer because a member names them as a parent or a spouse. A client draws
2097
+ * them, but the tree is not theirs.
2098
+ */
2099
+ external?: true;
2100
+ source: DefSource;
2101
+ file: string;
2102
+ /** 0-based. */
2103
+ line: number;
2104
+ }
2105
+ export interface DynastyTreeResult {
2106
+ /** False when the active profile's schema has no `dynasty` kind. */
2107
+ supported: boolean;
2108
+ /** The picker list. Empty when `params.dynasty` asked for one dynasty. */
2109
+ dynasties: DynastySummary[];
2110
+ /** Present exactly when `params.dynasty` named a dynasty the index knows. */
2111
+ dynasty?: DynastySummary;
2112
+ houses?: DynastyHouse[];
2113
+ /** Members plus the external parents and spouses they name. */
2114
+ characters?: DynastyCharacter[];
2115
+ /** Largest numeric character id across game and mods, plus one. */
2116
+ nextCharacterId?: string;
2117
+ /** Largest numeric dynasty id across game and mods, plus one. */
2118
+ nextDynastyId?: string;
2119
+ }