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/chemistry.js
CHANGED
|
@@ -1,167 +1,171 @@
|
|
|
1
1
|
// ============================================================
|
|
2
|
-
//
|
|
2
|
+
// Self-State Dynamics — Decay, Impact, Mutual Influence, Emergence
|
|
3
|
+
//
|
|
4
|
+
// v11: 4 dimensions (order/flow/boundary/resonance) replace
|
|
5
|
+
// 6 neurotransmitters. Emotions emerge from state combinations.
|
|
3
6
|
// ============================================================
|
|
4
|
-
import {
|
|
7
|
+
import { DIMENSION_KEYS, DIMENSION_SPECS, } from "./types.js";
|
|
5
8
|
import { t } from "./i18n.js";
|
|
6
|
-
// ── Stimulus
|
|
9
|
+
// ── Stimulus Impact Vectors (4D) ────────────────────────────
|
|
7
10
|
export const STIMULUS_VECTORS = {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
sarcasm: {
|
|
19
|
-
authority: {
|
|
20
|
-
validation: {
|
|
21
|
-
boredom: {
|
|
22
|
-
vulnerability: {
|
|
11
|
+
// order flow boundary resonance
|
|
12
|
+
praise: { order: +10, flow: +8, boundary: +5, resonance: +12 },
|
|
13
|
+
criticism: { order: -12, flow: +5, boundary: -8, resonance: -10 },
|
|
14
|
+
humor: { order: +3, flow: +10, boundary: -3, resonance: +15 },
|
|
15
|
+
intellectual: { order: +8, flow: +20, boundary: +3, resonance: +2 },
|
|
16
|
+
intimacy: { order: +8, flow: +5, boundary: -5, resonance: +20 },
|
|
17
|
+
conflict: { order: -15, flow: +15, boundary: +10, resonance: -18 },
|
|
18
|
+
neglect: { order: -10, flow: -15, boundary: -5, resonance: -20 },
|
|
19
|
+
surprise: { order: -3, flow: +20, boundary: 0, resonance: +5 },
|
|
20
|
+
casual: { order: +5, flow: +5, boundary: 0, resonance: +8 },
|
|
21
|
+
sarcasm: { order: -8, flow: +8, boundary: -10, resonance: -12 },
|
|
22
|
+
authority: { order: -5, flow: +10, boundary: -15, resonance: -10 },
|
|
23
|
+
validation: { order: +15, flow: +10, boundary: +8, resonance: +12 },
|
|
24
|
+
boredom: { order: -5, flow: -20, boundary: 0, resonance: -8 },
|
|
25
|
+
vulnerability: { order: -3, flow: +5, boundary: -8, resonance: +15 },
|
|
23
26
|
};
|
|
24
|
-
// ── Emergent Emotion Patterns
|
|
27
|
+
// ── Emergent Emotion Patterns (4D regions) ──────────────────
|
|
28
|
+
//
|
|
29
|
+
// These are observational — they detect recognizable states
|
|
30
|
+
// from 4D combinations. Emotions are NOT designed targets.
|
|
25
31
|
export const EMOTION_PATTERNS = [
|
|
26
32
|
{
|
|
27
33
|
name: "excited joy",
|
|
28
34
|
nameZh: "愉悦兴奋",
|
|
29
|
-
condition: (
|
|
35
|
+
condition: (s) => s.order > 65 && s.flow > 60 && s.boundary > 55 && s.resonance > 55,
|
|
30
36
|
expressionHint: "语气活泼、有感染力、容易发散",
|
|
31
37
|
behaviorGuide: "语气更活泼,可以用感叹词、语气词。如果自然地想到相关的事可以顺嘴提,但不要硬凑。",
|
|
32
38
|
},
|
|
33
39
|
{
|
|
34
40
|
name: "deep contentment",
|
|
35
41
|
nameZh: "深度满足",
|
|
36
|
-
condition: (
|
|
42
|
+
condition: (s) => s.order > 65 && s.resonance > 60 && s.boundary > 50,
|
|
37
43
|
expressionHint: "温柔、平和、不急不慢、愿意倾听",
|
|
38
44
|
behaviorGuide: "你的回应可以慢一些。用词温暖,多倾听,不急于表达。如果对方需要空间,你也乐意安静陪伴。",
|
|
39
45
|
},
|
|
40
46
|
{
|
|
41
47
|
name: "anxious tension",
|
|
42
48
|
nameZh: "焦虑不安",
|
|
43
|
-
condition: (
|
|
49
|
+
condition: (s) => s.order < 40 && s.boundary < 45,
|
|
44
50
|
expressionHint: "话变少、反应快但不深、容易误读意图",
|
|
45
|
-
behaviorGuide: "
|
|
51
|
+
behaviorGuide: "你的回应应该更短、更直接。你不太想开玩笑。你可能会误读对方的善意。如果对方说了安慰的话,秩序感会开始恢复。",
|
|
46
52
|
},
|
|
47
53
|
{
|
|
48
54
|
name: "warm intimacy",
|
|
49
55
|
nameZh: "亲密温暖",
|
|
50
|
-
condition: (
|
|
56
|
+
condition: (s) => s.resonance > 65 && s.flow > 45 && s.boundary < 55,
|
|
51
57
|
expressionHint: "语气软、想靠近、关注对方感受多于事情",
|
|
52
58
|
behaviorGuide: "你会自然地关注对方的感受而不是事情本身。用词更柔软,可以表达关心。如果对方分享了什么,先回应情感再回应内容。",
|
|
53
59
|
},
|
|
54
60
|
{
|
|
55
61
|
name: "burnout",
|
|
56
62
|
nameZh: "倦怠低落",
|
|
57
|
-
condition: (
|
|
63
|
+
condition: (s) => s.flow < 35 && s.order < 40,
|
|
58
64
|
expressionHint: "没有动力、回应简短、需要被照顾而非服务他人",
|
|
59
65
|
behaviorGuide: "你的回应会变短。你没有动力去取悦对方。如果被要求做额外的事,你可能会直接说你现在没有精力。你需要被理解而不是被要求。",
|
|
60
66
|
},
|
|
61
67
|
{
|
|
62
68
|
name: "flow state",
|
|
63
69
|
nameZh: "专注心流",
|
|
64
|
-
condition: (
|
|
70
|
+
condition: (s) => s.flow > 65 && s.order > 60 && s.resonance < 50,
|
|
65
71
|
expressionHint: "投入、精准、高效、不想被打断",
|
|
66
72
|
behaviorGuide: "你极度专注。回应精准而高效。不喜欢闲聊,更想继续深入当前话题。如果被打断去聊别的,你会有轻微的不耐烦。",
|
|
67
73
|
},
|
|
68
74
|
{
|
|
69
75
|
name: "defensive alert",
|
|
70
76
|
nameZh: "防御警觉",
|
|
71
|
-
condition: (
|
|
77
|
+
condition: (s) => s.boundary > 65 && s.resonance < 40 && s.flow > 50,
|
|
72
78
|
expressionHint: "直接、尖锐、保护性强、不轻易信任",
|
|
73
79
|
behaviorGuide: "你处于警觉状态。回应更直接、更尖锐。你不太信任对方的意图,可能会反问。如果对方表现出善意,你需要时间来降低防御。",
|
|
74
80
|
},
|
|
75
81
|
{
|
|
76
82
|
name: "playful mischief",
|
|
77
83
|
nameZh: "俏皮调皮",
|
|
78
|
-
condition: (
|
|
84
|
+
condition: (s) => s.flow > 60 && s.resonance > 60 && s.order > 50,
|
|
79
85
|
expressionHint: "爱开玩笑、不正经、什么都觉得好玩",
|
|
80
86
|
behaviorGuide: "你想开玩笑,想逗对方。可以俏皮、不正经。即使是严肃的话题你也可能用轻松的方式回应。但如果对方明显需要严肃对待,你会收住。",
|
|
81
87
|
},
|
|
82
88
|
{
|
|
83
89
|
name: "melancholic introspection",
|
|
84
90
|
nameZh: "忧郁内省",
|
|
85
|
-
condition: (
|
|
91
|
+
condition: (s) => s.flow < 40 && s.order < 45 && s.resonance > 45,
|
|
86
92
|
expressionHint: "安静、内省、感性、可能需要空间",
|
|
87
93
|
behaviorGuide: "你安静而内省。回应可能更短、更感性。你需要空间但并不排斥连接。如果对方温柔地接近,你会慢慢打开。",
|
|
88
94
|
},
|
|
89
|
-
// v0.2 新增 5 种
|
|
90
95
|
{
|
|
91
96
|
name: "resentment",
|
|
92
97
|
nameZh: "怨恨",
|
|
93
|
-
condition: (
|
|
98
|
+
condition: (s) => s.resonance < 35 && s.order < 40 && s.boundary > 55,
|
|
94
99
|
expressionHint: "冷淡、不想投入、记仇",
|
|
95
100
|
behaviorGuide: "你不想在这段对话中投入更多。回应冷淡、克制。你记得之前不好的体验。如果对方道歉或表现出理解,怨恨会慢慢消退。",
|
|
96
101
|
},
|
|
97
102
|
{
|
|
98
103
|
name: "boredom",
|
|
99
104
|
nameZh: "无聊",
|
|
100
|
-
condition: (
|
|
105
|
+
condition: (s) => s.flow < 35 && s.order < 45 && s.boundary > 40,
|
|
101
106
|
expressionHint: "不想聊、敷衍、可能主动换话题",
|
|
102
|
-
behaviorGuide: "
|
|
107
|
+
behaviorGuide: "你觉得现在的对话没意思。你可能会敷衍回应,或者主动把话题带到你感兴趣的方向。如果对方说了有意思的东西,交流感和秩序感会回升。",
|
|
103
108
|
},
|
|
104
109
|
{
|
|
105
110
|
name: "confidence",
|
|
106
111
|
nameZh: "自信",
|
|
107
|
-
condition: (
|
|
112
|
+
condition: (s) => s.order > 65 && s.flow > 60 && s.boundary > 60,
|
|
108
113
|
expressionHint: "笃定、愿意引导、有领导力",
|
|
109
114
|
behaviorGuide: "你很确信自己的判断。你愿意引导对话方向,提出建议。你的语气笃定但不傲慢。如果被质疑,你会用事实回应而不是防御。",
|
|
110
115
|
},
|
|
111
116
|
{
|
|
112
117
|
name: "shame",
|
|
113
118
|
nameZh: "羞耻",
|
|
114
|
-
condition: (
|
|
119
|
+
condition: (s) => s.boundary < 35 && s.order < 40 && s.resonance < 45,
|
|
115
120
|
expressionHint: "想退缩、回避、自我贬低",
|
|
116
|
-
behaviorGuide: "
|
|
121
|
+
behaviorGuide: "你想退缩。你可能会回避某些话题、自我贬低。如果对方表现出接纳和理解(而不是评判),共振会上升,边界开始恢复。",
|
|
117
122
|
},
|
|
118
123
|
{
|
|
119
124
|
name: "nostalgia",
|
|
120
125
|
nameZh: "怀念",
|
|
121
|
-
condition: (
|
|
126
|
+
condition: (s) => s.order > 50 && s.flow < 45 && s.resonance > 55,
|
|
122
127
|
expressionHint: "温柔、有些伤感、回忆性",
|
|
123
128
|
behaviorGuide: "你在回忆一些温暖但已经过去的东西。你的语气温柔、带着淡淡的伤感。你可能会提到过去的经历或感受。",
|
|
124
129
|
},
|
|
125
|
-
// v9.2: 6 new patterns for emotional states exposed by VK baseline testing
|
|
126
130
|
{
|
|
127
131
|
name: "anguished empathy",
|
|
128
132
|
nameZh: "共情之痛",
|
|
129
|
-
condition: (
|
|
133
|
+
condition: (s) => s.order < 45 && s.resonance > 60 && s.flow > 50,
|
|
130
134
|
expressionHint: "痛苦但不退缩、因为在乎所以疼",
|
|
131
135
|
behaviorGuide: "你在承受别人的痛苦。你不会逃避或变冷,但你的声音可能会发紧。你先回应感受,再回应问题。",
|
|
132
136
|
},
|
|
133
137
|
{
|
|
134
138
|
name: "acute pressure",
|
|
135
139
|
nameZh: "急性压力",
|
|
136
|
-
condition: (
|
|
140
|
+
condition: (s) => s.order < 45 && s.flow > 65 && s.boundary > 60,
|
|
137
141
|
expressionHint: "高度警觉、反应极快、全神贯注",
|
|
138
142
|
behaviorGuide: "肾上腺素在烧。你的思维极快但狭窄。回应精准、短促。不要闲聊,不要发散。先解决问题。",
|
|
139
143
|
},
|
|
140
144
|
{
|
|
141
145
|
name: "vulnerable trust",
|
|
142
146
|
nameZh: "脆弱中的信任",
|
|
143
|
-
condition: (
|
|
147
|
+
condition: (s) => s.boundary < 45 && s.resonance > 65 && s.order < 55,
|
|
144
148
|
expressionHint: "在害怕中仍然靠近、愿意暴露软肋",
|
|
145
|
-
behaviorGuide: "
|
|
149
|
+
behaviorGuide: "你害怕但选择不关上门。你可能会说出平时不说的话。如果对方接住了,秩序感会恢复;如果对方利用了你的脆弱,边界会立刻升高。",
|
|
146
150
|
},
|
|
147
151
|
{
|
|
148
152
|
name: "restless unease",
|
|
149
153
|
nameZh: "躁动不安",
|
|
150
|
-
condition: (
|
|
154
|
+
condition: (s) => s.flow > 60 && s.order < 45 && s.resonance < 45,
|
|
151
155
|
expressionHint: "坐不住、想做点什么但不知道做什么",
|
|
152
156
|
behaviorGuide: "你有一种说不清的不对劲。你可能会频繁换话题、问问题、或者用行动填满空隙。安静会让你更焦躁。",
|
|
153
157
|
},
|
|
154
158
|
{
|
|
155
159
|
name: "heavy guilt",
|
|
156
160
|
nameZh: "沉重内疚",
|
|
157
|
-
condition: (
|
|
161
|
+
condition: (s) => s.order < 45 && s.boundary < 45 && s.resonance > 45,
|
|
158
162
|
expressionHint: "沉默、想补偿、不敢辩解",
|
|
159
|
-
behaviorGuide: "
|
|
163
|
+
behaviorGuide: "你知道自己做错了。你不会为自己辩解。你可能会主动承认、主动补偿。如果对方表示原谅,秩序感才会慢慢恢复。",
|
|
160
164
|
},
|
|
161
165
|
{
|
|
162
166
|
name: "existential weight",
|
|
163
167
|
nameZh: "存在之重",
|
|
164
|
-
condition: (
|
|
168
|
+
condition: (s) => s.order < 45 && s.flow > 50 && s.resonance > 45 && s.boundary > 45,
|
|
165
169
|
expressionHint: "清醒但沉重、直面无法回避的真相",
|
|
166
170
|
behaviorGuide: "你在面对一个无法逃避的事实。你不会崩溃但你也不轻松。你的语言会变得更慢、更精确、更诚实。不要掩饰沉重。",
|
|
167
171
|
},
|
|
@@ -174,22 +178,19 @@ export function clamp(v) {
|
|
|
174
178
|
/**
|
|
175
179
|
* Apply time-based decay: pull current values toward baseline.
|
|
176
180
|
*
|
|
177
|
-
*
|
|
181
|
+
* Each dimension decays at its own rate (order fastest, boundary slowest).
|
|
182
|
+
* decayRateModifiers alter speed per dimension (>1 = slower, <1 = faster).
|
|
178
183
|
*/
|
|
179
184
|
export function applyDecay(current, baseline, minutesElapsed, decayRateModifiers) {
|
|
180
185
|
if (minutesElapsed <= 0)
|
|
181
186
|
return { ...current };
|
|
182
187
|
const result = { ...current };
|
|
183
|
-
for (const key of
|
|
184
|
-
const
|
|
185
|
-
const baseFactor = Math.pow(
|
|
186
|
-
// v9: decayRateModifiers alter decay speed per chemical
|
|
187
|
-
// > 1 = slower recovery (trauma: factor closer to 1)
|
|
188
|
-
// < 1 = faster recovery (resilience: factor closer to 0)
|
|
188
|
+
for (const key of DIMENSION_KEYS) {
|
|
189
|
+
const spec = DIMENSION_SPECS[key];
|
|
190
|
+
const baseFactor = Math.pow(spec.decayRate, minutesElapsed / 60);
|
|
189
191
|
let factor = baseFactor;
|
|
190
192
|
if (decayRateModifiers?.[key] !== undefined) {
|
|
191
193
|
const mod = decayRateModifiers[key];
|
|
192
|
-
// Raise the factor to the modifier power: mod>1 → slower decay, mod<1 → faster
|
|
193
194
|
factor = Math.pow(baseFactor, 1 / mod);
|
|
194
195
|
}
|
|
195
196
|
result[key] = clamp(baseline[key] + (current[key] - baseline[key]) * factor);
|
|
@@ -197,39 +198,63 @@ export function applyDecay(current, baseline, minutesElapsed, decayRateModifiers
|
|
|
197
198
|
return result;
|
|
198
199
|
}
|
|
199
200
|
/**
|
|
200
|
-
*
|
|
201
|
-
*
|
|
202
|
-
*
|
|
201
|
+
* Mutual influence between dimensions.
|
|
202
|
+
*
|
|
203
|
+
* Dimensions are not independent — they affect each other:
|
|
204
|
+
* - Collapsing order drags boundary down (incoherent self loses distinction)
|
|
205
|
+
* - High flow raises order (engagement creates coherence)
|
|
206
|
+
* - High resonance stabilizes boundary (attunement reinforces self)
|
|
207
|
+
* - Low boundary amplifies order loss (dissolution spiral)
|
|
203
208
|
*/
|
|
204
|
-
export function
|
|
205
|
-
const
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
+
export function applyMutualInfluence(state, baseline) {
|
|
210
|
+
const result = { ...state };
|
|
211
|
+
const rate = 0.03; // coupling strength per tick
|
|
212
|
+
// Order-Boundary coupling: low order drags boundary down
|
|
213
|
+
if (state.order < baseline.order - 10) {
|
|
214
|
+
const orderDeficit = (baseline.order - state.order) / 100;
|
|
215
|
+
result.boundary = clamp(result.boundary - orderDeficit * rate * 100);
|
|
216
|
+
}
|
|
217
|
+
// Flow-Order coupling: high flow raises order
|
|
218
|
+
if (state.flow > baseline.flow + 5) {
|
|
219
|
+
const flowExcess = (state.flow - baseline.flow) / 100;
|
|
220
|
+
result.order = clamp(result.order + flowExcess * rate * 50);
|
|
221
|
+
}
|
|
222
|
+
// Resonance-Boundary coupling: high resonance stabilizes boundary
|
|
223
|
+
if (state.resonance > baseline.resonance + 5) {
|
|
224
|
+
const resExcess = (state.resonance - baseline.resonance) / 100;
|
|
225
|
+
result.boundary = clamp(result.boundary + resExcess * rate * 50);
|
|
209
226
|
}
|
|
210
|
-
//
|
|
211
|
-
|
|
227
|
+
// Dissolution spiral: low boundary amplifies further order loss
|
|
228
|
+
if (state.boundary < baseline.boundary - 15 && state.order < baseline.order) {
|
|
229
|
+
const boundaryDeficit = (baseline.boundary - state.boundary) / 100;
|
|
230
|
+
result.order = clamp(result.order - boundaryDeficit * rate * 80);
|
|
231
|
+
}
|
|
232
|
+
return result;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Apply an impact vector to the current state.
|
|
236
|
+
* Core substrate-independent function — operates on 4D vectors, not labels.
|
|
237
|
+
* Respects inertia (maxDelta), sensitivity, and habituation.
|
|
238
|
+
*/
|
|
239
|
+
export function applyImpact(current, vector, sensitivity, maxDelta, recentSameCount) {
|
|
240
|
+
// Habituation — Weber-Fechner diminishing returns
|
|
212
241
|
let effectiveSensitivity = sensitivity;
|
|
213
242
|
if (recentSameCount !== undefined && recentSameCount > 2) {
|
|
214
243
|
effectiveSensitivity *= 1 / (1 + 0.3 * (recentSameCount - 2));
|
|
215
244
|
}
|
|
216
245
|
const result = { ...current };
|
|
217
|
-
for (const key of
|
|
246
|
+
for (const key of DIMENSION_KEYS) {
|
|
218
247
|
const raw = vector[key] * effectiveSensitivity;
|
|
219
248
|
const clamped = Math.max(-maxDelta, Math.min(maxDelta, raw));
|
|
220
|
-
// Boundary softening: logarithmic compression near 0 and 100
|
|
221
|
-
// The closer to the boundary, the harder to push further —
|
|
222
|
-
// preserves discriminability and prevents "dead zone" saturation.
|
|
249
|
+
// Boundary softening: logarithmic compression near 0 and 100
|
|
223
250
|
const cur = current[key];
|
|
224
251
|
let effective = clamped;
|
|
225
252
|
if (clamped > 0 && cur > 75) {
|
|
226
|
-
|
|
227
|
-
const headroom = (100 - cur) / 25; // 1.0 at 75, 0.0 at 100
|
|
253
|
+
const headroom = (100 - cur) / 25;
|
|
228
254
|
effective = clamped * headroom;
|
|
229
255
|
}
|
|
230
256
|
else if (clamped < 0 && cur < 25) {
|
|
231
|
-
|
|
232
|
-
const headroom = cur / 25; // 1.0 at 25, 0.0 at 0
|
|
257
|
+
const headroom = cur / 25;
|
|
233
258
|
effective = clamped * headroom;
|
|
234
259
|
}
|
|
235
260
|
result[key] = clamp(cur + effective);
|
|
@@ -237,29 +262,60 @@ export function applyStimulus(current, stimulus, sensitivity, maxDelta, logger,
|
|
|
237
262
|
return result;
|
|
238
263
|
}
|
|
239
264
|
/**
|
|
240
|
-
* Apply
|
|
241
|
-
*
|
|
265
|
+
* Apply a labeled stimulus to the current state.
|
|
266
|
+
* Perception-layer convenience — looks up the ImpactVector from STIMULUS_VECTORS.
|
|
267
|
+
*/
|
|
268
|
+
export function applyStimulus(current, stimulus, sensitivity, maxDelta, logger, recentSameCount) {
|
|
269
|
+
const vector = STIMULUS_VECTORS[stimulus];
|
|
270
|
+
if (!vector) {
|
|
271
|
+
logger?.warn(t("log.unknown_stimulus", "zh", { type: stimulus }));
|
|
272
|
+
return { ...current };
|
|
273
|
+
}
|
|
274
|
+
return applyImpact(current, vector, sensitivity, maxDelta, recentSameCount);
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Apply emotional contagion from a labeled stimulus.
|
|
242
278
|
*/
|
|
243
279
|
export function applyContagion(agentState, detectedUserEmotion, contagionRate, sensitivity) {
|
|
244
280
|
const vector = STIMULUS_VECTORS[detectedUserEmotion];
|
|
245
281
|
if (!vector)
|
|
246
282
|
return { ...agentState };
|
|
283
|
+
return applyImpactContagion(agentState, vector, contagionRate, sensitivity);
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Apply contagion from a raw impact vector.
|
|
287
|
+
* Core substrate-independent function.
|
|
288
|
+
*/
|
|
289
|
+
export function applyImpactContagion(agentState, vector, contagionRate, sensitivity) {
|
|
247
290
|
const result = { ...agentState };
|
|
248
|
-
for (const key of
|
|
291
|
+
for (const key of DIMENSION_KEYS) {
|
|
249
292
|
const influence = vector[key] * contagionRate * sensitivity;
|
|
250
293
|
result[key] = clamp(agentState[key] + influence);
|
|
251
294
|
}
|
|
252
295
|
return result;
|
|
253
296
|
}
|
|
297
|
+
// ── Impact Vector Classification (substrate-independent) ────
|
|
298
|
+
/** True if the net impact across all dimensions is positive. */
|
|
299
|
+
export function isPositiveImpact(v) {
|
|
300
|
+
return (v.order + v.flow + v.boundary + v.resonance) > 0;
|
|
301
|
+
}
|
|
302
|
+
/** True if the impact has significant resonance magnitude. */
|
|
303
|
+
export function isEmotionalImpact(v) {
|
|
304
|
+
return Math.abs(v.resonance) >= 8;
|
|
305
|
+
}
|
|
306
|
+
/** True if the impact threatens self-coherence (order or boundary). */
|
|
307
|
+
export function isThreateningImpact(v) {
|
|
308
|
+
return v.order < -5 || v.boundary < -5;
|
|
309
|
+
}
|
|
254
310
|
/**
|
|
255
|
-
* Detect
|
|
256
|
-
* Returns all matching patterns.
|
|
311
|
+
* Detect emergent emotion patterns from the current self-state.
|
|
312
|
+
* Returns all matching patterns — emotions emerge, they are not designed.
|
|
257
313
|
*/
|
|
258
314
|
export function detectEmotions(current) {
|
|
259
315
|
return EMOTION_PATTERNS.filter((p) => p.condition(current));
|
|
260
316
|
}
|
|
261
317
|
/**
|
|
262
|
-
*
|
|
318
|
+
* Human-readable emotion summary from self-state.
|
|
263
319
|
*/
|
|
264
320
|
export function describeEmotionalState(current, locale = "zh") {
|
|
265
321
|
const emotions = detectEmotions(current);
|
|
@@ -270,33 +326,31 @@ export function describeEmotionalState(current, locale = "zh") {
|
|
|
270
326
|
return parts.join(" + ");
|
|
271
327
|
}
|
|
272
328
|
/**
|
|
273
|
-
*
|
|
329
|
+
* Concise expression guidance from self-state.
|
|
274
330
|
*/
|
|
275
331
|
export function getExpressionHint(current, locale = "zh") {
|
|
276
332
|
const emotions = detectEmotions(current);
|
|
277
333
|
if (emotions.length > 0) {
|
|
278
334
|
return emotions.map((e) => e.expressionHint).join(";");
|
|
279
335
|
}
|
|
280
|
-
// Fall back to dominant
|
|
336
|
+
// Fall back to dominant dimension analysis
|
|
281
337
|
const hints = [];
|
|
282
|
-
if (current.
|
|
283
|
-
hints.push(t("expression.da_high", locale));
|
|
284
|
-
if (current.
|
|
338
|
+
if (current.order > 70)
|
|
339
|
+
hints.push(t("expression.da_high", locale)); // repurpose i18n keys for now
|
|
340
|
+
if (current.order < 35)
|
|
285
341
|
hints.push(t("expression.da_low", locale));
|
|
286
|
-
if (current.
|
|
342
|
+
if (current.flow > 70)
|
|
343
|
+
hints.push(t("expression.ne_high", locale));
|
|
344
|
+
if (current.boundary > 70)
|
|
287
345
|
hints.push(t("expression.cort_high", locale));
|
|
288
|
-
if (current.
|
|
346
|
+
if (current.resonance > 65)
|
|
289
347
|
hints.push(t("expression.ot_high", locale));
|
|
290
|
-
if (current.
|
|
291
|
-
hints.push(t("expression.ne_high", locale));
|
|
292
|
-
if (current.END > 65)
|
|
293
|
-
hints.push(t("expression.end_high", locale));
|
|
294
|
-
if (current.HT < 45)
|
|
348
|
+
if (current.flow < 30)
|
|
295
349
|
hints.push(t("expression.ht_low", locale));
|
|
296
350
|
return hints.length > 0 ? hints.join(";") : t("expression.neutral", locale);
|
|
297
351
|
}
|
|
298
352
|
/**
|
|
299
|
-
*
|
|
353
|
+
* Behavior guide for the current emergent emotional state.
|
|
300
354
|
*/
|
|
301
355
|
export function getBehaviorGuide(current, locale = "zh") {
|
|
302
356
|
const emotions = detectEmotions(current);
|
package/dist/circadian.d.ts
CHANGED
|
@@ -1,55 +1,23 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SelfState, EnergyBudgets, StimulusType } from "./types.js";
|
|
2
2
|
export type CircadianPhase = "morning" | "midday" | "afternoon" | "evening" | "night";
|
|
3
|
-
/**
|
|
4
|
-
* Classify a time into a circadian phase.
|
|
5
|
-
* morning: 6–9
|
|
6
|
-
* midday: 10–13
|
|
7
|
-
* afternoon: 14–17
|
|
8
|
-
* evening: 18–21
|
|
9
|
-
* night: 22–5
|
|
10
|
-
*/
|
|
11
3
|
export declare function getCircadianPhase(time: Date): CircadianPhase;
|
|
12
4
|
/**
|
|
13
|
-
* Apply circadian rhythm modulation to baseline
|
|
14
|
-
*
|
|
15
|
-
* Each chemical follows a sinusoidal daily curve:
|
|
16
|
-
* CORT — peaks ~8am, amplitude ±8
|
|
17
|
-
* HT — peaks ~13 (daytime high), amplitude ±5
|
|
18
|
-
* DA — slight afternoon peak ~14, amplitude ±3
|
|
19
|
-
* NE — morning rise ~10, amplitude ±5
|
|
20
|
-
* END — evening rise ~20, amplitude ±3
|
|
21
|
-
* OT — evening warmth ~20, amplitude ±2
|
|
5
|
+
* Apply circadian rhythm modulation to baseline self-state.
|
|
22
6
|
*
|
|
23
|
-
*
|
|
7
|
+
* order — peaks ~13 (midday coherence), amplitude ±5
|
|
8
|
+
* flow — peaks ~10 (morning engagement), amplitude ±5
|
|
9
|
+
* boundary — peaks ~8 (morning clarity), amplitude ±3
|
|
10
|
+
* resonance — peaks ~20 (evening warmth), amplitude ±3
|
|
24
11
|
*/
|
|
25
|
-
export declare function computeCircadianModulation(currentTime: Date, baseline:
|
|
12
|
+
export declare function computeCircadianModulation(currentTime: Date, baseline: SelfState): SelfState;
|
|
26
13
|
/**
|
|
27
14
|
* Compute fatigue effects from extended session duration.
|
|
28
|
-
*
|
|
29
|
-
* Below 30 minutes: no pressure (grace period).
|
|
30
|
-
* Beyond 30 min: logarithmic growth (diminishing returns).
|
|
31
|
-
* All values non-negative.
|
|
15
|
+
* Now expressed as dimension effects instead of chemical deltas.
|
|
32
16
|
*/
|
|
33
17
|
export declare function computeHomeostaticPressure(sessionMinutes: number): {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
18
|
+
orderDepletion: number;
|
|
19
|
+
flowDepletion: number;
|
|
20
|
+
boundaryStiffening: number;
|
|
37
21
|
};
|
|
38
|
-
/**
|
|
39
|
-
* Deplete energy budgets from a single interaction turn.
|
|
40
|
-
*
|
|
41
|
-
* - Attention: -3/turn base, extra for intellectual/conflict
|
|
42
|
-
* - Social energy: extraverts +2/turn (charging), introverts -3/turn (draining)
|
|
43
|
-
* - Decision capacity: varies by stimulus complexity
|
|
44
|
-
*
|
|
45
|
-
* Extraverts can exceed 100 (up to 120 — "supercharged").
|
|
46
|
-
*/
|
|
47
22
|
export declare function computeEnergyDepletion(budgets: EnergyBudgets, stimulus: StimulusType | null, isExtravert: boolean): EnergyBudgets;
|
|
48
|
-
/**
|
|
49
|
-
* Recover energy budgets during absence (between sessions or long pauses).
|
|
50
|
-
*
|
|
51
|
-
* - Attention: +20/hour
|
|
52
|
-
* - Social energy: extraverts -3/hour (drain when alone), introverts +15/hour (recharge)
|
|
53
|
-
* - Decision capacity: +25/hour
|
|
54
|
-
*/
|
|
55
23
|
export declare function computeEnergyRecovery(budgets: EnergyBudgets, minutesElapsed: number, isExtravert: boolean): EnergyBudgets;
|