psyche-ai 5.0.0 → 7.1.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 +67 -0
- package/dist/adapters/openclaw.js +7 -0
- package/dist/autonomic.d.ts +41 -0
- package/dist/autonomic.js +186 -0
- package/dist/circadian.d.ts +37 -0
- package/dist/circadian.js +97 -0
- package/dist/classify.d.ts +29 -2
- package/dist/classify.js +339 -53
- package/dist/cli.js +132 -13
- package/dist/core.d.ts +31 -2
- package/dist/core.js +246 -30
- package/dist/i18n.js +14 -0
- package/dist/index.d.ts +13 -5
- package/dist/index.js +11 -4
- package/dist/primary-systems.d.ts +55 -0
- package/dist/primary-systems.js +218 -0
- package/dist/profiles.d.ts +12 -1
- package/dist/profiles.js +42 -0
- package/dist/prompt.d.ts +26 -1
- package/dist/prompt.js +331 -33
- package/dist/psyche-file.d.ts +15 -1
- package/dist/psyche-file.js +147 -5
- package/dist/types.d.ts +16 -1
- package/dist/update.js +1 -1
- package/openclaw.plugin.json +35 -1
- package/package.json +4 -2
package/dist/cli.js
CHANGED
|
@@ -3,21 +3,24 @@
|
|
|
3
3
|
// psyche — Artificial Psyche CLI (v0.2)
|
|
4
4
|
//
|
|
5
5
|
// Usage:
|
|
6
|
-
// psyche init <dir> [--mbti TYPE] [--name NAME] [--lang LOCALE]
|
|
6
|
+
// psyche init <dir> [--mbti TYPE] [--name NAME] [--lang LOCALE] [--mode MODE] [--traits "O:80,C:40,E:90,A:60,N:30"] [--no-persist]
|
|
7
7
|
// psyche status <dir> [--json] [--user ID]
|
|
8
8
|
// psyche inject <dir> [--protocol] [--json] [--lang LOCALE] [--user ID]
|
|
9
9
|
// psyche decay <dir>
|
|
10
10
|
// psyche update <dir> '{"DA":80,"CORT":45}' [--user ID]
|
|
11
|
-
// psyche
|
|
11
|
+
// psyche mode <dir> <natural|work|companion>
|
|
12
|
+
// psyche intensity Show info about personality intensity config
|
|
13
|
+
// psyche reset <dir> [--full]
|
|
12
14
|
// psyche profiles [--json] [--mbti TYPE]
|
|
13
15
|
// ============================================================
|
|
14
16
|
import { resolve } from "node:path";
|
|
15
17
|
import { parseArgs } from "node:util";
|
|
16
18
|
import { loadState, saveState, decayAndSave, initializeState, mergeUpdates, generatePsycheMd, getRelationship, } from "./psyche-file.js";
|
|
17
|
-
import { describeEmotionalState, getExpressionHint } from "./chemistry.js";
|
|
18
|
-
import { getBaseline, getTemperament, getSensitivity, getDefaultSelfModel } from "./profiles.js";
|
|
19
|
+
import { describeEmotionalState, getExpressionHint, detectEmotions } from "./chemistry.js";
|
|
20
|
+
import { getBaseline, getTemperament, getSensitivity, getDefaultSelfModel, traitsToBaseline } from "./profiles.js";
|
|
19
21
|
import { buildDynamicContext, buildProtocolContext } from "./prompt.js";
|
|
20
|
-
import {
|
|
22
|
+
import { t } from "./i18n.js";
|
|
23
|
+
import { CHEMICAL_KEYS, CHEMICAL_NAMES_ZH, DRIVE_KEYS, DRIVE_NAMES_ZH } from "./types.js";
|
|
21
24
|
import { isMBTIType, isChemicalKey, isLocale } from "./guards.js";
|
|
22
25
|
// ── Logger ───────────────────────────────────────────────────
|
|
23
26
|
const cliLogger = {
|
|
@@ -49,12 +52,32 @@ function printChemistry(state) {
|
|
|
49
52
|
console.log(` ${label} ${nameZh} ${bar(val)} ${String(val).padStart(3)} (base:${base} ${a})`);
|
|
50
53
|
}
|
|
51
54
|
}
|
|
55
|
+
function printDrives(state) {
|
|
56
|
+
const icons = { survival: "🛡️", safety: "🏠", connection: "🤝", esteem: "⭐", curiosity: "🔍" };
|
|
57
|
+
for (const key of DRIVE_KEYS) {
|
|
58
|
+
const val = Math.round(state.drives[key]);
|
|
59
|
+
const icon = icons[key] ?? "·";
|
|
60
|
+
const status = val >= 60 ? "🟢" : val >= 40 ? "🟡" : "🔴";
|
|
61
|
+
const nameZh = DRIVE_NAMES_ZH[key].padEnd(6);
|
|
62
|
+
console.log(` ${icon} ${nameZh} ${bar(val, 20)} ${String(val).padStart(3)} ${status}`);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function printEmotions(state) {
|
|
66
|
+
const emotions = detectEmotions(state.current);
|
|
67
|
+
if (emotions.length > 0) {
|
|
68
|
+
const names = emotions.map((e) => e.nameZh).join("、");
|
|
69
|
+
console.log(` 涌现情绪: ${names}`);
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
console.log(` 涌现情绪: 平静`);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
52
75
|
function die(msg) {
|
|
53
76
|
console.error(`error: ${msg}`);
|
|
54
77
|
process.exit(1);
|
|
55
78
|
}
|
|
56
79
|
// ── Commands ─────────────────────────────────────────────────
|
|
57
|
-
async function cmdInit(dir, mbti, name, lang) {
|
|
80
|
+
async function cmdInit(dir, mbti, name, lang, mode, traits, noPersist) {
|
|
58
81
|
const absDir = resolve(dir);
|
|
59
82
|
const opts = {};
|
|
60
83
|
if (mbti) {
|
|
@@ -70,7 +93,46 @@ async function cmdInit(dir, mbti, name, lang) {
|
|
|
70
93
|
die(`invalid locale: ${lang}. Valid: zh, en`);
|
|
71
94
|
opts.locale = lang;
|
|
72
95
|
}
|
|
96
|
+
if (mode) {
|
|
97
|
+
const validModes = ["natural", "work", "companion"];
|
|
98
|
+
if (!validModes.includes(mode))
|
|
99
|
+
die(`invalid mode: ${mode}. Valid: ${validModes.join(", ")}`);
|
|
100
|
+
}
|
|
101
|
+
// Parse traits string like "O:80,C:40,E:90,A:60,N:30"
|
|
102
|
+
let parsedTraits;
|
|
103
|
+
if (traits) {
|
|
104
|
+
const traitMap = {
|
|
105
|
+
O: "openness", C: "conscientiousness", E: "extraversion", A: "agreeableness", N: "neuroticism",
|
|
106
|
+
};
|
|
107
|
+
const parsed = {};
|
|
108
|
+
for (const pair of traits.split(",")) {
|
|
109
|
+
const [key, val] = pair.trim().split(":");
|
|
110
|
+
const traitKey = traitMap[key?.toUpperCase()];
|
|
111
|
+
if (!traitKey)
|
|
112
|
+
die(`invalid trait key: ${key}. Valid: O, C, E, A, N`);
|
|
113
|
+
const num = parseInt(val, 10);
|
|
114
|
+
if (isNaN(num) || num < 0 || num > 100)
|
|
115
|
+
die(`trait value must be 0-100: ${val}`);
|
|
116
|
+
parsed[traitKey] = num;
|
|
117
|
+
}
|
|
118
|
+
if (Object.keys(parsed).length !== 5)
|
|
119
|
+
die("all 5 traits required: O, C, E, A, N");
|
|
120
|
+
parsedTraits = parsed;
|
|
121
|
+
}
|
|
73
122
|
const state = await initializeState(absDir, opts, cliLogger);
|
|
123
|
+
// Apply parsed traits to override baseline
|
|
124
|
+
if (parsedTraits) {
|
|
125
|
+
const { baseline } = traitsToBaseline(parsedTraits);
|
|
126
|
+
state.baseline = baseline;
|
|
127
|
+
state.current = { ...baseline };
|
|
128
|
+
await saveState(absDir, state);
|
|
129
|
+
await generatePsycheMd(absDir, state);
|
|
130
|
+
}
|
|
131
|
+
// Apply mode after initialization
|
|
132
|
+
if (mode) {
|
|
133
|
+
state.meta.mode = mode;
|
|
134
|
+
await saveState(absDir, state);
|
|
135
|
+
}
|
|
74
136
|
console.log(`\nPsyche initialized for ${state.meta.agentName} (${state.mbti})\n`);
|
|
75
137
|
printChemistry(state);
|
|
76
138
|
console.log(`\nFiles created:`);
|
|
@@ -98,6 +160,10 @@ async function cmdStatus(dir, json, userId) {
|
|
|
98
160
|
const elapsed = ((Date.now() - new Date(state.updatedAt).getTime()) / 60000).toFixed(1);
|
|
99
161
|
console.log(`\n${state.meta.agentName} (${state.mbti}) — ${emotion}\n`);
|
|
100
162
|
printChemistry(state);
|
|
163
|
+
console.log();
|
|
164
|
+
printDrives(state);
|
|
165
|
+
printEmotions(state);
|
|
166
|
+
console.log(` Mode: ${state.meta.mode ?? "natural"} — ${t(`mode.${state.meta.mode ?? "natural"}`, locale)}`);
|
|
101
167
|
console.log(`\n Expression: ${hint}`);
|
|
102
168
|
console.log(` Relationship (${userId ?? "_default"}): trust ${relationship.trust}, intimacy ${relationship.intimacy} (${relationship.phase})`);
|
|
103
169
|
console.log(` Interactions: ${state.meta.totalInteractions}`);
|
|
@@ -176,17 +242,22 @@ async function cmdUpdate(dir, updateJson, userId) {
|
|
|
176
242
|
printChemistry(merged);
|
|
177
243
|
console.log();
|
|
178
244
|
}
|
|
179
|
-
async function cmdReset(dir) {
|
|
245
|
+
async function cmdReset(dir, full) {
|
|
180
246
|
const absDir = resolve(dir);
|
|
181
247
|
const state = await loadState(absDir, cliLogger);
|
|
182
248
|
state.current = { ...state.baseline };
|
|
249
|
+
state.drives = { survival: 80, safety: 70, connection: 60, esteem: 60, curiosity: 70 };
|
|
183
250
|
state.updatedAt = new Date().toISOString();
|
|
184
251
|
state.empathyLog = null;
|
|
185
252
|
state.agreementStreak = 0;
|
|
186
253
|
state.lastDisagreement = null;
|
|
254
|
+
state.emotionalHistory = [];
|
|
255
|
+
if (full) {
|
|
256
|
+
state.relationships = { _default: { trust: 50, intimacy: 30, phase: "acquaintance" } };
|
|
257
|
+
}
|
|
187
258
|
await saveState(absDir, state);
|
|
188
259
|
await generatePsycheMd(absDir, state);
|
|
189
|
-
console.log(`\n${state.meta.agentName} reset to baseline (${state.mbti})\n`);
|
|
260
|
+
console.log(`\n${state.meta.agentName} reset to baseline (${state.mbti})${full ? " [full reset including relationships]" : ""}\n`);
|
|
190
261
|
printChemistry(state);
|
|
191
262
|
console.log();
|
|
192
263
|
}
|
|
@@ -256,6 +327,32 @@ function cmdProfiles(json, mbti) {
|
|
|
256
327
|
console.log();
|
|
257
328
|
}
|
|
258
329
|
}
|
|
330
|
+
async function cmdMode(dir, newMode) {
|
|
331
|
+
const absDir = resolve(dir);
|
|
332
|
+
const validModes = ["natural", "work", "companion"];
|
|
333
|
+
if (!validModes.includes(newMode))
|
|
334
|
+
die(`invalid mode: ${newMode}. Valid: ${validModes.join(", ")}`);
|
|
335
|
+
const state = await loadState(absDir, cliLogger);
|
|
336
|
+
state.meta.mode = newMode;
|
|
337
|
+
await saveState(absDir, state);
|
|
338
|
+
console.log(`\n${state.meta.agentName} mode set to: ${newMode}\n`);
|
|
339
|
+
}
|
|
340
|
+
function cmdIntensity() {
|
|
341
|
+
console.log(`
|
|
342
|
+
Personality intensity controls how strongly Psyche affects AI behavior.
|
|
343
|
+
|
|
344
|
+
0.0 = Traditional warm AI (no emotional variation)
|
|
345
|
+
0.5 = Subtle emotional responses
|
|
346
|
+
0.7 = Default
|
|
347
|
+
1.0 = Full Psyche experience
|
|
348
|
+
|
|
349
|
+
Set via PsycheEngine config:
|
|
350
|
+
new PsycheEngine({ personalityIntensity: 0.7 }, storage)
|
|
351
|
+
|
|
352
|
+
Or in OpenClaw plugin config:
|
|
353
|
+
{ "personalityIntensity": 0.7 }
|
|
354
|
+
`);
|
|
355
|
+
}
|
|
259
356
|
// ── Usage ────────────────────────────────────────────────────
|
|
260
357
|
function usage() {
|
|
261
358
|
console.log(`
|
|
@@ -263,12 +360,14 @@ psyche — Artificial Psyche CLI (v0.2)
|
|
|
263
360
|
Plug-and-play emotional intelligence for any AI agent.
|
|
264
361
|
|
|
265
362
|
Usage:
|
|
266
|
-
psyche init <dir> [--mbti TYPE] [--name NAME] [--lang LOCALE]
|
|
363
|
+
psyche init <dir> [--mbti TYPE] [--name NAME] [--lang LOCALE] [--mode MODE] [--traits "O:80,C:40,..."] [--no-persist]
|
|
267
364
|
psyche status <dir> [--json] [--user ID]
|
|
268
365
|
psyche inject <dir> [--protocol] [--json] [--lang LOCALE] [--user ID]
|
|
269
366
|
psyche decay <dir>
|
|
270
367
|
psyche update <dir> '{"DA":80,"CORT":45}' [--user ID]
|
|
271
|
-
psyche
|
|
368
|
+
psyche mode <dir> <natural|work|companion>
|
|
369
|
+
psyche intensity Show info about personality intensity config
|
|
370
|
+
psyche reset <dir> [--full]
|
|
272
371
|
psyche profiles [--mbti TYPE] [--json]
|
|
273
372
|
|
|
274
373
|
Options:
|
|
@@ -318,12 +417,15 @@ async function main() {
|
|
|
318
417
|
mbti: { type: "string" },
|
|
319
418
|
name: { type: "string" },
|
|
320
419
|
lang: { type: "string" },
|
|
420
|
+
mode: { type: "string" },
|
|
421
|
+
traits: { type: "string" },
|
|
422
|
+
"no-persist": { type: "boolean", default: false },
|
|
321
423
|
},
|
|
322
424
|
allowPositionals: true,
|
|
323
425
|
});
|
|
324
426
|
if (positionals.length === 0)
|
|
325
427
|
die("missing <dir> argument");
|
|
326
|
-
await cmdInit(positionals[0], values.mbti, values.name, values.lang);
|
|
428
|
+
await cmdInit(positionals[0], values.mbti, values.name, values.lang, values.mode, values.traits, values["no-persist"]);
|
|
327
429
|
break;
|
|
328
430
|
}
|
|
329
431
|
case "status": {
|
|
@@ -377,9 +479,16 @@ async function main() {
|
|
|
377
479
|
break;
|
|
378
480
|
}
|
|
379
481
|
case "reset": {
|
|
380
|
-
|
|
482
|
+
const { values: resetVals, positionals: resetPos } = parseArgs({
|
|
483
|
+
args: rest,
|
|
484
|
+
options: {
|
|
485
|
+
full: { type: "boolean", default: false },
|
|
486
|
+
},
|
|
487
|
+
allowPositionals: true,
|
|
488
|
+
});
|
|
489
|
+
if (resetPos.length === 0)
|
|
381
490
|
die("missing <dir> argument");
|
|
382
|
-
await cmdReset(
|
|
491
|
+
await cmdReset(resetPos[0], resetVals.full ?? false);
|
|
383
492
|
break;
|
|
384
493
|
}
|
|
385
494
|
case "profiles": {
|
|
@@ -394,6 +503,16 @@ async function main() {
|
|
|
394
503
|
cmdProfiles(values.json ?? false, values.mbti);
|
|
395
504
|
break;
|
|
396
505
|
}
|
|
506
|
+
case "mode": {
|
|
507
|
+
if (rest.length < 2)
|
|
508
|
+
die("usage: psyche mode <dir> <natural|work|companion>");
|
|
509
|
+
await cmdMode(rest[0], rest[1]);
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
case "intensity": {
|
|
513
|
+
cmdIntensity();
|
|
514
|
+
break;
|
|
515
|
+
}
|
|
397
516
|
default:
|
|
398
517
|
die(`unknown command: ${command}. Run 'psyche help' for usage.`);
|
|
399
518
|
}
|
package/dist/core.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PsycheState, StimulusType, Locale, MBTIType, OutcomeScore } from "./types.js";
|
|
1
|
+
import type { PsycheState, StimulusType, Locale, MBTIType, OutcomeScore, PsycheMode, PersonalityTraits } from "./types.js";
|
|
2
2
|
import type { StorageAdapter } from "./storage.js";
|
|
3
3
|
export interface PsycheEngineConfig {
|
|
4
4
|
mbti?: MBTIType;
|
|
@@ -9,6 +9,14 @@ export interface PsycheEngineConfig {
|
|
|
9
9
|
maxChemicalDelta?: number;
|
|
10
10
|
/** Compact mode: algorithms handle chemistry, LLM only sees behavioral output. Default: true */
|
|
11
11
|
compactMode?: boolean;
|
|
12
|
+
/** Operating mode: "natural" (default), "work" (minimal emotions), "companion" (full emotions) */
|
|
13
|
+
mode?: PsycheMode;
|
|
14
|
+
/** Personality intensity: 0.0 (traditional warm AI) to 1.0 (full Psyche). Default: 0.7 */
|
|
15
|
+
personalityIntensity?: number;
|
|
16
|
+
/** Whether to persist state to disk. Default: true. When false, uses in-memory storage. */
|
|
17
|
+
persist?: boolean;
|
|
18
|
+
/** Big Five traits. If provided, overrides MBTI for baseline calculation. */
|
|
19
|
+
traits?: PersonalityTraits;
|
|
12
20
|
}
|
|
13
21
|
export interface ProcessInputResult {
|
|
14
22
|
/** Cacheable protocol prompt (stable across turns) */
|
|
@@ -32,7 +40,10 @@ export interface ProcessOutcomeResult {
|
|
|
32
40
|
}
|
|
33
41
|
export declare class PsycheEngine {
|
|
34
42
|
private state;
|
|
35
|
-
private
|
|
43
|
+
private storage;
|
|
44
|
+
/** Whether the algorithm applied a stimulus in the last processInput call */
|
|
45
|
+
private _lastAlgorithmApplied;
|
|
46
|
+
private readonly traits;
|
|
36
47
|
private readonly cfg;
|
|
37
48
|
private readonly protocolCache;
|
|
38
49
|
/** Pending prediction from last processInput for auto-learning */
|
|
@@ -77,6 +88,24 @@ export declare class PsycheEngine {
|
|
|
77
88
|
* Get the cacheable protocol prompt for a locale.
|
|
78
89
|
*/
|
|
79
90
|
getProtocol(locale?: Locale): string;
|
|
91
|
+
/**
|
|
92
|
+
* End the current session: compress emotionalHistory into a rich summary
|
|
93
|
+
* stored in relationship.memory[], then clear the history.
|
|
94
|
+
* No-op if history has fewer than 2 entries.
|
|
95
|
+
*/
|
|
96
|
+
endSession(opts?: {
|
|
97
|
+
userId?: string;
|
|
98
|
+
}): Promise<void>;
|
|
80
99
|
private ensureInitialized;
|
|
81
100
|
private createDefaultState;
|
|
101
|
+
/**
|
|
102
|
+
* Reset state to baseline. Optionally preserves relationships.
|
|
103
|
+
*/
|
|
104
|
+
resetState(opts?: {
|
|
105
|
+
preserveRelationships?: boolean;
|
|
106
|
+
}): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Get a single-line status summary with emoji.
|
|
109
|
+
*/
|
|
110
|
+
getStatusSummary(): string;
|
|
82
111
|
}
|