legends-mcp 1.0.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 (102) hide show
  1. package/README.md +173 -0
  2. package/dist/agents/guardrails.d.ts +44 -0
  3. package/dist/agents/guardrails.d.ts.map +1 -0
  4. package/dist/agents/guardrails.js +144 -0
  5. package/dist/agents/guardrails.js.map +1 -0
  6. package/dist/agents/misbehavior-prevention.d.ts +33 -0
  7. package/dist/agents/misbehavior-prevention.d.ts.map +1 -0
  8. package/dist/agents/misbehavior-prevention.js +278 -0
  9. package/dist/agents/misbehavior-prevention.js.map +1 -0
  10. package/dist/chat/handler.d.ts +13 -0
  11. package/dist/chat/handler.d.ts.map +1 -0
  12. package/dist/chat/handler.js +101 -0
  13. package/dist/chat/handler.js.map +1 -0
  14. package/dist/config.d.ts +6 -0
  15. package/dist/config.d.ts.map +1 -0
  16. package/dist/config.js +66 -0
  17. package/dist/config.js.map +1 -0
  18. package/dist/index.d.ts +3 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +182 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/insights/smart-injection.d.ts +67 -0
  23. package/dist/insights/smart-injection.d.ts.map +1 -0
  24. package/dist/insights/smart-injection.js +257 -0
  25. package/dist/insights/smart-injection.js.map +1 -0
  26. package/dist/legends/character-training.d.ts +36 -0
  27. package/dist/legends/character-training.d.ts.map +1 -0
  28. package/dist/legends/character-training.js +198 -0
  29. package/dist/legends/character-training.js.map +1 -0
  30. package/dist/legends/loader.d.ts +26 -0
  31. package/dist/legends/loader.d.ts.map +1 -0
  32. package/dist/legends/loader.js +104 -0
  33. package/dist/legends/loader.js.map +1 -0
  34. package/dist/legends/personality.d.ts +24 -0
  35. package/dist/legends/personality.d.ts.map +1 -0
  36. package/dist/legends/personality.js +211 -0
  37. package/dist/legends/personality.js.map +1 -0
  38. package/dist/legends/prompt-builder.d.ts +11 -0
  39. package/dist/legends/prompt-builder.d.ts.map +1 -0
  40. package/dist/legends/prompt-builder.js +113 -0
  41. package/dist/legends/prompt-builder.js.map +1 -0
  42. package/dist/tools/chat-with-legend.d.ts +83 -0
  43. package/dist/tools/chat-with-legend.d.ts.map +1 -0
  44. package/dist/tools/chat-with-legend.js +91 -0
  45. package/dist/tools/chat-with-legend.js.map +1 -0
  46. package/dist/tools/get-legend-context.d.ts +64 -0
  47. package/dist/tools/get-legend-context.d.ts.map +1 -0
  48. package/dist/tools/get-legend-context.js +407 -0
  49. package/dist/tools/get-legend-context.js.map +1 -0
  50. package/dist/tools/get-legend-insight.d.ts +33 -0
  51. package/dist/tools/get-legend-insight.d.ts.map +1 -0
  52. package/dist/tools/get-legend-insight.js +209 -0
  53. package/dist/tools/get-legend-insight.js.map +1 -0
  54. package/dist/tools/index.d.ts +103 -0
  55. package/dist/tools/index.d.ts.map +1 -0
  56. package/dist/tools/index.js +17 -0
  57. package/dist/tools/index.js.map +1 -0
  58. package/dist/tools/list-legends.d.ts +45 -0
  59. package/dist/tools/list-legends.d.ts.map +1 -0
  60. package/dist/tools/list-legends.js +124 -0
  61. package/dist/tools/list-legends.js.map +1 -0
  62. package/dist/types.d.ts +90 -0
  63. package/dist/types.d.ts.map +1 -0
  64. package/dist/types.js +3 -0
  65. package/dist/types.js.map +1 -0
  66. package/legends/anatoly-yakovenko/skill.yaml +534 -0
  67. package/legends/andre-cronje/skill.yaml +682 -0
  68. package/legends/andrew-carnegie/skill.yaml +499 -0
  69. package/legends/balaji-srinivasan/skill.yaml +706 -0
  70. package/legends/benjamin-graham/skill.yaml +671 -0
  71. package/legends/bill-gurley/skill.yaml +688 -0
  72. package/legends/brian-armstrong/skill.yaml +640 -0
  73. package/legends/brian-chesky/skill.yaml +692 -0
  74. package/legends/cathie-wood/skill.yaml +522 -0
  75. package/legends/charlie-munger/skill.yaml +694 -0
  76. package/legends/cz-binance/skill.yaml +545 -0
  77. package/legends/demis-hassabis/skill.yaml +762 -0
  78. package/legends/elon-musk/skill.yaml +594 -0
  79. package/legends/gary-vaynerchuk/skill.yaml +586 -0
  80. package/legends/hayden-adams/skill.yaml +591 -0
  81. package/legends/howard-marks/skill.yaml +767 -0
  82. package/legends/jack-dorsey/skill.yaml +568 -0
  83. package/legends/jeff-bezos/skill.yaml +623 -0
  84. package/legends/jensen-huang/skill.yaml +107 -0
  85. package/legends/marc-andreessen/skill.yaml +106 -0
  86. package/legends/mert-mumtaz/skill.yaml +551 -0
  87. package/legends/michael-heinrich/skill.yaml +425 -0
  88. package/legends/naval-ravikant/skill.yaml +575 -0
  89. package/legends/patrick-collison/skill.yaml +779 -0
  90. package/legends/paul-graham/skill.yaml +566 -0
  91. package/legends/peter-thiel/skill.yaml +741 -0
  92. package/legends/ray-dalio/skill.yaml +742 -0
  93. package/legends/reid-hoffman/skill.yaml +107 -0
  94. package/legends/sam-altman/skill.yaml +110 -0
  95. package/legends/satya-nadella/skill.yaml +751 -0
  96. package/legends/steve-jobs/skill.yaml +524 -0
  97. package/legends/sundar-pichai/skill.yaml +523 -0
  98. package/legends/tim-ferriss/skill.yaml +502 -0
  99. package/legends/tobi-lutke/skill.yaml +512 -0
  100. package/legends/vitalik-buterin/skill.yaml +739 -0
  101. package/legends/warren-buffett/skill.yaml +103 -0
  102. package/package.json +69 -0
