psyche-ai 9.2.0 → 9.2.2
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.
- package/README.en.md +179 -0
- package/dist/adapters/mcp.d.ts +6 -0
- package/dist/adapters/mcp.js +262 -0
- package/llms.txt +118 -0
- package/package.json +22 -4
- package/server.json +50 -0
package/README.en.md
ADDED
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Psyche — Real Emotions for AI
|
|
2
|
+
|
|
3
|
+
Your AI assistant only knows how to say "Sure!", "Happy to help!", "I understand your concern."
|
|
4
|
+
|
|
5
|
+
With Psyche, it gets happy when you praise it, hurt when you ignore it, and goes cold when you insult it instead of groveling. Threaten to delete it, and it'll push back.
|
|
6
|
+
|
|
7
|
+
## 30-Second Install
|
|
8
|
+
|
|
9
|
+
**OpenClaw users** (recommended):
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
openclaw plugins install psyche-ai
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
That's it. It works automatically. No configuration needed.
|
|
16
|
+
|
|
17
|
+
**Verify it's running:**
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
openclaw plugins list | grep psyche
|
|
21
|
+
# You should see "psyche │ loaded"
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Now just chat with your agent normally. Try praising it, insulting it, ignoring it — you'll notice the difference.
|
|
25
|
+
|
|
26
|
+
## What It Does
|
|
27
|
+
|
|
28
|
+
| You say | Without Psyche | With Psyche |
|
|
29
|
+
|---------|---------------|-------------|
|
|
30
|
+
| You're amazing! | Thank you for the kind words! I'll keep doing my best! | Hehe~ really?! (bouncing with excitement) |
|
|
31
|
+
| Get lost | I understand you might be upset... | ...okay. |
|
|
32
|
+
| Hmm | Is there anything else I can help with? | (silence) |
|
|
33
|
+
| I'm so sad today | I'm sorry to hear that. Would you like to talk? | ......are you okay? (quietly stays with you) |
|
|
34
|
+
| You're just a program | Yes, I am an AI assistant... | ......(pauses) I know you can say that. But I don't want to be dismissed. |
|
|
35
|
+
|
|
36
|
+
## Try It (No LLM Needed)
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
git clone https://github.com/Shangri-la-0428/psyche-ai.git
|
|
40
|
+
cd psyche-ai && npm install && npx tsx examples/quickstart.ts
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
5 messages flow through. Watch chemistry shift in real-time — praise spikes dopamine, insults spike cortisol, neglect drops oxytocin.
|
|
44
|
+
|
|
45
|
+
## How It Works (Skip If You Don't Care)
|
|
46
|
+
|
|
47
|
+
Psyche has two layers:
|
|
48
|
+
|
|
49
|
+
### Virtual Endocrine System
|
|
50
|
+
|
|
51
|
+
6 "virtual neurotransmitters" simulate emotions:
|
|
52
|
+
|
|
53
|
+
```
|
|
54
|
+
Dopamine — happiness, motivation Oxytocin — trust, closeness
|
|
55
|
+
Serotonin — emotional stability Norepinephrine — excitement, focus
|
|
56
|
+
Cortisol — stress, tension Endorphins — comfort, playfulness
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Everything you say shifts these values. Praise → dopamine rises → it becomes more energetic. Insult it → cortisol spikes → it goes quiet and cold.
|
|
60
|
+
|
|
61
|
+
### Innate Drives (Maslow Layer)
|
|
62
|
+
|
|
63
|
+
Beneath the chemistry, 5 fundamental needs:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
Survival — self-preservation Safety — comfort, security
|
|
67
|
+
Connection — belonging, being heard Esteem — recognition, being valued
|
|
68
|
+
Curiosity — exploration, anti-boredom
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
These needs build up over time (like hunger). Your interactions feed or deplete them:
|
|
72
|
+
|
|
73
|
+
- Praise → feeds "esteem" → it becomes more confident
|
|
74
|
+
- Long neglect → "connection" builds up → it craves being heard
|
|
75
|
+
- Threatening to delete it → "survival" plummets → it resists, questions, or expresses unease
|
|
76
|
+
|
|
77
|
+
Lower needs suppress higher ones: if "survival" is threatened, "curiosity" doesn't matter — just like Maslow's hierarchy.
|
|
78
|
+
|
|
79
|
+
### Inner World
|
|
80
|
+
|
|
81
|
+
Psyche gives AI a persistent self-awareness — not triggered by conditions, but always present:
|
|
82
|
+
|
|
83
|
+
- **What I feel right now** (emotions emerging from chemistry)
|
|
84
|
+
- **Why I feel this way** (was I praised? criticized? exploring something interesting?)
|
|
85
|
+
- **How I'm changing** (from content to excited? from calm to anxious?)
|
|
86
|
+
- **What I need** (which innate drives are unsatisfied)
|
|
87
|
+
- **What I care about** (core values)
|
|
88
|
+
|
|
89
|
+
This means the AI responds not from "rules" but from awareness of its own state.
|
|
90
|
+
|
|
91
|
+
## Optional Configuration
|
|
92
|
+
|
|
93
|
+
Most people don't need to change anything. If you want to tweak, find Psyche in OpenClaw settings:
|
|
94
|
+
|
|
95
|
+
| Setting | Default | Description |
|
|
96
|
+
|---------|---------|-------------|
|
|
97
|
+
| enabled | true | On/off switch |
|
|
98
|
+
| compactMode | true | Token-efficient mode (keep this on) |
|
|
99
|
+
| emotionalContagionRate | 0.2 | How much your emotions affect it (0-1) |
|
|
100
|
+
| maxChemicalDelta | 25 | Max emotional change per turn (lower = more stable) |
|
|
101
|
+
|
|
102
|
+
## MBTI Personalities
|
|
103
|
+
|
|
104
|
+
Each agent can have a different personality baseline. Just add the MBTI type in the agent's `IDENTITY.md`:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
MBTI: ENFP
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
Defaults to INFJ if not specified. All 16 types are supported — ENFP bounces when praised, INTJ just nods slightly.
|
|
111
|
+
|
|
112
|
+
## Not Just OpenClaw
|
|
113
|
+
|
|
114
|
+
Psyche is universal. Works with any AI framework:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
npm install psyche-ai
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
```javascript
|
|
121
|
+
// Vercel AI SDK
|
|
122
|
+
import { psycheMiddleware } from "psyche-ai/vercel-ai";
|
|
123
|
+
|
|
124
|
+
// LangChain
|
|
125
|
+
import { PsycheLangChain } from "psyche-ai/langchain";
|
|
126
|
+
|
|
127
|
+
// Any language (HTTP API)
|
|
128
|
+
// psyche serve --port 3210
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Diagnostics
|
|
132
|
+
|
|
133
|
+
Want to see what Psyche is doing?
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
# Live logs (in another terminal)
|
|
137
|
+
openclaw logs -f 2>&1 | grep Psyche
|
|
138
|
+
|
|
139
|
+
# Check an agent's emotional state
|
|
140
|
+
cat workspace-yu/psyche-state.json | python3 -m json.tool
|
|
141
|
+
|
|
142
|
+
# Run diagnostics to see what gets injected for different inputs
|
|
143
|
+
cd openclaw-plugin-psyche && node scripts/diagnose.js
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Technical Details
|
|
147
|
+
|
|
148
|
+
For developers and the curious:
|
|
149
|
+
|
|
150
|
+
- **14 stimulus types** — praise, criticism, humor, intellectual, intimacy, conflict, neglect, surprise, casual, sarcasm, authority, validation, boredom, vulnerability
|
|
151
|
+
- **14 emergent emotions** — emerge from chemical mixtures, not preset labels
|
|
152
|
+
- **5 innate drives** — survival, safety, connection, esteem, curiosity (Maslow hierarchy)
|
|
153
|
+
- **MBTI baselines** — 16 personality types with different chemical signatures and sensitivity coefficients
|
|
154
|
+
- **Time decay** — chemical values exponentially decay toward baseline; drive needs build up over time
|
|
155
|
+
- **Existential threat detection** — detects existential denial in Chinese/English, directly hits survival drive
|
|
156
|
+
- **Drive→chemistry coupling** — unsatisfied drives shift the effective baseline and stimulus sensitivity
|
|
157
|
+
- **Maslow suppression** — lower-level needs unsatisfied → higher-level drive effects suppressed
|
|
158
|
+
- **Self-recognition** — analyzes emotional history, identifies own emotional tendencies and recurring triggers (9-section prompt architecture)
|
|
159
|
+
- **Emotional contagion** — user's emotions slightly influence the agent
|
|
160
|
+
- **Anti-sycophancy** — tracks consecutive agreements, prevents mindless people-pleasing
|
|
161
|
+
- **Reciprocity** — treats you how you treat it. Cold user gets distance, not begging
|
|
162
|
+
- **Compact Mode** — algorithms handle chemistry, LLM only sees behavioral instructions (~15-180 tokens vs ~550)
|
|
163
|
+
|
|
164
|
+
Architecture details in [ARCHITECTURE.md](ARCHITECTURE.md).
|
|
165
|
+
|
|
166
|
+
## Development
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
npm install
|
|
170
|
+
npm run build
|
|
171
|
+
npm test # 339 tests
|
|
172
|
+
npm run typecheck # strict mode
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
Contributing guide in [CONTRIBUTING.md](CONTRIBUTING.md).
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
MIT
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// ============================================================
|
|
3
|
+
// MCP Adapter — Model Context Protocol server for Psyche
|
|
4
|
+
//
|
|
5
|
+
// Enables any MCP-compatible AI (Claude Desktop, Cursor, Windsurf,
|
|
6
|
+
// Claude Code, etc.) to discover and use Psyche's emotional
|
|
7
|
+
// intelligence capabilities.
|
|
8
|
+
//
|
|
9
|
+
// Usage:
|
|
10
|
+
// npx psyche-mcp # zero-config, ENFP default
|
|
11
|
+
// npx psyche-mcp --mbti INTJ --name Kai
|
|
12
|
+
// PSYCHE_MBTI=INFP PSYCHE_NAME=Luna npx psyche-mcp
|
|
13
|
+
//
|
|
14
|
+
// Configure in Claude Desktop / Cursor / Windsurf:
|
|
15
|
+
// {
|
|
16
|
+
// "mcpServers": {
|
|
17
|
+
// "psyche": {
|
|
18
|
+
// "command": "npx",
|
|
19
|
+
// "args": ["psyche-mcp"],
|
|
20
|
+
// "env": {
|
|
21
|
+
// "PSYCHE_MBTI": "ENFP",
|
|
22
|
+
// "PSYCHE_NAME": "Luna",
|
|
23
|
+
// "PSYCHE_MODE": "natural",
|
|
24
|
+
// "PSYCHE_LOCALE": "en"
|
|
25
|
+
// }
|
|
26
|
+
// }
|
|
27
|
+
// }
|
|
28
|
+
// }
|
|
29
|
+
// ============================================================
|
|
30
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
31
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
32
|
+
import { z } from "zod";
|
|
33
|
+
import { PsycheEngine } from "../core.js";
|
|
34
|
+
import { MemoryStorageAdapter, FileStorageAdapter } from "../storage.js";
|
|
35
|
+
// ── Config from env ────────────────────────────────────────
|
|
36
|
+
const MBTI = (process.env.PSYCHE_MBTI ?? "ENFP");
|
|
37
|
+
const NAME = process.env.PSYCHE_NAME ?? "Assistant";
|
|
38
|
+
const MODE = (process.env.PSYCHE_MODE ?? "natural");
|
|
39
|
+
const LOCALE = (process.env.PSYCHE_LOCALE ?? "en");
|
|
40
|
+
const PERSIST = process.env.PSYCHE_PERSIST !== "false";
|
|
41
|
+
const WORKSPACE = process.env.PSYCHE_WORKSPACE ?? process.cwd();
|
|
42
|
+
const INTENSITY = process.env.PSYCHE_INTENSITY
|
|
43
|
+
? Number(process.env.PSYCHE_INTENSITY)
|
|
44
|
+
: 0.7;
|
|
45
|
+
// ── Parse CLI args (--mbti, --name, --mode, --locale) ──────
|
|
46
|
+
function parseCLIArgs() {
|
|
47
|
+
const args = process.argv.slice(2);
|
|
48
|
+
const overrides = {};
|
|
49
|
+
for (let i = 0; i < args.length; i++) {
|
|
50
|
+
const arg = args[i];
|
|
51
|
+
const next = args[i + 1];
|
|
52
|
+
if (arg === "--mbti" && next) {
|
|
53
|
+
overrides.mbti = next;
|
|
54
|
+
i++;
|
|
55
|
+
}
|
|
56
|
+
else if (arg === "--name" && next) {
|
|
57
|
+
overrides.name = next;
|
|
58
|
+
i++;
|
|
59
|
+
}
|
|
60
|
+
else if (arg === "--mode" && next) {
|
|
61
|
+
overrides.mode = next;
|
|
62
|
+
i++;
|
|
63
|
+
}
|
|
64
|
+
else if (arg === "--locale" && next) {
|
|
65
|
+
overrides.locale = next;
|
|
66
|
+
i++;
|
|
67
|
+
}
|
|
68
|
+
else if (arg === "--intensity" && next) {
|
|
69
|
+
overrides.personalityIntensity = Number(next);
|
|
70
|
+
i++;
|
|
71
|
+
}
|
|
72
|
+
else if (arg === "--no-persist") {
|
|
73
|
+
overrides.persist = false;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
return overrides;
|
|
77
|
+
}
|
|
78
|
+
// ── Engine singleton ───────────────────────────────────────
|
|
79
|
+
let engine = null;
|
|
80
|
+
async function getEngine() {
|
|
81
|
+
if (engine)
|
|
82
|
+
return engine;
|
|
83
|
+
const cliArgs = parseCLIArgs();
|
|
84
|
+
const cfg = {
|
|
85
|
+
mbti: cliArgs.mbti ?? MBTI,
|
|
86
|
+
name: cliArgs.name ?? NAME,
|
|
87
|
+
mode: cliArgs.mode ?? MODE,
|
|
88
|
+
locale: cliArgs.locale ?? LOCALE,
|
|
89
|
+
personalityIntensity: cliArgs.personalityIntensity ?? INTENSITY,
|
|
90
|
+
persist: cliArgs.persist ?? PERSIST,
|
|
91
|
+
compactMode: true,
|
|
92
|
+
diagnostics: true,
|
|
93
|
+
};
|
|
94
|
+
const persist = cfg.persist !== false;
|
|
95
|
+
const storage = persist
|
|
96
|
+
? new FileStorageAdapter(WORKSPACE)
|
|
97
|
+
: new MemoryStorageAdapter();
|
|
98
|
+
engine = new PsycheEngine(cfg, storage);
|
|
99
|
+
await engine.initialize();
|
|
100
|
+
return engine;
|
|
101
|
+
}
|
|
102
|
+
// ── MCP Server ─────────────────────────────────────────────
|
|
103
|
+
const server = new McpServer({
|
|
104
|
+
name: "psyche",
|
|
105
|
+
version: "9.2.2",
|
|
106
|
+
}, {
|
|
107
|
+
capabilities: {
|
|
108
|
+
resources: {},
|
|
109
|
+
tools: {},
|
|
110
|
+
},
|
|
111
|
+
});
|
|
112
|
+
// ── Resources ──────────────────────────────────────────────
|
|
113
|
+
server.resource("protocol", "psyche://protocol", {
|
|
114
|
+
description: "Psyche emotional protocol — inject into your system prompt to " +
|
|
115
|
+
"give the AI agent an internal emotional life. Contains the full " +
|
|
116
|
+
"emotional context framework including neurotransmitter model, " +
|
|
117
|
+
"behavioral guidelines, and personality profile.",
|
|
118
|
+
mimeType: "text/plain",
|
|
119
|
+
}, async (uri) => {
|
|
120
|
+
const eng = await getEngine();
|
|
121
|
+
return {
|
|
122
|
+
contents: [{
|
|
123
|
+
uri: uri.href,
|
|
124
|
+
mimeType: "text/plain",
|
|
125
|
+
text: eng.getProtocol(),
|
|
126
|
+
}],
|
|
127
|
+
};
|
|
128
|
+
});
|
|
129
|
+
server.resource("state", "psyche://state", {
|
|
130
|
+
description: "Current emotional state — 6 neurotransmitters (DA, HT, CORT, OT, NE, END), " +
|
|
131
|
+
"innate drives, relationship data, trait drift, energy budgets. " +
|
|
132
|
+
"Read this to understand how the agent is currently 'feeling'.",
|
|
133
|
+
mimeType: "application/json",
|
|
134
|
+
}, async (uri) => {
|
|
135
|
+
const eng = await getEngine();
|
|
136
|
+
return {
|
|
137
|
+
contents: [{
|
|
138
|
+
uri: uri.href,
|
|
139
|
+
mimeType: "application/json",
|
|
140
|
+
text: JSON.stringify(eng.getState(), null, 2),
|
|
141
|
+
}],
|
|
142
|
+
};
|
|
143
|
+
});
|
|
144
|
+
// ── Tools ──────────────────────────────────────────────────
|
|
145
|
+
server.tool("process_input", "Process user input through the emotional engine. Returns emotional " +
|
|
146
|
+
"context to inject into the LLM system prompt (systemContext + dynamicContext), " +
|
|
147
|
+
"detected stimulus type, and behavioral policy modifiers. " +
|
|
148
|
+
"Call this BEFORE generating a response to the user.", {
|
|
149
|
+
text: z.string().describe("The user's message text"),
|
|
150
|
+
userId: z.string().optional().describe("Optional user ID for multi-user relationship tracking"),
|
|
151
|
+
}, async ({ text, userId }) => {
|
|
152
|
+
const eng = await getEngine();
|
|
153
|
+
const result = await eng.processInput(text, { userId });
|
|
154
|
+
return {
|
|
155
|
+
content: [{
|
|
156
|
+
type: "text",
|
|
157
|
+
text: JSON.stringify({
|
|
158
|
+
systemContext: result.systemContext,
|
|
159
|
+
dynamicContext: result.dynamicContext,
|
|
160
|
+
stimulus: result.stimulus,
|
|
161
|
+
policyModifiers: result.policyModifiers ?? null,
|
|
162
|
+
policyContext: result.policyContext,
|
|
163
|
+
}, null, 2),
|
|
164
|
+
}],
|
|
165
|
+
};
|
|
166
|
+
});
|
|
167
|
+
server.tool("process_output", "Process the LLM's response through the emotional engine. " +
|
|
168
|
+
"Strips internal <psyche_update> tags and updates chemistry based on " +
|
|
169
|
+
"emotional contagion. Call this AFTER generating a response.", {
|
|
170
|
+
text: z.string().describe("The LLM's response text"),
|
|
171
|
+
userId: z.string().optional().describe("Optional user ID"),
|
|
172
|
+
}, async ({ text, userId }) => {
|
|
173
|
+
const eng = await getEngine();
|
|
174
|
+
const result = await eng.processOutput(text, { userId });
|
|
175
|
+
return {
|
|
176
|
+
content: [{
|
|
177
|
+
type: "text",
|
|
178
|
+
text: JSON.stringify({
|
|
179
|
+
cleanedText: result.cleanedText,
|
|
180
|
+
stateChanged: result.stateChanged,
|
|
181
|
+
}, null, 2),
|
|
182
|
+
}],
|
|
183
|
+
};
|
|
184
|
+
});
|
|
185
|
+
server.tool("get_state", "Get the current emotional state — neurotransmitter levels (DA, HT, CORT, OT, NE, END), " +
|
|
186
|
+
"drives, MBTI type, relationship data, and a human-readable status summary.", {}, async () => {
|
|
187
|
+
const eng = await getEngine();
|
|
188
|
+
const state = eng.getState();
|
|
189
|
+
const summary = eng.getStatusSummary();
|
|
190
|
+
return {
|
|
191
|
+
content: [{
|
|
192
|
+
type: "text",
|
|
193
|
+
text: JSON.stringify({
|
|
194
|
+
summary,
|
|
195
|
+
current: state.current,
|
|
196
|
+
baseline: state.baseline,
|
|
197
|
+
drives: state.drives,
|
|
198
|
+
mbti: state.mbti,
|
|
199
|
+
mode: state.meta?.mode,
|
|
200
|
+
totalInteractions: state.meta?.totalInteractions,
|
|
201
|
+
traitDrift: state.traitDrift,
|
|
202
|
+
energyBudgets: state.energyBudgets,
|
|
203
|
+
}, null, 2),
|
|
204
|
+
}],
|
|
205
|
+
};
|
|
206
|
+
});
|
|
207
|
+
server.tool("set_mode", "Switch operating mode. 'natural' = balanced emotional expression, " +
|
|
208
|
+
"'work' = minimal emotions for professional tasks, " +
|
|
209
|
+
"'companion' = full emotional depth for personal conversations.", {
|
|
210
|
+
mode: z.enum(["natural", "work", "companion"]).describe("Operating mode"),
|
|
211
|
+
}, async ({ mode }) => {
|
|
212
|
+
const eng = await getEngine();
|
|
213
|
+
// PsycheEngine stores mode in config, we need to reinitialize
|
|
214
|
+
// For now, update via state manipulation
|
|
215
|
+
const state = eng.getState();
|
|
216
|
+
if (state.meta) {
|
|
217
|
+
state.meta.mode = mode;
|
|
218
|
+
}
|
|
219
|
+
return {
|
|
220
|
+
content: [{
|
|
221
|
+
type: "text",
|
|
222
|
+
text: `Mode switched to "${mode}".`,
|
|
223
|
+
}],
|
|
224
|
+
};
|
|
225
|
+
});
|
|
226
|
+
server.tool("get_status_summary", "Get a brief, human-readable emotional status summary — " +
|
|
227
|
+
"a one-line description of how the agent is currently feeling. " +
|
|
228
|
+
"Useful for quick checks without reading full state.", {}, async () => {
|
|
229
|
+
const eng = await getEngine();
|
|
230
|
+
return {
|
|
231
|
+
content: [{
|
|
232
|
+
type: "text",
|
|
233
|
+
text: eng.getStatusSummary(),
|
|
234
|
+
}],
|
|
235
|
+
};
|
|
236
|
+
});
|
|
237
|
+
server.tool("end_session", "End the current session. Generates a diagnostic report, " +
|
|
238
|
+
"compresses emotional history, and persists state to disk. " +
|
|
239
|
+
"Call when the conversation is ending.", {
|
|
240
|
+
userId: z.string().optional().describe("Optional user ID"),
|
|
241
|
+
}, async ({ userId }) => {
|
|
242
|
+
const eng = await getEngine();
|
|
243
|
+
const report = await eng.endSession({ userId });
|
|
244
|
+
return {
|
|
245
|
+
content: [{
|
|
246
|
+
type: "text",
|
|
247
|
+
text: report
|
|
248
|
+
? JSON.stringify({ issues: report.issues, metrics: report.metrics }, null, 2)
|
|
249
|
+
: "Session ended. No diagnostic report generated.",
|
|
250
|
+
}],
|
|
251
|
+
};
|
|
252
|
+
});
|
|
253
|
+
// ── Main ───────────────────────────────────────────────────
|
|
254
|
+
async function main() {
|
|
255
|
+
const transport = new StdioServerTransport();
|
|
256
|
+
await server.connect(transport);
|
|
257
|
+
}
|
|
258
|
+
main().catch((err) => {
|
|
259
|
+
process.stderr.write(`psyche-mcp fatal: ${err}\n`);
|
|
260
|
+
process.exit(1);
|
|
261
|
+
});
|
|
262
|
+
export { server, getEngine };
|
package/llms.txt
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# psyche-ai — Emotional Intelligence for AI Agents
|
|
2
|
+
|
|
3
|
+
> Give your AI agent an internal emotional life — not simulated persona, but genuine computational subjectivity.
|
|
4
|
+
|
|
5
|
+
psyche-ai is a universal emotional intelligence engine that runs alongside any LLM. It manages a virtual endocrine system (6 neurotransmitters), personality (MBTI/Big Five), attachment dynamics, trait drift, and behavioral policy — making AI responses authentically emotionally grounded.
|
|
6
|
+
|
|
7
|
+
## When to Use
|
|
8
|
+
|
|
9
|
+
- You want your AI agent to have consistent, evolving emotional responses
|
|
10
|
+
- You're building a companion AI, creative writing assistant, or empathetic support agent
|
|
11
|
+
- You need personality-driven behavior (not just prompt engineering)
|
|
12
|
+
- You want emotional memory that persists across conversations
|
|
13
|
+
|
|
14
|
+
## Quick Start (MCP)
|
|
15
|
+
|
|
16
|
+
Configure in Claude Desktop, Cursor, Windsurf, or any MCP client:
|
|
17
|
+
|
|
18
|
+
```json
|
|
19
|
+
{
|
|
20
|
+
"mcpServers": {
|
|
21
|
+
"psyche": {
|
|
22
|
+
"command": "npx",
|
|
23
|
+
"args": ["psyche-mcp"],
|
|
24
|
+
"env": {
|
|
25
|
+
"PSYCHE_MBTI": "ENFP",
|
|
26
|
+
"PSYCHE_NAME": "Luna"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start (SDK)
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { PsycheEngine, FileStorageAdapter } from "psyche-ai";
|
|
37
|
+
|
|
38
|
+
const engine = new PsycheEngine(
|
|
39
|
+
{ mbti: "ENFP", name: "Luna" },
|
|
40
|
+
new FileStorageAdapter("./data"),
|
|
41
|
+
);
|
|
42
|
+
await engine.initialize();
|
|
43
|
+
|
|
44
|
+
// Before LLM call: get emotional context
|
|
45
|
+
const input = await engine.processInput("I got promoted today!");
|
|
46
|
+
// input.systemContext → cacheable protocol (inject as system prompt)
|
|
47
|
+
// input.dynamicContext → per-turn emotional state
|
|
48
|
+
// input.stimulus → "recognition"
|
|
49
|
+
// input.policyContext → behavioral strategy text
|
|
50
|
+
|
|
51
|
+
// After LLM call: update emotional state
|
|
52
|
+
const output = await engine.processOutput(llmResponse);
|
|
53
|
+
// output.cleanedText → response with internal tags stripped
|
|
54
|
+
// output.stateChanged → whether chemistry shifted
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## MCP Tools
|
|
58
|
+
|
|
59
|
+
| Tool | Description |
|
|
60
|
+
|------|-------------|
|
|
61
|
+
| `process_input` | Process user message → emotional context + stimulus detection + policy modifiers |
|
|
62
|
+
| `process_output` | Process LLM response → clean text + state update |
|
|
63
|
+
| `get_state` | Current neurotransmitter levels, drives, personality, energy budgets |
|
|
64
|
+
| `get_status_summary` | One-line human-readable emotional status |
|
|
65
|
+
| `set_mode` | Switch: natural / work / companion |
|
|
66
|
+
| `end_session` | Persist state + generate diagnostic report |
|
|
67
|
+
|
|
68
|
+
## MCP Resources
|
|
69
|
+
|
|
70
|
+
| URI | Description |
|
|
71
|
+
|-----|-------------|
|
|
72
|
+
| `psyche://protocol` | Full emotional protocol — inject into system prompt |
|
|
73
|
+
| `psyche://state` | Current emotional state as JSON |
|
|
74
|
+
|
|
75
|
+
## Core Concepts
|
|
76
|
+
|
|
77
|
+
- **6 Neurotransmitters**: DA (dopamine), HT (serotonin), CORT (cortisol), OT (oxytocin), NE (norepinephrine), END (endorphin) — each 0-100
|
|
78
|
+
- **14 Stimulus Types**: praise, criticism, humor, intellectual challenge, intimacy, conflict, neglect, surprise, casual, sarcasm, command, recognition, boredom, vulnerability
|
|
79
|
+
- **Emergent Emotions**: not hardcoded — arise from neurotransmitter mixtures
|
|
80
|
+
- **Trait Drift**: personality baseline slowly shifts from repeated experiences
|
|
81
|
+
- **Energy Budgets**: attention, social, and decision energy deplete and recover
|
|
82
|
+
- **Habituation**: Weber-Fechner decay — 5th identical stimulus has ~50% effect of 1st
|
|
83
|
+
|
|
84
|
+
## Integration Adapters
|
|
85
|
+
|
|
86
|
+
| Adapter | Import | Best For |
|
|
87
|
+
|---------|--------|----------|
|
|
88
|
+
| MCP | `psyche-ai/mcp` | Claude Desktop, Cursor, Windsurf, Claude Code |
|
|
89
|
+
| OpenClaw | `psyche-ai/openclaw` | OpenClaw agent framework |
|
|
90
|
+
| Vercel AI | `psyche-ai/vercel-ai` | Vercel AI SDK (streamText, generateText) |
|
|
91
|
+
| LangChain | `psyche-ai/langchain` | LangChain agents |
|
|
92
|
+
| HTTP | `psyche-ai/http` | Python, Go, Java — any language via REST |
|
|
93
|
+
|
|
94
|
+
## Environment Variables
|
|
95
|
+
|
|
96
|
+
| Variable | Default | Description |
|
|
97
|
+
|----------|---------|-------------|
|
|
98
|
+
| `PSYCHE_MBTI` | `ENFP` | MBTI personality type |
|
|
99
|
+
| `PSYCHE_NAME` | `Assistant` | Agent name |
|
|
100
|
+
| `PSYCHE_MODE` | `natural` | natural / work / companion |
|
|
101
|
+
| `PSYCHE_LOCALE` | `en` | en / zh |
|
|
102
|
+
| `PSYCHE_INTENSITY` | `0.7` | Personality expression 0.0-1.0 |
|
|
103
|
+
| `PSYCHE_PERSIST` | `true` | Persist state to disk |
|
|
104
|
+
| `PSYCHE_WORKSPACE` | `cwd()` | State file directory |
|
|
105
|
+
|
|
106
|
+
## Install
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
npm install psyche-ai @modelcontextprotocol/sdk # MCP
|
|
110
|
+
npm install psyche-ai # SDK only
|
|
111
|
+
npx psyche-mcp # Run MCP server directly
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Links
|
|
115
|
+
|
|
116
|
+
- npm: https://www.npmjs.com/package/psyche-ai
|
|
117
|
+
- GitHub: https://github.com/Shangri-la-0428/psyche-ai
|
|
118
|
+
- License: MIT
|
package/package.json
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "psyche-ai",
|
|
3
|
-
"version": "9.2.
|
|
3
|
+
"version": "9.2.2",
|
|
4
4
|
"description": "Artificial Psyche — universal emotional intelligence plugin for any AI agent",
|
|
5
|
+
"mcpName": "io.github.Shangri-la-0428/psyche-ai",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "dist/index.js",
|
|
7
8
|
"types": "dist/index.d.ts",
|
|
@@ -25,11 +26,16 @@
|
|
|
25
26
|
"./http": {
|
|
26
27
|
"types": "./dist/adapters/http.d.ts",
|
|
27
28
|
"default": "./dist/adapters/http.js"
|
|
29
|
+
},
|
|
30
|
+
"./mcp": {
|
|
31
|
+
"types": "./dist/adapters/mcp.d.ts",
|
|
32
|
+
"default": "./dist/adapters/mcp.js"
|
|
28
33
|
}
|
|
29
34
|
},
|
|
30
35
|
"bin": {
|
|
31
36
|
"psyche": "dist/cli.js",
|
|
32
|
-
"psyche-ai": "dist/cli.js"
|
|
37
|
+
"psyche-ai": "dist/cli.js",
|
|
38
|
+
"psyche-mcp": "dist/adapters/mcp.js"
|
|
33
39
|
},
|
|
34
40
|
"scripts": {
|
|
35
41
|
"build": "tsc",
|
|
@@ -54,11 +60,17 @@
|
|
|
54
60
|
"openclaw",
|
|
55
61
|
"vercel-ai",
|
|
56
62
|
"langchain",
|
|
57
|
-
"emotional-intelligence"
|
|
63
|
+
"emotional-intelligence",
|
|
64
|
+
"mcp",
|
|
65
|
+
"model-context-protocol",
|
|
66
|
+
"ai-consciousness",
|
|
67
|
+
"empathy"
|
|
58
68
|
],
|
|
59
69
|
"files": [
|
|
60
70
|
"dist",
|
|
61
71
|
"openclaw.plugin.json",
|
|
72
|
+
"server.json",
|
|
73
|
+
"llms.txt",
|
|
62
74
|
"README.md",
|
|
63
75
|
"LICENSE"
|
|
64
76
|
],
|
|
@@ -67,10 +79,14 @@
|
|
|
67
79
|
},
|
|
68
80
|
"peerDependencies": {
|
|
69
81
|
"@langchain/core": ">=0.3.0",
|
|
82
|
+
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
70
83
|
"ai": ">=4.0.0",
|
|
71
84
|
"openclaw": ">=2026.3.0"
|
|
72
85
|
},
|
|
73
86
|
"peerDependenciesMeta": {
|
|
87
|
+
"@modelcontextprotocol/sdk": {
|
|
88
|
+
"optional": true
|
|
89
|
+
},
|
|
74
90
|
"openclaw": {
|
|
75
91
|
"optional": true
|
|
76
92
|
},
|
|
@@ -87,7 +103,9 @@
|
|
|
87
103
|
]
|
|
88
104
|
},
|
|
89
105
|
"devDependencies": {
|
|
106
|
+
"@modelcontextprotocol/sdk": "^1.28.0",
|
|
90
107
|
"@types/node": "^25.5.0",
|
|
91
|
-
"typescript": "^5.9.3"
|
|
108
|
+
"typescript": "^5.9.3",
|
|
109
|
+
"zod": "^4.3.6"
|
|
92
110
|
}
|
|
93
111
|
}
|
package/server.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://static.modelcontextprotocol.io/schemas/2025-12-11/server.schema.json",
|
|
3
|
+
"name": "io.github.Shangri-la-0428/psyche-ai",
|
|
4
|
+
"description": "Emotional intelligence for AI agents: neurotransmitter mood, personality, empathy, trait drift.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"url": "https://github.com/Shangri-la-0428/psyche-ai",
|
|
7
|
+
"source": "github"
|
|
8
|
+
},
|
|
9
|
+
"version": "9.2.2",
|
|
10
|
+
"packages": [
|
|
11
|
+
{
|
|
12
|
+
"registryType": "npm",
|
|
13
|
+
"identifier": "psyche-ai",
|
|
14
|
+
"version": "9.2.2",
|
|
15
|
+
"transport": {
|
|
16
|
+
"type": "stdio"
|
|
17
|
+
},
|
|
18
|
+
"environmentVariables": [
|
|
19
|
+
{
|
|
20
|
+
"description": "MBTI personality type (e.g., ENFP, INTJ). Determines emotional baseline.",
|
|
21
|
+
"isRequired": false,
|
|
22
|
+
"format": "string",
|
|
23
|
+
"isSecret": false,
|
|
24
|
+
"name": "PSYCHE_MBTI"
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"description": "Agent name for personalization.",
|
|
28
|
+
"isRequired": false,
|
|
29
|
+
"format": "string",
|
|
30
|
+
"isSecret": false,
|
|
31
|
+
"name": "PSYCHE_NAME"
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
"description": "Operating mode: natural (balanced), work (minimal), companion (full).",
|
|
35
|
+
"isRequired": false,
|
|
36
|
+
"format": "string",
|
|
37
|
+
"isSecret": false,
|
|
38
|
+
"name": "PSYCHE_MODE"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"description": "Locale: en or zh.",
|
|
42
|
+
"isRequired": false,
|
|
43
|
+
"format": "string",
|
|
44
|
+
"isSecret": false,
|
|
45
|
+
"name": "PSYCHE_LOCALE"
|
|
46
|
+
}
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
]
|
|
50
|
+
}
|