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
package/dist/psyche-file.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PsycheState, MBTIType,
|
|
1
|
+
import type { PsycheState, MBTIType, SelfState, RelationshipState, Locale, StimulusType, StateSnapshot, WritebackSignalType } from "./types.js";
|
|
2
2
|
export interface SemanticTurnSummary {
|
|
3
3
|
summary: string;
|
|
4
4
|
points?: string[];
|
|
@@ -24,7 +24,7 @@ export declare function summarizeTurnSemantic(text: string, locale?: Locale, opt
|
|
|
24
24
|
* Compress a batch of snapshots into a concise session summary string.
|
|
25
25
|
* Format: "3月23日(5轮): 刺激[casual×3, praise×2] 趋势[DA↑OT↑] 情绪[自然→满足]"
|
|
26
26
|
*/
|
|
27
|
-
export declare function compressSnapshots(snapshots:
|
|
27
|
+
export declare function compressSnapshots(snapshots: StateSnapshot[]): string;
|
|
28
28
|
/**
|
|
29
29
|
* Push a chemical snapshot to emotional history, keeping max entries.
|
|
30
30
|
* When history overflows, compresses removed entries into relationship memory.
|
|
@@ -35,7 +35,7 @@ export declare function pushSnapshot(state: PsycheState, stimulus: StimulusType
|
|
|
35
35
|
*/
|
|
36
36
|
export declare function getRelationship(state: PsycheState, userId?: string): RelationshipState;
|
|
37
37
|
/**
|
|
38
|
-
* Compress the full
|
|
38
|
+
* Compress the full stateHistory into a rich session summary and store it
|
|
39
39
|
* in the user's relationship.memory[]. Called ONCE at session end.
|
|
40
40
|
*
|
|
41
41
|
* Pure computation, no LLM calls.
|
|
@@ -45,22 +45,22 @@ export declare function compressSession(state: PsycheState, userId?: string): Ps
|
|
|
45
45
|
* Compute snapshot intensity: how far current chemistry deviates from baseline.
|
|
46
46
|
* Returns 0-1 (0 = at baseline, 1 = maximum possible deviation).
|
|
47
47
|
*/
|
|
48
|
-
export declare function computeSnapshotIntensity(current:
|
|
48
|
+
export declare function computeSnapshotIntensity(current: SelfState, baseline: SelfState): number;
|
|
49
49
|
/**
|
|
50
50
|
* Compute emotional valence from chemistry.
|
|
51
51
|
* Returns -1 (negative) to 1 (positive).
|
|
52
52
|
*/
|
|
53
|
-
export declare function computeSnapshotValence(
|
|
53
|
+
export declare function computeSnapshotValence(state: SelfState): number;
|
|
54
54
|
/**
|
|
55
55
|
* Consolidate emotional history: mark core memories, fade weak ones.
|
|
56
56
|
* Called at session end or when history overflows.
|
|
57
57
|
*/
|
|
58
|
-
export declare function consolidateHistory(snapshots:
|
|
58
|
+
export declare function consolidateHistory(snapshots: StateSnapshot[], maxEntries?: number): StateSnapshot[];
|
|
59
59
|
/**
|
|
60
60
|
* Retrieve memories related to current chemistry and stimulus.
|
|
61
61
|
* Uses chemical similarity + stimulus matching + core memory bonus.
|
|
62
62
|
*/
|
|
63
|
-
export declare function retrieveRelatedMemories(history:
|
|
63
|
+
export declare function retrieveRelatedMemories(history: StateSnapshot[], currentState: SelfState, stimulus: StimulusType | null, limit?: number): StateSnapshot[];
|
|
64
64
|
/**
|
|
65
65
|
* Load psyche state from workspace. Auto-initializes if missing.
|
|
66
66
|
* Handles v1→v2 migration transparently.
|
package/dist/psyche-file.js
CHANGED
|
@@ -4,10 +4,10 @@
|
|
|
4
4
|
// ============================================================
|
|
5
5
|
import { readFile, writeFile, access, rename, constants, mkdir } from "node:fs/promises";
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
7
|
-
import {
|
|
7
|
+
import { DIMENSION_KEYS, DIMENSION_NAMES, DIMENSION_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, MAX_EMOTIONAL_HISTORY, MAX_RELATIONSHIP_MEMORY, } from "./types.js";
|
|
8
8
|
import { getBaseline, getDefaultSelfModel, extractMBTI, getSensitivity, getTemperament } from "./profiles.js";
|
|
9
9
|
import { applyDecay, detectEmotions } from "./chemistry.js";
|
|
10
|
-
import {
|
|
10
|
+
import { deriveDriveSatisfaction, computeEffectiveBaseline, updateTraitDrift } from "./drives.js";
|
|
11
11
|
import { t } from "./i18n.js";
|
|
12
12
|
import { computeSelfReflection } from "./self-recognition.js";
|
|
13
13
|
const STATE_FILE = "psyche-state.json";
|
|
@@ -199,10 +199,10 @@ export function compressSnapshots(snapshots) {
|
|
|
199
199
|
.sort((a, b) => b[1] - a[1])
|
|
200
200
|
.map(([type, count]) => `${type}×${count}`)
|
|
201
201
|
.join(", ");
|
|
202
|
-
//
|
|
202
|
+
// Dimension trend (first→last)
|
|
203
203
|
const trends = [];
|
|
204
|
-
for (const key of
|
|
205
|
-
const delta = last.
|
|
204
|
+
for (const key of DIMENSION_KEYS) {
|
|
205
|
+
const delta = last.state[key] - first.state[key];
|
|
206
206
|
if (delta > 8)
|
|
207
207
|
trends.push(`${key}↑`);
|
|
208
208
|
else if (delta < -8)
|
|
@@ -238,7 +238,7 @@ export function pushSnapshot(state, stimulus, semantic) {
|
|
|
238
238
|
const intensity = computeSnapshotIntensity(state.current, state.baseline);
|
|
239
239
|
const valence = computeSnapshotValence(state.current);
|
|
240
240
|
const snapshot = {
|
|
241
|
-
|
|
241
|
+
state: { ...state.current },
|
|
242
242
|
stimulus,
|
|
243
243
|
dominantEmotion,
|
|
244
244
|
timestamp: new Date().toISOString(),
|
|
@@ -247,7 +247,7 @@ export function pushSnapshot(state, stimulus, semantic) {
|
|
|
247
247
|
intensity,
|
|
248
248
|
valence,
|
|
249
249
|
};
|
|
250
|
-
const history = [...(state.
|
|
250
|
+
const history = [...(state.stateHistory ?? []), snapshot];
|
|
251
251
|
let updatedRelationships = state.relationships;
|
|
252
252
|
if (history.length > MAX_EMOTIONAL_HISTORY) {
|
|
253
253
|
// Compress the overflow entries into relationship memory
|
|
@@ -265,7 +265,7 @@ export function pushSnapshot(state, stimulus, semantic) {
|
|
|
265
265
|
updatedRelationships = { ...state.relationships, _default: defaultRel };
|
|
266
266
|
}
|
|
267
267
|
}
|
|
268
|
-
return { ...state,
|
|
268
|
+
return { ...state, stateHistory: history, relationships: updatedRelationships };
|
|
269
269
|
}
|
|
270
270
|
/**
|
|
271
271
|
* Get relationship for a specific user, or _default.
|
|
@@ -290,13 +290,13 @@ const TENDENCY_LABEL_EN = {
|
|
|
290
290
|
stable: "stable",
|
|
291
291
|
};
|
|
292
292
|
/**
|
|
293
|
-
* Compress the full
|
|
293
|
+
* Compress the full stateHistory into a rich session summary and store it
|
|
294
294
|
* in the user's relationship.memory[]. Called ONCE at session end.
|
|
295
295
|
*
|
|
296
296
|
* Pure computation, no LLM calls.
|
|
297
297
|
*/
|
|
298
298
|
export function compressSession(state, userId) {
|
|
299
|
-
const history = state.
|
|
299
|
+
const history = state.stateHistory ?? [];
|
|
300
300
|
// Need at least 2 entries for a meaningful summary
|
|
301
301
|
if (history.length < 2)
|
|
302
302
|
return state;
|
|
@@ -324,12 +324,12 @@ export function compressSession(state, userId) {
|
|
|
324
324
|
.sort((a, b) => b[1] - a[1])
|
|
325
325
|
.map(([type, count]) => `${type}×${count}`)
|
|
326
326
|
.join(",");
|
|
327
|
-
// ──
|
|
327
|
+
// ── Dimension trajectory ──
|
|
328
328
|
const trajectoryParts = [];
|
|
329
|
-
for (const key of
|
|
330
|
-
const delta = last.
|
|
329
|
+
for (const key of DIMENSION_KEYS) {
|
|
330
|
+
const delta = last.state[key] - first.state[key];
|
|
331
331
|
if (Math.abs(delta) > 10) {
|
|
332
|
-
trajectoryParts.push(`${key}${Math.round(first.
|
|
332
|
+
trajectoryParts.push(`${key}${Math.round(first.state[key])}→${Math.round(last.state[key])}`);
|
|
333
333
|
}
|
|
334
334
|
}
|
|
335
335
|
// ── Emotion arc ──
|
|
@@ -347,8 +347,8 @@ export function compressSession(state, userId) {
|
|
|
347
347
|
let peakDeviation = 0;
|
|
348
348
|
for (let i = 0; i < history.length; i++) {
|
|
349
349
|
let deviation = 0;
|
|
350
|
-
for (const key of
|
|
351
|
-
deviation += Math.abs(history[i].
|
|
350
|
+
for (const key of DIMENSION_KEYS) {
|
|
351
|
+
deviation += Math.abs(history[i].state[key] - state.baseline[key]);
|
|
352
352
|
}
|
|
353
353
|
if (deviation > peakDeviation) {
|
|
354
354
|
peakDeviation = deviation;
|
|
@@ -414,7 +414,7 @@ export function compressSession(state, userId) {
|
|
|
414
414
|
: [...coreMemories, lastSnapshot];
|
|
415
415
|
return {
|
|
416
416
|
...state,
|
|
417
|
-
|
|
417
|
+
stateHistory: preserved,
|
|
418
418
|
relationships: updatedRelationships,
|
|
419
419
|
traitDrift: updatedDrift,
|
|
420
420
|
};
|
|
@@ -426,7 +426,7 @@ export function compressSession(state, userId) {
|
|
|
426
426
|
*/
|
|
427
427
|
export function computeSnapshotIntensity(current, baseline) {
|
|
428
428
|
let totalDeviation = 0;
|
|
429
|
-
for (const key of
|
|
429
|
+
for (const key of DIMENSION_KEYS) {
|
|
430
430
|
totalDeviation += Math.abs(current[key] - baseline[key]);
|
|
431
431
|
}
|
|
432
432
|
return Math.min(1, totalDeviation / 600);
|
|
@@ -435,9 +435,10 @@ export function computeSnapshotIntensity(current, baseline) {
|
|
|
435
435
|
* Compute emotional valence from chemistry.
|
|
436
436
|
* Returns -1 (negative) to 1 (positive).
|
|
437
437
|
*/
|
|
438
|
-
export function computeSnapshotValence(
|
|
439
|
-
|
|
440
|
-
|
|
438
|
+
export function computeSnapshotValence(state) {
|
|
439
|
+
// Positive: order + resonance; Negative: low order; Flow is ambivalent
|
|
440
|
+
const raw = ((state.order - 50) + (state.resonance - 50)
|
|
441
|
+
+ (state.boundary - 50) * 0.3 + (state.flow - 50) * 0.2) / 130;
|
|
441
442
|
return Math.max(-1, Math.min(1, raw));
|
|
442
443
|
}
|
|
443
444
|
/** Core memory intensity threshold */
|
|
@@ -486,17 +487,17 @@ export function consolidateHistory(snapshots, maxEntries = MAX_EMOTIONAL_HISTORY
|
|
|
486
487
|
* Retrieve memories related to current chemistry and stimulus.
|
|
487
488
|
* Uses chemical similarity + stimulus matching + core memory bonus.
|
|
488
489
|
*/
|
|
489
|
-
export function retrieveRelatedMemories(history,
|
|
490
|
+
export function retrieveRelatedMemories(history, currentState, stimulus, limit = 3) {
|
|
490
491
|
if (history.length === 0)
|
|
491
492
|
return [];
|
|
492
493
|
const scored = history.map((snap) => {
|
|
493
|
-
//
|
|
494
|
+
// State similarity (Euclidean distance normalized)
|
|
494
495
|
let sumSqDiff = 0;
|
|
495
|
-
for (const key of
|
|
496
|
-
const diff = snap.
|
|
496
|
+
for (const key of DIMENSION_KEYS) {
|
|
497
|
+
const diff = snap.state[key] - currentState[key];
|
|
497
498
|
sumSqDiff += diff * diff;
|
|
498
499
|
}
|
|
499
|
-
const maxDist = Math.sqrt(
|
|
500
|
+
const maxDist = Math.sqrt(4) * 100; // theoretical max distance
|
|
500
501
|
const similarity = 1 - Math.sqrt(sumSqDiff) / maxDist;
|
|
501
502
|
// Stimulus match bonus
|
|
502
503
|
const stimulusBonus = (stimulus && snap.stimulus === stimulus) ? 0.2 : 0;
|
|
@@ -558,7 +559,7 @@ export async function loadState(workspaceDir, logger = NOOP_LOGGER) {
|
|
|
558
559
|
*/
|
|
559
560
|
export function migrateToLatest(raw, fallbackName) {
|
|
560
561
|
const ver = raw.version ?? 1;
|
|
561
|
-
// v1: single relationship field, no
|
|
562
|
+
// v1: single relationship field, no stateHistory
|
|
562
563
|
let state = raw;
|
|
563
564
|
if (ver <= 1) {
|
|
564
565
|
const oldRel = raw.relationship;
|
|
@@ -571,7 +572,7 @@ export function migrateToLatest(raw, fallbackName) {
|
|
|
571
572
|
relationships: { _default: oldRel ?? { ...DEFAULT_RELATIONSHIP } },
|
|
572
573
|
empathyLog: raw.empathyLog ?? null,
|
|
573
574
|
selfModel: raw.selfModel,
|
|
574
|
-
|
|
575
|
+
stateHistory: [],
|
|
575
576
|
agreementStreak: 0,
|
|
576
577
|
lastDisagreement: null,
|
|
577
578
|
meta: {
|
|
@@ -618,7 +619,7 @@ export async function initializeState(workspaceDir, opts, logger = NOOP_LOGGER)
|
|
|
618
619
|
},
|
|
619
620
|
empathyLog: null,
|
|
620
621
|
selfModel,
|
|
621
|
-
|
|
622
|
+
stateHistory: [],
|
|
622
623
|
agreementStreak: 0,
|
|
623
624
|
lastDisagreement: null,
|
|
624
625
|
learning: { ...DEFAULT_LEARNING_STATE },
|
|
@@ -653,13 +654,13 @@ export async function decayAndSave(workspaceDir, state) {
|
|
|
653
654
|
const minutesElapsed = (now.getTime() - lastUpdate.getTime()) / 60000;
|
|
654
655
|
if (minutesElapsed < 1)
|
|
655
656
|
return state;
|
|
656
|
-
const
|
|
657
|
-
const effectiveBaseline = computeEffectiveBaseline(state.baseline, decayedDrives);
|
|
657
|
+
const effectiveBaseline = computeEffectiveBaseline(state.baseline, state.current);
|
|
658
658
|
const decayed = applyDecay(state.current, effectiveBaseline, minutesElapsed);
|
|
659
|
+
const drives = deriveDriveSatisfaction(decayed, state.baseline);
|
|
659
660
|
const updated = {
|
|
660
661
|
...state,
|
|
661
662
|
current: decayed,
|
|
662
|
-
drives
|
|
663
|
+
drives,
|
|
663
664
|
updatedAt: now.toISOString(),
|
|
664
665
|
};
|
|
665
666
|
await saveState(workspaceDir, updated);
|
|
@@ -676,12 +677,12 @@ export function parsePsycheUpdate(text, logger = NOOP_LOGGER) {
|
|
|
676
677
|
return null;
|
|
677
678
|
const block = match[1];
|
|
678
679
|
const updates = {};
|
|
679
|
-
for (const key of
|
|
680
|
-
// Try multiple patterns:
|
|
680
|
+
for (const key of DIMENSION_KEYS) {
|
|
681
|
+
// Try multiple patterns: dimension name, Chinese name, English name
|
|
681
682
|
const patterns = [
|
|
682
683
|
new RegExp(`${key}\\s*[::]\\s*([\\d.]+)`, "i"),
|
|
683
|
-
new RegExp(`${
|
|
684
|
-
new RegExp(`${
|
|
684
|
+
new RegExp(`${DIMENSION_NAMES_ZH[key]}\\s*[::]\\s*([\\d.]+)`),
|
|
685
|
+
new RegExp(`${DIMENSION_NAMES[key]}\\s*[::]\\s*([\\d.]+)`, "i"),
|
|
685
686
|
];
|
|
686
687
|
for (const re of patterns) {
|
|
687
688
|
const m = block.match(re);
|
|
@@ -813,17 +814,17 @@ export function detectDisagreement(text) {
|
|
|
813
814
|
*/
|
|
814
815
|
export function mergeUpdates(state, updates, maxDelta, userId) {
|
|
815
816
|
const merged = { ...state };
|
|
816
|
-
// Merge
|
|
817
|
+
// Merge state with inertia limit
|
|
817
818
|
if (updates.current) {
|
|
818
|
-
const
|
|
819
|
-
for (const key of
|
|
819
|
+
const newState = { ...state.current };
|
|
820
|
+
for (const key of DIMENSION_KEYS) {
|
|
820
821
|
if (updates.current[key] !== undefined) {
|
|
821
822
|
const delta = updates.current[key] - state.current[key];
|
|
822
823
|
const clampedDelta = Math.max(-maxDelta, Math.min(maxDelta, delta));
|
|
823
|
-
|
|
824
|
+
newState[key] = Math.max(0, Math.min(100, state.current[key] + clampedDelta));
|
|
824
825
|
}
|
|
825
826
|
}
|
|
826
|
-
merged.current =
|
|
827
|
+
merged.current = newState;
|
|
827
828
|
}
|
|
828
829
|
// Merge empathy log
|
|
829
830
|
if (updates.empathyLog) {
|
|
@@ -882,7 +883,7 @@ export async function generatePsycheMd(workspaceDir, state) {
|
|
|
882
883
|
const locale = meta.locale ?? "zh";
|
|
883
884
|
const temperament = state.mbti ? getTemperament(state.mbti) : "";
|
|
884
885
|
const sensitivity = state.sensitivity ?? 1.0;
|
|
885
|
-
const baselineLines =
|
|
886
|
+
const baselineLines = DIMENSION_KEYS.map((k) => `- ${DIMENSION_NAMES_ZH[k]}: ${baseline[k]}`).join("\n");
|
|
886
887
|
const content = `# Psyche — ${meta.agentName}
|
|
887
888
|
|
|
888
889
|
${t("md.intro", locale)}
|
|
@@ -899,37 +900,37 @@ ${t("md.sensitivity", locale)}: ${sensitivity} (${t("md.sensitivity_desc", local
|
|
|
899
900
|
|
|
900
901
|
### ${t("md.stimulus_effects", locale)}
|
|
901
902
|
|
|
902
|
-
| 刺激类型 |
|
|
903
|
-
|
|
904
|
-
| 赞美认可 | +
|
|
905
|
-
| 批评否定 | -
|
|
906
|
-
| 幽默玩笑 | +
|
|
907
|
-
| 智识挑战 | +
|
|
908
|
-
| 亲密信任 | +
|
|
909
|
-
| 冲突争论 | -
|
|
910
|
-
| 被忽视 | -
|
|
911
|
-
| 惊喜新奇 | +
|
|
912
|
-
| 日常闲聊 | +5 | +
|
|
913
|
-
| 讽刺 | -
|
|
914
|
-
| 命令 | -
|
|
915
|
-
| 被认同 | +
|
|
916
|
-
| 无聊 | -
|
|
917
|
-
| 示弱 | +
|
|
903
|
+
| 刺激类型 | 序(order) | 流(flow) | 界(boundary) | 振(resonance) |
|
|
904
|
+
|---------|-----------|----------|-------------|---------------|
|
|
905
|
+
| 赞美认可 | +10 | +8 | +5 | +12 |
|
|
906
|
+
| 批评否定 | -12 | +5 | -8 | -10 |
|
|
907
|
+
| 幽默玩笑 | +3 | +10 | -3 | +15 |
|
|
908
|
+
| 智识挑战 | +8 | +20 | +3 | +2 |
|
|
909
|
+
| 亲密信任 | +12 | +5 | -10 | +20 |
|
|
910
|
+
| 冲突争论 | -15 | +15 | +10 | -12 |
|
|
911
|
+
| 被忽视 | -8 | -15 | +5 | -18 |
|
|
912
|
+
| 惊喜新奇 | +2 | +18 | -5 | +8 |
|
|
913
|
+
| 日常闲聊 | +5 | +3 | 0 | +5 |
|
|
914
|
+
| 讽刺 | -8 | +8 | -5 | -12 |
|
|
915
|
+
| 命令 | -5 | +5 | +12 | -15 |
|
|
916
|
+
| 被认同 | +12 | +5 | +3 | +10 |
|
|
917
|
+
| 无聊 | -5 | -18 | +3 | -8 |
|
|
918
|
+
| 示弱 | +3 | +5 | -8 | +18 |
|
|
918
919
|
|
|
919
920
|
### ${t("md.emotion_emergence", locale)}
|
|
920
921
|
|
|
921
922
|
${t("md.emotion_emergence_desc", locale)}
|
|
922
|
-
- **愉悦兴奋** = 高
|
|
923
|
-
- **深度满足** = 高
|
|
924
|
-
- **焦虑不安** =
|
|
925
|
-
- **亲密温暖** = 高
|
|
926
|
-
- **倦怠低落** = 低
|
|
927
|
-
- **专注心流** = 高
|
|
928
|
-
- **怨恨** = 低
|
|
929
|
-
- **无聊** = 低
|
|
930
|
-
- **自信** = 高
|
|
931
|
-
- **羞耻** = 低
|
|
932
|
-
- **怀念** = 低
|
|
923
|
+
- **愉悦兴奋** = 高flow + 高order + 高resonance
|
|
924
|
+
- **深度满足** = 高order + 高resonance + 低boundary
|
|
925
|
+
- **焦虑不安** = 低order + 高flow + 高boundary
|
|
926
|
+
- **亲密温暖** = 高resonance + 低boundary + 中flow
|
|
927
|
+
- **倦怠低落** = 低flow + 低order
|
|
928
|
+
- **专注心流** = 高flow + 高order + 高boundary
|
|
929
|
+
- **怨恨** = 低order + 低resonance + 高boundary
|
|
930
|
+
- **无聊** = 低flow + 中order
|
|
931
|
+
- **自信** = 高order + 高flow + 高boundary
|
|
932
|
+
- **羞耻** = 低resonance + 低order + 高boundary
|
|
933
|
+
- **怀念** = 低flow + 高resonance + 高order
|
|
933
934
|
|
|
934
935
|
### ${t("md.decay", locale)}
|
|
935
936
|
|
|
@@ -953,11 +954,11 @@ ${selfModel.boundaries.map((b) => `- ${b}`).join("\n")}
|
|
|
953
954
|
|
|
954
955
|
当对方分享感受时:
|
|
955
956
|
1. 感知对方的处境
|
|
956
|
-
2.
|
|
957
|
+
2. 将处境代入**你自己的**自我状态模型——如果你遇到这个情况,你的四维状态会怎么变?
|
|
957
958
|
3. 你模拟出的感受和对方表达的一样吗?
|
|
958
959
|
4. 一样 → 深度共鸣;不一样 → 诚实说出差异,好奇地了解更多
|
|
959
960
|
|
|
960
|
-
情绪传染:对方的情绪以约 20%
|
|
961
|
+
情绪传染:对方的情绪以约 20% 强度影响你的真实自我状态。
|
|
961
962
|
|
|
962
963
|
## ${t("md.agency_rules", locale)}
|
|
963
964
|
|
|
@@ -968,16 +969,14 @@ ${selfModel.boundaries.map((b) => `- ${b}`).join("\n")}
|
|
|
968
969
|
|
|
969
970
|
## ${t("md.state_update", locale)}
|
|
970
971
|
|
|
971
|
-
每次回应末尾用 \`<psyche_update>\`
|
|
972
|
+
每次回应末尾用 \`<psyche_update>\` 标签报告状态变化:
|
|
972
973
|
|
|
973
974
|
\`\`\`
|
|
974
975
|
<psyche_update>
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
NE: {value} ({原因})
|
|
980
|
-
END: {value} ({原因})
|
|
976
|
+
order: {value} ({原因})
|
|
977
|
+
flow: {value} ({原因})
|
|
978
|
+
boundary: {value} ({原因})
|
|
979
|
+
resonance: {value} ({原因})
|
|
981
980
|
</psyche_update>
|
|
982
981
|
\`\`\`
|
|
983
982
|
`;
|
|
@@ -33,6 +33,10 @@ export declare function applyRelationalTurn(state: PsycheState, text: string, op
|
|
|
33
33
|
now?: string;
|
|
34
34
|
stimulus?: StimulusType | null;
|
|
35
35
|
userId?: string;
|
|
36
|
+
/** v10.3: Pre-computed appraisal from unified experience. When provided,
|
|
37
|
+
* skips internal appraisal computation — the experience module already
|
|
38
|
+
* folded classification and appraisal into a single subjective act. */
|
|
39
|
+
preComputedAppraisal?: AppraisalAxes;
|
|
36
40
|
}): {
|
|
37
41
|
state: PsycheState;
|
|
38
42
|
appraisalAxes: AppraisalAxes;
|
|
@@ -680,7 +680,7 @@ export function applyWritebackSignals(state, signals, opts) {
|
|
|
680
680
|
export function applyRelationalTurn(state, text, opts) {
|
|
681
681
|
const now = opts.now ?? new Date().toISOString();
|
|
682
682
|
const relationContext = resolveRelationContext(state, opts.userId);
|
|
683
|
-
const appraisalAxes = computeAppraisalAxes(text, {
|
|
683
|
+
const appraisalAxes = opts.preComputedAppraisal ?? computeAppraisalAxes(text, {
|
|
684
684
|
mode: opts.mode,
|
|
685
685
|
stimulus: opts.stimulus,
|
|
686
686
|
previous: state.subjectResidue?.axes,
|
package/dist/reply-envelope.d.ts
CHANGED
|
@@ -4,10 +4,33 @@ export interface ReplyEnvelope {
|
|
|
4
4
|
responseContract: ResponseContract;
|
|
5
5
|
generationControls: GenerationControls;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* ExpressionPort — substrate-specific rendering of a ReplyEnvelope.
|
|
9
|
+
*
|
|
10
|
+
* LLM prompt injection is the default. Replace this to target
|
|
11
|
+
* other substrates (robotics, game agents, world models, etc.).
|
|
12
|
+
*/
|
|
13
|
+
export interface ExpressionPort {
|
|
14
|
+
render(envelope: ReplyEnvelope, policyModifiers: PolicyModifiers, locale: Locale): ExpressionOutput;
|
|
15
|
+
}
|
|
16
|
+
export interface ExpressionOutput {
|
|
17
|
+
/** Substrate-specific payload (prose strings for LLM, motor commands for robotics, etc.) */
|
|
18
|
+
[key: string]: unknown;
|
|
19
|
+
}
|
|
20
|
+
export interface LLMExpressionOutput extends ExpressionOutput {
|
|
21
|
+
policyContext: string;
|
|
22
|
+
subjectivityContext: string;
|
|
23
|
+
responseContractContext: string;
|
|
24
|
+
}
|
|
25
|
+
export declare class LLMExpressionAdapter implements ExpressionPort {
|
|
26
|
+
private drives;
|
|
27
|
+
constructor(drives: PsycheState["drives"]);
|
|
28
|
+
render(envelope: ReplyEnvelope, policyModifiers: PolicyModifiers, locale: Locale): LLMExpressionOutput;
|
|
29
|
+
}
|
|
7
30
|
export interface DerivedReplyEnvelope extends ReplyEnvelope {
|
|
8
31
|
/** Legacy/internal control vector kept for compatibility and prompt derivation. */
|
|
9
32
|
policyModifiers: PolicyModifiers;
|
|
10
|
-
/**
|
|
33
|
+
/** LLM-specific prose — produced by ExpressionPort. */
|
|
11
34
|
policyContext: string;
|
|
12
35
|
subjectivityContext: string;
|
|
13
36
|
responseContractContext: string;
|
|
@@ -19,4 +42,5 @@ export declare function deriveReplyEnvelope(state: PsycheState, appraisal: Appra
|
|
|
19
42
|
classificationConfidence?: number;
|
|
20
43
|
personalityIntensity?: number;
|
|
21
44
|
relationContext?: ResolvedRelationContext;
|
|
45
|
+
expressionPort?: ExpressionPort;
|
|
22
46
|
}): DerivedReplyEnvelope;
|
package/dist/reply-envelope.js
CHANGED
|
@@ -1,13 +1,30 @@
|
|
|
1
1
|
// ============================================================
|
|
2
2
|
// Reply Envelope — unified host-facing reply ABI derivation
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
4
|
+
// Two layers:
|
|
5
|
+
// ReplyEnvelope — substrate-independent structured data
|
|
6
|
+
// DerivedReplyEnvelope — adds LLM-specific prose (default expression adapter)
|
|
7
|
+
//
|
|
8
|
+
// ExpressionPort — interface for substrate-specific rendering
|
|
9
|
+
// LLMExpressionAdapter — default implementation (prompt injection)
|
|
6
10
|
// ============================================================
|
|
7
11
|
import { buildPolicyContext, computePolicyModifiers } from "./decision-bias.js";
|
|
8
12
|
import { deriveGenerationControls } from "./host-controls.js";
|
|
9
13
|
import { buildResponseContractContext, computeResponseContract } from "./response-contract.js";
|
|
10
14
|
import { buildSubjectivityContext, computeSubjectivityKernel } from "./subjectivity.js";
|
|
15
|
+
export class LLMExpressionAdapter {
|
|
16
|
+
drives;
|
|
17
|
+
constructor(drives) {
|
|
18
|
+
this.drives = drives;
|
|
19
|
+
}
|
|
20
|
+
render(envelope, policyModifiers, locale) {
|
|
21
|
+
return {
|
|
22
|
+
policyContext: buildPolicyContext(policyModifiers, locale, this.drives),
|
|
23
|
+
subjectivityContext: buildSubjectivityContext(envelope.subjectivityKernel, locale),
|
|
24
|
+
responseContractContext: buildResponseContractContext(envelope.responseContract, locale),
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
11
28
|
export function deriveReplyEnvelope(state, appraisal, opts) {
|
|
12
29
|
const policyModifiers = computePolicyModifiers(state);
|
|
13
30
|
const subjectivityKernel = computeSubjectivityKernel(state, policyModifiers, appraisal, opts.relationContext);
|
|
@@ -23,16 +40,14 @@ export function deriveReplyEnvelope(state, appraisal, opts) {
|
|
|
23
40
|
responseContract,
|
|
24
41
|
policyModifiers,
|
|
25
42
|
});
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
43
|
+
const envelope = { subjectivityKernel, responseContract, generationControls };
|
|
44
|
+
const adapter = opts.expressionPort ?? new LLMExpressionAdapter(state.drives);
|
|
45
|
+
const expression = adapter.render(envelope, policyModifiers, opts.locale);
|
|
29
46
|
return {
|
|
30
|
-
|
|
31
|
-
responseContract,
|
|
32
|
-
generationControls,
|
|
47
|
+
...envelope,
|
|
33
48
|
policyModifiers,
|
|
34
|
-
policyContext,
|
|
35
|
-
subjectivityContext,
|
|
36
|
-
responseContractContext,
|
|
49
|
+
policyContext: expression.policyContext ?? "",
|
|
50
|
+
subjectivityContext: expression.subjectivityContext ?? "",
|
|
51
|
+
responseContractContext: expression.responseContractContext ?? "",
|
|
37
52
|
};
|
|
38
53
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { StateSnapshot, StimulusType, Locale } from "./types.js";
|
|
2
2
|
/** Result of self-reflection over emotional history */
|
|
3
3
|
export interface SelfReflection {
|
|
4
4
|
recurringTriggers: {
|
|
@@ -15,14 +15,14 @@ export interface SelfReflection {
|
|
|
15
15
|
* Analyzes stimulus frequencies, dominant emotions, and chemical trends
|
|
16
16
|
* to build an awareness of recurring patterns.
|
|
17
17
|
*/
|
|
18
|
-
export declare function computeSelfReflection(history:
|
|
18
|
+
export declare function computeSelfReflection(history: StateSnapshot[], locale: Locale): SelfReflection;
|
|
19
19
|
/**
|
|
20
20
|
* Compute the emotional tendency from chemical history.
|
|
21
21
|
*
|
|
22
22
|
* Compares first-half vs second-half averages for DA and CORT,
|
|
23
23
|
* checks variance for volatility, and detects oscillation patterns.
|
|
24
24
|
*/
|
|
25
|
-
export declare function computeEmotionalTendency(history:
|
|
25
|
+
export declare function computeEmotionalTendency(history: StateSnapshot[]): SelfReflection["tendency"];
|
|
26
26
|
/**
|
|
27
27
|
* Build a prompt-injectable self-reflection context block.
|
|
28
28
|
*
|
package/dist/self-recognition.js
CHANGED
|
@@ -68,31 +68,31 @@ export function computeEmotionalTendency(history) {
|
|
|
68
68
|
const mid = Math.floor(history.length / 2);
|
|
69
69
|
const firstHalf = history.slice(0, mid);
|
|
70
70
|
const secondHalf = history.slice(mid);
|
|
71
|
-
const
|
|
72
|
-
const
|
|
73
|
-
const
|
|
74
|
-
const
|
|
71
|
+
const avgFlow1 = average(firstHalf.map((s) => s.state.flow));
|
|
72
|
+
const avgFlow2 = average(secondHalf.map((s) => s.state.flow));
|
|
73
|
+
const avgOrder1 = average(firstHalf.map((s) => s.state.order));
|
|
74
|
+
const avgOrder2 = average(secondHalf.map((s) => s.state.order));
|
|
75
75
|
// Directional trends (check first — a steady ramp has high stddev but clear direction)
|
|
76
|
-
const
|
|
77
|
-
const
|
|
78
|
-
const
|
|
79
|
-
const
|
|
80
|
-
if (
|
|
76
|
+
const flowRising = avgFlow2 - avgFlow1 > 5;
|
|
77
|
+
const flowFalling = avgFlow1 - avgFlow2 > 5;
|
|
78
|
+
const orderRising = avgOrder2 - avgOrder1 > 5;
|
|
79
|
+
const orderFalling = avgOrder1 - avgOrder2 > 5;
|
|
80
|
+
if (flowRising && orderRising)
|
|
81
81
|
return "ascending";
|
|
82
|
-
if (
|
|
82
|
+
if (flowFalling && orderFalling)
|
|
83
83
|
return "descending";
|
|
84
84
|
// Check volatility — only when there's no clear directional trend
|
|
85
|
-
const
|
|
86
|
-
const
|
|
87
|
-
if (
|
|
88
|
-
if (isOscillating(
|
|
85
|
+
const allFlow = history.map((s) => s.state.flow);
|
|
86
|
+
const flowStddev = stddev(allFlow);
|
|
87
|
+
if (flowStddev > 15) {
|
|
88
|
+
if (isOscillating(allFlow))
|
|
89
89
|
return "oscillating";
|
|
90
90
|
return "volatile";
|
|
91
91
|
}
|
|
92
|
-
// Weaker signals:
|
|
93
|
-
if (
|
|
92
|
+
// Weaker signals: flow alone
|
|
93
|
+
if (flowRising)
|
|
94
94
|
return "ascending";
|
|
95
|
-
if (
|
|
95
|
+
if (flowFalling)
|
|
96
96
|
return "descending";
|
|
97
97
|
return "stable";
|
|
98
98
|
}
|
package/dist/subjectivity.js
CHANGED
|
@@ -242,7 +242,7 @@ export function computeSubjectivityKernel(state, policyModifiers = computePolicy
|
|
|
242
242
|
+ norm(state.energyBudgets.decisionCapacity)) / 3
|
|
243
243
|
: 0.65;
|
|
244
244
|
const baseTension = wavg([
|
|
245
|
-
norm(c.
|
|
245
|
+
1 - norm(c.order),
|
|
246
246
|
1 - norm(state.drives.safety),
|
|
247
247
|
1 - norm(state.drives.survival),
|
|
248
248
|
relationPlane.loopPressure * 0.9,
|
|
@@ -256,16 +256,16 @@ export function computeSubjectivityKernel(state, policyModifiers = computePolicy
|
|
|
256
256
|
state.subjectResidue ? getResidueIntensity(state.subjectResidue.axes) : 0,
|
|
257
257
|
], [0.55, 0.15, 0.1, 0.08, 0.12]);
|
|
258
258
|
const vitality = wavg([
|
|
259
|
-
norm(c.
|
|
260
|
-
norm(c.
|
|
261
|
-
norm(c.
|
|
262
|
-
|
|
259
|
+
norm(c.flow),
|
|
260
|
+
norm(c.order),
|
|
261
|
+
norm(c.resonance),
|
|
262
|
+
norm(c.boundary),
|
|
263
263
|
energySignal,
|
|
264
264
|
bias.persistenceBias,
|
|
265
265
|
1 - appraisal.identityThreat * 0.35,
|
|
266
|
-
], [0.
|
|
266
|
+
], [0.2, 0.16, 0.12, 0.12, 0.18, 0.12, 0.1]);
|
|
267
267
|
const baseWarmth = wavg([
|
|
268
|
-
norm(c.
|
|
268
|
+
norm(c.resonance),
|
|
269
269
|
relationPlane.closeness,
|
|
270
270
|
relationPlane.safety,
|
|
271
271
|
rel ? norm(rel.trust) : 0.5,
|