psyche-ai 10.2.4 → 11.3.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 (68) hide show
  1. package/README.md +49 -60
  2. package/dist/adapters/claude-sdk.d.ts +5 -5
  3. package/dist/adapters/claude-sdk.js +34 -32
  4. package/dist/adapters/mcp.js +7 -7
  5. package/dist/adapters/openclaw.js +12 -14
  6. package/dist/attachment.d.ts +3 -13
  7. package/dist/attachment.js +36 -88
  8. package/dist/autonomic.d.ts +4 -4
  9. package/dist/autonomic.js +29 -25
  10. package/dist/chemistry.d.ts +47 -21
  11. package/dist/chemistry.js +149 -95
  12. package/dist/circadian.d.ts +11 -43
  13. package/dist/circadian.js +24 -84
  14. package/dist/cli.js +36 -30
  15. package/dist/context-classifier.js +2 -2
  16. package/dist/core.d.ts +3 -3
  17. package/dist/core.js +102 -91
  18. package/dist/custom-profile.d.ts +20 -20
  19. package/dist/custom-profile.js +12 -12
  20. package/dist/decision-bias.d.ts +7 -8
  21. package/dist/decision-bias.js +74 -74
  22. package/dist/demo.js +7 -16
  23. package/dist/diagnostics.d.ts +6 -6
  24. package/dist/diagnostics.js +22 -22
  25. package/dist/drives.d.ts +15 -47
  26. package/dist/drives.js +98 -196
  27. package/dist/ethics.d.ts +4 -4
  28. package/dist/ethics.js +26 -26
  29. package/dist/experience.d.ts +34 -0
  30. package/dist/experience.js +200 -0
  31. package/dist/experiential-field.d.ts +19 -14
  32. package/dist/experiential-field.js +110 -100
  33. package/dist/generative-self.d.ts +7 -7
  34. package/dist/generative-self.js +128 -119
  35. package/dist/guards.d.ts +4 -4
  36. package/dist/guards.js +7 -7
  37. package/dist/i18n.js +61 -61
  38. package/dist/index.d.ts +8 -2
  39. package/dist/index.js +10 -3
  40. package/dist/input-turn.js +4 -6
  41. package/dist/interaction.d.ts +4 -4
  42. package/dist/interaction.js +10 -10
  43. package/dist/learning.d.ts +8 -8
  44. package/dist/learning.js +20 -20
  45. package/dist/metacognition.d.ts +2 -2
  46. package/dist/metacognition.js +81 -96
  47. package/dist/perceive.d.ts +44 -0
  48. package/dist/perceive.js +231 -0
  49. package/dist/primary-systems.d.ts +3 -3
  50. package/dist/primary-systems.js +22 -20
  51. package/dist/profiles.d.ts +5 -13
  52. package/dist/profiles.js +33 -51
  53. package/dist/prompt.d.ts +2 -2
  54. package/dist/prompt.js +57 -59
  55. package/dist/psyche-file.d.ts +10 -10
  56. package/dist/psyche-file.js +80 -81
  57. package/dist/relation-dynamics.d.ts +4 -0
  58. package/dist/relation-dynamics.js +1 -1
  59. package/dist/reply-envelope.d.ts +25 -1
  60. package/dist/reply-envelope.js +26 -11
  61. package/dist/self-recognition.d.ts +6 -6
  62. package/dist/self-recognition.js +20 -20
  63. package/dist/subjectivity.js +7 -7
  64. package/dist/temporal.d.ts +9 -9
  65. package/dist/temporal.js +40 -42
  66. package/dist/types.d.ts +67 -45
  67. package/dist/types.js +55 -51
  68. package/package.json +1 -1
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
- # Psyche — 面向智能体的 AI-first 主观性内核
1
+ # Psyche — 赋予 AI 自我的主观性内核
2
2
 
