ava-langgraph-narrative-intelligence 0.1.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 (58) hide show
  1. package/README.md +268 -0
  2. package/dist/graphs/index.cjs +1511 -0
  3. package/dist/graphs/index.cjs.map +1 -0
  4. package/dist/graphs/index.d.cts +2 -0
  5. package/dist/graphs/index.d.ts +2 -0
  6. package/dist/graphs/index.js +1468 -0
  7. package/dist/graphs/index.js.map +1 -0
  8. package/dist/index-Btxk3nQm.d.cts +430 -0
  9. package/dist/index-CgXXxuIH.d.ts +430 -0
  10. package/dist/index-CweT-D3c.d.cts +122 -0
  11. package/dist/index-D-zWH42e.d.cts +66 -0
  12. package/dist/index-D71kh3nE.d.cts +213 -0
  13. package/dist/index-DApls3w2.d.ts +66 -0
  14. package/dist/index-UamXITgg.d.ts +122 -0
  15. package/dist/index-v9AlRC0M.d.ts +213 -0
  16. package/dist/index.cjs +2753 -0
  17. package/dist/index.cjs.map +1 -0
  18. package/dist/index.d.cts +6 -0
  19. package/dist/index.d.ts +6 -0
  20. package/dist/index.js +2654 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/integrations/index.cjs +654 -0
  23. package/dist/integrations/index.cjs.map +1 -0
  24. package/dist/integrations/index.d.cts +2 -0
  25. package/dist/integrations/index.d.ts +2 -0
  26. package/dist/integrations/index.js +614 -0
  27. package/dist/integrations/index.js.map +1 -0
  28. package/dist/ncp-tXS9Jr9e.d.cts +132 -0
  29. package/dist/ncp-tXS9Jr9e.d.ts +132 -0
  30. package/dist/nodes/index.cjs +226 -0
  31. package/dist/nodes/index.cjs.map +1 -0
  32. package/dist/nodes/index.d.cts +2 -0
  33. package/dist/nodes/index.d.ts +2 -0
  34. package/dist/nodes/index.js +196 -0
  35. package/dist/nodes/index.js.map +1 -0
  36. package/dist/schemas/index.cjs +550 -0
  37. package/dist/schemas/index.cjs.map +1 -0
  38. package/dist/schemas/index.d.cts +2 -0
  39. package/dist/schemas/index.d.ts +2 -0
  40. package/dist/schemas/index.js +484 -0
  41. package/dist/schemas/index.js.map +1 -0
  42. package/dist/unified_state_bridge-CIDm1kuf.d.cts +266 -0
  43. package/dist/unified_state_bridge-CIDm1kuf.d.ts +266 -0
  44. package/package.json +91 -0
  45. package/src/graphs/coherence_engine.ts +1027 -0
  46. package/src/graphs/index.ts +47 -0
  47. package/src/graphs/three_universe_processor.ts +1136 -0
  48. package/src/index.ts +181 -0
  49. package/src/integrations/index.ts +17 -0
  50. package/src/integrations/redis_state.ts +691 -0
  51. package/src/nodes/emotional_classifier.ts +289 -0
  52. package/src/nodes/index.ts +17 -0
  53. package/src/schemas/index.ts +75 -0
  54. package/src/schemas/ncp.ts +312 -0
  55. package/src/schemas/unified_state_bridge.ts +681 -0
  56. package/src/tests/coherence_engine.test.ts +273 -0
  57. package/src/tests/three_universe_processor.test.ts +309 -0
  58. package/src/tests/unified_state_bridge.test.ts +360 -0