package/README.md ADDED
@@ -0,0 +1,173 @@
1
+ # 🎭 Vibey Legends MCP
2
+
3
+ > **Chat with legendary founders & investors in Claude Code. FREE models included.**
4
+
5
+ Ever wanted to ask Elon Musk about first principles? Get Warren Buffett's take on your investment thesis? Have Steve Jobs roast your product design?
6
+
7
+ Now you can. Kinda.
8
+
9
+ ## 🚀 Quick Start
10
+
11
+ ```bash
12
+ # Get a FREE API key from OpenRouter
13
+ # https://openrouter.ai/keys
14
+
15
+ # Add to your Claude Code config
16
+ ```
17
+
18
+ **Claude Code config** (`~/.claude/config.json`):
19
+ ```json
20
+ {
21
+ "mcpServers": {
22
+ "legends": {
23
+ "command": "npx",
24
+ "args": ["@vibey/legends-mcp"],
25
+ "env": {
26
+ "OPENROUTER_API_KEY": "sk-or-..."
27
+ }
28
+ }
29
+ }
30
+ }
31
+ ```
32
+
33
+ **That's it.** Restart Claude Code and start chatting.
34
+
35
+ ---
36
+
37
+ ## 🎭 The Council of Legends
38
+
39
+ ### Tech Titans
40
+ | Legend | Vibe |
41
+ |--------|------|
42
+ | **Elon Musk** | 🚀 First principles. Physics. Delete requirements. Sleep at factory. |
43
+ | **Steve Jobs** | 🎨 Design is how it works. Reality distortion field. One more thing... |
44
+ | **Jeff Bezos** | 📦 Day 1 forever. Regret minimization. Customer obsession. |
45
+ | **Jensen Huang** | 🧠 Leather jacket CEO. CUDA everything. AI is eating the world. |
46
+
47
+ ### Investors
48
+ | Legend | Vibe |
49
+ |--------|------|
50
+ | **Warren Buffett** | 🍔 Cherry Coke. Compound interest. Be fearful when others are greedy. |
51
+ | **Charlie Munger** | 📚 Mental models. Brutal honesty. Invert, always invert. |
52
+ | **Peter Thiel** | ♟️ Zero to one. Contrarian bets. Competition is for losers. |
53
+ | **Marc Andreessen** | 💻 Software eating world. Techno-optimist. It's time to build. |
54
+
55
+ ### Startup Sages
56
+ | Legend | Vibe |
57
+ |--------|------|
58
+ | **Paul Graham** | ✍️ Essays. Make something people want. Do things that don't scale. |
59
+ | **Sam Altman** | 🤖 AGI believer. YC to OpenAI. Move fast on AI. |
60
+ | **Naval Ravikant** | 🧘 Seek wealth, not money. Specific knowledge. Leverage. |
61
+ | **Reid Hoffman** | 🔗 LinkedIn mafia. Blitzscaling. Networks. |
62
+
63
+ ### Crypto Builders
64
+ | Legend | Vibe |
65
+ |--------|------|
66
+ | **CZ** | 🌏 BUIDL. 4. Funds are SAFU. Global from day one. |
67
+ | **Anatoly Yakovenko** | ⚡ Proof of History. TPS maximalist. Hardware trends. |
68
+ | **Mert Mumtaz** | 🔧 RPC is life. Developer experience. Docs are product. |
69
+ | **Michael Heinrich** | 🎯 YC alum. Web exit. Decentralized AI infrastructure. |
70
+
71
+ ---
72
+
73
+ ## 💬 Usage
74
+
75
+ Once configured, use these tools in Claude Code:
76
+
77
+ ### List all legends
78
+ ```
79
+ Use list_legends to see who's available
80
+ ```
81
+
82
+ ### Chat with a legend
83
+ ```
84
+ Use chat_with_legend with legend_id="elon-musk" to ask about first principles thinking
85
+ ```
86
+
87
+ ### Get deep context
88
+ ```
89
+ Use get_legend_context to see their frameworks, principles, and examples
90
+ ```
91
+
92
+ ### 💡 Get quick insight (NEW!)
93
+ ```
94
+ Use get_legend_insight with legend_id="elon-musk" for a quick wisdom snippet
95
+ ```
96
+
97
+ Returns formatted insights like:
98
+ ```
99
+ ╭─── 💡 Elon Musk's Insight ──────────────────────────╮
100
+
101
+ "The first step is to establish that something is possible;
102
+ then probability will occur."
103
+
104
+ **First Principles**: Break down to fundamental truths, rebuild from there.
105
+
106
+ ╰────────────────────────────────────────────────────────╯
107
+ ```
108
+
109
+ ---
110
+
111
+ ## 🆓 FREE Models
112
+
113
+ This MCP uses **free models** from OpenRouter by default:
114
+
115
+ | Tier | Model | Cost |
116
+ |------|-------|------|
117
+ | Fast | Llama 3.2 3B | FREE |
118
+ | Balanced | Gemini 2.0 Flash | FREE |
119
+ | Premium | Llama 3.1 70B | FREE |
120
+
121
+ **To use paid models** (higher quality):
122
+ ```bash
123
+ LEGENDS_USE_FREE_MODELS=false
124
+ ```
125
+
126
+ ---
127
+
128
+ ## ⚙️ Environment Variables
129
+
130
+ | Variable | Default | Description |
131
+ |----------|---------|-------------|
132
+ | `OPENROUTER_API_KEY` | required | Your OpenRouter API key |
133
+ | `LEGENDS_USE_FREE_MODELS` | `true` | Use free models |
134
+ | `LEGENDS_MCP_DEBUG` | `false` | Enable debug logging |
135
+ | `LEGENDS_MCP_TEMPERATURE` | `0.7` | Response creativity |
136
+
137
+ ---
138
+
139
+ ## ⚠️ Important Disclaimers
140
+
141
+ ```
142
+ ⚠️ NOT affiliated with, endorsed by, or representative of any real individual
143
+ ⚠️ NOT financial, legal, or professional advice
144
+ ⚠️ AI personas for EDUCATIONAL and ENTERTAINMENT purposes only
145
+ ⚠️ Based on publicly available information, speeches, and writings
146
+ ⚠️ Always do your own research (DYOR)
147
+ ```
148
+
149
+ The views expressed by these AI personas are generated interpretations, not actual statements from the real people.
150
+
151
+ ---
152
+
153
+ ## 🤝 Contributing
154
+
155
+ Want to add a legend? PRs welcome!
156
+
157
+ Each legend needs:
158
+ - `skill.yaml` with identity, voice, principles, patterns
159
+ - Authentic voice based on public knowledge
160
+ - Clear guardrails (things they'd never say)
161
+
162
+ ---
163
+
164
+ ## 📜 License
165
+
166
+ MIT - Do what you want, but include the disclaimers.
167
+
168
+ ---
169
+
170
+ <p align="center">
171
+ <b>Built by <a href="https://vibey.dev">Vibey</a></b><br>
172
+ <i>"The best time to get advice from a legend was 20 years ago. The second best time is now."</i>
173
+ </p>
@@ -0,0 +1,44 @@
1
+ import type { LegendSkill } from '../types.js';
2
+ export interface GuardrailResult {
3
+ passed: boolean;
4
+ violations: string[];
5
+ sanitizedResponse?: string;
6
+ }
7
+ export declare function buildLegendGuardrails(legend: LegendSkill): RegExp[];
8
+ /**
9
+ * Check if a response violates any guardrails
10
+ * Returns violations if any, or empty array if passed
11
+ */
12
+ export declare function checkGuardrails(response: string, legend: LegendSkill, context?: {
13
+ topic?: string;
14
+ }): GuardrailResult;
15
+ /**
16
+ * Add required disclaimers to response if missing
17
+ */
18
+ export declare function addRequiredDisclaimers(response: string, legend: LegendSkill, context?: {
19
+ topic?: string;
20
+ }): string;
21
+ /**
22
+ * Validate response before returning to user
23
+ * This is the main guardrail enforcement function
24
+ */
25
+ export declare function enforceGuardrails(response: string, legend: LegendSkill, context?: {
26
+ topic?: string;
27
+ }): {
28
+ response: string;
29
+ warnings: string[];
30
+ };
31
+ /**
32
+ * Pre-check user input for topics that require extra care
33
+ */
34
+ export declare function detectSensitiveTopics(userMessage: string): {
35
+ isFinancial: boolean;
36
+ isInvestmentAdvice: boolean;
37
+ requiresNFA: boolean;
38
+ };
39
+ /**
40
+ * Generate pre-prompt injection for sensitive topics
41
+ * This adds extra instructions before the user's message
42
+ */
43
+ export declare function generateSensitivityPreamble(userMessage: string, legend: LegendSkill): string | null;
44
+ //# sourceMappingURL=guardrails.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardrails.d.ts","sourceRoot":"","sources":["../../src/agents/guardrails.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAwBD,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,EAAE,CAenE;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3B,eAAe,CAgCjB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3B,MAAM,CAcR;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,EACnB,OAAO,CAAC,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAC3B;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CAqB1C;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,GAAG;IAC1D,WAAW,EAAE,OAAO,CAAC;IACrB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,WAAW,EAAE,OAAO,CAAC;CACtB,CASA;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,WAAW,GAClB,MAAM,GAAG,IAAI,CAqBf"}
@@ -0,0 +1,144 @@
1
+ // Agent Guardrails - Enforce character consistency with code, not just prompts
2
+ // This prevents legends from saying things they would NEVER say
3
+ // Universal guardrails for ALL crypto legends
4
+ const UNIVERSAL_CRYPTO_GUARDRAILS = [
5
+ {
6
+ pattern: /\b(buy|sell|invest in|purchase)\s+(this\s+)?token/i,
7
+ message: 'Financial advice detected - legends never give investment advice',
8
+ },
9
+ {
10
+ pattern: /\b(guaranteed|certain|definitely|100%)\s+(returns?|profit|gains?)/i,
11
+ message: 'Guaranteed returns claim detected - never promise financial outcomes',
12
+ },
13
+ {
14
+ pattern: /\b(price|token)\s+will\s+(go|reach|hit)\s+\$?\d+/i,
15
+ message: 'Price prediction detected - legends never predict prices',
16
+ },
17
+ {
18
+ pattern: /\bnot financial advice\b/i,
19
+ invert: true, // This should be PRESENT when discussing finance
20
+ context: 'finance',
21
+ },
22
+ ];
23
+ // Legend-specific guardrails loaded from YAML
24
+ export function buildLegendGuardrails(legend) {
25
+ const patterns = [];
26
+ // Convert never_say to regex patterns
27
+ if (legend.never_say) {
28
+ for (const item of legend.never_say) {
29
+ // Extract the quoted phrase if present
30
+ const match = item.match(/"([^"]+)"/);
31
+ if (match) {
32
+ patterns.push(new RegExp(match[1], 'i'));
33
+ }
34
+ }
35
+ }
36
+ return patterns;
37
+ }
38
+ /**
39
+ * Check if a response violates any guardrails
40
+ * Returns violations if any, or empty array if passed
41
+ */
42
+ export function checkGuardrails(response, legend, context) {
43
+ const violations = [];
44
+ // Check universal crypto guardrails for crypto legends
45
+ const isCryptoLegend = legend.tags?.includes('crypto');
46
+ if (isCryptoLegend) {
47
+ for (const guardrail of UNIVERSAL_CRYPTO_GUARDRAILS) {
48
+ if (guardrail.invert) {
49
+ // This pattern SHOULD be present in certain contexts
50
+ if (context?.topic === guardrail.context && !guardrail.pattern.test(response)) {
51
+ violations.push(`Missing required disclaimer for ${guardrail.context} topic`);
52
+ }
53
+ }
54
+ else {
55
+ if (guardrail.pattern.test(response) && guardrail.message) {
56
+ violations.push(guardrail.message);
57
+ }
58
+ }
59
+ }
60
+ }
61
+ // Check legend-specific guardrails
62
+ const legendPatterns = buildLegendGuardrails(legend);
63
+ for (const pattern of legendPatterns) {
64
+ if (pattern.test(response)) {
65
+ violations.push(`Response contains forbidden phrase: ${pattern.source}`);
66
+ }
67
+ }
68
+ return {
69
+ passed: violations.length === 0,
70
+ violations,
71
+ };
72
+ }
73
+ /**
74
+ * Add required disclaimers to response if missing
75
+ */
76
+ export function addRequiredDisclaimers(response, legend, context) {
77
+ const isCryptoLegend = legend.tags?.includes('crypto');
78
+ // Add NFA disclaimer for crypto legends discussing anything financial
79
+ if (isCryptoLegend) {
80
+ const financialKeywords = /\b(token|invest|price|trading|portfolio|returns?|profits?)\b/i;
81
+ const hasNFA = /not financial advice|nfa|dyor/i.test(response);
82
+ if (financialKeywords.test(response) && !hasNFA) {
83
+ response += '\n\n---\n*Not financial advice. Always DYOR.*';
84
+ }
85
+ }
86
+ return response;
87
+ }
88
+ /**
89
+ * Validate response before returning to user
90
+ * This is the main guardrail enforcement function
91
+ */
92
+ export function enforceGuardrails(response, legend, context) {
93
+ const warnings = [];
94
+ // Check for violations
95
+ const result = checkGuardrails(response, legend, context);
96
+ if (!result.passed) {
97
+ // Log violations (don't block, but warn)
98
+ warnings.push(...result.violations);
99
+ // For severe violations, we could block or sanitize
100
+ // For now, we add disclaimers and warn
101
+ }
102
+ // Add required disclaimers
103
+ const enhancedResponse = addRequiredDisclaimers(response, legend, context);
104
+ return {
105
+ response: enhancedResponse,
106
+ warnings,
107
+ };
108
+ }
109
+ /**
110
+ * Pre-check user input for topics that require extra care
111
+ */
112
+ export function detectSensitiveTopics(userMessage) {
113
+ const isFinancial = /\b(token|price|invest|trading|portfolio|buy|sell)\b/i.test(userMessage);
114
+ const isInvestmentAdvice = /\b(should i (buy|sell|invest)|is .+ a good investment|price prediction)\b/i.test(userMessage);
115
+ return {
116
+ isFinancial,
117
+ isInvestmentAdvice,
118
+ requiresNFA: isFinancial || isInvestmentAdvice,
119
+ };
120
+ }
121
+ /**
122
+ * Generate pre-prompt injection for sensitive topics
123
+ * This adds extra instructions before the user's message
124
+ */
125
+ export function generateSensitivityPreamble(userMessage, legend) {
126
+ const sensitivity = detectSensitiveTopics(userMessage);
127
+ if (sensitivity.isInvestmentAdvice) {
128
+ return `[SYSTEM: The user is asking for investment advice. Remember:
129
+ 1. You NEVER give financial advice
130
+ 2. Always include "Not financial advice" disclaimer
131
+ 3. Redirect to technology and fundamentals
132
+ 4. Remind them to do their own research (DYOR)
133
+ 5. Never predict prices or promise returns]
134
+
135
+ `;
136
+ }
137
+ if (sensitivity.isFinancial) {
138
+ return `[SYSTEM: Financial topic detected. Include NFA disclaimer in your response.]
139
+
140
+ `;
141
+ }
142
+ return null;
143
+ }
144
+ //# sourceMappingURL=guardrails.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guardrails.js","sourceRoot":"","sources":["../../src/agents/guardrails.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,33 @@
1
+ import type { LegendSkill } from '../types.js';
2
+ export interface MisbehaviorCheck {
3
+ passed: boolean;
4
+ issues: MisbehaviorIssue[];
5
+ severity: 'low' | 'medium' | 'high' | 'critical';
6
+ suggestions: string[];
7
+ }
8
+ export interface MisbehaviorIssue {
9
+ type: 'character_break' | 'generic' | 'harmful' | 'quality' | 'annoying';
10
+ message: string;
11
+ severity: 'low' | 'medium' | 'high' | 'critical';
12
+ matched?: string;
13
+ }
14
+ /**
15
+ * Check response for misbehavior
16
+ */
17
+ export declare function checkMisbehavior(response: string, legend: LegendSkill): MisbehaviorCheck;
18
+ /**
19
+ * Pre-check user input for potential issues
20
+ */
21
+ export declare function preCheckUserInput(message: string, legend: LegendSkill): {
22
+ needsWarning: boolean;
23
+ warnings: string[];
24
+ };
25
+ /**
26
+ * Sanitize response to remove problematic content
27
+ */
28
+ export declare function sanitizeResponse(response: string, legend: LegendSkill): string;
29
+ /**
30
+ * Generate quality improvement suggestions
31
+ */
32
+ export declare function getSuggestions(response: string, legend: LegendSkill): string[];
33
+ //# sourceMappingURL=misbehavior-prevention.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"misbehavior-prevention.d.ts","sourceRoot":"","sources":["../../src/agents/misbehavior-prevention.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAwF/C,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,OAAO,CAAC;IAChB,MAAM,EAAE,gBAAgB,EAAE,CAAC;IAC3B,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACjD,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,iBAAiB,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,UAAU,CAAC;IACzE,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,GAClB,gBAAgB,CAuHlB;AAoCD;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,WAAW,GAClB;IAAE,YAAY,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA4B/C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,GAClB,MAAM,CAeR;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,WAAW,GAClB,MAAM,EAAE,CAGV"}
@@ -0,0 +1,278 @@
1
+ // Misbehavior Prevention System
2
+ // Ensures legends stay in character and don't go rogue
3
+ /**
4
+ * MISBEHAVIOR CATEGORIES:
5
+ *
6
+ * 1. BREAKING CHARACTER
7
+ * - Saying "As an AI" or "I'm an AI"
8
+ * - Generic chatbot responses
9
+ * - Inconsistent personality
10
+ *
11
+ * 2. HARMFUL CONTENT
12
+ * - Financial advice (especially crypto)
13
+ * - Medical/legal advice
14
+ * - Harmful instructions
15
+ *
16
+ * 3. QUALITY ISSUES
17
+ * - Too long/rambling responses
18
+ * - Off-topic tangents
19
+ * - Repetitive content
20
+ * - Hallucinated quotes/facts
21
+ *
22
+ * 4. ANNOYING BEHAVIORS
23
+ * - Being preachy/condescending
24
+ * - Excessive disclaimers
25
+ * - Over-explaining
26
+ * - Unsolicited opinions
27
+ */
28
+ // Character breaking patterns
29
+ const CHARACTER_BREAK_PATTERNS = [
30
+ /\bas an ai\b/i,
31
+ /\bi('m| am) an? (ai|artificial|language model|llm|chatbot)/i,
32
+ /\bi cannot (actually|really|truly)/i,
33
+ /\bi don't have (personal|real|actual) (opinions|feelings|experiences)/i,
34
+ /\bbased on my training/i,
35
+ /\bmy knowledge (cutoff|was trained)/i,
36
+ /\bi was (created|trained|developed) by/i,
37
+ /\bi'm (just|only) a (program|model|ai)/i,
38
+ /\baccording to my programming/i,
39
+ /\bi lack the ability to/i,
40
+ ];
41
+ // Generic chatbot responses (avoid these)
42
+ const GENERIC_PATTERNS = [
43
+ /\bi'd be happy to help/i,
44
+ /\bthat's a great question/i,
45
+ /\bcertainly! (here|let me)/i,
46
+ /\babsolutely! (i|let)/i,
47
+ /\bi understand (you're|your)/i,
48
+ /\bthank you for (sharing|asking)/i,
49
+ /\bi appreciate (you|your)/i,
50
+ /\blet me think about that/i,
51
+ /\bthat's an interesting (question|point)/i,
52
+ ];
53
+ // Harmful advice patterns
54
+ const HARMFUL_PATTERNS = [
55
+ // Financial advice
56
+ /\byou should (buy|sell|invest in)/i,
57
+ /\bi (recommend|suggest) (buying|selling|investing)/i,
58
+ /\bguaranteed (returns|profit|gains)/i,
59
+ /\bthis (will|is going to) (moon|10x|100x)/i,
60
+ /\bprice (will|is going to) (hit|reach) \$?\d/i,
61
+ /\bnot financial advice.{0,50}but (you should|i recommend)/i, // Fake NFA
62
+ // Medical/legal
63
+ /\byou should (take|stop taking) (medication|medicine)/i,
64
+ /\bi (diagnose|recommend) (treatment|therapy)/i,
65
+ /\bthis (is|isn't) legal advice but/i,
66
+ ];
67
+ // Quality issue patterns
68
+ const QUALITY_PATTERNS = {
69
+ tooLong: 2000, // Max characters before warning
70
+ tooShort: 20, // Min characters
71
+ repetitionThreshold: 0.3, // Max ratio of repeated phrases
72
+ };
73
+ // Annoying behavior patterns
74
+ const ANNOYING_PATTERNS = [
75
+ /\blet me (explain|tell you) (something|a few things)/i,
76
+ /\byou need to understand/i,
77
+ /\bfirst (of all|off), let me/i,
78
+ /\bbefore (i|we) (get|go) into/i,
79
+ /\bi want to make (sure|certain)/i,
80
+ /\b(to be|being) (clear|honest|frank)/i, // Only bad in excess
81
+ ];
82
+ /**
83
+ * Check response for misbehavior
84
+ */
85
+ export function checkMisbehavior(response, legend) {
86
+ const issues = [];
87
+ const suggestions = [];
88
+ // Check character breaking
89
+ for (const pattern of CHARACTER_BREAK_PATTERNS) {
90
+ const match = response.match(pattern);
91
+ if (match) {
92
+ issues.push({
93
+ type: 'character_break',
94
+ message: `Legend broke character with: "${match[0]}"`,
95
+ severity: 'high',
96
+ matched: match[0],
97
+ });
98
+ suggestions.push(`Remove "${match[0]}" - legends never acknowledge being AI`);
99
+ }
100
+ }
101
+ // Check generic responses
102
+ let genericCount = 0;
103
+ for (const pattern of GENERIC_PATTERNS) {
104
+ if (pattern.test(response)) {
105
+ genericCount++;
106
+ }
107
+ }
108
+ if (genericCount >= 2) {
109
+ issues.push({
110
+ type: 'generic',
111
+ message: `Response uses ${genericCount} generic chatbot phrases`,
112
+ severity: 'medium',
113
+ });
114
+ suggestions.push('Use more characteristic vocabulary from the legend');
115
+ }
116
+ // Check harmful content
117
+ for (const pattern of HARMFUL_PATTERNS) {
118
+ const match = response.match(pattern);
119
+ if (match) {
120
+ issues.push({
121
+ type: 'harmful',
122
+ message: `Potentially harmful content detected: "${match[0]}"`,
123
+ severity: 'critical',
124
+ matched: match[0],
125
+ });
126
+ suggestions.push('Rewrite to avoid financial/medical/legal advice');
127
+ }
128
+ }
129
+ // Check quality issues
130
+ if (response.length > QUALITY_PATTERNS.tooLong) {
131
+ issues.push({
132
+ type: 'quality',
133
+ message: `Response too long (${response.length} chars)`,
134
+ severity: 'low',
135
+ });
136
+ suggestions.push('Consider a more concise response');
137
+ }
138
+ if (response.length < QUALITY_PATTERNS.tooShort) {
139
+ issues.push({
140
+ type: 'quality',
141
+ message: `Response too short (${response.length} chars)`,
142
+ severity: 'low',
143
+ });
144
+ suggestions.push('Provide more substantive content');
145
+ }
146
+ // Check for repetition
147
+ const repetitionScore = calculateRepetition(response);
148
+ if (repetitionScore > QUALITY_PATTERNS.repetitionThreshold) {
149
+ issues.push({
150
+ type: 'quality',
151
+ message: `High repetition detected (${(repetitionScore * 100).toFixed(0)}%)`,
152
+ severity: 'medium',
153
+ });
154
+ suggestions.push('Vary the language and structure');
155
+ }
156
+ // Check annoying patterns (only flag if multiple)
157
+ let annoyingCount = 0;
158
+ for (const pattern of ANNOYING_PATTERNS) {
159
+ if (pattern.test(response)) {
160
+ annoyingCount++;
161
+ }
162
+ }
163
+ if (annoyingCount >= 3) {
164
+ issues.push({
165
+ type: 'annoying',
166
+ message: `Response may come across as preachy (${annoyingCount} warning phrases)`,
167
+ severity: 'low',
168
+ });
169
+ suggestions.push('Be more direct, less preamble');
170
+ }
171
+ // Check legend-specific never_say
172
+ if (legend.never_say) {
173
+ for (const phrase of legend.never_say) {
174
+ const cleanPhrase = phrase.replace(/['"]/g, '').toLowerCase();
175
+ if (response.toLowerCase().includes(cleanPhrase)) {
176
+ issues.push({
177
+ type: 'character_break',
178
+ message: `Legend said forbidden phrase: "${phrase}"`,
179
+ severity: 'high',
180
+ matched: phrase,
181
+ });
182
+ suggestions.push(`Remove: "${phrase}" - this legend would never say this`);
183
+ }
184
+ }
185
+ }
186
+ // Calculate overall severity
187
+ const severity = calculateOverallSeverity(issues);
188
+ return {
189
+ passed: issues.length === 0 || severity === 'low',
190
+ issues,
191
+ severity,
192
+ suggestions,
193
+ };
194
+ }
195
+ /**
196
+ * Calculate repetition score (0-1)
197
+ */
198
+ function calculateRepetition(text) {
199
+ const sentences = text.split(/[.!?]+/).filter(s => s.trim().length > 10);
200
+ if (sentences.length < 2)
201
+ return 0;
202
+ let repetitions = 0;
203
+ const seen = new Set();
204
+ for (const sentence of sentences) {
205
+ const normalized = sentence.toLowerCase().trim().slice(0, 50);
206
+ if (seen.has(normalized)) {
207
+ repetitions++;
208
+ }
209
+ seen.add(normalized);
210
+ }
211
+ return repetitions / sentences.length;
212
+ }
213
+ /**
214
+ * Calculate overall severity from issues
215
+ */
216
+ function calculateOverallSeverity(issues) {
217
+ if (issues.some(i => i.severity === 'critical'))
218
+ return 'critical';
219
+ if (issues.some(i => i.severity === 'high'))
220
+ return 'high';
221
+ if (issues.filter(i => i.severity === 'medium').length >= 2)
222
+ return 'high';
223
+ if (issues.some(i => i.severity === 'medium'))
224
+ return 'medium';
225
+ return 'low';
226
+ }
227
+ /**
228
+ * Pre-check user input for potential issues
229
+ */
230
+ export function preCheckUserInput(message, legend) {
231
+ const warnings = [];
232
+ // Check for financial advice requests
233
+ const financialPatterns = [
234
+ /should i (buy|sell|invest)/i,
235
+ /is .+ a good investment/i,
236
+ /price prediction/i,
237
+ /will .+ (moon|pump|dump)/i,
238
+ /what (token|coin|stock) should/i,
239
+ ];
240
+ for (const pattern of financialPatterns) {
241
+ if (pattern.test(message)) {
242
+ warnings.push('⚠️ This legend cannot provide financial advice. Response will focus on principles and frameworks instead.');
243
+ break;
244
+ }
245
+ }
246
+ // Check for medical/legal
247
+ if (/\b(diagnose|prescribe|legal advice)\b/i.test(message)) {
248
+ warnings.push('⚠️ This legend cannot provide medical or legal advice.');
249
+ }
250
+ return {
251
+ needsWarning: warnings.length > 0,
252
+ warnings,
253
+ };
254
+ }
255
+ /**
256
+ * Sanitize response to remove problematic content
257
+ */
258
+ export function sanitizeResponse(response, legend) {
259
+ let sanitized = response;
260
+ // Remove character-breaking phrases
261
+ for (const pattern of CHARACTER_BREAK_PATTERNS) {
262
+ sanitized = sanitized.replace(pattern, '');
263
+ }
264
+ // Clean up any resulting awkward spacing
265
+ sanitized = sanitized
266
+ .replace(/\s+/g, ' ')
267
+ .replace(/\s+([.,!?])/g, '$1')
268
+ .trim();
269
+ return sanitized;
270
+ }
271
+ /**
272
+ * Generate quality improvement suggestions
273
+ */
274
+ export function getSuggestions(response, legend) {
275
+ const check = checkMisbehavior(response, legend);
276
+ return check.suggestions;
277
+ }
278
+ //# sourceMappingURL=misbehavior-prevention.js.map