@iamjameslennon/ddb-mcp 2.8.0 → 2.9.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.
Files changed (88) hide show
  1. package/dist/browser.d.ts.map +1 -1
  2. package/dist/browser.js +19 -4
  3. package/dist/browser.js.map +1 -1
  4. package/dist/index.js +10 -18
  5. package/dist/index.js.map +1 -1
  6. package/dist/tools/campaign.js +1 -1
  7. package/dist/tools/campaign.js.map +1 -1
  8. package/dist/tools/character/ac.d.ts +20 -0
  9. package/dist/tools/character/ac.d.ts.map +1 -0
  10. package/dist/tools/character/ac.js +83 -0
  11. package/dist/tools/character/ac.js.map +1 -0
  12. package/dist/tools/character/actions.d.ts +22 -0
  13. package/dist/tools/character/actions.d.ts.map +1 -0
  14. package/dist/tools/character/actions.js +110 -0
  15. package/dist/tools/character/actions.js.map +1 -0
  16. package/dist/tools/character/core.d.ts +15 -0
  17. package/dist/tools/character/core.d.ts.map +1 -0
  18. package/dist/tools/character/core.js +156 -0
  19. package/dist/tools/character/core.js.map +1 -0
  20. package/dist/tools/character/defenses.d.ts +16 -0
  21. package/dist/tools/character/defenses.d.ts.map +1 -0
  22. package/dist/tools/character/defenses.js +27 -0
  23. package/dist/tools/character/defenses.js.map +1 -0
  24. package/dist/tools/character/definition.d.ts +14 -0
  25. package/dist/tools/character/definition.d.ts.map +1 -0
  26. package/dist/tools/character/definition.js +205 -0
  27. package/dist/tools/character/definition.js.map +1 -0
  28. package/dist/tools/character/features.d.ts +26 -0
  29. package/dist/tools/character/features.d.ts.map +1 -0
  30. package/dist/tools/character/features.js +107 -0
  31. package/dist/tools/character/features.js.map +1 -0
  32. package/dist/tools/character/helpers.d.ts +57 -0
  33. package/dist/tools/character/helpers.d.ts.map +1 -0
  34. package/dist/tools/character/helpers.js +80 -0
  35. package/dist/tools/character/helpers.js.map +1 -0
  36. package/dist/tools/character/identity.d.ts +19 -0
  37. package/dist/tools/character/identity.d.ts.map +1 -0
  38. package/dist/tools/character/identity.js +84 -0
  39. package/dist/tools/character/identity.js.map +1 -0
  40. package/dist/tools/character/inventory.d.ts +21 -0
  41. package/dist/tools/character/inventory.d.ts.map +1 -0
  42. package/dist/tools/character/inventory.js +61 -0
  43. package/dist/tools/character/inventory.js.map +1 -0
  44. package/dist/tools/character/notes.d.ts +20 -0
  45. package/dist/tools/character/notes.d.ts.map +1 -0
  46. package/dist/tools/character/notes.js +63 -0
  47. package/dist/tools/character/notes.js.map +1 -0
  48. package/dist/tools/character/parse.d.ts +13 -0
  49. package/dist/tools/character/parse.d.ts.map +1 -0
  50. package/dist/tools/character/parse.js +82 -0
  51. package/dist/tools/character/parse.js.map +1 -0
  52. package/dist/tools/character/spells.d.ts +26 -0
  53. package/dist/tools/character/spells.d.ts.map +1 -0
  54. package/dist/tools/character/spells.js +237 -0
  55. package/dist/tools/character/spells.js.map +1 -0
  56. package/dist/tools/character/stats.d.ts +33 -0
  57. package/dist/tools/character/stats.d.ts.map +1 -0
  58. package/dist/tools/character/stats.js +372 -0
  59. package/dist/tools/character/stats.js.map +1 -0
  60. package/dist/tools/character/templates.d.ts +22 -0
  61. package/dist/tools/character/templates.d.ts.map +1 -0
  62. package/dist/tools/character/templates.js +61 -0
  63. package/dist/tools/character/templates.js.map +1 -0
  64. package/dist/tools/character/types.d.ts +133 -0
  65. package/dist/tools/character/types.d.ts.map +1 -0
  66. package/dist/tools/character/types.js +12 -0
  67. package/dist/tools/character/types.js.map +1 -0
  68. package/dist/tools/character/vitals.d.ts +34 -0
  69. package/dist/tools/character/vitals.d.ts.map +1 -0
  70. package/dist/tools/character/vitals.js +198 -0
  71. package/dist/tools/character/vitals.js.map +1 -0
  72. package/dist/tools/character/weapons.d.ts +13 -0
  73. package/dist/tools/character/weapons.d.ts.map +1 -0
  74. package/dist/tools/character/weapons.js +79 -0
  75. package/dist/tools/character/weapons.js.map +1 -0
  76. package/dist/tools/character.d.ts +13 -3
  77. package/dist/tools/character.d.ts.map +1 -1
  78. package/dist/tools/character.js +18 -1181
  79. package/dist/tools/character.js.map +1 -1
  80. package/dist/tools/library.d.ts +32 -4
  81. package/dist/tools/library.d.ts.map +1 -1
  82. package/dist/tools/library.js +181 -86
  83. package/dist/tools/library.js.map +1 -1
  84. package/dist/tools/search.d.ts +1 -2
  85. package/dist/tools/search.d.ts.map +1 -1
  86. package/dist/tools/search.js +36 -59
  87. package/dist/tools/search.js.map +1 -1
  88. package/package.json +2 -1
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Features domain — feats (real + disguised), class features, racial traits,
3
+ * background feature. Owns the features block.
4
+ *
5
+ * Phase 5c of the character.ts refactor — see docs/character-refactor.md.
6
+ *
7
+ * Output strings are pre-formatted (e.g. featLines = ["• Great Weapon Master: …"])
8
+ * to preserve byte-for-byte parity with the original inline code.
9
+ */
10
+ import { arr, hasTag, num, obj, str, stripHtml } from "./helpers.js";
11
+ // ── Feats ────────────────────────────────────────────────────────────────────
12
+ function buildFeatLines(char, resolveTemplates) {
13
+ // DDB stores some non-feat entries in the feats array.
14
+ // __DISGUISE_FEAT = class features surfaced as feats (shown in OTHER FEATURES).
15
+ // __INITIAL_ASI = 2024 background Ability Score Improvements (already in ABILITY SCORES; drop entirely).
16
+ const allFeats = arr(char.feats);
17
+ const realFeats = allFeats.filter(f => !hasTag(f, "__DISGUISE_FEAT") && !hasTag(f, "__INITIAL_ASI"));
18
+ const disguisedFeats = allFeats.filter(f => hasTag(f, "__DISGUISE_FEAT"));
19
+ const featLines = realFeats.map(f => {
20
+ const def = obj(f.definition);
21
+ const snippet = resolveTemplates(stripHtml(str(def.snippet || def.description))).slice(0, 120);
22
+ return `• ${str(def.name)}${snippet ? `: ${snippet}${snippet.length >= 120 ? "…" : ""}` : ""}`;
23
+ });
24
+ const disguisedFeatLines = disguisedFeats.map(f => `• ${str(obj(f.definition).name)}`);
25
+ return { featLines, disguisedFeatLines, realFeatCount: realFeats.length };
26
+ }
27
+ // ── Class features ───────────────────────────────────────────────────────────
28
+ function buildClassFeatureLines(classes) {
29
+ const lines = [];
30
+ const seen = new Set();
31
+ for (const c of classes) {
32
+ const charLevel = num(c.level);
33
+ for (const cf of arr(c.classFeatures)) {
34
+ const def = obj(cf.definition);
35
+ const line = `• ${str(def.name)} (${str(obj(c.definition).name)} ${num(def.requiredLevel || 1)})`;
36
+ if (num(def.requiredLevel || 0) <= charLevel && !seen.has(line)) {
37
+ seen.add(line);
38
+ lines.push(line);
39
+ }
40
+ }
41
+ }
42
+ return lines;
43
+ }
44
+ // ── Racial traits ────────────────────────────────────────────────────────────
45
+ function buildRacialTraitLines(char) {
46
+ return arr(obj(char.race).racialTraits).map(t => `• ${str(obj(t.definition).name)}`);
47
+ }
48
+ // ── Background feature ───────────────────────────────────────────────────────
49
+ function buildBackgroundFeature(char, resolveTemplates) {
50
+ // For custom backgrounds, featureName may reflect a feat name rather than
51
+ // the actual background feature. Check customBackground first if present.
52
+ const bgObj = obj(char.background);
53
+ const customBg = obj(bgObj.customBackground);
54
+ const featuresBackgroundDef = obj(obj(customBg.featuresBackground).definition);
55
+ const customBgDef = Object.keys(featuresBackgroundDef).length > 0
56
+ ? featuresBackgroundDef
57
+ : obj(customBg.definition);
58
+ const bgDef = Object.keys(customBgDef).length > 0 ? customBgDef : obj(bgObj.definition);
59
+ return {
60
+ name: str(bgDef.featureName),
61
+ isFeat: bgDef.featureIsFeat === true,
62
+ descSnippet: bgDef.featureDescription
63
+ ? resolveTemplates(stripHtml(str(bgDef.featureDescription))).slice(0, 300)
64
+ : "",
65
+ };
66
+ }
67
+ // ── Public API ───────────────────────────────────────────────────────────────
68
+ export function computeFeatures(core) {
69
+ const { char, classes, resolveTemplates } = core;
70
+ const { featLines, disguisedFeatLines, realFeatCount } = buildFeatLines(char, resolveTemplates);
71
+ return {
72
+ featLines,
73
+ disguisedFeatLines,
74
+ realFeatCount,
75
+ classFeatureLines: buildClassFeatureLines(classes),
76
+ racialTraitLines: buildRacialTraitLines(char),
77
+ background: buildBackgroundFeature(char, resolveTemplates),
78
+ };
79
+ }
80
+ export function formatFeaturesBlock(f) {
81
+ return [
82
+ `FEATS (${f.realFeatCount})`,
83
+ ...(f.featLines.length ? f.featLines : [" (none)"]),
84
+ ``,
85
+ ...(f.disguisedFeatLines.length ? [
86
+ `OTHER FEATURES (stored as feats in API but NOT player-chosen feats)`,
87
+ ...f.disguisedFeatLines,
88
+ ``,
89
+ ] : []),
90
+ `CLASS FEATURES`,
91
+ ...f.classFeatureLines,
92
+ ``,
93
+ `RACIAL TRAITS`,
94
+ ...f.racialTraitLines,
95
+ ``,
96
+ ...(!f.background.name || f.background.isFeat ? [] : (() => {
97
+ const desc = f.background.descSnippet;
98
+ const descSnippet = desc ? `${desc}${desc.length >= 300 ? "…" : ""}` : "";
99
+ return [
100
+ `BACKGROUND FEATURE`,
101
+ ` ${f.background.name}${descSnippet ? `: ${descSnippet}` : ""}`,
102
+ ``,
103
+ ];
104
+ })()),
105
+ ];
106
+ }
107
+ //# sourceMappingURL=features.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"features.js","sourceRoot":"","sources":["../../../src/tools/character/features.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Primitive helpers shared across the character module.
3
+ *
4
+ * Phase 1 of the character.ts refactor — see docs/character-refactor.md.
5
+ * No business logic — pure type/string/number utilities.
6
+ */
7
+ import type { Mod, ProficiencyMod, ExpertiseMod, HalfProficiencyMod, BonusMod, SetMod, SetBaseMod, SenseMod, ResistanceMod, ImmunityMod, VulnerabilityMod, LanguageMod } from "./types.js";
8
+ export declare const str: (v: unknown) => string;
9
+ export declare const num: (v: unknown) => number;
10
+ export declare const arr: <T>(v: unknown) => T[];
11
+ export declare const obj: (v: unknown) => Record<string, unknown>;
12
+ export declare const signed: (n: number) => string;
13
+ export declare const modOf: (score: number) => number;
14
+ export declare const capitalize: (s: string) => string;
15
+ /**
16
+ * Lightweight HTML strip + whitespace collapse. Used for character snippets
17
+ * (one-line summaries). For full HTML stripping with entity decoding, see
18
+ * `stripHtml` in `src/utils.ts`.
19
+ */
20
+ export declare const stripHtml: (s: string) => string;
21
+ /** Returns true if the feat has the given category tagName. */
22
+ export declare const hasTag: (feat: Mod, tag: string) => boolean;
23
+ export declare const isProficiencyMod: (m: Mod) => m is Mod & ProficiencyMod;
24
+ export declare const isExpertiseMod: (m: Mod) => m is Mod & ExpertiseMod;
25
+ export declare const isHalfProficiencyMod: (m: Mod) => m is Mod & HalfProficiencyMod;
26
+ export declare const isBonusMod: (m: Mod) => m is Mod & BonusMod;
27
+ export declare const isSetMod: (m: Mod) => m is Mod & SetMod;
28
+ export declare const isSetBaseMod: (m: Mod) => m is Mod & SetBaseMod;
29
+ export declare const isSenseMod: (m: Mod) => m is Mod & SenseMod;
30
+ export declare const isResistanceMod: (m: Mod) => m is Mod & ResistanceMod;
31
+ export declare const isImmunityMod: (m: Mod) => m is Mod & ImmunityMod;
32
+ export declare const isVulnerabilityMod: (m: Mod) => m is Mod & VulnerabilityMod;
33
+ export declare const isLanguageMod: (m: Mod) => m is Mod & LanguageMod;
34
+ /**
35
+ * True if any class entry is a Champion Fighter at level 7+ — the
36
+ * threshold at which the Remarkable Athlete feature kicks in. DDB does
37
+ * NOT emit a `half-proficiency` modifier for Remarkable Athlete (the way
38
+ * it does for Bard's Jack of All Trades), so this predicate is the only
39
+ * way to detect the feature reliably. Used by:
40
+ * - vitals.ts: adds half prof to initiative
41
+ * - stats.ts: adds half prof to non-proficient STR/DEX/CON skills
42
+ *
43
+ * Detection accepts both shapes DDB has used for subclassDefinition
44
+ * (`{ name: "..." }` and `{ definition: { name: "..." } }`).
45
+ */
46
+ export declare function hasRemarkableAthlete(classes: ReadonlyArray<Record<string, unknown>>): boolean;
47
+ /** Display labels for the six ability scores, in canonical order. */
48
+ export declare const statNames: string[];
49
+ /** Internal slugs for the six ability scores, in canonical order (matches statNames). */
50
+ export declare const statKeys: string[];
51
+ /**
52
+ * Levenshtein edit distance between two strings. Used by character-name
53
+ * fuzzy resolution (character.ts) and definition-query matching
54
+ * (definition.ts).
55
+ */
56
+ export declare function levenshteinDistance(a: string, b: string): number;
57
+ //# sourceMappingURL=helpers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/tools/character/helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,cAAc,EAAE,YAAY,EAAE,kBAAkB,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,aAAa,EAAE,WAAW,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAE3L,eAAO,MAAM,GAAG,GAAI,GAAG,OAAO,KAAG,MAAsC,CAAC;AACxE,eAAO,MAAM,GAAG,GAAI,GAAG,OAAO,KAAG,MAAyC,CAAC;AAC3E,eAAO,MAAM,GAAG,GAAI,CAAC,EAAE,GAAG,OAAO,KAAG,CAAC,EAA0C,CAAC;AAChF,eAAO,MAAM,GAAG,GAAI,GAAG,OAAO,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAEd,CAAC;AAE1C,eAAO,MAAM,MAAM,GAAI,GAAG,MAAM,KAAG,MAAqC,CAAC;AACzE,eAAO,MAAM,KAAK,GAAI,OAAO,MAAM,KAAG,MAAsC,CAAC;AAC7E,eAAO,MAAM,UAAU,GAAI,GAAG,MAAM,KAAG,MAAgD,CAAC;AAExF;;;;GAIG;AACH,eAAO,MAAM,SAAS,GAAI,GAAG,MAAM,KAAG,MACiB,CAAC;AAExD,+DAA+D;AAC/D,eAAO,MAAM,MAAM,GAAI,MAAM,GAAG,EAAE,KAAK,MAAM,KAAG,OAC4C,CAAC;AAO7F,eAAO,MAAM,gBAAgB,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,cACM,CAAC;AAE5D,eAAO,MAAM,cAAc,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,YACM,CAAC;AAE1D,eAAO,MAAM,oBAAoB,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,kBACO,CAAC;AAEjE,eAAO,MAAM,UAAU,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,QACM,CAAC;AAEtD,eAAO,MAAM,QAAQ,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,MACM,CAAC;AAEpD,eAAO,MAAM,YAAY,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,UACO,CAAC;AAEzD,eAAO,MAAM,UAAU,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,QACM,CAAC;AAEtD,eAAO,MAAM,eAAe,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,aACM,CAAC;AAE3D,eAAO,MAAM,aAAa,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,WACM,CAAC;AAEzD,eAAO,MAAM,kBAAkB,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,gBACM,CAAC;AAE9D,eAAO,MAAM,aAAa,GAAI,GAAG,GAAG,KAAG,CAAC,IAAI,GAAG,GAAG,WACM,CAAC;AAEzD;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG,OAAO,CAM7F;AAED,qEAAqE;AACrE,eAAO,MAAM,SAAS,UAA6C,CAAC;AAEpE,yFAAyF;AACzF,eAAO,MAAM,QAAQ,UAAkF,CAAC;AAExG;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAahE"}
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Primitive helpers shared across the character module.
3
+ *
4
+ * Phase 1 of the character.ts refactor — see docs/character-refactor.md.
5
+ * No business logic — pure type/string/number utilities.
6
+ */
7
+ export const str = (v) => (v != null ? String(v) : "");
8
+ export const num = (v) => (typeof v === "number" ? v : 0);
9
+ export const arr = (v) => (Array.isArray(v) ? v : []);
10
+ export const obj = (v) => v != null && typeof v === "object" && !Array.isArray(v)
11
+ ? v : {};
12
+ export const signed = (n) => (n >= 0 ? `+${n}` : `${n}`);
13
+ export const modOf = (score) => Math.floor((score - 10) / 2);
14
+ export const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);
15
+ /**
16
+ * Lightweight HTML strip + whitespace collapse. Used for character snippets
17
+ * (one-line summaries). For full HTML stripping with entity decoding, see
18
+ * `stripHtml` in `src/utils.ts`.
19
+ */
20
+ export const stripHtml = (s) => s.replace(/<[^>]+>/g, "").replace(/\s+/g, " ").trim();
21
+ /** Returns true if the feat has the given category tagName. */
22
+ export const hasTag = (feat, tag) => arr(obj(feat.definition).categories).some(c => c.tagName === tag);
23
+ // ── Mod type guards (follow-up A) ─────────────────────────────────────────────
24
+ // Narrow `Mod` (Record<string, unknown>) to the discriminated shapes in
25
+ // `types.ts`. Each guard checks `type` and the fields the consumer reads, so
26
+ // downstream code sees `subType: string` directly without a `str()` wrapper.
27
+ export const isProficiencyMod = (m) => m.type === "proficiency" && typeof m.subType === "string";
28
+ export const isExpertiseMod = (m) => m.type === "expertise" && typeof m.subType === "string";
29
+ export const isHalfProficiencyMod = (m) => m.type === "half-proficiency" && typeof m.subType === "string";
30
+ export const isBonusMod = (m) => m.type === "bonus" && typeof m.subType === "string";
31
+ export const isSetMod = (m) => m.type === "set" && typeof m.subType === "string";
32
+ export const isSetBaseMod = (m) => m.type === "set-base" && typeof m.subType === "string";
33
+ export const isSenseMod = (m) => m.type === "sense" && typeof m.subType === "string";
34
+ export const isResistanceMod = (m) => m.type === "resistance" && typeof m.subType === "string";
35
+ export const isImmunityMod = (m) => m.type === "immunity" && typeof m.subType === "string";
36
+ export const isVulnerabilityMod = (m) => m.type === "vulnerability" && typeof m.subType === "string";
37
+ export const isLanguageMod = (m) => m.type === "language" && typeof m.subType === "string";
38
+ /**
39
+ * True if any class entry is a Champion Fighter at level 7+ — the
40
+ * threshold at which the Remarkable Athlete feature kicks in. DDB does
41
+ * NOT emit a `half-proficiency` modifier for Remarkable Athlete (the way
42
+ * it does for Bard's Jack of All Trades), so this predicate is the only
43
+ * way to detect the feature reliably. Used by:
44
+ * - vitals.ts: adds half prof to initiative
45
+ * - stats.ts: adds half prof to non-proficient STR/DEX/CON skills
46
+ *
47
+ * Detection accepts both shapes DDB has used for subclassDefinition
48
+ * (`{ name: "..." }` and `{ definition: { name: "..." } }`).
49
+ */
50
+ export function hasRemarkableAthlete(classes) {
51
+ return classes.some(cls => {
52
+ const sub = obj(cls.subclassDefinition);
53
+ const subName = str(obj(sub.definition ?? cls.subclassDefinition).name || sub.name);
54
+ return /champion/i.test(subName) && num(cls.level) >= 7;
55
+ });
56
+ }
57
+ /** Display labels for the six ability scores, in canonical order. */
58
+ export const statNames = ["STR", "DEX", "CON", "INT", "WIS", "CHA"];
59
+ /** Internal slugs for the six ability scores, in canonical order (matches statNames). */
60
+ export const statKeys = ["strength", "dexterity", "constitution", "intelligence", "wisdom", "charisma"];
61
+ /**
62
+ * Levenshtein edit distance between two strings. Used by character-name
63
+ * fuzzy resolution (character.ts) and definition-query matching
64
+ * (definition.ts).
65
+ */
66
+ export function levenshteinDistance(a, b) {
67
+ if (a.length === 0)
68
+ return b.length;
69
+ if (b.length === 0)
70
+ return a.length;
71
+ const matrix = Array.from({ length: a.length + 1 }, (_, i) => Array.from({ length: b.length + 1 }, (_, j) => (i === 0 ? j : j === 0 ? i : 0)));
72
+ for (let i = 1; i <= a.length; i++) {
73
+ for (let j = 1; j <= b.length; j++) {
74
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
75
+ matrix[i][j] = Math.min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + cost);
76
+ }
77
+ }
78
+ return matrix[a.length][b.length];
79
+ }
80
+ //# sourceMappingURL=helpers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/tools/character/helpers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Identity domain — name, race (with 2024 variant detection), class line,
3
+ * background, XP, inspiration. Owns the header block.
4
+ *
5
+ * Phase 3 of the character.ts refactor — see docs/character-refactor.md.
6
+ */
7
+ import type { CoreStats } from "./types.js";
8
+ export interface Identity {
9
+ charName: string;
10
+ race: string;
11
+ classLine: string;
12
+ totalLevel: number;
13
+ background: string;
14
+ xp: number;
15
+ inspiration: boolean;
16
+ }
17
+ export declare function computeIdentity(core: CoreStats): Identity;
18
+ export declare function formatHeaderBlock(i: Identity): string[];
19
+ //# sourceMappingURL=identity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../../../src/tools/character/identity.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,EAAwB,SAAS,EAAE,MAAM,YAAY,CAAC;AAElE,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,OAAO,CAAC;CACtB;AAoDD,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,GAAG,QAAQ,CAWzD;AAED,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,QAAQ,GAAG,MAAM,EAAE,CAUvD"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Identity domain — name, race (with 2024 variant detection), class line,
3
+ * background, XP, inspiration. Owns the header block.
4
+ *
5
+ * Phase 3 of the character.ts refactor — see docs/character-refactor.md.
6
+ */
7
+ import { arr, num, obj, str } from "./helpers.js";
8
+ /**
9
+ * 2024 races store the sub-selection (Elven Lineage, Fiendish Legacy, Giant
10
+ * Ancestry, Gnomish Lineage, …) in `char.options.race[]` rather than in the
11
+ * subRaceShortName field that 2014 characters use. The option name encodes
12
+ * the chosen variant — e.g. "Wood Elf Lineage", "Infernal Legacy",
13
+ * "Stone's Endurance (Stone Giant)". Pattern-match the suffix so this is
14
+ * generic across every 2024 race that follows the same naming convention.
15
+ *
16
+ * Note: 2024 Aasimar Celestial Revelation is *not* a creation-time choice —
17
+ * the player picks one of Heavenly Wings / Inner Radiance / Necrotic Shroud
18
+ * each time they transform, and `char.options.race` is empty for Aasimar.
19
+ * Header correctly shows just "Aasimar" with no parenthetical.
20
+ */
21
+ function detectRaceVariant(char) {
22
+ for (const opt of arr(obj(char.options).race)) {
23
+ const name = str(obj(opt.definition).name).trim();
24
+ if (!name)
25
+ continue;
26
+ // "Wood Elf Lineage" / "High Elf Lineage" / "Drow Lineage"
27
+ // / "Forest Gnome Lineage" / "Rock Gnome Lineage" / …
28
+ let m = name.match(/^(.+?)\s+Lineage$/);
29
+ if (m)
30
+ return m[1];
31
+ // "Infernal Legacy" / "Abyssal Legacy" / "Chthonic Legacy"
32
+ m = name.match(/^(.+?)\s+Legacy$/);
33
+ if (m)
34
+ return m[1];
35
+ // Giant Ancestry: "Stone's Endurance (Stone Giant)" etc.
36
+ m = name.match(/\(([A-Za-z]+)\s+Giant\)$/);
37
+ if (m)
38
+ return m[1];
39
+ }
40
+ return null;
41
+ }
42
+ function deriveRace(char) {
43
+ const base = str(obj(char.race).fullName || obj(char.race).baseName);
44
+ const variant = detectRaceVariant(char);
45
+ if (!variant)
46
+ return base;
47
+ // Avoid "Wood Elf (Wood Elf)" if the base race name already mentions the
48
+ // variant (defensive — happens when fullName has been pre-decorated).
49
+ if (base.toLowerCase().includes(variant.toLowerCase()))
50
+ return base;
51
+ return `${base} (${variant})`;
52
+ }
53
+ function buildClassLine(classes) {
54
+ return classes.map(c => {
55
+ const def = obj(c.definition);
56
+ const sub = obj(c.subclassDefinition);
57
+ const lvl = num(c.level);
58
+ return sub.name ? `${def.name} (${sub.name}) ${lvl}` : `${def.name} ${lvl}`;
59
+ }).join(" / ");
60
+ }
61
+ export function computeIdentity(core) {
62
+ const { char, classes, totalLevel } = core;
63
+ return {
64
+ charName: str(char.name),
65
+ race: deriveRace(char),
66
+ classLine: buildClassLine(classes),
67
+ totalLevel,
68
+ background: str(obj(obj(char.background).definition).name),
69
+ xp: num(char.currentXp),
70
+ inspiration: !!char.inspiration,
71
+ };
72
+ }
73
+ export function formatHeaderBlock(i) {
74
+ return [
75
+ `═══════════════════════════════════════`,
76
+ ` ${i.charName}`,
77
+ ` ${i.race} | ${i.classLine} | Level ${i.totalLevel}`,
78
+ ` Background: ${i.background || "—"} | XP: ${i.xp}`,
79
+ ` Inspiration: ${i.inspiration ? "Yes" : "No"}`,
80
+ `═══════════════════════════════════════`,
81
+ ``,
82
+ ];
83
+ }
84
+ //# sourceMappingURL=identity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"identity.js","sourceRoot":"","sources":["../../../src/tools/character/identity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Inventory domain — equipped armor, carried (non-weapon) items, attunement
3
+ * count, and currency. Owns the inventory block.
4
+ *
5
+ * Phase 8 of the character.ts refactor — see docs/character-refactor.md.
6
+ *
7
+ * Weapons are intentionally excluded — they're surfaced in the ACTIONS
8
+ * block (Phase 6a). Equipped armor is shown separately with its AC value;
9
+ * everything else non-weapon is rolled into a single comma-separated
10
+ * INVENTORY line with ×N consolidation.
11
+ */
12
+ import type { CoreStats } from "./types.js";
13
+ export interface Inventory {
14
+ equippedNonWeapons: string[];
15
+ inventoryLine: string;
16
+ attuned: number;
17
+ currencyLine: string;
18
+ }
19
+ export declare function computeInventory(core: CoreStats): Inventory;
20
+ export declare function formatInventoryBlock(inv: Inventory): string[];
21
+ //# sourceMappingURL=inventory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory.d.ts","sourceRoot":"","sources":["../../../src/tools/character/inventory.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,KAAK,EAAY,SAAS,EAAE,MAAM,YAAY,CAAC;AAEtD,MAAM,WAAW,SAAS;IACxB,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAUD,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,GAAG,SAAS,CA2B3D;AAED,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,EAAE,CAU7D"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Inventory domain — equipped armor, carried (non-weapon) items, attunement
3
+ * count, and currency. Owns the inventory block.
4
+ *
5
+ * Phase 8 of the character.ts refactor — see docs/character-refactor.md.
6
+ *
7
+ * Weapons are intentionally excluded — they're surfaced in the ACTIONS
8
+ * block (Phase 6a). Equipped armor is shown separately with its AC value;
9
+ * everything else non-weapon is rolled into a single comma-separated
10
+ * INVENTORY line with ×N consolidation.
11
+ */
12
+ import { num, obj, str } from "./helpers.js";
13
+ function buildCurrencyLine(char) {
14
+ const currencies = obj(char.currencies);
15
+ return ["pp", "gp", "ep", "sp", "cp"]
16
+ .map(c => `${num(currencies[c])}${c}`)
17
+ .filter(c => !c.startsWith("0"))
18
+ .join(", ") || "none";
19
+ }
20
+ export function computeInventory(core) {
21
+ const { char, inventory } = core;
22
+ const equippedNonWeapons = [];
23
+ const carriedItems = new Map();
24
+ let attuned = 0;
25
+ for (const i of inventory) {
26
+ const def = obj(i.definition);
27
+ const iName = str(def.name);
28
+ const filterType = str(def.filterType);
29
+ const qty = num(i.quantity) || 1;
30
+ if (i.isAttuned)
31
+ attuned++;
32
+ if (i.equipped && filterType === "Armor") {
33
+ const ac2 = num(def.armorClass);
34
+ equippedNonWeapons.push(`${iName}${ac2 ? ` (AC ${ac2})` : ""}`);
35
+ }
36
+ else if (filterType !== "Weapon") {
37
+ carriedItems.set(iName, (carriedItems.get(iName) ?? 0) + qty);
38
+ }
39
+ }
40
+ const inventoryLine = [...carriedItems.entries()]
41
+ .map(([n, q]) => q > 1 ? `${n} ×${q}` : n)
42
+ .join(", ");
43
+ return {
44
+ equippedNonWeapons,
45
+ inventoryLine,
46
+ attuned,
47
+ currencyLine: buildCurrencyLine(char),
48
+ };
49
+ }
50
+ export function formatInventoryBlock(inv) {
51
+ return [
52
+ ...(inv.equippedNonWeapons.length
53
+ ? [`EQUIPPED`, ...inv.equippedNonWeapons.map(e => ` ${e}`), ``]
54
+ : []),
55
+ ...(inv.inventoryLine ? [`INVENTORY`, ` ${inv.inventoryLine}`, ``] : []),
56
+ `ATTUNEMENT: ${inv.attuned}/3 slots used`,
57
+ ``,
58
+ `CURRENCY: ${inv.currencyLine}`,
59
+ ];
60
+ }
61
+ //# sourceMappingURL=inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inventory.js","sourceRoot":"","sources":["../../../src/tools/character/inventory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Notes domain — personality traits, backstory, allies/organisations, and
3
+ * additional possessions/notes. Owns the notes block.
4
+ *
5
+ * Phase 8 of the character.ts refactor — see docs/character-refactor.md.
6
+ *
7
+ * Uses the full `stripHtml` from `../../utils.js` (which decodes HTML
8
+ * entities) rather than the lightweight helpers version — backstory and
9
+ * traits frequently contain entities like `&rsquo;` and `&mdash;`.
10
+ */
11
+ import type { CoreStats } from "./types.js";
12
+ export interface Notes {
13
+ traitLines: string[];
14
+ backstoryText: string | null;
15
+ allyLines: string[];
16
+ extraLines: string[];
17
+ }
18
+ export declare function computeNotes(core: CoreStats): Notes;
19
+ export declare function formatNotesBlock(n: Notes): string[];
20
+ //# sourceMappingURL=notes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notes.d.ts","sourceRoot":"","sources":["../../../src/tools/character/notes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,MAAM,WAAW,KAAK;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAYD,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,KAAK,CA6BnD;AAED,wBAAgB,gBAAgB,CAAC,CAAC,EAAE,KAAK,GAAG,MAAM,EAAE,CAWnD"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Notes domain — personality traits, backstory, allies/organisations, and
3
+ * additional possessions/notes. Owns the notes block.
4
+ *
5
+ * Phase 8 of the character.ts refactor — see docs/character-refactor.md.
6
+ *
7
+ * Uses the full `stripHtml` from `../../utils.js` (which decodes HTML
8
+ * entities) rather than the lightweight helpers version — backstory and
9
+ * traits frequently contain entities like `&rsquo;` and `&mdash;`.
10
+ */
11
+ import { stripHtml } from "../../utils.js";
12
+ import { obj, str } from "./helpers.js";
13
+ const field = (v) => {
14
+ const s = stripHtml(str(v)).trim();
15
+ return s || null;
16
+ };
17
+ const labelled = (label, pad, v) => {
18
+ const t = field(v);
19
+ return t ? ` ${label.padEnd(pad)}${t}` : null;
20
+ };
21
+ export function computeNotes(core) {
22
+ const { char } = core;
23
+ const traits = obj(char.traits);
24
+ const notes = obj(char.notes);
25
+ const traitLines = [
26
+ labelled("Traits:", 13, traits.personalityTraits),
27
+ labelled("Ideals:", 13, traits.ideals),
28
+ labelled("Bonds:", 13, traits.bonds),
29
+ labelled("Flaws:", 13, traits.flaws),
30
+ labelled("Appearance:", 13, traits.appearance),
31
+ ].filter((l) => l !== null);
32
+ const allyLines = [
33
+ labelled("Allies:", 15, notes.allies),
34
+ labelled("Organisations:", 15, notes.organizations),
35
+ ].filter((l) => l !== null);
36
+ const extraLines = [
37
+ labelled("Possessions:", 13, notes.personalPossessions),
38
+ labelled("Other:", 13, notes.otherNotes),
39
+ ].filter((l) => l !== null);
40
+ return {
41
+ traitLines,
42
+ backstoryText: field(notes.backstory),
43
+ allyLines,
44
+ extraLines,
45
+ };
46
+ }
47
+ export function formatNotesBlock(n) {
48
+ const hasAny = n.traitLines.length || n.backstoryText || n.allyLines.length || n.extraLines.length;
49
+ if (!hasAny) {
50
+ return ["No notes or backstory have been recorded for this character."];
51
+ }
52
+ const out = [];
53
+ if (n.traitLines.length)
54
+ out.push("PERSONALITY", ...n.traitLines, "");
55
+ if (n.backstoryText)
56
+ out.push("BACKSTORY", ` ${n.backstoryText}`, "");
57
+ if (n.allyLines.length)
58
+ out.push("ALLIES & ORGANISATIONS", ...n.allyLines, "");
59
+ if (n.extraLines.length)
60
+ out.push("ADDITIONAL NOTES", ...n.extraLines, "");
61
+ return out;
62
+ }
63
+ //# sourceMappingURL=notes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"notes.js","sourceRoot":"","sources":["../../../src/tools/character/notes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * `parseCharacterData(raw, sections)` — the orchestrator.
3
+ *
4
+ * Phase 9 of the character.ts refactor — see docs/character-refactor.md.
5
+ *
6
+ * Every domain (identity, vitals, ac, stats, defenses, features, actions,
7
+ * spells, inventory, notes) computed once via `computeCoreStats`, then
8
+ * routed through `sections` to pick which blocks to render. No business
9
+ * logic lives here — only the section → block routing.
10
+ */
11
+ import type { CharData, ParseSection } from "./types.js";
12
+ export declare function parseCharacterData(raw: CharData, sections?: ParseSection): string;
13
+ //# sourceMappingURL=parse.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../../../src/tools/character/parse.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAYzD,wBAAgB,kBAAkB,CAChC,GAAG,EAAE,QAAQ,EACb,QAAQ,GAAE,YAAqB,GAC9B,MAAM,CAkER"}