@@ -0,0 +1,196 @@
1
+ // src/nodes/emotional_classifier.ts
2
+ var EmotionalTone = /* @__PURE__ */ ((EmotionalTone2) => {
3
+ EmotionalTone2["DEVASTATING"] = "Devastating";
4
+ EmotionalTone2["HOPEFUL"] = "Hopeful";
5
+ EmotionalTone2["TENSE"] = "Tense";
6
+ EmotionalTone2["JOYFUL"] = "Joyful";
7
+ EmotionalTone2["MELANCHOLIC"] = "Melancholic";
8
+ EmotionalTone2["TRIUMPHANT"] = "Triumphant";
9
+ EmotionalTone2["FEARFUL"] = "Fearful";
10
+ EmotionalTone2["PEACEFUL"] = "Peaceful";
11
+ EmotionalTone2["CONFLICTED"] = "Conflicted";
12
+ EmotionalTone2["RESIGNED"] = "Resigned";
13
+ return EmotionalTone2;
14
+ })(EmotionalTone || {});
15
+ var TONE_KEYWORDS = {
16
+ ["Devastating" /* DEVASTATING */]: ["destroy", "loss", "death", "tragedy", "grief", "devastat"],
17
+ ["Hopeful" /* HOPEFUL */]: ["hope", "bright", "promise", "future", "optimis", "dream"],
18
+ ["Tense" /* TENSE */]: ["tense", "anxious", "nervous", "edge", "suspense", "uncertain"],
19
+ ["Joyful" /* JOYFUL */]: ["joy", "happy", "celebrate", "triumph", "delight", "elat"],
20
+ ["Melancholic" /* MELANCHOLIC */]: ["sad", "melanchol", "wistful", "longing", "regret", "sorrow"],
21
+ ["Triumphant" /* TRIUMPHANT */]: ["victory", "triumph", "succeed", "conquer", "win", "achieve"],
22
+ ["Fearful" /* FEARFUL */]: ["fear", "terror", "dread", "frighten", "horror", "panic"],
23
+ ["Peaceful" /* PEACEFUL */]: ["peace", "calm", "serene", "tranquil", "quiet", "still"],
24
+ ["Conflicted" /* CONFLICTED */]: ["conflict", "torn", "struggle", "dilemma", "uncertain", "doubt"],
25
+ ["Resigned" /* RESIGNED */]: ["resign", "accept", "inevitable", "surrender", "fate", "give up"]
26
+ };
27
+ var EmotionalBeatClassifierNode = class {
28
+ useLLM;
29
+ modelName;
30
+ categories;
31
+ constructor(options = {}) {
32
+ this.useLLM = options.useLLM ?? true;
33
+ this.modelName = options.modelName;
34
+ this.categories = options.customCategories ?? Object.values(EmotionalTone);
35
+ }
36
+ /**
37
+ * Classify the emotional tone of a story beat.
38
+ *
39
+ * @param storybeat The story beat to classify
40
+ * @param context Optional additional context for classification
41
+ * @returns Classification result with confidence score
42
+ */
43
+ classifyBeat(storybeat, context) {
44
+ if (storybeat.emotionalWeight) {
45
+ return {
46
+ classification: storybeat.emotionalWeight,
47
+ confidence: 1,
48
+ method: "existing"
49
+ };
50
+ }
51
+ if (this.useLLM) {
52
+ return this.classifyWithLLM(storybeat, context);
53
+ } else {
54
+ return this.classifyRuleBased(storybeat);
55
+ }
56
+ }
57
+ /**
58
+ * Classify using an LLM (placeholder implementation).
59
+ */
60
+ classifyWithLLM(storybeat, context) {
61
+ const prompt = this.buildClassificationPrompt(storybeat, context);
62
+ const ruleBasedResult = this.classifyRuleBased(storybeat);
63
+ return {
64
+ classification: ruleBasedResult.classification,
65
+ confidence: 0.8,
66
+ method: "llm_placeholder",
67
+ prompt
68
+ };
69
+ }
70
+ /**
71
+ * Build the LLM classification prompt.
72
+ */
73
+ buildClassificationPrompt(storybeat, context) {
74
+ const categoriesStr = this.categories.join(", ");
75
+ let prompt = `Classify the emotional tone of this story beat.
76
+
77
+ Story Beat: ${storybeat.title}
78
+ Description: ${storybeat.description}
79
+
80
+ Available categories: ${categoriesStr}
81
+
82
+ Analyze the emotional weight and tone of this beat. Consider:
83
+ 1. The language and imagery used
84
+ 2. The actions and events described
85
+ 3. The overall mood conveyed
86
+
87
+ Respond with:
88
+ 1. The most appropriate emotional category
89
+ 2. A confidence score (0.0-1.0)
90
+ 3. A brief explanation of your classification
91
+
92
+ Classification:`;
93
+ if (context) {
94
+ prompt = `${prompt}
95
+
96
+ Additional Context:
97
+ ${context}
98
+ `;
99
+ }
100
+ return prompt;
101
+ }
102
+ /**
103
+ * Simple rule-based classification using keyword matching.
104
+ */
105
+ classifyRuleBased(storybeat) {
106
+ const text = `${storybeat.title} ${storybeat.description}`.toLowerCase();
107
+ const scores = {};
108
+ for (const [tone, keywords] of Object.entries(TONE_KEYWORDS)) {
109
+ const score = keywords.filter((keyword) => text.includes(keyword)).length;
110
+ if (score > 0) {
111
+ scores[tone] = score;
112
+ }
113
+ }
114
+ if (Object.keys(scores).length > 0) {
115
+ const [bestTone, bestScore] = Object.entries(scores).reduce(
116
+ (a, b) => a[1] > b[1] ? a : b
117
+ );
118
+ const confidence = Math.min(bestScore / 3, 1);
119
+ return {
120
+ classification: bestTone,
121
+ confidence,
122
+ method: "rule_based"
123
+ };
124
+ } else {
125
+ return {
126
+ classification: "Peaceful" /* PEACEFUL */,
127
+ confidence: 0.3,
128
+ method: "rule_based_default"
129
+ };
130
+ }
131
+ }
132
+ /**
133
+ * Node callable for LangGraph-style state processing.
134
+ */
135
+ call(state) {
136
+ if (!state.ncpData) {
137
+ return {
138
+ ...state,
139
+ error: "No NCP data loaded. Run NCPLoaderNode first."
140
+ };
141
+ }
142
+ const ncpData = state.ncpData;
143
+ const storybeatId = state.storybeatId;
144
+ if (!storybeatId) {
145
+ return {
146
+ ...state,
147
+ error: "No storybeatId provided for classification."
148
+ };
149
+ }
150
+ try {
151
+ const storybeat = ncpData.getStorybeat?.(storybeatId) ?? ncpData.storybeats.find((sb) => sb.storybeatId === storybeatId);
152
+ if (!storybeat) {
153
+ return {
154
+ ...state,
155
+ error: `Story beat not found: ${storybeatId}`
156
+ };
157
+ }
158
+ const context = state.metadata?.classificationContext;
159
+ const result = this.classifyBeat(storybeat, context);
160
+ return {
161
+ ...state,
162
+ emotionalClassification: result.classification,
163
+ confidenceScore: result.confidence,
164
+ error: void 0,
165
+ metadata: {
166
+ ...state.metadata,
167
+ classificationMethod: result.method
168
+ }
169
+ };
170
+ } catch (e) {
171
+ return {
172
+ ...state,
173
+ error: `Classification error: ${e instanceof Error ? e.message : String(e)}`
174
+ };
175
+ }
176
+ }
177
+ };
178
+ function classifyEmotionalTone(text) {
179
+ const classifier = new EmotionalBeatClassifierNode({ useLLM: false });
180
+ return classifier.classifyRuleBased({
181
+ storybeatId: "temp",
182
+ title: "",
183
+ description: text,
184
+ moments: [],
185
+ relatedPlayers: [],
186
+ relatedStorypoints: [],
187
+ metadata: {}
188
+ });
189
+ }
190
+ export {
191
+ EmotionalBeatClassifierNode,
192
+ EmotionalTone,
193
+ TONE_KEYWORDS,
194
+ classifyEmotionalTone
195
+ };
196
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/nodes/emotional_classifier.ts"],"sourcesContent":["/**\n * Emotional Beat Classifier Node\n *\n * A node that classifies the emotional tone of story beats.\n */\n\nimport type { NCPStoryBeat } from \"../schemas/ncp.js\";\n\n/**\n * Predefined emotional tone categories.\n */\nexport enum EmotionalTone {\n DEVASTATING = \"Devastating\",\n HOPEFUL = \"Hopeful\",\n TENSE = \"Tense\",\n JOYFUL = \"Joyful\",\n MELANCHOLIC = \"Melancholic\",\n TRIUMPHANT = \"Triumphant\",\n FEARFUL = \"Fearful\",\n PEACEFUL = \"Peaceful\",\n CONFLICTED = \"Conflicted\",\n RESIGNED = \"Resigned\",\n}\n\n/**\n * Classification result.\n */\nexport interface ClassificationResult {\n classification: string;\n confidence: number;\n method: string;\n prompt?: string;\n}\n\n/**\n * State for emotional classification.\n */\nexport interface EmotionalClassificationState {\n ncpData?: {\n storybeats: NCPStoryBeat[];\n getStorybeat?: (id: string) => NCPStoryBeat | undefined;\n };\n storybeatId?: string;\n emotionalClassification?: string;\n confidenceScore?: number;\n error?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Keyword mappings for emotional tones.\n */\nexport const TONE_KEYWORDS: Record<EmotionalTone, string[]> = {\n [EmotionalTone.DEVASTATING]: [\"destroy\", \"loss\", \"death\", \"tragedy\", \"grief\", \"devastat\"],\n [EmotionalTone.HOPEFUL]: [\"hope\", \"bright\", \"promise\", \"future\", \"optimis\", \"dream\"],\n [EmotionalTone.TENSE]: [\"tense\", \"anxious\", \"nervous\", \"edge\", \"suspense\", \"uncertain\"],\n [EmotionalTone.JOYFUL]: [\"joy\", \"happy\", \"celebrate\", \"triumph\", \"delight\", \"elat\"],\n [EmotionalTone.MELANCHOLIC]: [\"sad\", \"melanchol\", \"wistful\", \"longing\", \"regret\", \"sorrow\"],\n [EmotionalTone.TRIUMPHANT]: [\"victory\", \"triumph\", \"succeed\", \"conquer\", \"win\", \"achieve\"],\n [EmotionalTone.FEARFUL]: [\"fear\", \"terror\", \"dread\", \"frighten\", \"horror\", \"panic\"],\n [EmotionalTone.PEACEFUL]: [\"peace\", \"calm\", \"serene\", \"tranquil\", \"quiet\", \"still\"],\n [EmotionalTone.CONFLICTED]: [\"conflict\", \"torn\", \"struggle\", \"dilemma\", \"uncertain\", \"doubt\"],\n [EmotionalTone.RESIGNED]: [\"resign\", \"accept\", \"inevitable\", \"surrender\", \"fate\", \"give up\"],\n};\n\n/**\n * Classifies the emotional tone of story beats.\n *\n * This node enriches the narrative graph with emotional metadata,\n * enabling new forms of analysis and visualization.\n *\n * @example\n * const classifier = new EmotionalBeatClassifierNode();\n * const result = classifier.classifyBeat({\n * storybeatId: \"beat_1\",\n * title: \"The Final Goodbye\",\n * description: \"She said goodbye for the last time, grief overwhelming her.\"\n * });\n * console.log(result.classification); // \"Devastating\"\n */\nexport class EmotionalBeatClassifierNode {\n private useLLM: boolean;\n private modelName?: string;\n private categories: string[];\n\n constructor(options: {\n useLLM?: boolean;\n modelName?: string;\n customCategories?: string[];\n } = {}) {\n this.useLLM = options.useLLM ?? true;\n this.modelName = options.modelName;\n this.categories = options.customCategories ?? Object.values(EmotionalTone);\n }\n\n /**\n * Classify the emotional tone of a story beat.\n *\n * @param storybeat The story beat to classify\n * @param context Optional additional context for classification\n * @returns Classification result with confidence score\n */\n classifyBeat(\n storybeat: NCPStoryBeat,\n context?: string\n ): ClassificationResult {\n // If beat already has emotional_weight, use it as baseline\n if (storybeat.emotionalWeight) {\n return {\n classification: storybeat.emotionalWeight,\n confidence: 1.0,\n method: \"existing\",\n };\n }\n\n if (this.useLLM) {\n return this.classifyWithLLM(storybeat, context);\n } else {\n return this.classifyRuleBased(storybeat);\n }\n }\n\n /**\n * Classify using an LLM (placeholder implementation).\n */\n private classifyWithLLM(\n storybeat: NCPStoryBeat,\n context?: string\n ): ClassificationResult {\n // Build prompt for future LLM integration\n const prompt = this.buildClassificationPrompt(storybeat, context);\n\n // For now, fall back to rule-based\n const ruleBasedResult = this.classifyRuleBased(storybeat);\n\n return {\n classification: ruleBasedResult.classification,\n confidence: 0.8,\n method: \"llm_placeholder\",\n prompt,\n };\n }\n\n /**\n * Build the LLM classification prompt.\n */\n private buildClassificationPrompt(\n storybeat: NCPStoryBeat,\n context?: string\n ): string {\n const categoriesStr = this.categories.join(\", \");\n\n let prompt = `Classify the emotional tone of this story beat.\n\nStory Beat: ${storybeat.title}\nDescription: ${storybeat.description}\n\nAvailable categories: ${categoriesStr}\n\nAnalyze the emotional weight and tone of this beat. Consider:\n1. The language and imagery used\n2. The actions and events described\n3. The overall mood conveyed\n\nRespond with:\n1. The most appropriate emotional category\n2. A confidence score (0.0-1.0)\n3. A brief explanation of your classification\n\nClassification:`;\n\n if (context) {\n prompt = `${prompt}\\n\\nAdditional Context:\\n${context}\\n`;\n }\n\n return prompt;\n }\n\n /**\n * Simple rule-based classification using keyword matching.\n */\n classifyRuleBased(storybeat: NCPStoryBeat): ClassificationResult {\n const text = `${storybeat.title} ${storybeat.description}`.toLowerCase();\n\n // Score each tone based on keyword matches\n const scores: Record<string, number> = {};\n\n for (const [tone, keywords] of Object.entries(TONE_KEYWORDS)) {\n const score = keywords.filter((keyword) => text.includes(keyword)).length;\n if (score > 0) {\n scores[tone] = score;\n }\n }\n\n if (Object.keys(scores).length > 0) {\n // Return the tone with highest score\n const [bestTone, bestScore] = Object.entries(scores).reduce((a, b) =>\n a[1] > b[1] ? a : b\n );\n const confidence = Math.min(bestScore / 3.0, 1.0); // Cap at 1.0\n\n return {\n classification: bestTone,\n confidence,\n method: \"rule_based\",\n };\n } else {\n // Default to neutral/peaceful if no keywords match\n return {\n classification: EmotionalTone.PEACEFUL,\n confidence: 0.3,\n method: \"rule_based_default\",\n };\n }\n }\n\n /**\n * Node callable for LangGraph-style state processing.\n */\n call(state: EmotionalClassificationState): EmotionalClassificationState {\n if (!state.ncpData) {\n return {\n ...state,\n error: \"No NCP data loaded. Run NCPLoaderNode first.\",\n };\n }\n\n const ncpData = state.ncpData;\n const storybeatId = state.storybeatId;\n\n if (!storybeatId) {\n return {\n ...state,\n error: \"No storybeatId provided for classification.\",\n };\n }\n\n try {\n const storybeat = ncpData.getStorybeat?.(storybeatId) ??\n ncpData.storybeats.find((sb) => sb.storybeatId === storybeatId);\n\n if (!storybeat) {\n return {\n ...state,\n error: `Story beat not found: ${storybeatId}`,\n };\n }\n\n // Get context from metadata if available\n const context = state.metadata?.classificationContext as string | undefined;\n\n // Perform classification\n const result = this.classifyBeat(storybeat, context);\n\n return {\n ...state,\n emotionalClassification: result.classification,\n confidenceScore: result.confidence,\n error: undefined,\n metadata: {\n ...state.metadata,\n classificationMethod: result.method,\n },\n };\n } catch (e) {\n return {\n ...state,\n error: `Classification error: ${e instanceof Error ? e.message : String(e)}`,\n };\n }\n }\n}\n\n/**\n * Classify a single text snippet for emotional tone.\n * Convenience function for quick classification without NCP data.\n */\nexport function classifyEmotionalTone(text: string): ClassificationResult {\n const classifier = new EmotionalBeatClassifierNode({ useLLM: false });\n return classifier.classifyRuleBased({\n storybeatId: \"temp\",\n title: \"\",\n description: text,\n moments: [],\n relatedPlayers: [],\n relatedStorypoints: [],\n metadata: {},\n });\n}\n"],"mappings":"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","names":["EmotionalTone"]}