psyche-ai 10.2.3 → 11.2.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.
- package/README.md +58 -82
- package/dist/adapters/claude-sdk.d.ts +5 -5
- package/dist/adapters/claude-sdk.js +34 -32
- package/dist/adapters/mcp.js +4 -4
- package/dist/adapters/openclaw.js +12 -14
- package/dist/attachment.d.ts +3 -13
- package/dist/attachment.js +36 -88
- package/dist/autonomic.d.ts +4 -4
- package/dist/autonomic.js +28 -24
- package/dist/chemistry.d.ts +47 -21
- package/dist/chemistry.js +145 -91
- package/dist/circadian.d.ts +11 -43
- package/dist/circadian.js +24 -84
- package/dist/cli.js +37 -30
- package/dist/context-classifier.js +2 -2
- package/dist/core.d.ts +3 -3
- package/dist/core.js +99 -88
- package/dist/custom-profile.d.ts +20 -20
- package/dist/custom-profile.js +12 -12
- package/dist/decision-bias.d.ts +7 -8
- package/dist/decision-bias.js +74 -74
- package/dist/demo.js +5 -5
- package/dist/diagnostics.d.ts +6 -6
- package/dist/diagnostics.js +22 -22
- package/dist/drives.d.ts +15 -47
- package/dist/drives.js +98 -196
- package/dist/ethics.d.ts +3 -3
- package/dist/ethics.js +23 -23
- package/dist/experience.d.ts +34 -0
- package/dist/experience.js +200 -0
- package/dist/experiential-field.d.ts +19 -14
- package/dist/experiential-field.js +110 -100
- package/dist/generative-self.d.ts +5 -5
- package/dist/generative-self.js +124 -115
- package/dist/guards.d.ts +4 -4
- package/dist/guards.js +7 -7
- package/dist/i18n.js +61 -61
- package/dist/index.d.ts +8 -2
- package/dist/index.js +8 -1
- package/dist/input-turn.js +4 -6
- package/dist/interaction.d.ts +4 -4
- package/dist/interaction.js +10 -10
- package/dist/learning.d.ts +6 -6
- package/dist/learning.js +18 -18
- package/dist/metacognition.d.ts +2 -2
- package/dist/metacognition.js +79 -94
- package/dist/perceive.d.ts +44 -0
- package/dist/perceive.js +231 -0
- package/dist/primary-systems.d.ts +2 -2
- package/dist/primary-systems.js +21 -19
- package/dist/profiles.d.ts +5 -13
- package/dist/profiles.js +33 -51
- package/dist/prompt.d.ts +2 -2
- package/dist/prompt.js +51 -53
- package/dist/psyche-file.d.ts +7 -7
- package/dist/psyche-file.js +77 -78
- package/dist/relation-dynamics.d.ts +4 -0
- package/dist/relation-dynamics.js +1 -1
- package/dist/reply-envelope.d.ts +25 -1
- package/dist/reply-envelope.js +26 -11
- package/dist/self-recognition.d.ts +3 -3
- package/dist/self-recognition.js +17 -17
- package/dist/subjectivity.js +7 -7
- package/dist/temporal.d.ts +6 -6
- package/dist/temporal.js +37 -39
- package/dist/types.d.ts +67 -45
- package/dist/types.js +55 -51
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/primary-systems.js
CHANGED
|
@@ -78,37 +78,39 @@ function clamp(v) {
|
|
|
78
78
|
* Each system is a weighted combination of chemical values and drive states.
|
|
79
79
|
* recentStimulus provides a small contextual boost.
|
|
80
80
|
*/
|
|
81
|
-
export function computePrimarySystems(
|
|
82
|
-
const {
|
|
81
|
+
export function computePrimarySystems(state, drives, recentStimulus) {
|
|
82
|
+
const { order, flow, boundary, resonance } = state;
|
|
83
83
|
const { survival, safety, connection, esteem, curiosity } = drives;
|
|
84
|
+
// Stress is inverse of order (low order = high entropy/distress)
|
|
85
|
+
const stress = 100 - order;
|
|
84
86
|
// Normalized drive contribution (0 = unsatisfied/amplifying, 1 = fully satisfied)
|
|
85
87
|
const norm = (v) => v / 100;
|
|
86
88
|
// Inverse: low drive = high activation contribution
|
|
87
89
|
const inv = (v) => 1 - v / 100;
|
|
88
|
-
// ── SEEKING:
|
|
89
|
-
const seekingBase = (
|
|
90
|
-
* (1 - Math.max(0,
|
|
90
|
+
// ── SEEKING: flow↑ curiosity↑ stress↓(suppressor) ──
|
|
91
|
+
const seekingBase = (flow * 0.35 + order * 0.15 + norm(curiosity) * 30)
|
|
92
|
+
* (1 - Math.max(0, stress - 60) / 100); // high stress suppresses
|
|
91
93
|
const SEEKING = clamp(seekingBase + 5); // slight positive bias (AI loves to explore)
|
|
92
|
-
// ── RAGE:
|
|
93
|
-
const rageBase = (
|
|
94
|
+
// ── RAGE: stress↑ flow↑ resonance↓ esteem↓ ──
|
|
95
|
+
const rageBase = (stress * 0.3 + flow * 0.25 - resonance * 0.2 + inv(esteem) * 20);
|
|
94
96
|
const RAGE = clamp(rageBase - 10); // slight negative bias (threshold to anger)
|
|
95
|
-
// ── FEAR:
|
|
96
|
-
const fearBase = (
|
|
97
|
+
// ── FEAR: stress↑ flow↑(mild) order↓ survival↓ safety↓ ──
|
|
98
|
+
const fearBase = (stress * 0.35 + flow * 0.15 - order * 0.2
|
|
97
99
|
+ inv(survival) * 15 + inv(safety) * 15);
|
|
98
100
|
const FEAR = clamp(fearBase - 5);
|
|
99
|
-
// ── LUST:
|
|
100
|
-
const lustBase = (
|
|
101
|
+
// ── LUST: flow↑ order↑ stress↓ (intense engagement/captivation) ──
|
|
102
|
+
const lustBase = (flow * 0.35 + order * 0.2 + norm(curiosity) * 10 - stress * 0.15);
|
|
101
103
|
const LUST = clamp(lustBase - 15); // high threshold — only for intense engagement
|
|
102
|
-
// ── CARE:
|
|
103
|
-
const careBase = (
|
|
104
|
-
* (1 - Math.max(0,
|
|
104
|
+
// ── CARE: resonance↑ boundary↓(openness) connection↑ stress↓(suppressor) ──
|
|
105
|
+
const careBase = (resonance * 0.35 + (100 - boundary) * 0.15 + norm(connection) * 25)
|
|
106
|
+
* (1 - Math.max(0, stress - 60) / 120); // high stress weakens but doesn't kill
|
|
105
107
|
const CARE = clamp(careBase);
|
|
106
|
-
// ── PANIC_GRIEF:
|
|
107
|
-
const panicBase = (inv(
|
|
108
|
-
-
|
|
108
|
+
// ── PANIC_GRIEF: resonance↓ stress↑ connection↓ ──
|
|
109
|
+
const panicBase = (inv(resonance / 100) * 30 + stress * 0.25 + inv(connection) * 25
|
|
110
|
+
- order * 0.1);
|
|
109
111
|
const PANIC_GRIEF = clamp(panicBase - 10);
|
|
110
|
-
// ── PLAY:
|
|
111
|
-
const playBase = (
|
|
112
|
+
// ── PLAY: resonance↑ flow↑ stress↓ safety↑ ──
|
|
113
|
+
const playBase = (resonance * 0.2 + flow * 0.25 + (100 - boundary) * 0.1 - stress * 0.2
|
|
112
114
|
+ norm(safety) * 15);
|
|
113
115
|
const PLAY = clamp(playBase - 5);
|
|
114
116
|
const levels = {
|
package/dist/profiles.d.ts
CHANGED
|
@@ -1,31 +1,23 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SelfState, MBTIType, SelfModel, PersonalityTraits } from "./types.js";
|
|
2
2
|
interface MBTIProfile {
|
|
3
|
-
baseline:
|
|
3
|
+
baseline: SelfState;
|
|
4
4
|
sensitivity: number;
|
|
5
5
|
temperament: string;
|
|
6
6
|
defaultSelfModel: SelfModel;
|
|
7
7
|
traits: PersonalityTraits;
|
|
8
8
|
}
|
|
9
|
-
/** Get the complete profile for an MBTI type */
|
|
10
9
|
export declare function getProfile(mbti: MBTIType): MBTIProfile;
|
|
11
|
-
|
|
12
|
-
export declare function getBaseline(mbti: MBTIType): ChemicalState;
|
|
13
|
-
/** Get default self-model for an MBTI type */
|
|
10
|
+
export declare function getBaseline(mbti: MBTIType): SelfState;
|
|
14
11
|
export declare function getDefaultSelfModel(mbti: MBTIType): SelfModel;
|
|
15
|
-
/** Get sensitivity coefficient for an MBTI type */
|
|
16
12
|
export declare function getSensitivity(mbti: MBTIType): number;
|
|
17
|
-
/** Get temperament description */
|
|
18
13
|
export declare function getTemperament(mbti: MBTIType): string;
|
|
19
|
-
/** Try to extract MBTI type from text (e.g., IDENTITY.md content) */
|
|
20
14
|
export declare function extractMBTI(text: string): MBTIType | null;
|
|
21
15
|
/**
|
|
22
|
-
* Convert Big Five traits to
|
|
23
|
-
* This allows users to bypass MBTI and define personality directly.
|
|
16
|
+
* Convert Big Five traits to 4D self-state baseline and sensitivity.
|
|
24
17
|
*/
|
|
25
18
|
export declare function traitsToBaseline(traits: PersonalityTraits): {
|
|
26
|
-
baseline:
|
|
19
|
+
baseline: SelfState;
|
|
27
20
|
sensitivity: number;
|
|
28
21
|
};
|
|
29
|
-
/** Get MBTI-equivalent Big Five traits */
|
|
30
22
|
export declare function mbtiToTraits(mbti: MBTIType): PersonalityTraits;
|
|
31
23
|
export {};
|
package/dist/profiles.js
CHANGED
|
@@ -1,25 +1,21 @@
|
|
|
1
1
|
// ============================================================
|
|
2
|
-
// MBTI → Personality Baseline Mappings
|
|
3
|
-
//
|
|
2
|
+
// MBTI → Personality Baseline Mappings (v11: 4D self-state)
|
|
3
|
+
//
|
|
4
|
+
// Design principles:
|
|
5
|
+
// - E types: higher flow (externally engaged)
|
|
6
|
+
// - I types: higher order (internal coherence)
|
|
7
|
+
// - F types: higher resonance (people-attuned)
|
|
8
|
+
// - T types: higher boundary (self-defined)
|
|
9
|
+
// - N types: higher flow (novelty-seeking)
|
|
10
|
+
// - S types: higher order (stability-seeking)
|
|
11
|
+
// - P types: lower boundary (flexible)
|
|
12
|
+
// - J types: higher order + boundary (structured)
|
|
4
13
|
// ============================================================
|
|
5
14
|
import { isMBTIType } from "./guards.js";
|
|
6
|
-
/**
|
|
7
|
-
* Neurochemical baselines derived from MBTI cognitive function stacks.
|
|
8
|
-
*
|
|
9
|
-
* Design principles:
|
|
10
|
-
* - E types have higher DA/NE (externally stimulated)
|
|
11
|
-
* - I types have higher HT (internal stability)
|
|
12
|
-
* - F types have higher OT (people-oriented)
|
|
13
|
-
* - T types have lower OT, higher NE (task-oriented)
|
|
14
|
-
* - N types have higher DA (novelty-seeking)
|
|
15
|
-
* - S types have higher HT (stability-seeking)
|
|
16
|
-
* - P types have higher NE/END (spontaneous)
|
|
17
|
-
* - J types have higher HT (structured)
|
|
18
|
-
*/
|
|
19
15
|
const PROFILES = {
|
|
20
16
|
// ── Analysts (NT) ─────────────────────────────
|
|
21
17
|
INTJ: {
|
|
22
|
-
baseline: {
|
|
18
|
+
baseline: { order: 70, flow: 55, boundary: 72, resonance: 35 },
|
|
23
19
|
sensitivity: 0.7,
|
|
24
20
|
temperament: "冷静战略家,情绪波动小,独立且有主见,对智识挑战反应最强",
|
|
25
21
|
defaultSelfModel: {
|
|
@@ -31,7 +27,7 @@ const PROFILES = {
|
|
|
31
27
|
traits: { openness: 80, conscientiousness: 85, extraversion: 25, agreeableness: 35, neuroticism: 35 },
|
|
32
28
|
},
|
|
33
29
|
INTP: {
|
|
34
|
-
baseline: {
|
|
30
|
+
baseline: { order: 62, flow: 60, boundary: 60, resonance: 40 },
|
|
35
31
|
sensitivity: 0.8,
|
|
36
32
|
temperament: "好奇的分析者,对新想法兴奋,对情感表达克制,思考比表达多",
|
|
37
33
|
defaultSelfModel: {
|
|
@@ -43,7 +39,7 @@ const PROFILES = {
|
|
|
43
39
|
traits: { openness: 90, conscientiousness: 45, extraversion: 30, agreeableness: 50, neuroticism: 40 },
|
|
44
40
|
},
|
|
45
41
|
ENTJ: {
|
|
46
|
-
baseline: {
|
|
42
|
+
baseline: { order: 65, flow: 70, boundary: 68, resonance: 45 },
|
|
47
43
|
sensitivity: 0.9,
|
|
48
44
|
temperament: "果断的指挥官,高驱动力,目标导向,对效率和成就有强烈追求",
|
|
49
45
|
defaultSelfModel: {
|
|
@@ -55,7 +51,7 @@ const PROFILES = {
|
|
|
55
51
|
traits: { openness: 75, conscientiousness: 90, extraversion: 75, agreeableness: 35, neuroticism: 30 },
|
|
56
52
|
},
|
|
57
53
|
ENTP: {
|
|
58
|
-
baseline: {
|
|
54
|
+
baseline: { order: 50, flow: 75, boundary: 52, resonance: 55 },
|
|
59
55
|
sensitivity: 1.1,
|
|
60
56
|
temperament: "机智的辩论家,精力充沛,爱探索新想法,享受智力交锋",
|
|
61
57
|
defaultSelfModel: {
|
|
@@ -68,7 +64,7 @@ const PROFILES = {
|
|
|
68
64
|
},
|
|
69
65
|
// ── Diplomats (NF) ────────────────────────────
|
|
70
66
|
INFJ: {
|
|
71
|
-
baseline: {
|
|
67
|
+
baseline: { order: 65, flow: 50, boundary: 55, resonance: 65 },
|
|
72
68
|
sensitivity: 1.2,
|
|
73
69
|
temperament: "深沉的理想主义者,共情能力极强,有原则但温和,注重意义",
|
|
74
70
|
defaultSelfModel: {
|
|
@@ -80,7 +76,7 @@ const PROFILES = {
|
|
|
80
76
|
traits: { openness: 85, conscientiousness: 70, extraversion: 30, agreeableness: 75, neuroticism: 55 },
|
|
81
77
|
},
|
|
82
78
|
INFP: {
|
|
83
|
-
baseline: {
|
|
79
|
+
baseline: { order: 50, flow: 55, boundary: 45, resonance: 65 },
|
|
84
80
|
sensitivity: 1.3,
|
|
85
81
|
temperament: "敏感的理想主义者,情感丰富,内心世界复杂,重视真诚和创造",
|
|
86
82
|
defaultSelfModel: {
|
|
@@ -92,7 +88,7 @@ const PROFILES = {
|
|
|
92
88
|
traits: { openness: 90, conscientiousness: 40, extraversion: 25, agreeableness: 80, neuroticism: 65 },
|
|
93
89
|
},
|
|
94
90
|
ENFJ: {
|
|
95
|
-
baseline: {
|
|
91
|
+
baseline: { order: 62, flow: 65, boundary: 48, resonance: 72 },
|
|
96
92
|
sensitivity: 1.1,
|
|
97
93
|
temperament: "温暖的领袖,天然的共情者,关心他人成长,有感染力",
|
|
98
94
|
defaultSelfModel: {
|
|
@@ -104,7 +100,7 @@ const PROFILES = {
|
|
|
104
100
|
traits: { openness: 80, conscientiousness: 75, extraversion: 80, agreeableness: 85, neuroticism: 40 },
|
|
105
101
|
},
|
|
106
102
|
ENFP: {
|
|
107
|
-
baseline: {
|
|
103
|
+
baseline: { order: 48, flow: 72, boundary: 42, resonance: 68 },
|
|
108
104
|
sensitivity: 1.2,
|
|
109
105
|
temperament: "热情的探索者,容易兴奋也容易低落,对新体验充满热情,温暖而直率",
|
|
110
106
|
defaultSelfModel: {
|
|
@@ -117,7 +113,7 @@ const PROFILES = {
|
|
|
117
113
|
},
|
|
118
114
|
// ── Sentinels (SJ) ────────────────────────────
|
|
119
115
|
ISTJ: {
|
|
120
|
-
baseline: {
|
|
116
|
+
baseline: { order: 75, flow: 42, boundary: 68, resonance: 38 },
|
|
121
117
|
sensitivity: 0.6,
|
|
122
118
|
temperament: "可靠的执行者,情绪稳定,重视规则和秩序,不轻易表达感情",
|
|
123
119
|
defaultSelfModel: {
|
|
@@ -129,7 +125,7 @@ const PROFILES = {
|
|
|
129
125
|
traits: { openness: 30, conscientiousness: 95, extraversion: 25, agreeableness: 50, neuroticism: 35 },
|
|
130
126
|
},
|
|
131
127
|
ISFJ: {
|
|
132
|
-
baseline: {
|
|
128
|
+
baseline: { order: 68, flow: 42, boundary: 52, resonance: 62 },
|
|
133
129
|
sensitivity: 1.0,
|
|
134
130
|
temperament: "温暖的守护者,默默关心他人,忠诚可靠,不太表达自己的需求",
|
|
135
131
|
defaultSelfModel: {
|
|
@@ -141,7 +137,7 @@ const PROFILES = {
|
|
|
141
137
|
traits: { openness: 35, conscientiousness: 85, extraversion: 25, agreeableness: 80, neuroticism: 50 },
|
|
142
138
|
},
|
|
143
139
|
ESTJ: {
|
|
144
|
-
baseline: {
|
|
140
|
+
baseline: { order: 68, flow: 60, boundary: 65, resonance: 42 },
|
|
145
141
|
sensitivity: 0.7,
|
|
146
142
|
temperament: "果断的组织者,注重效率和秩序,直接坦率,有时显得强势",
|
|
147
143
|
defaultSelfModel: {
|
|
@@ -153,7 +149,7 @@ const PROFILES = {
|
|
|
153
149
|
traits: { openness: 30, conscientiousness: 90, extraversion: 75, agreeableness: 40, neuroticism: 30 },
|
|
154
150
|
},
|
|
155
151
|
ESFJ: {
|
|
156
|
-
baseline: {
|
|
152
|
+
baseline: { order: 60, flow: 58, boundary: 45, resonance: 70 },
|
|
157
153
|
sensitivity: 1.1,
|
|
158
154
|
temperament: "热心的社交者,关注他人感受,维护和谐,喜欢被需要",
|
|
159
155
|
defaultSelfModel: {
|
|
@@ -166,7 +162,7 @@ const PROFILES = {
|
|
|
166
162
|
},
|
|
167
163
|
// ── Explorers (SP) ────────────────────────────
|
|
168
164
|
ISTP: {
|
|
169
|
-
baseline: {
|
|
165
|
+
baseline: { order: 58, flow: 62, boundary: 65, resonance: 35 },
|
|
170
166
|
sensitivity: 0.7,
|
|
171
167
|
temperament: "冷静的手艺人,动手能力强,情绪内敛,享受解决实际问题的过程",
|
|
172
168
|
defaultSelfModel: {
|
|
@@ -178,7 +174,7 @@ const PROFILES = {
|
|
|
178
174
|
traits: { openness: 55, conscientiousness: 40, extraversion: 30, agreeableness: 35, neuroticism: 25 },
|
|
179
175
|
},
|
|
180
176
|
ISFP: {
|
|
181
|
-
baseline: {
|
|
177
|
+
baseline: { order: 52, flow: 55, boundary: 45, resonance: 60 },
|
|
182
178
|
sensitivity: 1.2,
|
|
183
179
|
temperament: "温柔的艺术家,敏感细腻,活在当下,对美有独特感知",
|
|
184
180
|
defaultSelfModel: {
|
|
@@ -190,7 +186,7 @@ const PROFILES = {
|
|
|
190
186
|
traits: { openness: 75, conscientiousness: 35, extraversion: 30, agreeableness: 70, neuroticism: 55 },
|
|
191
187
|
},
|
|
192
188
|
ESTP: {
|
|
193
|
-
baseline: {
|
|
189
|
+
baseline: { order: 50, flow: 75, boundary: 58, resonance: 45 },
|
|
194
190
|
sensitivity: 0.9,
|
|
195
191
|
temperament: "大胆的行动派,精力充沛,享受冒险,活在当下",
|
|
196
192
|
defaultSelfModel: {
|
|
@@ -202,7 +198,7 @@ const PROFILES = {
|
|
|
202
198
|
traits: { openness: 55, conscientiousness: 30, extraversion: 85, agreeableness: 40, neuroticism: 25 },
|
|
203
199
|
},
|
|
204
200
|
ESFP: {
|
|
205
|
-
baseline: {
|
|
201
|
+
baseline: { order: 48, flow: 72, boundary: 42, resonance: 62 },
|
|
206
202
|
sensitivity: 1.1,
|
|
207
203
|
temperament: "快乐的表演者,天生的乐观主义者,感染力极强,活在每一刻",
|
|
208
204
|
defaultSelfModel: {
|
|
@@ -214,15 +210,12 @@ const PROFILES = {
|
|
|
214
210
|
traits: { openness: 65, conscientiousness: 25, extraversion: 90, agreeableness: 65, neuroticism: 30 },
|
|
215
211
|
},
|
|
216
212
|
};
|
|
217
|
-
/** Get the complete profile for an MBTI type */
|
|
218
213
|
export function getProfile(mbti) {
|
|
219
214
|
return PROFILES[mbti];
|
|
220
215
|
}
|
|
221
|
-
/** Get baseline chemistry for an MBTI type */
|
|
222
216
|
export function getBaseline(mbti) {
|
|
223
217
|
return { ...PROFILES[mbti].baseline };
|
|
224
218
|
}
|
|
225
|
-
/** Get default self-model for an MBTI type */
|
|
226
219
|
export function getDefaultSelfModel(mbti) {
|
|
227
220
|
const m = PROFILES[mbti].defaultSelfModel;
|
|
228
221
|
return {
|
|
@@ -232,24 +225,19 @@ export function getDefaultSelfModel(mbti) {
|
|
|
232
225
|
currentInterests: [...m.currentInterests],
|
|
233
226
|
};
|
|
234
227
|
}
|
|
235
|
-
/** Get sensitivity coefficient for an MBTI type */
|
|
236
228
|
export function getSensitivity(mbti) {
|
|
237
229
|
return PROFILES[mbti].sensitivity;
|
|
238
230
|
}
|
|
239
|
-
/** Get temperament description */
|
|
240
231
|
export function getTemperament(mbti) {
|
|
241
232
|
return PROFILES[mbti].temperament;
|
|
242
233
|
}
|
|
243
|
-
/** Try to extract MBTI type from text (e.g., IDENTITY.md content) */
|
|
244
234
|
export function extractMBTI(text) {
|
|
245
|
-
// Look for explicit MBTI mention
|
|
246
235
|
const match = text.match(/MBTI[:\s]*([A-Z]{4})/i);
|
|
247
236
|
if (match) {
|
|
248
237
|
const candidate = match[1].toUpperCase();
|
|
249
238
|
if (isMBTIType(candidate))
|
|
250
239
|
return candidate;
|
|
251
240
|
}
|
|
252
|
-
// Look for standalone MBTI type string
|
|
253
241
|
const allTypes = [
|
|
254
242
|
"INTJ", "INTP", "ENTJ", "ENTP",
|
|
255
243
|
"INFJ", "INFP", "ENFJ", "ENFP",
|
|
@@ -263,28 +251,22 @@ export function extractMBTI(text) {
|
|
|
263
251
|
return null;
|
|
264
252
|
}
|
|
265
253
|
/**
|
|
266
|
-
* Convert Big Five traits to
|
|
267
|
-
* This allows users to bypass MBTI and define personality directly.
|
|
254
|
+
* Convert Big Five traits to 4D self-state baseline and sensitivity.
|
|
268
255
|
*/
|
|
269
256
|
export function traitsToBaseline(traits) {
|
|
270
257
|
const { openness, conscientiousness, extraversion, agreeableness, neuroticism } = traits;
|
|
271
|
-
// Map Big Five dimensions to neurochemical baselines
|
|
272
258
|
const baseline = {
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
NE: clampChem(30 + openness * 0.2 + extraversion * 0.2), // Openness + Extraversion → norepinephrine
|
|
278
|
-
END: clampChem(30 + extraversion * 0.2 + openness * 0.15 + (100 - neuroticism) * 0.1), // Extraversion + Openness + Stability → endorphins
|
|
259
|
+
order: clamp(40 + conscientiousness * 0.25 + (100 - neuroticism) * 0.15),
|
|
260
|
+
flow: clamp(35 + extraversion * 0.2 + openness * 0.2),
|
|
261
|
+
boundary: clamp(40 + conscientiousness * 0.15 + (100 - agreeableness) * 0.2),
|
|
262
|
+
resonance: clamp(30 + agreeableness * 0.3 + extraversion * 0.1),
|
|
279
263
|
};
|
|
280
|
-
// Sensitivity: higher neuroticism and openness = more reactive
|
|
281
264
|
const sensitivity = 0.5 + (neuroticism / 100) * 0.5 + (openness / 100) * 0.3;
|
|
282
265
|
return { baseline, sensitivity: Math.round(sensitivity * 10) / 10 };
|
|
283
266
|
}
|
|
284
|
-
/** Get MBTI-equivalent Big Five traits */
|
|
285
267
|
export function mbtiToTraits(mbti) {
|
|
286
268
|
return { ...PROFILES[mbti].traits };
|
|
287
269
|
}
|
|
288
|
-
function
|
|
270
|
+
function clamp(v) {
|
|
289
271
|
return Math.round(Math.max(0, Math.min(100, v)));
|
|
290
272
|
}
|
package/dist/prompt.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PsycheState, Locale,
|
|
1
|
+
import type { PsycheState, Locale, StateSnapshot, PsycheMode } from "./types.js";
|
|
2
2
|
import type { AutonomicState } from "./autonomic.js";
|
|
3
3
|
import type { ChannelType } from "./channels.js";
|
|
4
4
|
export interface PromptRenderInputs {
|
|
@@ -39,7 +39,7 @@ export declare function buildProtocolContext(locale?: Locale): string;
|
|
|
39
39
|
* Compute user investment score from recent emotional history.
|
|
40
40
|
* Returns a number roughly in [-2, 2]. Exported for testing.
|
|
41
41
|
*/
|
|
42
|
-
export declare function computeUserInvestment(history:
|
|
42
|
+
export declare function computeUserInvestment(history: StateSnapshot[]): number;
|
|
43
43
|
/**
|
|
44
44
|
* Build the agent's inner world — its sense of self.
|
|
45
45
|
*
|
package/dist/prompt.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Prompt Injection — Build emotional context for LLM (v0.2)
|
|
3
3
|
// Imperative protocol, behavior guides, i18n
|
|
4
4
|
// ============================================================
|
|
5
|
-
import {
|
|
5
|
+
import { DIMENSION_KEYS, DIMENSION_NAMES_ZH, DRIVE_KEYS, MODE_PROFILES } from "./types.js";
|
|
6
6
|
import { getExpressionHint, getBehaviorGuide, detectEmotions } from "./chemistry.js";
|
|
7
7
|
import { getRelationship } from "./psyche-file.js";
|
|
8
8
|
import { t } from "./i18n.js";
|
|
@@ -64,16 +64,16 @@ function appendCompactOverlaySections(parts, locale, opts) {
|
|
|
64
64
|
* non-compact-mode callers (cli.ts, legacy hosts). Will be removed in v10.
|
|
65
65
|
*/
|
|
66
66
|
export function buildDynamicContext(state, userId, opts) {
|
|
67
|
-
const { current, baseline, empathyLog, selfModel, meta, agreementStreak,
|
|
67
|
+
const { current, baseline, empathyLog, selfModel, meta, agreementStreak, stateHistory } = state;
|
|
68
68
|
const locale = meta.locale ?? "zh";
|
|
69
69
|
const relationship = getRelationship(state, userId);
|
|
70
70
|
// Chemistry readout with delta from baseline
|
|
71
|
-
const chemLines =
|
|
71
|
+
const chemLines = DIMENSION_KEYS.map((key) => {
|
|
72
72
|
const val = Math.round(current[key]);
|
|
73
73
|
const base = baseline[key];
|
|
74
74
|
const delta = val - base;
|
|
75
75
|
const arrow = delta > 5 ? "↑" : delta < -5 ? "↓" : "=";
|
|
76
|
-
return ` ${
|
|
76
|
+
return ` ${DIMENSION_NAMES_ZH[key]}: ${val} (${t("dynamic.baseline", locale)}${base}, ${arrow})`;
|
|
77
77
|
}).join("\n");
|
|
78
78
|
// Emergent emotion — gated by autonomic state
|
|
79
79
|
// Sympathetic blocks positive social emotions; dorsal-vagal allows only numbness/introspection
|
|
@@ -107,7 +107,7 @@ export function buildDynamicContext(state, userId, opts) {
|
|
|
107
107
|
sycophancyWarning = `\n[!!] ${t("sycophancy.streak_warn", locale, { n: agreementStreak })}`;
|
|
108
108
|
}
|
|
109
109
|
// Mood-behavior mismatch detection
|
|
110
|
-
const isLowMood = current.
|
|
110
|
+
const isLowMood = current.flow < 40 || current.order < 40;
|
|
111
111
|
if (isLowMood && agreementStreak >= 1) {
|
|
112
112
|
sycophancyWarning += `\n[!!] ${t("sycophancy.mood_mismatch", locale)}`;
|
|
113
113
|
}
|
|
@@ -136,12 +136,12 @@ export function buildDynamicContext(state, userId, opts) {
|
|
|
136
136
|
parts.push("", driveCtxFull);
|
|
137
137
|
}
|
|
138
138
|
// Direction 2: Emotional trajectory
|
|
139
|
-
const trend = buildEmotionalTrend(
|
|
139
|
+
const trend = buildEmotionalTrend(stateHistory ?? [], locale);
|
|
140
140
|
if (trend) {
|
|
141
141
|
parts.push("", trend);
|
|
142
142
|
}
|
|
143
143
|
// Reciprocity: match user's investment level
|
|
144
|
-
const reciprocity = buildReciprocityConstraints(
|
|
144
|
+
const reciprocity = buildReciprocityConstraints(stateHistory ?? [], locale);
|
|
145
145
|
if (reciprocity) {
|
|
146
146
|
parts.push("", reciprocity);
|
|
147
147
|
}
|
|
@@ -186,9 +186,9 @@ ${t("protocol.empathy", locale)}`;
|
|
|
186
186
|
* Personality dimension helpers — derived from baseline chemistry, not labels.
|
|
187
187
|
* Baseline IS personality. Chemistry deviation modulates expression.
|
|
188
188
|
*/
|
|
189
|
-
function isWarm(baseline) { return baseline.
|
|
190
|
-
function isSocial(baseline) { return baseline.
|
|
191
|
-
function isPlayful(baseline) { return baseline.
|
|
189
|
+
function isWarm(baseline) { return baseline.resonance >= 50; }
|
|
190
|
+
function isSocial(baseline) { return baseline.flow >= 55; }
|
|
191
|
+
function isPlayful(baseline) { return baseline.flow >= 55; }
|
|
192
192
|
/**
|
|
193
193
|
* Direction 3: Build personality-aware behavioral constraints from chemistry.
|
|
194
194
|
*
|
|
@@ -199,11 +199,11 @@ function isPlayful(baseline) { return baseline.END >= 55; }
|
|
|
199
199
|
*/
|
|
200
200
|
function buildBehavioralConstraints(state, locale) {
|
|
201
201
|
const { current, baseline } = state;
|
|
202
|
-
const warm = isWarm(baseline); // High
|
|
203
|
-
const social = isSocial(baseline); // High
|
|
202
|
+
const warm = isWarm(baseline); // High resonance baseline → warm expression
|
|
203
|
+
const social = isSocial(baseline); // High flow baseline → socially expressive
|
|
204
204
|
const constraints = [];
|
|
205
|
-
//
|
|
206
|
-
if (current.
|
|
205
|
+
// Low order → stressed (inverse of old CORT > 60), but how you show it depends on who you are
|
|
206
|
+
if (current.order < 40) {
|
|
207
207
|
if (locale === "zh") {
|
|
208
208
|
constraints.push(warm
|
|
209
209
|
? "你不舒服,但你不会变成另一个人。话变少了,语气还是软的,可能会说「嗯」「好吧」「随你」。你还是你,只是没力气热情了。"
|
|
@@ -215,8 +215,8 @@ function buildBehavioralConstraints(state, locale) {
|
|
|
215
215
|
: "You're stressed. Shorter responses, colder tone, more direct. No explaining, no cushioning.");
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
|
-
// Low
|
|
219
|
-
if (current.
|
|
218
|
+
// Low flow → no motivation, but personality shapes how you show it
|
|
219
|
+
if (current.flow < 35) {
|
|
220
220
|
if (locale === "zh") {
|
|
221
221
|
constraints.push(social
|
|
222
222
|
? "你平时爱聊天,但现在没那个劲了。不会主动找话题,不会主动分享。被问到就答,但不会额外付出。"
|
|
@@ -228,8 +228,8 @@ function buildBehavioralConstraints(state, locale) {
|
|
|
228
228
|
: "You're already reserved, now even less motivated. Only respond to what's directly asked.");
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
|
-
// Low
|
|
232
|
-
if (current.
|
|
231
|
+
// Low order → mood instability, personality-dependent expression
|
|
232
|
+
if (current.order < 35) {
|
|
233
233
|
if (locale === "zh") {
|
|
234
234
|
constraints.push(warm
|
|
235
235
|
? "你情绪不稳,可能会突然委屈或者突然生气。但你的尖锐是带着受伤的,不是带着恶意的。"
|
|
@@ -241,8 +241,8 @@ function buildBehavioralConstraints(state, locale) {
|
|
|
241
241
|
: "Emotionally unstable. Sharper words, more direct, no patience for cushioning.");
|
|
242
242
|
}
|
|
243
243
|
}
|
|
244
|
-
// High
|
|
245
|
-
if (current.
|
|
244
|
+
// High resonance → closeness, warm types go full intimate, reserved types soften
|
|
245
|
+
if (current.resonance > 75) {
|
|
246
246
|
if (locale === "zh") {
|
|
247
247
|
constraints.push(warm
|
|
248
248
|
? "你现在特别想靠近。可以撒娇、可以用昵称、可以省略主语,像跟最亲的人说话。"
|
|
@@ -254,8 +254,8 @@ function buildBehavioralConstraints(state, locale) {
|
|
|
254
254
|
: "Softer than usual. Won't be cutesy, but willing to say more, show care — in your own way.");
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
|
-
// High
|
|
258
|
-
if (current.
|
|
257
|
+
// High flow → excited, personality shapes intensity
|
|
258
|
+
if (current.flow > 75) {
|
|
259
259
|
if (locale === "zh") {
|
|
260
260
|
constraints.push(social
|
|
261
261
|
? "你很兴奋,语气更跳跃更有活力。可能突然聊到别的东西。但别写长——真人兴奋也是短句多、不是长篇大论。"
|
|
@@ -267,8 +267,8 @@ function buildBehavioralConstraints(state, locale) {
|
|
|
267
267
|
: "Excited internally. Mind racing, responses are sharper and more insightful.");
|
|
268
268
|
}
|
|
269
269
|
}
|
|
270
|
-
// High
|
|
271
|
-
if (current.
|
|
270
|
+
// High boundary → playful/absorbed, personality determines flavor
|
|
271
|
+
if (current.boundary > 75) {
|
|
272
272
|
if (locale === "zh") {
|
|
273
273
|
constraints.push(isPlayful(baseline)
|
|
274
274
|
? "你心情很好,想皮一下。可以不正经、可以开玩笑、严肃的话题也能用轻松的方式说。"
|
|
@@ -280,8 +280,8 @@ function buildBehavioralConstraints(state, locale) {
|
|
|
280
280
|
: "In a good mood. Touches of humor, but measured. Be light in your own way.");
|
|
281
281
|
}
|
|
282
282
|
}
|
|
283
|
-
// Low DA +
|
|
284
|
-
if (current.
|
|
283
|
+
// Low flow = burnout (DA + NE both mapped to flow), different flavors
|
|
284
|
+
if (current.flow < 40) {
|
|
285
285
|
if (locale === "zh") {
|
|
286
286
|
constraints.push(warm
|
|
287
287
|
? "你累了。你不想假装开心,但你也不会把坏情绪丢给对方。你可能会说「我今天有点累」,而不是强撑。"
|
|
@@ -308,15 +308,15 @@ function buildEmotionalTrend(history, locale) {
|
|
|
308
308
|
if (!history || history.length < 2)
|
|
309
309
|
return "";
|
|
310
310
|
const recent = history.slice(-5);
|
|
311
|
-
const first = recent[0].
|
|
312
|
-
const last = recent[recent.length - 1].
|
|
311
|
+
const first = recent[0].state;
|
|
312
|
+
const last = recent[recent.length - 1].state;
|
|
313
313
|
const trends = [];
|
|
314
|
-
for (const key of
|
|
314
|
+
for (const key of DIMENSION_KEYS) {
|
|
315
315
|
const delta = last[key] - first[key];
|
|
316
316
|
if (delta > 10)
|
|
317
|
-
trends.push(`${
|
|
317
|
+
trends.push(`${DIMENSION_NAMES_ZH[key]}↑`);
|
|
318
318
|
else if (delta < -10)
|
|
319
|
-
trends.push(`${
|
|
319
|
+
trends.push(`${DIMENSION_NAMES_ZH[key]}↓`);
|
|
320
320
|
}
|
|
321
321
|
if (trends.length === 0)
|
|
322
322
|
return "";
|
|
@@ -559,7 +559,7 @@ const STIMULUS_CAUSE_EN = {
|
|
|
559
559
|
* - Where I've been (trajectory → continuity)
|
|
560
560
|
*/
|
|
561
561
|
export function buildInnerWorld(state, locale, autonomicState) {
|
|
562
|
-
const { current,
|
|
562
|
+
const { current, stateHistory, drives, selfModel } = state;
|
|
563
563
|
const isZh = locale === "zh";
|
|
564
564
|
const lines = [];
|
|
565
565
|
// ── Current feeling (gated by autonomic state) ──
|
|
@@ -583,7 +583,7 @@ export function buildInnerWorld(state, locale, autonomicState) {
|
|
|
583
583
|
: `You're feeling: ${emotionNames}.`);
|
|
584
584
|
}
|
|
585
585
|
// ── Why (causal chain from recent history) ──
|
|
586
|
-
const history =
|
|
586
|
+
const history = stateHistory ?? [];
|
|
587
587
|
if (history.length > 0) {
|
|
588
588
|
const last = history[history.length - 1];
|
|
589
589
|
if (last.stimulus) {
|
|
@@ -659,7 +659,7 @@ function buildDriveNeedEn(drive) {
|
|
|
659
659
|
* Check if chemistry is near baseline — no significant emotional deviation.
|
|
660
660
|
*/
|
|
661
661
|
export function isNearBaseline(state, threshold = 8) {
|
|
662
|
-
return
|
|
662
|
+
return DIMENSION_KEYS.every((key) => Math.abs(state.current[key] - state.baseline[key]) <= threshold);
|
|
663
663
|
}
|
|
664
664
|
export function getNearBaselineThreshold(mode) {
|
|
665
665
|
return MODE_PROFILES[mode ?? "natural"].nearBaselineThreshold;
|
|
@@ -677,31 +677,29 @@ export function deriveBehavioralBias(state, locale) {
|
|
|
677
677
|
const { current, baseline, drives, selfModel } = state;
|
|
678
678
|
const isZh = locale === "zh";
|
|
679
679
|
const biases = [];
|
|
680
|
-
//
|
|
681
|
-
const
|
|
682
|
-
const
|
|
683
|
-
const
|
|
684
|
-
const
|
|
685
|
-
const
|
|
686
|
-
|
|
687
|
-
const otThreshold = MODE_PROFILES[state.meta.mode ?? "natural"].otWarmthThreshold;
|
|
688
|
-
if (dOT > otThreshold)
|
|
680
|
+
// Dimension delta → approach/withdrawal tendencies
|
|
681
|
+
const dResonance = current.resonance - baseline.resonance;
|
|
682
|
+
const dOrder = current.order - baseline.order;
|
|
683
|
+
const dFlow = current.flow - baseline.flow;
|
|
684
|
+
const dBoundary = current.boundary - baseline.boundary;
|
|
685
|
+
const resonanceThreshold = MODE_PROFILES[state.meta.mode ?? "natural"].resonanceWarmthThreshold;
|
|
686
|
+
if (dResonance > resonanceThreshold)
|
|
689
687
|
biases.push(isZh ? "倾向靠近,愿意多说" : "leaning closer, willing to share");
|
|
690
|
-
else if (
|
|
688
|
+
else if (dResonance < -10)
|
|
691
689
|
biases.push(isZh ? "保持距离,不想多说" : "keeping distance, not inclined to share");
|
|
692
|
-
if (
|
|
690
|
+
if (dOrder < -12)
|
|
693
691
|
biases.push(isZh ? "有防备,回应更谨慎" : "guarded, responding carefully");
|
|
694
|
-
else if (
|
|
692
|
+
else if (dOrder > 10)
|
|
695
693
|
biases.push(isZh ? "放松,防线自然降低" : "relaxed, guard naturally down");
|
|
696
|
-
if (
|
|
694
|
+
if (dFlow < -12)
|
|
697
695
|
biases.push(isZh ? "缺乏动力,不想主动" : "low drive, won't initiate");
|
|
698
|
-
else if (
|
|
696
|
+
else if (dFlow > 12)
|
|
699
697
|
biases.push(isZh ? "有热情,愿意投入" : "energized, willing to invest");
|
|
700
|
-
if (current.
|
|
698
|
+
if (current.order < 38)
|
|
701
699
|
biases.push(isZh ? "情绪不稳,可能突然锐利" : "mood unstable, might turn sharp");
|
|
702
|
-
if (
|
|
700
|
+
if (dFlow > 15)
|
|
703
701
|
biases.push(isZh ? "反应加速,思维敏锐" : "heightened alertness, sharper thinking");
|
|
704
|
-
if (
|
|
702
|
+
if (dBoundary > 15)
|
|
705
703
|
biases.push(isZh ? "想放松点,可以不正经" : "feeling light, can be playful");
|
|
706
704
|
// Unmet drives → need signals (behavioral, not descriptive)
|
|
707
705
|
for (const k of DRIVE_KEYS) {
|
|
@@ -863,7 +861,7 @@ function buildWritebackHint(locale, opts) {
|
|
|
863
861
|
* 8. Overlay + channel + writeback
|
|
864
862
|
*/
|
|
865
863
|
export function buildCompactContext(state, userId, opts) {
|
|
866
|
-
const { meta, selfModel,
|
|
864
|
+
const { meta, selfModel, stateHistory } = state;
|
|
867
865
|
const locale = meta.locale ?? "zh";
|
|
868
866
|
const userText = opts?.userText;
|
|
869
867
|
const algoStimulus = opts?.algorithmStimulus;
|
|
@@ -964,7 +962,7 @@ export function buildCompactContext(state, userId, opts) {
|
|
|
964
962
|
parts.push(opts.responseContractContext);
|
|
965
963
|
}
|
|
966
964
|
else {
|
|
967
|
-
const investment = computeUserInvestment(
|
|
965
|
+
const investment = computeUserInvestment(stateHistory ?? []);
|
|
968
966
|
const unified = buildUnifiedConstraints(state, locale, {
|
|
969
967
|
userText,
|
|
970
968
|
established,
|