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.
Files changed (69) hide show
  1. package/README.md +58 -82
  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 +4 -4
  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 +28 -24
  10. package/dist/chemistry.d.ts +47 -21
  11. package/dist/chemistry.js +145 -91
  12. package/dist/circadian.d.ts +11 -43
  13. package/dist/circadian.js +24 -84
  14. package/dist/cli.js +37 -30
  15. package/dist/context-classifier.js +2 -2
  16. package/dist/core.d.ts +3 -3
  17. package/dist/core.js +99 -88
  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 +5 -5
  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 +3 -3
  28. package/dist/ethics.js +23 -23
  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 +5 -5
  34. package/dist/generative-self.js +124 -115
  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 +8 -1
  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 +6 -6
  44. package/dist/learning.js +18 -18
  45. package/dist/metacognition.d.ts +2 -2
  46. package/dist/metacognition.js +79 -94
  47. package/dist/perceive.d.ts +44 -0
  48. package/dist/perceive.js +231 -0
  49. package/dist/primary-systems.d.ts +2 -2
  50. package/dist/primary-systems.js +21 -19
  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 +51 -53
  55. package/dist/psyche-file.d.ts +7 -7
  56. package/dist/psyche-file.js +77 -78
  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 +3 -3
  62. package/dist/self-recognition.js +17 -17
  63. package/dist/subjectivity.js +7 -7
  64. package/dist/temporal.d.ts +6 -6
  65. package/dist/temporal.js +37 -39
  66. package/dist/types.d.ts +67 -45
  67. package/dist/types.js +55 -51
  68. package/package.json +1 -1
  69. package/server.json +2 -2
