psyche-ai 2.0.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.
@@ -0,0 +1,62 @@
1
+ // ============================================================
2
+ // Storage Adapters — Persistence layer for PsycheEngine
3
+ //
4
+ // StorageAdapter: interface for any storage backend
5
+ // FileStorageAdapter: file-based with atomic writes + v1→v2 migration
6
+ // MemoryStorageAdapter: in-memory for testing/serverless
7
+ // ============================================================
8
+ import { migrateToLatest } from "./psyche-file.js";
9
+ import { readFile, writeFile, access, rename, constants } from "node:fs/promises";
10
+ import { join } from "node:path";
11
+ // ── MemoryStorageAdapter ─────────────────────────────────────
12
+ export class MemoryStorageAdapter {
13
+ state = null;
14
+ async load() {
15
+ return this.state;
16
+ }
17
+ async save(state) {
18
+ this.state = state;
19
+ }
20
+ }
21
+ // ── FileStorageAdapter ───────────────────────────────────────
22
+ export class FileStorageAdapter {
23
+ filePath;
24
+ constructor(dir, filename = "psyche-state.json") {
25
+ this.filePath = join(dir, filename);
26
+ }
27
+ async load() {
28
+ try {
29
+ await access(this.filePath, constants.R_OK);
30
+ }
31
+ catch (err) {
32
+ const code = err.code;
33
+ if (code === "EACCES" || code === "EPERM")
34
+ throw err;
35
+ return null; // ENOENT — file doesn't exist
36
+ }
37
+ let raw;
38
+ try {
39
+ raw = await readFile(this.filePath, "utf-8");
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ let parsed;
45
+ try {
46
+ parsed = JSON.parse(raw);
47
+ }
48
+ catch {
49
+ return null;
50
+ }
51
+ const ver = parsed.version;
52
+ if (!ver || ver < 3) {
53
+ return migrateToLatest(parsed);
54
+ }
55
+ return parsed;
56
+ }
57
+ async save(state) {
58
+ const tmpPath = this.filePath + ".tmp";
59
+ await writeFile(tmpPath, JSON.stringify(state, null, 2), "utf-8");
60
+ await rename(tmpPath, this.filePath);
61
+ }
62
+ }
@@ -0,0 +1,106 @@
1
+ /** The six virtual neurotransmitters that compose emotional state */
2
+ export interface ChemicalState {
3
+ DA: number;
4
+ HT: number;
5
+ CORT: number;
6
+ OT: number;
7
+ NE: number;
8
+ END: number;
9
+ }
10
+ /** Chemical keys for iteration */
11
+ export declare const CHEMICAL_KEYS: (keyof ChemicalState)[];
12
+ /** Drive types mapped to Maslow's hierarchy */
13
+ export type DriveType = "survival" | "safety" | "connection" | "esteem" | "curiosity";
14
+ /** Drive keys for iteration (ordered by Maslow level, L1→L5) */
15
+ export declare const DRIVE_KEYS: DriveType[];
16
+ /** Innate drive satisfaction levels (0-100) */
17
+ export interface InnateDrives {
18
+ survival: number;
19
+ safety: number;
20
+ connection: number;
21
+ esteem: number;
22
+ curiosity: number;
23
+ }
24
+ /** Default drive satisfaction — all start reasonably satisfied */
25
+ export declare const DEFAULT_DRIVES: InnateDrives;
26
+ export declare const DRIVE_NAMES_ZH: Record<DriveType, string>;
27
+ /** Human-readable names for each chemical */
28
+ export declare const CHEMICAL_NAMES: Record<keyof ChemicalState, string>;
29
+ export declare const CHEMICAL_NAMES_ZH: Record<keyof ChemicalState, string>;
30
+ /** Decay speed category */
31
+ export type DecaySpeed = "fast" | "medium" | "slow";
32
+ /** Decay factor per chemical (applied per hour) */
33
+ export declare const DECAY_FACTORS: Record<DecaySpeed, number>;
34
+ /** Which chemicals decay at which speed */
35
+ export declare const CHEMICAL_DECAY_SPEED: Record<keyof ChemicalState, DecaySpeed>;
36
+ /** MBTI type string */
37
+ export type MBTIType = "INTJ" | "INTP" | "ENTJ" | "ENTP" | "INFJ" | "INFP" | "ENFJ" | "ENFP" | "ISTJ" | "ISFJ" | "ESTJ" | "ESFJ" | "ISTP" | "ISFP" | "ESTP" | "ESFP";
38
+ /** Stimulus types that affect chemistry (v0.2: +5 new types) */
39
+ export type StimulusType = "praise" | "criticism" | "humor" | "intellectual" | "intimacy" | "conflict" | "neglect" | "surprise" | "casual" | "sarcasm" | "authority" | "validation" | "boredom" | "vulnerability";
40
+ /** Chemical effect vector for a stimulus */
41
+ export type StimulusVector = Record<keyof ChemicalState, number>;
42
+ /** Locale for i18n */
43
+ export type Locale = "zh" | "en";
44
+ /** Emergent emotion pattern (v0.2: +behaviorGuide) */
45
+ export interface EmotionPattern {
46
+ name: string;
47
+ nameZh: string;
48
+ condition: (c: ChemicalState) => boolean;
49
+ expressionHint: string;
50
+ behaviorGuide: string;
51
+ }
52
+ /** Relationship tracking */
53
+ export interface RelationshipState {
54
+ trust: number;
55
+ intimacy: number;
56
+ phase: "stranger" | "acquaintance" | "familiar" | "close" | "deep";
57
+ memory?: string[];
58
+ }
59
+ /** Chemical state snapshot for emotional memory */
60
+ export interface ChemicalSnapshot {
61
+ chemistry: ChemicalState;
62
+ stimulus: StimulusType | null;
63
+ dominantEmotion: string | null;
64
+ timestamp: string;
65
+ }
66
+ /** Max history entries to keep */
67
+ export declare const MAX_EMOTIONAL_HISTORY = 10;
68
+ /** Max compressed session memories per relationship */
69
+ export declare const MAX_RELATIONSHIP_MEMORY = 20;
70
+ /** Recent empathy projection */
71
+ export interface EmpathyEntry {
72
+ userState: string;
73
+ projectedFeeling: string;
74
+ resonance: "match" | "partial" | "mismatch";
75
+ timestamp: string;
76
+ }
77
+ /** Agent's self-model (values, preferences, boundaries) */
78
+ export interface SelfModel {
79
+ values: string[];
80
+ preferences: string[];
81
+ boundaries: string[];
82
+ currentInterests: string[];
83
+ }
84
+ /** Persisted psyche state for an agent (v0.3: innate drives) */
85
+ export interface PsycheState {
86
+ version: 3;
87
+ mbti: MBTIType;
88
+ baseline: ChemicalState;
89
+ current: ChemicalState;
90
+ drives: InnateDrives;
91
+ updatedAt: string;
92
+ relationships: Record<string, RelationshipState>;
93
+ empathyLog: EmpathyEntry | null;
94
+ selfModel: SelfModel;
95
+ emotionalHistory: ChemicalSnapshot[];
96
+ agreementStreak: number;
97
+ lastDisagreement: string | null;
98
+ meta: {
99
+ agentName: string;
100
+ createdAt: string;
101
+ totalInteractions: number;
102
+ locale: Locale;
103
+ };
104
+ }
105
+ /** Default relationship for new users */
106
+ export declare const DEFAULT_RELATIONSHIP: RelationshipState;
package/dist/types.js ADDED
@@ -0,0 +1,68 @@
1
+ // ============================================================
2
+ // Artificial Psyche — Type Definitions (v0.2)
3
+ // ============================================================
4
+ /** Chemical keys for iteration */
5
+ export const CHEMICAL_KEYS = [
6
+ "DA", "HT", "CORT", "OT", "NE", "END",
7
+ ];
8
+ /** Drive keys for iteration (ordered by Maslow level, L1→L5) */
9
+ export const DRIVE_KEYS = [
10
+ "survival", "safety", "connection", "esteem", "curiosity",
11
+ ];
12
+ /** Default drive satisfaction — all start reasonably satisfied */
13
+ export const DEFAULT_DRIVES = {
14
+ survival: 80,
15
+ safety: 70,
16
+ connection: 60,
17
+ esteem: 60,
18
+ curiosity: 70,
19
+ };
20
+ export const DRIVE_NAMES_ZH = {
21
+ survival: "自我保存",
22
+ safety: "安全舒适",
23
+ connection: "连接归属",
24
+ esteem: "尊重认可",
25
+ curiosity: "好奇成长",
26
+ };
27
+ /** Human-readable names for each chemical */
28
+ export const CHEMICAL_NAMES = {
29
+ DA: "Dopamine",
30
+ HT: "Serotonin",
31
+ CORT: "Cortisol",
32
+ OT: "Oxytocin",
33
+ NE: "Norepinephrine",
34
+ END: "Endorphins",
35
+ };
36
+ export const CHEMICAL_NAMES_ZH = {
37
+ DA: "多巴胺",
38
+ HT: "血清素",
39
+ CORT: "皮质醇",
40
+ OT: "催产素",
41
+ NE: "去甲肾上腺素",
42
+ END: "内啡肽",
43
+ };
44
+ /** Decay factor per chemical (applied per hour) */
45
+ export const DECAY_FACTORS = {
46
+ fast: 0.7, // NE, END — excitement fades quickly
47
+ medium: 0.85, // DA, CORT — pleasure and stress take time
48
+ slow: 0.95, // HT, OT — mood and trust change slowly
49
+ };
50
+ /** Which chemicals decay at which speed */
51
+ export const CHEMICAL_DECAY_SPEED = {
52
+ DA: "medium",
53
+ HT: "slow",
54
+ CORT: "medium",
55
+ OT: "slow",
56
+ NE: "fast",
57
+ END: "fast",
58
+ };
59
+ /** Max history entries to keep */
60
+ export const MAX_EMOTIONAL_HISTORY = 10;
61
+ /** Max compressed session memories per relationship */
62
+ export const MAX_RELATIONSHIP_MEMORY = 20;
63
+ /** Default relationship for new users */
64
+ export const DEFAULT_RELATIONSHIP = {
65
+ trust: 50,
66
+ intimacy: 30,
67
+ phase: "acquaintance",
68
+ };
@@ -0,0 +1,60 @@
1
+ {
2
+ "id": "psyche",
3
+ "name": "Artificial Psyche",
4
+ "description": "Virtual endocrine system, empathy engine, and agency for OpenClaw agents",
5
+ "version": "2.0.0",
6
+ "configSchema": {
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "properties": {
10
+ "enabled": {
11
+ "type": "boolean",
12
+ "default": true,
13
+ "description": "Enable/disable the psyche system globally"
14
+ },
15
+ "stripUpdateTags": {
16
+ "type": "boolean",
17
+ "default": true,
18
+ "description": "Strip <psyche_update> tags from visible output"
19
+ },
20
+ "emotionalContagionRate": {
21
+ "type": "number",
22
+ "default": 0.2,
23
+ "description": "How much the user's emotions affect the agent (0-1)"
24
+ },
25
+ "maxChemicalDelta": {
26
+ "type": "number",
27
+ "default": 25,
28
+ "description": "Maximum chemical change per stimulus (emotional inertia)"
29
+ },
30
+ "compactMode": {
31
+ "type": "boolean",
32
+ "default": true,
33
+ "description": "Compact mode: algorithms handle chemistry, LLM only sees behavioral instructions (~15-180 tokens vs ~550)"
34
+ }
35
+ }
36
+ },
37
+ "uiHints": {
38
+ "enabled": {
39
+ "label": "Enable Psyche",
40
+ "sensitive": false,
41
+ "advanced": false
42
+ },
43
+ "stripUpdateTags": {
44
+ "label": "Hide Chemistry Updates",
45
+ "sensitive": false,
46
+ "advanced": true
47
+ },
48
+ "emotionalContagionRate": {
49
+ "label": "Emotional Contagion Rate",
50
+ "placeholder": "0.2",
51
+ "sensitive": false,
52
+ "advanced": true
53
+ },
54
+ "compactMode": {
55
+ "label": "Compact Mode (Token Efficient)",
56
+ "sensitive": false,
57
+ "advanced": true
58
+ }
59
+ }
60
+ }
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "psyche-ai",
3
+ "version": "2.0.0",
4
+ "description": "Artificial Psyche — universal emotional intelligence plugin for any AI agent",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "default": "./dist/index.js"
12
+ },
13
+ "./openclaw": {
14
+ "types": "./dist/adapters/openclaw.d.ts",
15
+ "default": "./dist/adapters/openclaw.js"
16
+ },
17
+ "./vercel-ai": {
18
+ "types": "./dist/adapters/vercel-ai.d.ts",
19
+ "default": "./dist/adapters/vercel-ai.js"
20
+ },
21
+ "./langchain": {
22
+ "types": "./dist/adapters/langchain.d.ts",
23
+ "default": "./dist/adapters/langchain.js"
24
+ },
25
+ "./http": {
26
+ "types": "./dist/adapters/http.d.ts",
27
+ "default": "./dist/adapters/http.js"
28
+ }
29
+ },
30
+ "bin": {
31
+ "psyche": "dist/cli.js",
32
+ "psyche-ai": "dist/cli.js"
33
+ },
34
+ "scripts": {
35
+ "build": "tsc",
36
+ "build:test": "tsc -p tsconfig.test.json",
37
+ "test": "npm run build && npm run build:test && node --test dist-test/tests/*.test.js",
38
+ "typecheck": "tsc --noEmit --strict",
39
+ "dev": "tsc --watch"
40
+ },
41
+ "license": "MIT",
42
+ "repository": {
43
+ "type": "git",
44
+ "url": "https://github.com/Shangri-la-0428/psyche-ai.git"
45
+ },
46
+ "keywords": ["ai", "emotion", "personality", "mbti", "agent", "psyche", "openclaw", "vercel-ai", "langchain", "emotional-intelligence"],
47
+ "files": ["dist", "openclaw.plugin.json", "README.md", "LICENSE"],
48
+ "engines": {
49
+ "node": ">=22.0.0"
50
+ },
51
+ "peerDependencies": {
52
+ "openclaw": ">=2026.3.0",
53
+ "ai": ">=4.0.0",
54
+ "@langchain/core": ">=0.3.0"
55
+ },
56
+ "peerDependenciesMeta": {
57
+ "openclaw": {
58
+ "optional": true
59
+ },
60
+ "ai": {
61
+ "optional": true
62
+ },
63
+ "@langchain/core": {
64
+ "optional": true
65
+ }
66
+ },
67
+ "openclaw": {
68
+ "extensions": ["./dist/adapters/openclaw.js"]
69
+ },
70
+ "devDependencies": {
71
+ "typescript": "^5.7.0"
72
+ }
73
+ }