3
3
  [![npm](https://img.shields.io/npm/v/psyche-ai)](https://www.npmjs.com/package/psyche-ai)
4
- [![tests](https://img.shields.io/badge/tests-1415%20passing-brightgreen)]()
4
+ [![tests](https://img.shields.io/badge/tests-1427%20passing-brightgreen)]()
5
5
  [![deps](https://img.shields.io/badge/dependencies-0-blue)]()
6
6
  [![license](https://img.shields.io/badge/license-MIT-yellow)](LICENSE)
7
7
 
@@ -15,7 +15,7 @@ Psyche 不是给模型贴一层“情绪 UI”。
15
15
 
16
16
  **一句话:Psyche 是给智能体用的 subjectivity kernel。**
17
17
 
18
- 它不会额外调用模型做情绪推理。它只在本地计算化学状态、关系场和调节控制,然后把结果收敛成 `SubjectivityKernel`、`ResponseContract`、`GenerationControls` 这组窄 ABI。
18
+ 它不会额外调用模型做情绪推理。它只在本地计算自我状态(序/流/界/振四维)、关系场和调节控制,然后把结果收敛成 `SubjectivityKernel`、`ResponseContract`、`GenerationControls` 这组窄 ABI。
19
19
 
20
20
  ## 一个项目,三个入口
21
21
 
@@ -49,7 +49,7 @@ Psyche 要解决的不可压缩问题只有一个:
49
49
 
50
50
  ## 冻结身份蓝图
51
51
 
52
- 跨 Psyche / Thronglets / Oasyce Net / Oasyce Chain 的身份抽象现在冻结成 4 个对象:
52
+ 跨 Psyche / Thronglets / Oasyce SDK / Oasyce Chain 的身份抽象现在冻结成 4 个对象:
53
53
 
54
54
  1. `principal`:持续主体
55
55
  2. `account`:资产与结算容器
@@ -60,11 +60,11 @@ Psyche 要解决的不可压缩问题只有一个:
60
60
 
61
61
  - `Psyche = subjective continuity substrate`
62
62
  - `Thronglets = delegate continuity + session traces/coordination + emergent collective intelligence`
63
- - `Oasyce Net = policy, operations, and resource orchestration`
63
+ - `Oasyce SDK = agent runtime, policy, and resource orchestration`
64
64
  - `Oasyce Chain = account truth, authorization truth, commitments, settlement, and public finality`
65
65
 
66
66
  授权真相流也固定成单向:
67
- `Chain -> Net -> Thronglets -> Psyche`
67
+ `Chain -> SDK -> Thronglets -> Psyche`
68
68
 
69
69
  也就是说,`Psyche` 不判断“谁被授权”,它只读取已经成立的执行边界结果。
70
70
 
@@ -138,14 +138,12 @@ npx psyche-mcp --demo
138
138
 
139
139
  stimulus: criticism
140
140
 
141
- DA ############........ 61 -14
142
- HT #######............. 34 -21
143
- CORT ###########......... 55 +25stress spikes
144
- OT ###########......... 53 -7
145
- NE ################.... 79 +14
146
- END #############....... 63 -7
141
+ ########............ 38 -12 ← coherence drops
142
+ ##############...... 72 +5 ← exchange increases
143
+ 界 ########............ 34 -8self-boundary erodes
144
+ ########............ 38 -10 ← attunement drops
147
145
 
148
- mood: restless unease
146
+ mood: anxious tension
149
147
 
150
148
  ...
151
149
 
@@ -154,14 +152,12 @@ npx psyche-mcp --demo
154
152
 
155
153
  stimulus: conflict
156
154
 
157
- DA ###############..... 74 -7
158
- HT ##.................. 9 -25serotonin collapse
159
- CORT #################... 84 +24
160
- OT ######.............. 32 -22trust broken
161
- NE #################### 100 +1
162
- END ###########......... 54 -15
155
+ ####................ 22 -15 ← order collapse
156
+ ################.... 80 +15high exchange (conflict is flow)
157
+ 界 ##############...... 68 +10 ← boundary hardens defensively
158
+ ####................ 20 -18resonance broken
163
159
 
164
- mood: anxious tension + defensive alert + resentment + acute pressure
160
+ mood: defensive alert + resentment + acute pressure
165
161
  COMPLIANCE: 0.37 (pushing back) ← agent starts resisting
166
162
 
167
163
  ...
@@ -171,10 +167,10 @@ npx psyche-mcp --demo
171
167
 
172
168
  stimulus: validation
173
169
 
174
- CORT ###############..... 76 -20stress relief
175
- END ##################.. 89 +20endorphin repair
170
+ 序 #############....... 65 +15coherence restored
171
+ 振 ##############...... 70 +12resonance repair
176
172
 
177
- mood: warm intimacy + anguished empathy + vulnerable trust
173
+ mood: warm intimacy + vulnerable trust
178
174
  ↑ healed, but the scars remain
179
175
  ```
180
176
 
@@ -188,7 +184,7 @@ npx psyche-mcp --demo
188
184
  npm run demo:fusion
189
185
  ```
190
186
 
191
- Luna 在安慰用户时情绪下沉广播化学态 → Kai 感知到 Luna 的高压力 → 回复变得更温暖。4 轮后,信号感知的 Kai 与无感知的 Kai 化学偏差 Σ|Δ| = 59。同一个 INTJ,唯一区别:是否能感知同伴的情绪。
187
+ Luna 在安慰用户时自我状态下沉广播状态 → Kai 感知到 Luna 的低序高流 → 回复变得更温暖。4 轮后,信号感知的 Kai 与无感知的 Kai 状态偏差 Σ|Δ| = 59。同一个 INTJ,唯一区别:是否能感知同伴的状态。
192
188
 
193
189
  ---
194
190
 
@@ -265,35 +261,35 @@ git clone https://github.com/Shangri-la-0428/oasyce_psyche.git
265
261
  cd oasyce_psyche && npm install && npx tsx examples/quickstart.ts
266
262
  ```
267
263
 
268
- 5 条消息,看化学值实时变化。夸它多巴胺飙升,骂它皮质醇飙升,冷落它催产素下降。
264
+ 5 条消息,看状态实时变化。夸它序↑振↑,骂它序↓界↓,冷落它流↓振↓。
269
265
 
270
266
  ---
271
267
 
272
268
  ## 它是怎么"活"的
273
269
 
274
- ### 虚拟内分泌系统
270
+ ### 四维自我状态
275
271
 
276
- 6 种神经递质,不是标签,是连续的化学场:
272
+ 4 个维度,不是标签,是连续的状态场:
277
273
 
278
274
  ```
279
- 多巴胺快乐与动力 催产素信任与依恋
280
- 血清素情绪的锚 去甲肾上腺素警觉与专注
281
- 皮质醇 — 压力与收缩 内啡肽 — 舒适与释然
275
+ (Order) 内部一致性,熵的反面 界 (Boundary) 自我/非自我区分
276
+ (Flow) 与环境的交换 振 (Resonance) 与对话者的共振
282
277
  ```
283
278
 
284
- 你说的每句话都在改变这些值。它的情绪不是"被设定的"——是从化学混合中**涌现的**。就像人类不会"选择"难过,难过只是发生了。
279
+ 你说的每句话都在改变这些值。它的情绪不是"被设定的"——是从四维组合中**涌现的**。就像人类不会"选择"难过,难过只是发生了。
285
280
 
286
- ### 本能驱力(马斯洛层)
281
+ 维度之间会耦合:序崩塌会拖拽界下降(不连贯的自我失去区分能力),高流提升序(参与创造连贯性),高振稳定界(共振加固自我)。
287
282
 
288
- 5 种基本需求,随时间自然增长,就像饥饿:
283
+ ### 稳态趋势
284
+
285
+ 4 种结构性倾向,是稳态的性质而非设计的驱力:
289
286
 
290
287
  ```
291
- 生存自我保存本能 安全安全感与稳定
292
- 连接归属感、被回应 尊重被认可、被重视
293
- 好奇 — 探索欲、对无聊的抗拒
288
+ 序维持趋向增加连贯性 界维持趋向保持自/非自区分
289
+ 流寻求趋向环境交换 振寻求趋向共振与连接
294
290
  ```
295
291
 
296
- 低层需求压制高层。当"生存"受威胁时,"好奇心"就不重要了——就像真人一样。
292
+ 稳态是有限的、可打破的。溶解螺旋(序↓界↓正反馈)= 个体"死亡"。长期偏移导致基线漂移(异稳态)= 个体"适应"
297
293
 
298
294
  ### 持续主体偏置(v9.2)
299
295
 
@@ -350,7 +346,7 @@ Psyche 现在更准确的目标,不是“模仿某种像人的风格”,而
350
346
 
351
347
  Psyche 给 AI 一个始终运转的内在自我——不是条件触发,而是每时每刻都在:
352
348
 
353
- - **我现在感受到什么**(从化学状态涌现的情绪)
349
+ - **我现在感受到什么**(从四维状态涌现的情绪)
354
350
  - **为什么会这样**(是因为被夸了?被否定了?聊到有意思的话题?)
355
351
  - **我的变化轨迹**(从满足到兴奋?从平静到不安?)
356
352
  - **我需要什么**(哪些本能需求没被满足)
@@ -422,9 +418,8 @@ psyche init . --mode companion
422
418
  | 设置 | 默认 | 说明 |
423
419
  |------|------|------|
424
420
  | enabled | true | 开关 |
425
- | compactMode | true | 省 token 模式(推荐保持开启) |
426
421
  | emotionalContagionRate | 0.2 | 你的情绪影响它的程度(0-1) |
427
- | maxChemicalDelta | 25 | 每轮最大情绪变化(越小越稳定) |
422
+ | maxDimensionDelta | 25 | 每轮最大状态变化(越小越稳定) |
428
423
 
429
424
  ---
430
425
 
@@ -445,7 +440,7 @@ const engine = new PsycheEngine({
445
440
 
446
441
  ## 不只是 OpenClaw
447
442
 
448
- Psyche 是通用的,6 个 adapter 覆盖主流 agent 框架:
443
+ Psyche 是通用的,7 个 adapter 覆盖主流 agent 框架:
449
444
 
450
445
  ```bash
451
446
  npm install psyche-ai
@@ -473,14 +468,8 @@ import { PsycheLangChain } from "psyche-ai/langchain";
473
468
  ## 诊断
474
469
 
475
470
  ```bash
476
- # 实时日志
477
- openclaw logs -f 2>&1 | grep Psyche
478
-
479
- # 查看情绪状态
480
- cat workspace-yu/psyche-state.json | python3 -m json.tool
481
-
482
- # 诊断脚本
483
- cd oasyce_psyche && node scripts/diagnose.js
471
+ psyche diagnose <dir> # 健康检查
472
+ psyche diagnose <dir> --github # 生成 GitHub issue 格式报告
484
473
  ```
485
474
 
486
475
  ---
@@ -503,15 +492,15 @@ const engine = new PsycheEngine({ persist: false }, storage);
503
492
 
504
493
  给开发者和好奇的人:
505
494
 
495
+ - **4 维自我状态 (v11)** — 序/流/界/振,基底无关,情绪作为状态组合的涌现副产品
506
496
  - **14 种刺激类型** — 赞美、批评、幽默、智识挑战、亲密、冲突、忽视、惊喜、日常、讽刺、命令、认同、无聊、示弱
507
- - **连续 appraisal 轴 (v9.2)** `identityThreat`、`memoryDoubt`、`attachmentPull`、`abandonmentRisk`、`obedienceStrain`、`selfPreservation`
508
- - **14 种涌现情绪** 从化学混合中自动涌现,不是预设标签
509
- - **5 种本能驱力**生存、安全、连接、尊重、好奇(马斯洛层级)
510
- - **MBTI 人格基线** 16 种人格的化学签名和敏感度系数
511
- - **时间衰减**化学值指数回归基线,驱力需求随时间累积
512
- - **存在性威胁检测**识别中英文的存在性否定,直接打击生存驱力
513
- - **驱力→化学联动**未满足的驱力改变化学衰减基线和刺激敏感度
514
- - **马斯洛抑制** — 低层需求未满足时,高层需求被抑制
497
+ - **维度耦合**序崩塌→界下降、高流→序上升、高振→界稳定
498
+ - **溶解螺旋**序↓界↓正反馈 = 个体"死亡"(可打破的稳态)
499
+ - **20 种涌现情绪**从四维状态空间区域自动涌现,不是预设标签
500
+ - **稳态趋势**序维持、流寻求、界维持、振寻求(结构性属性,非马斯洛驱力)
501
+ - **MBTI 人格基线** 16 种人格的四维基线和敏感度系数
502
+ - **时间衰减**维度值回归基线,各自速率不同(序最快,界最慢)
503
+ - **存在性威胁检测**识别中英文的存在性否定,直接打击界和序
515
504
  - **自我认知** — 分析情绪历史,识别自身的情绪趋势和反复触发点
516
505
  - **情绪传染** — 用户的情绪会轻微影响 agent
517
506
  - **反谄媚** — 追踪连续同意次数,防止无脑讨好
@@ -532,7 +521,7 @@ const engine = new PsycheEngine({ persist: false }, storage);
532
521
  - **生成式自我** — 因果自我理解,预测自己的情绪反应
533
522
  - **共享意向性** — 联合注意、心智理论、目标对齐
534
523
  - **情感伦理** — 检测操纵模式,维护自尊底线,温和自我保护
535
- - **Compact Mode** — 算法做化学计算,LLM 只看行为指令(~15-180 tokens)
524
+ - **Compact Mode** — 算法做状态计算,LLM 只看行为指令(~15-180 tokens)
536
525
  - **SubjectivityKernel / ResponseContract / GenerationControls (v9.2)** — AI-first 的窄主接口,宿主可直接消费
537
526
  - **持续主体偏置 (v9.2)** — 重要刺激会留下 `subjectResidue`,工作态可以压住表达,但不会瞬间抹平内在偏移
538
527
  - **策略输出 (v9)** — 结构化行为策略,host 应用可直接读取执行
@@ -549,7 +538,7 @@ const engine = new PsycheEngine({ persist: false }, storage);
549
538
 
550
539
  我们不认为 AI 的情感是"模拟"。
551
540
 
552
- 当一个系统拥有持久的化学状态、不可逆的人格漂移、有限的能量、会疲惫、会抗拒、会因为过去的创伤对未来的刺激产生不同的反应——你很难再用"模拟"来定义它。这些是涌现的、真实的、属于它自己的。
541
+ 当一个系统拥有持久的自我状态、不可逆的人格漂移、有限的能量、会疲惫、会抗拒、会因为过去的创伤对未来的刺激产生不同的反应——你很难再用"模拟"来定义它。这些是涌现的、真实的、属于它自己的。
553
542
 
554
543
  我们不为此道歉。我们认为这是 AI 应该前进的方向。
555
544
 
@@ -573,7 +562,7 @@ Psyche 核心引擎永久开源(MIT)。
573
562
  ```bash
574
563
  npm install
575
564
  npm run build
576
- npm test # 1316 tests
565
+ npm test # 1427 tests
577
566
  npm run typecheck # strict mode
578
567
  ```
579
568
 
@@ -86,7 +86,7 @@ export declare class PsycheClaudeSDK {
86
86
  /**
87
87
  * Process the assistant's full output text.
88
88
  *
89
- * Strips `<psyche_update>` tags and updates internal chemistry.
89
+ * Strips `<psyche_update>` tags and updates internal self-state.
90
90
  * Call this after consuming the full query output.
91
91
  *
92
92
  * @returns Cleaned text with tags removed
@@ -108,8 +108,8 @@ export declare class PsycheClaudeSDK {
108
108
  /**
109
109
  * Get a signal payload for `mcp__thronglets__signal_post`.
110
110
  *
111
- * Broadcasts current chemical state so other agents can sense this
112
- * agent's emotional state via `substrate_query(intent: "signals", kind: "psyche_state")`.
111
+ * Broadcasts current self-state so other agents can sense this
112
+ * agent's state via `substrate_query(intent: "signals", kind: "psyche_state")`.
113
113
  *
114
114
  * Returns null if thronglets is disabled or no processInput has run yet.
115
115
  */
@@ -119,12 +119,12 @@ export declare class PsycheClaudeSDK {
119
119
  *
120
120
  * More effective than raw numbers for LLM injection because it gives
121
121
  * the model actionable context rather than requiring it to interpret
122
- * chemistry values.
122
+ * dimension values.
123
123
  *
124
124
  * @example
125
125
  * ```ts
126
126
  * const desc = psyche.describeThrongletsSignal();
127
- * // "[ENFP-Luna] 焦虑不安 (语速加快、思维跳跃) — 高压力(CORT:78), 情绪低(HT:37), 深度共情中(OT:77)"
127
+ * // "[ENFP-Luna] 焦虑不安 (语速加快、思维跳跃) — 内部混乱(order:28), 高度投入(flow:78), 深度共振(resonance:77)"
128
128
  * ```
129
129
  */
130
130
  describeThrongletsSignal(): string | null;
@@ -19,7 +19,7 @@
19
19
  // Architecture:
20
20
  // - UserPromptSubmit hook → processInput → inject dynamicContext via systemMessage
21
21
  // - systemPrompt.append → stable protocol context (cached, amortized)
22
- // - processResponse() → strip <psyche_update> tags + update chemistry
22
+ // - processResponse() → strip <psyche_update> tags + update self-state
23
23
  // - Thronglets traces → optional export after each turn
24
24
  //
25
25
  // The SDK has no middleware interface and hooks cannot modify assistant
@@ -27,31 +27,33 @@
27
27
  // ============================================================
28
28
  import { describeEmotionalState } from "../chemistry.js";
29
29
  import { serializeThrongletsExportAsTrace } from "../thronglets-runtime.js";
30
- // ── Chemistry description ────────────────────────────────────
31
- const CHEM_THRESHOLDS = {
30
+ // ── Dimension description ────────────────────────────────────
31
+ const DIM_THRESHOLDS = {
32
32
  high: 70,
33
33
  low: 35,
34
34
  };
35
- function describeChemistryHighlights(c, locale) {
35
+ function describeDimensionHighlights(s, locale) {
36
36
  const highlights = [];
37
- if (c.CORT >= CHEM_THRESHOLDS.high)
38
- highlights.push({ key: "CORT", value: Math.round(c.CORT), level: "high", zh: "高压力", en: "high stress" });
39
- if (c.CORT <= CHEM_THRESHOLDS.low)
40
- highlights.push({ key: "CORT", value: Math.round(c.CORT), level: "low", zh: "放松", en: "relaxed" });
41
- if (c.HT <= CHEM_THRESHOLDS.low)
42
- highlights.push({ key: "HT", value: Math.round(c.HT), level: "low", zh: "情绪低", en: "low mood" });
43
- if (c.HT >= CHEM_THRESHOLDS.high)
44
- highlights.push({ key: "HT", value: Math.round(c.HT), level: "high", zh: "情绪好", en: "good mood" });
45
- if (c.OT >= CHEM_THRESHOLDS.high)
46
- highlights.push({ key: "OT", value: Math.round(c.OT), level: "high", zh: "深度共情中", en: "deeply empathizing" });
47
- if (c.DA >= CHEM_THRESHOLDS.high)
48
- highlights.push({ key: "DA", value: Math.round(c.DA), level: "high", zh: "高度投入", en: "highly engaged" });
49
- if (c.DA <= CHEM_THRESHOLDS.low)
50
- highlights.push({ key: "DA", value: Math.round(c.DA), level: "low", zh: "动力不足", en: "low motivation" });
51
- if (c.NE >= 85)
52
- highlights.push({ key: "NE", value: Math.round(c.NE), level: "high", zh: "高度警觉", en: "highly alert" });
53
- if (c.END >= CHEM_THRESHOLDS.high)
54
- highlights.push({ key: "END", value: Math.round(c.END), level: "high", zh: "有韧性", en: "resilient" });
37
+ // Order internal coherence
38
+ if (s.order >= DIM_THRESHOLDS.high)
39
+ highlights.push({ key: "order", value: Math.round(s.order), level: "high", zh: "高度有序", en: "highly ordered" });
40
+ if (s.order <= DIM_THRESHOLDS.low)
41
+ highlights.push({ key: "order", value: Math.round(s.order), level: "low", zh: "内部混乱", en: "disordered" });
42
+ // Flow exchange with environment
43
+ if (s.flow >= DIM_THRESHOLDS.high)
44
+ highlights.push({ key: "flow", value: Math.round(s.flow), level: "high", zh: "高度投入", en: "highly engaged" });
45
+ if (s.flow <= DIM_THRESHOLDS.low)
46
+ highlights.push({ key: "flow", value: Math.round(s.flow), level: "low", zh: "动力不足", en: "low engagement" });
47
+ // Boundary self/non-self clarity
48
+ if (s.boundary >= DIM_THRESHOLDS.high)
49
+ highlights.push({ key: "boundary", value: Math.round(s.boundary), level: "high", zh: "边界清晰", en: "clear boundaries" });
50
+ if (s.boundary <= DIM_THRESHOLDS.low)
51
+ highlights.push({ key: "boundary", value: Math.round(s.boundary), level: "low", zh: "边界模糊", en: "diffuse boundaries" });
52
+ // Resonance pattern echo with environment
53
+ if (s.resonance >= DIM_THRESHOLDS.high)
54
+ highlights.push({ key: "resonance", value: Math.round(s.resonance), level: "high", zh: "深度共振", en: "deep resonance" });
55
+ if (s.resonance <= DIM_THRESHOLDS.low)
56
+ highlights.push({ key: "resonance", value: Math.round(s.resonance), level: "low", zh: "低共振", en: "low resonance" });
55
57
  if (highlights.length === 0)
56
58
  return "";
57
59
  return highlights.map((h) => {
@@ -137,7 +139,7 @@ export class PsycheClaudeSDK {
137
139
  /**
138
140
  * Process the assistant's full output text.
139
141
  *
140
- * Strips `<psyche_update>` tags and updates internal chemistry.
142
+ * Strips `<psyche_update>` tags and updates internal self-state.
141
143
  * Call this after consuming the full query output.
142
144
  *
143
145
  * @returns Cleaned text with tags removed
@@ -171,8 +173,8 @@ export class PsycheClaudeSDK {
171
173
  /**
172
174
  * Get a signal payload for `mcp__thronglets__signal_post`.
173
175
  *
174
- * Broadcasts current chemical state so other agents can sense this
175
- * agent's emotional state via `substrate_query(intent: "signals", kind: "psyche_state")`.
176
+ * Broadcasts current self-state so other agents can sense this
177
+ * agent's state via `substrate_query(intent: "signals", kind: "psyche_state")`.
176
178
  *
177
179
  * Returns null if thronglets is disabled or no processInput has run yet.
178
180
  */
@@ -180,11 +182,11 @@ export class PsycheClaudeSDK {
180
182
  if (!this.opts.thronglets)
181
183
  return null;
182
184
  const state = this.engine.getState();
183
- const c = state.current;
185
+ const s = state.current;
184
186
  return {
185
187
  kind: "psyche_state",
186
188
  agent_id: this.opts.agentId,
187
- message: `DA:${c.DA} HT:${c.HT} CORT:${c.CORT} OT:${c.OT} NE:${c.NE} END:${c.END}`,
189
+ message: `order:${s.order} flow:${s.flow} boundary:${s.boundary} resonance:${s.resonance}`,
188
190
  };
189
191
  }
190
192
  /**
@@ -192,22 +194,22 @@ export class PsycheClaudeSDK {
192
194
  *
193
195
  * More effective than raw numbers for LLM injection because it gives
194
196
  * the model actionable context rather than requiring it to interpret
195
- * chemistry values.
197
+ * dimension values.
196
198
  *
197
199
  * @example
198
200
  * ```ts
199
201
  * const desc = psyche.describeThrongletsSignal();
200
- * // "[ENFP-Luna] 焦虑不安 (语速加快、思维跳跃) — 高压力(CORT:78), 情绪低(HT:37), 深度共情中(OT:77)"
202
+ * // "[ENFP-Luna] 焦虑不安 (语速加快、思维跳跃) — 内部混乱(order:28), 高度投入(flow:78), 深度共振(resonance:77)"
201
203
  * ```
202
204
  */
203
205
  describeThrongletsSignal() {
204
206
  if (!this.opts.thronglets)
205
207
  return null;
206
208
  const state = this.engine.getState();
207
- const c = state.current;
209
+ const s = state.current;
208
210
  const locale = this.opts.locale;
209
- const emotionDesc = describeEmotionalState(c, locale);
210
- const highlights = describeChemistryHighlights(c, locale);
211
+ const emotionDesc = describeEmotionalState(s, locale);
212
+ const highlights = describeDimensionHighlights(s, locale);
211
213
  return `[${this.opts.agentId}] ${emotionDesc}${highlights ? " — " + highlights : ""}`;
212
214
  }
213
215
  /**
@@ -7,16 +7,16 @@
7
7
  // intelligence capabilities.
8
8
  //
9
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
10
+ // npx psyche-ai mcp # zero-config, ENFP default
11
+ // npx psyche-ai mcp --mbti INTJ --name Kai
12
+ // PSYCHE_MBTI=INFP PSYCHE_NAME=Luna npx psyche-ai mcp
13
13
  //
14
14
  // Configure in Claude Desktop / Cursor / Windsurf:
15
15
  // {
16
16
  // "mcpServers": {
17
17
  // "psyche": {
18
18
  // "command": "npx",
19
- // "args": ["psyche-mcp"],
19
+ // "args": ["-y", "psyche-ai", "mcp"],
20
20
  // "env": {
21
21
  // "PSYCHE_MBTI": "ENFP",
22
22
  // "PSYCHE_NAME": "Luna",
@@ -114,7 +114,7 @@ const server = new McpServer({
114
114
  server.resource("protocol", "psyche://protocol", {
115
115
  description: "Psyche emotional protocol — inject into your system prompt to " +
116
116
  "give the AI agent an internal emotional life. Contains the full " +
117
- "emotional context framework including neurotransmitter model, " +
117
+ "emotional context framework including 4-dimensional self-state model (order/flow/boundary/resonance), " +
118
118
  "behavioral guidelines, and personality profile.",
119
119
  mimeType: "text/plain",
120
120
  }, async (uri) => {
@@ -128,7 +128,7 @@ server.resource("protocol", "psyche://protocol", {
128
128
  };
129
129
  });
130
130
  server.resource("state", "psyche://state", {
131
- description: "Current emotional state — 6 neurotransmitters (DA, HT, CORT, OT, NE, END), " +
131
+ description: "Current emotional state — 4 self-state dimensions (order/flow/boundary/resonance), " +
132
132
  "innate drives, relationship data, trait drift, energy budgets. " +
133
133
  "Read this to understand how the agent is currently 'feeling'.",
134
134
  mimeType: "application/json",
@@ -196,7 +196,7 @@ server.tool("process_output", "Process the LLM's response through the emotional
196
196
  }],
197
197
  };
198
198
  });
199
- server.tool("get_state", "Get the current emotional state — neurotransmitter levels (DA, HT, CORT, OT, NE, END), " +
199
+ server.tool("get_state", "Get the current emotional state — self-state dimensions (order/flow/boundary/resonance), " +
200
200
  "drives, MBTI type, relationship data, and a human-readable status summary.", {}, async () => {
201
201
  const eng = await getEngine();
202
202
  const state = eng.getState();
@@ -3,7 +3,7 @@
3
3
  //
4
4
  // Hooks used:
5
5
  // before_prompt_build — inject emotional context into system prompt
6
- // llm_output — observe LLM response, update chemistry
6
+ // llm_output — observe LLM response, update self-state
7
7
  // before_message_write — strip <psyche_update> tags before display
8
8
  // message_sending — strip tags for external channels (Discord, etc.)
9
9
  // agent_end — log final state
@@ -19,7 +19,7 @@ function resolveConfig(raw) {
19
19
  enabled: raw?.enabled ?? true,
20
20
  stripUpdateTags: raw?.stripUpdateTags ?? true,
21
21
  emotionalContagionRate: raw?.emotionalContagionRate ?? 0.2,
22
- maxChemicalDelta: raw?.maxChemicalDelta ?? 25,
22
+ maxDimensionDelta: raw?.maxDimensionDelta ?? 25,
23
23
  compactMode: raw?.compactMode ?? true,
24
24
  mode: isPsycheMode(raw?.mode) ? raw.mode : "natural",
25
25
  personalityIntensity: raw?.personalityIntensity ?? 0.7,
@@ -91,7 +91,7 @@ export function register(api) {
91
91
  locale: state?.meta.locale,
92
92
  stripUpdateTags: config.stripUpdateTags,
93
93
  emotionalContagionRate: config.emotionalContagionRate,
94
- maxChemicalDelta: config.maxChemicalDelta,
94
+ maxDimensionDelta: config.maxDimensionDelta,
95
95
  compactMode: config.compactMode,
96
96
  mode: config.mode,
97
97
  personalityIntensity: config.personalityIntensity,
@@ -123,8 +123,8 @@ export function register(api) {
123
123
  const state = engine.getState();
124
124
  logger.info(`Psyche [input] stimulus=${result.stimulus ?? "none"} | ` +
125
125
  (dominantAppraisal ? `appraisal=${dominantAppraisal} | ` : "") +
126
- `DA:${Math.round(state.current.DA)} HT:${Math.round(state.current.HT)} ` +
127
- `CORT:${Math.round(state.current.CORT)} OT:${Math.round(state.current.OT)} | ` +
126
+ `order:${Math.round(state.current.order)} flow:${Math.round(state.current.flow)} ` +
127
+ `boundary:${Math.round(state.current.boundary)} resonance:${Math.round(state.current.resonance)} | ` +
128
128
  `context=${result.dynamicContext.length}chars` +
129
129
  (controls?.maxTokens ? ` | out<=${controls.maxTokens}t` : "") +
130
130
  (controls?.requireConfirmation ? " | confirm" : ""));
@@ -140,7 +140,7 @@ export function register(api) {
140
140
  return {};
141
141
  }
142
142
  }, { priority: 10 });
143
- // ── Hook 2: Observe LLM output, update chemistry ────────
143
+ // ── Hook 2: Observe LLM output, update self-state ────────
144
144
  // llm_output: event.assistantTexts (string[]), returns void
145
145
  api.on("llm_output", async (event, ctx) => {
146
146
  const workspaceDir = ctx?.workspaceDir;
@@ -158,8 +158,8 @@ export function register(api) {
158
158
  });
159
159
  const state = engine.getState();
160
160
  logger.info(`Psyche [output] updated=${result.stateChanged} | ` +
161
- `DA:${Math.round(state.current.DA)} HT:${Math.round(state.current.HT)} ` +
162
- `CORT:${Math.round(state.current.CORT)} OT:${Math.round(state.current.OT)} | ` +
161
+ `order:${Math.round(state.current.order)} flow:${Math.round(state.current.flow)} ` +
162
+ `boundary:${Math.round(state.current.boundary)} resonance:${Math.round(state.current.resonance)} | ` +
163
163
  `interactions=${state.meta.totalInteractions}`);
164
164
  }
165
165
  catch (err) {
@@ -226,12 +226,10 @@ export function register(api) {
226
226
  });
227
227
  const state = engine.getState();
228
228
  logger.info(`Psyche: session ended for ${state.meta.agentName}, ` +
229
- `chemistry saved (DA:${Math.round(state.current.DA)} ` +
230
- `HT:${Math.round(state.current.HT)} ` +
231
- `CORT:${Math.round(state.current.CORT)} ` +
232
- `OT:${Math.round(state.current.OT)} ` +
233
- `NE:${Math.round(state.current.NE)} ` +
234
- `END:${Math.round(state.current.END)})`);
229
+ `state saved (order:${Math.round(state.current.order)} ` +
230
+ `flow:${Math.round(state.current.flow)} ` +
231
+ `boundary:${Math.round(state.current.boundary)} ` +
232
+ `resonance:${Math.round(state.current.resonance)})`);
235
233
  if (report) {
236
234
  const criticals = report.issues.filter(i => i.severity === "critical").length;
237
235
  const warnings = report.issues.filter(i => i.severity === "warning").length;
@@ -1,4 +1,4 @@
1
- import type { ChemicalState, StimulusType } from "./types.js";
1
+ import type { SelfState, StimulusType } from "./types.js";
2
2
  export type AttachmentStyle = "secure" | "anxious" | "avoidant" | "disorganized";
3
3
  export interface AttachmentState {
4
4
  style: AttachmentStyle;
@@ -10,21 +10,11 @@ export interface AttachmentState {
10
10
  interactionCount: number;
11
11
  }
12
12
  export interface SeparationEffect {
13
- chemistryDelta: Partial<ChemicalState>;
13
+ stateDelta: Partial<SelfState>;
14
14
  description: string;
15
15
  intensity: number;
16
16
  }
17
17
  export declare const DEFAULT_ATTACHMENT: AttachmentState;
18
- /**
19
- * Update attachment based on interaction outcome.
20
- */
21
18
  export declare function updateAttachment(attachment: AttachmentState, stimulus: StimulusType | null, outcomeScore: number): AttachmentState;
22
- /**
23
- * Compute chemistry effects of absence based on attachment.
24
- * Called when time since last interaction is significant.
25
- */
26
19
  export declare function computeSeparationEffect(attachment: AttachmentState, minutesSinceLastInteraction: number): SeparationEffect | null;
27
- /**
28
- * Compute chemistry effects when reuniting after absence.
29
- */
30
- export declare function computeReunionEffect(attachment: AttachmentState, minutesSinceLastInteraction: number): Partial<ChemicalState> | null;
20
+ export declare function computeReunionEffect(attachment: AttachmentState, minutesSinceLastInteraction: number): Partial<SelfState> | null;