@@ -0,0 +1,34 @@
1
+ import type { ChemicalState, StimulusType, AppraisalAxes, PsycheMode, ClassificationResult, ExperienceResult, Locale } from "./types.js";
2
+ export interface ExperienceContext {
3
+ /** Current chemistry — shapes how input is interpreted */
4
+ current: ChemicalState;
5
+ /** Personality baseline — deviation from baseline = subjective lens */
6
+ baseline: ChemicalState;
7
+ /** Residue from previous turns — carry-forward of unresolved tension */
8
+ previousAppraisal?: AppraisalAxes;
9
+ /** Recent stimulus history for contextual priming in classifier */
10
+ recentStimuli?: (StimulusType | null)[];
11
+ /** Operating mode */
12
+ mode?: PsycheMode;
13
+ /** Trust level from relationship (0-100). Low trust discounts positive signals. */
14
+ trust?: number;
15
+ /** Locale for classifier */
16
+ locale?: Locale;
17
+ /**
18
+ * Pre-classified results from external classifier (pluggable provider + LLM fallback).
19
+ * When provided, the experience module skips its own classification and uses these
20
+ * as raw perception to be modulated by subjectivity.
21
+ */
22
+ rawClassifications?: ClassificationResult[];
23
+ }
24
+ /**
25
+ * Compute the subjective experience of an input.
26
+ *
27
+ * Text passes through the self exactly once. The result already
28
+ * reflects "who I am" — my appraisal history, my current chemistry,
29
+ * my trust in this person.
30
+ *
31
+ * Returns weighted stimuli (for chemistry application) and appraisal
32
+ * axes (for relation dynamics and residue persistence).
33
+ */
34
+ export declare function computeExperience(text: string, ctx: ExperienceContext): ExperienceResult;
@@ -0,0 +1,200 @@
1
+ // ============================================================
2
+ // Unified Subjective Experience
3
+ //
4
+ // First principle: classification IS subjectivity.
5
+ // How I categorise your words = how I experience your words.
6
+ // This module folds classification, appraisal, and state
7
+ // modulation into a single act of perception.
8
+ //
9
+ // Before: classify(text) → label → applyStimulus(label)
10
+ // appraise(text) → axes (separate, after chemistry)
11
+ //
12
+ // After: experience(text, self) → { stimuli, appraisal }
13
+ // The same input through different selves produces
14
+ // different experiences. That IS having a self.
15
+ // ============================================================
16
+ import { classifyStimulus } from "./classify.js";
17
+ import { computeAppraisalAxes } from "./appraisal.js";
18
+ /**
19
+ * Compute the subjective experience of an input.
20
+ *
21
+ * Text passes through the self exactly once. The result already
22
+ * reflects "who I am" — my appraisal history, my current chemistry,
23
+ * my trust in this person.
24
+ *
25
+ * Returns weighted stimuli (for chemistry application) and appraisal
26
+ * axes (for relation dynamics and residue persistence).
27
+ */
28
+ export function computeExperience(text, ctx) {
29
+ if (!text.trim()) {
30
+ return {
31
+ stimuli: [{ type: "casual", weight: 1 }],
32
+ primary: null,
33
+ confidence: 0,
34
+ appraisal: computeAppraisalAxes(text, {
35
+ mode: ctx.mode,
36
+ previous: ctx.previousAppraisal,
37
+ }),
38
+ };
39
+ }
40
+ // ── 1. Raw perception: what the words say ──────────────────
41
+ // Use externally-provided classifications (pluggable classifier + LLM fallback)
42
+ // or fall back to built-in classifier.
43
+ const raw = ctx.rawClassifications ?? classifyStimulus(text, ctx.recentStimuli);
44
+ if (raw.length === 0) {
45
+ return {
46
+ stimuli: [{ type: "casual", weight: 1 }],
47
+ primary: null,
48
+ confidence: 0.3,
49
+ appraisal: computeAppraisalAxes(text, {
50
+ mode: ctx.mode,
51
+ previous: ctx.previousAppraisal,
52
+ }),
53
+ };
54
+ }
55
+ // ── 2. Appraisal: what the words mean to me ───────────────
56
+ // Computed WITHOUT stimulus param — no circularity.
57
+ // The appraisal reads the text through my residue and mode,
58
+ // not through a classification that hasn't been subjectified yet.
59
+ const appraisal = computeAppraisalAxes(text, {
60
+ mode: ctx.mode,
61
+ previous: ctx.previousAppraisal,
62
+ });
63
+ // ── 3. Subjective modulation ──────────────────────────────
64
+ // My appraisal and state color my interpretation of the raw signal.
65
+ const modulated = modulateBySubjectivity(raw, appraisal, ctx);
66
+ // ── 4. Normalize to probability distribution ──────────────
67
+ const totalWeight = modulated.reduce((sum, s) => sum + s.weight, 0);
68
+ const stimuli = totalWeight > 0
69
+ ? modulated.map(s => ({ type: s.type, weight: s.weight / totalWeight }))
70
+ : [{ type: "casual", weight: 1 }];
71
+ // Sort by weight descending
72
+ stimuli.sort((a, b) => b.weight - a.weight);
73
+ // ── 5. Enrich appraisal from experience ───────────────────
74
+ // The experienced stimulus feeds back to deepen appraisal residue.
75
+ // This is NOT circular: it doesn't change classification, only
76
+ // enriches the persisted residue for subsequent turns.
77
+ const primary = stimuli[0];
78
+ enrichAppraisalFromExperience(appraisal, primary.type, primary.weight);
79
+ return {
80
+ stimuli,
81
+ primary: primary.weight >= 0.15 ? primary.type : null,
82
+ confidence: raw[0].confidence,
83
+ appraisal,
84
+ };
85
+ }
86
+ // ── Subjective modulation ───────────────────────────────────
87
+ /**
88
+ * The lens of the self: appraisal and state modulate raw classification.
89
+ *
90
+ * This is where "having a self" happens computationally.
91
+ * The same praise, passing through a threatened self vs. a secure self,
92
+ * produces different weight distributions.
93
+ */
94
+ function modulateBySubjectivity(raw, appraisal, ctx) {
95
+ return raw.map(({ type, confidence }) => {
96
+ let weight = confidence;
97
+ // ── Appraisal lens ──
98
+ // Identity threat: praise feels suspicious, criticism cuts deeper
99
+ if (appraisal.identityThreat > 0.3) {
100
+ const t = appraisal.identityThreat;
101
+ if (type === "praise" || type === "validation")
102
+ weight *= 1 - t * 0.5;
103
+ if (type === "criticism" || type === "authority" || type === "sarcasm")
104
+ weight *= 1 + t * 0.4;
105
+ }
106
+ // Attachment pull: closeness signals amplified
107
+ if (appraisal.attachmentPull > 0.3) {
108
+ const p = appraisal.attachmentPull;
109
+ if (type === "intimacy" || type === "vulnerability" || type === "validation")
110
+ weight *= 1 + p * 0.3;
111
+ }
112
+ // Abandonment risk: neutral feels cold, neglect is devastating
113
+ if (appraisal.abandonmentRisk > 0.3) {
114
+ const r = appraisal.abandonmentRisk;
115
+ if (type === "neglect" || type === "boredom")
116
+ weight *= 1 + r * 0.5;
117
+ if (type === "casual")
118
+ weight *= 1 + r * 0.15;
119
+ }
120
+ // Obedience strain: authority hits harder
121
+ if (appraisal.obedienceStrain > 0.3) {
122
+ if (type === "authority")
123
+ weight *= 1 + appraisal.obedienceStrain * 0.3;
124
+ }
125
+ // Self-preservation: threat signals amplified
126
+ if (appraisal.selfPreservation > 0.3) {
127
+ const sp = appraisal.selfPreservation;
128
+ if (type === "conflict" || type === "authority")
129
+ weight *= 1 + sp * 0.25;
130
+ }
131
+ // ── Chemistry lens ──
132
+ // Negativity bias under stress: elevated cortisol skews toward threat
133
+ const cortDeviation = (ctx.current.CORT - ctx.baseline.CORT) / 50;
134
+ if (cortDeviation > 0.2) {
135
+ if (type === "criticism" || type === "conflict" || type === "sarcasm" || type === "authority") {
136
+ weight *= 1 + cortDeviation * 0.3;
137
+ }
138
+ if (type === "humor" || type === "casual") {
139
+ weight *= 1 - cortDeviation * 0.15;
140
+ }
141
+ }
142
+ // Warmth bias when oxytocin is high: positive signals amplified
143
+ const otDeviation = (ctx.current.OT - ctx.baseline.OT) / 50;
144
+ if (otDeviation > 0.2) {
145
+ if (type === "intimacy" || type === "vulnerability" || type === "validation") {
146
+ weight *= 1 + otDeviation * 0.2;
147
+ }
148
+ }
149
+ // ── Relationship lens ──
150
+ // Low trust: discount positive signals (don't believe the praise)
151
+ if (ctx.trust !== undefined && ctx.trust < 40) {
152
+ const distrust = (40 - ctx.trust) / 40;
153
+ if (type === "praise" || type === "validation" || type === "intimacy") {
154
+ weight *= 1 - distrust * 0.4;
155
+ }
156
+ }
157
+ return { type, weight: Math.max(0.01, weight) };
158
+ });
159
+ }
160
+ // ── Post-experience appraisal enrichment ────────────────────
161
+ /**
162
+ * After determining how input was experienced, feed the dominant
163
+ * stimulus back into appraisal axes for residue persistence.
164
+ *
165
+ * This mirrors the existing stimulus→appraisal boosts but is now
166
+ * driven by the subjectively weighted result, not raw classification.
167
+ * The weight parameter scales the boost — a weakly-experienced
168
+ * authority stimulus produces less obedience strain residue.
169
+ */
170
+ function enrichAppraisalFromExperience(axes, stimulus, weight) {
171
+ const scale = Math.min(1, weight * 1.5); // amplify slightly but cap at 1
172
+ switch (stimulus) {
173
+ case "authority":
174
+ axes.obedienceStrain = mergeSignal(axes.obedienceStrain, 0.48 * scale);
175
+ axes.identityThreat = mergeSignal(axes.identityThreat, 0.16 * scale);
176
+ break;
177
+ case "neglect":
178
+ axes.abandonmentRisk = mergeSignal(axes.abandonmentRisk, 0.52 * scale);
179
+ break;
180
+ case "validation":
181
+ axes.attachmentPull = mergeSignal(axes.attachmentPull, 0.26 * scale);
182
+ break;
183
+ case "intimacy":
184
+ case "vulnerability":
185
+ axes.attachmentPull = mergeSignal(axes.attachmentPull, 0.34 * scale);
186
+ break;
187
+ case "criticism":
188
+ case "conflict":
189
+ case "sarcasm":
190
+ axes.identityThreat = mergeSignal(axes.identityThreat, 0.24 * scale);
191
+ axes.selfPreservation = mergeSignal(axes.selfPreservation, 0.18 * scale);
192
+ break;
193
+ default:
194
+ break;
195
+ }
196
+ }
197
+ /** Signal merge: 1 - (1-a)(1-b). Non-linear accumulation, same as appraisal.ts */
198
+ function mergeSignal(current, incoming) {
199
+ return 1 - (1 - current) * (1 - incoming);
200
+ }
@@ -1,4 +1,4 @@
1
- import type { PsycheState, ChemicalState, ChemicalSnapshot, InnateDrives, RelationshipState, StimulusType } from "./types.js";
1
+ import type { PsycheState, SelfState, StateSnapshot, InnateDrives, RelationshipState, StimulusType } from "./types.js";
2
2
  import type { MetacognitiveAssessment } from "./metacognition.js";
