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
|
@@ -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,
|
|
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?:
|
|
27
|
+
coreMemories?: StateSnapshot[];
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
-
* Map
|
|
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(
|
|
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
|
|
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:
|
|
52
|
-
* the same story.
|
|
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
|
|
55
|
-
* but
|
|
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:
|
|
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
|
|
65
|
-
*
|
|
66
|
-
*
|
|
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(
|
|
73
|
+
export declare function detectUnnamedEmotion(state: SelfState, drives: InnateDrives, _currentQuality: ExperientialQuality): UnnamedEmotion | null;
|
|
69
74
|
export {};
|