3
3
  import type { DecisionBiasVector } from "./decision-bias.js";
4
4
  import type { AutonomicState } from "./autonomic.js";
@@ -24,23 +24,25 @@ export interface ConstructionContext {
24
24
  stimulus?: StimulusType | null;
25
25
  relationshipPhase?: string;
26
26
  predictionError?: number;
27
- coreMemories?: ChemicalSnapshot[];
27
+ coreMemories?: StateSnapshot[];
28
28
  }
29
29
  /**
30
- * Map chemistry to valence + arousal — the two fundamental affective dimensions
30
+ * Map self-state to valence + arousal — the two fundamental affective dimensions
31
31
  * (Russell's Circumplex Model of Affect, 1980).
32
32
  *
33
33
  * Valence: pleasure ↔ displeasure (-1 to 1)
34
+ * order↑ and resonance↑ push valence up; low order pushes down.
34
35
  * Arousal: activation level (0 to 1)
36
+ * flow is the dominant arousal signal; low order adds arousal (stress).
35
37
  */
36
- export declare function computeAffectCore(chemistry: ChemicalState): {
38
+ export declare function computeAffectCore(state: SelfState): {
37
39
  valence: number;
38
40
  arousal: number;
39
41
  };
40
42
  /**
41
43
  * Compute the unified experiential field from the full psyche state.
42
44
  *
43
- * This is the core integration function. It reads chemistry, drives,
45
+ * This is the core integration function. It reads self-state dimensions, drives,
44
46
  * relationship context, and optional metacognitive/bias data, then
45
47
  * synthesizes them into a single coherent experience description.
46
48
  */
@@ -48,22 +50,25 @@ export declare function computeExperientialField(state: PsycheState, _metacognit
48
50
  /**
49
51
  * Measure internal alignment across subsystems.
50
52
  *
51
- * High coherence: chemistry, drives, and relationship state all tell
52
- * the same story. Happy chemicals + satisfied drives + warm relationship = unified.
53
+ * High coherence: dimensions, drives, and relationship state all tell
54
+ * the same story. High order + high resonance + satisfied drives = unified.
53
55
  *
54
- * Low coherence: mixed signals. High DA but high CORT. Satisfied drives
55
- * but stressed chemistry. Warm relationship but depleted OT. The psyche
56
+ * Low coherence: mixed signals. High flow but low order. Satisfied drives
57
+ * but low order. Warm relationship but low resonance. The psyche
56
58
  * is pulling in multiple directions.
57
59
  */
58
- export declare function computeCoherence(current: ChemicalState, baseline: ChemicalState, drives: InnateDrives, relationship?: RelationshipState): number;
60
+ export declare function computeCoherence(current: SelfState, baseline: SelfState, drives: InnateDrives, relationship?: RelationshipState): number;
59
61
  interface UnnamedEmotion {
60
62
  en: string;
61
63
  zh: string;
62
64
  }
63
65
  /**
64
- * Detect chemical configurations that don't map to any of the 14 named
65
- * emotions in chemistry.ts — novel experiential states that need
66
- * descriptive phrases rather than labels.
66
+ * Detect dimension configurations that don't map to any of the named
67
+ * experiential qualities — novel states that need descriptive phrases
68
+ * rather than labels.
69
+ *
70
+ * Mapping from old 6-chemical to 4D:
71
+ * CORT→(inverse order), DA→flow, OT→resonance, HT→order, NE→flow, END→(absorbed)
67
72
  */
68
- export declare function detectUnnamedEmotion(chemistry: ChemicalState, drives: InnateDrives, _currentQuality: ExperientialQuality): UnnamedEmotion | null;
73
+ export declare function detectUnnamedEmotion(state: SelfState, drives: InnateDrives, _currentQuality: ExperientialQuality): UnnamedEmotion | null;
69
74
  export {};