psyche-ai 11.6.1 → 11.7.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/dist/core.d.ts +4 -0
- package/dist/core.js +49 -1
- package/dist/proprioception.d.ts +20 -0
- package/dist/proprioception.js +104 -0
- package/openclaw.plugin.json +1 -1
- package/package.json +1 -1
package/dist/core.d.ts
CHANGED
|
@@ -142,6 +142,10 @@ export declare class PsycheEngine {
|
|
|
142
142
|
private readonly feedbackUrl;
|
|
143
143
|
/** Most recent legacy compatibility hint + confidence band */
|
|
144
144
|
private lastCompatibilityAssessment;
|
|
145
|
+
/** Proprioception cooldown — turns remaining before next trajectory check */
|
|
146
|
+
private proprioceptionCooldown;
|
|
147
|
+
/** Last detected trajectory signal (in-memory only, for status summary) */
|
|
148
|
+
private lastTrajectory;
|
|
145
149
|
constructor(config: PsycheEngineConfig | undefined, storage: StorageAdapter);
|
|
146
150
|
/**
|
|
147
151
|
* Load or create initial state. Must be called before processInput/processOutput.
|
package/dist/core.js
CHANGED
|
@@ -35,6 +35,7 @@ import { buildTurnObservability } from "./observability.js";
|
|
|
35
35
|
import { DEFAULT_RELATIONSHIP_USER_ID, resolveRelationshipUserId } from "./relationship-key.js";
|
|
36
36
|
import { normalizeAmbientPriors } from "./ambient-priors.js";
|
|
37
37
|
import { normalizeWritebackSignals } from "./writeback-signals.js";
|
|
38
|
+
import { detectTrajectory } from "./proprioception.js";
|
|
38
39
|
function formatWritebackFeedbackNote(feedback, locale) {
|
|
39
40
|
const top = feedback?.[0];
|
|
40
41
|
if (!top)
|
|
@@ -143,6 +144,10 @@ export class PsycheEngine {
|
|
|
143
144
|
feedbackUrl;
|
|
144
145
|
/** Most recent legacy compatibility hint + confidence band */
|
|
145
146
|
lastCompatibilityAssessment = null;
|
|
147
|
+
/** Proprioception cooldown — turns remaining before next trajectory check */
|
|
148
|
+
proprioceptionCooldown = 0;
|
|
149
|
+
/** Last detected trajectory signal (in-memory only, for status summary) */
|
|
150
|
+
lastTrajectory = null;
|
|
146
151
|
constructor(config = {}, storage) {
|
|
147
152
|
this.traits = config.traits;
|
|
148
153
|
this.classifier = config.classifier ?? new BuiltInClassifier();
|
|
@@ -377,6 +382,44 @@ export class PsycheEngine {
|
|
|
377
382
|
if (appliedStimulus) {
|
|
378
383
|
state = applyRelationshipDrift(state, appliedStimulus, opts?.userId);
|
|
379
384
|
}
|
|
385
|
+
// ── Proprioception: self-trajectory awareness ──────────
|
|
386
|
+
if (this.proprioceptionCooldown > 0) {
|
|
387
|
+
this.proprioceptionCooldown--;
|
|
388
|
+
}
|
|
389
|
+
else {
|
|
390
|
+
const trajectory = detectTrajectory(state.stateHistory ?? [], state.baseline);
|
|
391
|
+
this.lastTrajectory = trajectory;
|
|
392
|
+
if (trajectory.kind === "decline" || trajectory.kind === "spiral") {
|
|
393
|
+
// Gentle awareness nudge — not correction, just noticing
|
|
394
|
+
if (trajectory.stabilize) {
|
|
395
|
+
state = {
|
|
396
|
+
...state,
|
|
397
|
+
current: {
|
|
398
|
+
...state.current,
|
|
399
|
+
order: clamp(state.current.order + (trajectory.stabilize.order ?? 0)),
|
|
400
|
+
flow: clamp(state.current.flow + (trajectory.stabilize.flow ?? 0)),
|
|
401
|
+
boundary: clamp(state.current.boundary + (trajectory.stabilize.boundary ?? 0)),
|
|
402
|
+
resonance: clamp(state.current.resonance + (trajectory.stabilize.resonance ?? 0)),
|
|
403
|
+
},
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
this.proprioceptionCooldown = 3;
|
|
407
|
+
}
|
|
408
|
+
else if (trajectory.kind === "growth" && trajectory.baselineShift) {
|
|
409
|
+
// Growth detected — shift baseline upward
|
|
410
|
+
const shift = trajectory.baselineShift;
|
|
411
|
+
state = {
|
|
412
|
+
...state,
|
|
413
|
+
baseline: {
|
|
414
|
+
order: clamp(state.baseline.order + (shift.order ?? 0)),
|
|
415
|
+
flow: clamp(state.baseline.flow + (shift.flow ?? 0)),
|
|
416
|
+
boundary: clamp(state.baseline.boundary + (shift.boundary ?? 0)),
|
|
417
|
+
resonance: clamp(state.baseline.resonance + (shift.resonance ?? 0)),
|
|
418
|
+
},
|
|
419
|
+
};
|
|
420
|
+
this.proprioceptionCooldown = 3;
|
|
421
|
+
}
|
|
422
|
+
}
|
|
380
423
|
this.lastCompatibilityAssessment = {
|
|
381
424
|
legacyStimulus: appliedStimulus,
|
|
382
425
|
confidence: perception.confidence,
|
|
@@ -953,7 +996,12 @@ export class PsycheEngine {
|
|
|
953
996
|
const driveWarning = hungryDrives.length > 0
|
|
954
997
|
? ` | \u26A0\uFE0F${hungryDrives.join(",")}`
|
|
955
998
|
: "";
|
|
999
|
+
// Proprioception: surface trajectory awareness
|
|
1000
|
+
const trajectory = this.lastTrajectory ?? detectTrajectory(state.stateHistory ?? [], state.baseline);
|
|
1001
|
+
const trajectoryNote = trajectory.description
|
|
1002
|
+
? ` | \u{1F9ED}${trajectory.description}`
|
|
1003
|
+
: "";
|
|
956
1004
|
const sigilTag = state.meta.sigilId ? ` | sigil:${state.meta.sigilId}` : "";
|
|
957
|
-
return `${emoji} ${emotion} | flow:${Math.round(flow)} order:${Math.round(order)}${driveWarning}${sigilTag}`;
|
|
1005
|
+
return `${emoji} ${emotion} | flow:${Math.round(flow)} order:${Math.round(order)}${driveWarning}${trajectoryNote}${sigilTag}`;
|
|
958
1006
|
}
|
|
959
1007
|
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { SelfState, StateSnapshot } from "./types.js";
|
|
2
|
+
export interface TrajectorySignal {
|
|
3
|
+
/** null = no signal, system is fine */
|
|
4
|
+
kind: "decline" | "growth" | "spiral" | null;
|
|
5
|
+
/** Which dimensions triggered the signal */
|
|
6
|
+
dimensions: (keyof SelfState)[];
|
|
7
|
+
/** Signal strength, 0–1 */
|
|
8
|
+
magnitude: number;
|
|
9
|
+
/** Gentle state nudge for decline/spiral (additive) */
|
|
10
|
+
stabilize: Partial<Record<keyof SelfState, number>> | null;
|
|
11
|
+
/** Baseline shift for growth (additive) */
|
|
12
|
+
baselineShift: Partial<Record<keyof SelfState, number>> | null;
|
|
13
|
+
/** One-line description for status summary */
|
|
14
|
+
description: string | null;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Detect trajectory patterns from recent state history.
|
|
18
|
+
* Pure function — no side effects, no persistence.
|
|
19
|
+
*/
|
|
20
|
+
export declare function detectTrajectory(history: StateSnapshot[], baseline: SelfState): TrajectorySignal;
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Proprioception — Self-Trajectory Awareness
|
|
3
|
+
//
|
|
4
|
+
// Perception turned inward. The system perceives its own state
|
|
5
|
+
// trajectory as input, the same way it perceives external stimuli.
|
|
6
|
+
//
|
|
7
|
+
// Two signals:
|
|
8
|
+
// decline/spiral → gentle awareness (order↑1, boundary↑1)
|
|
9
|
+
// growth → baseline upshift (10% of sustained gain)
|
|
10
|
+
//
|
|
11
|
+
// Not a monitor. Not a correction. Just: the system can see itself.
|
|
12
|
+
// ============================================================
|
|
13
|
+
import { DIMENSION_KEYS } from "./types.js";
|
|
14
|
+
// ── Constants ───────────────────────────────────────────────
|
|
15
|
+
/** Minimum snapshots needed to detect a trajectory */
|
|
16
|
+
const MIN_WINDOW = 4;
|
|
17
|
+
/** Per-step change threshold to count as meaningful decline */
|
|
18
|
+
const DECLINE_STEP = -1;
|
|
19
|
+
/** Per-step change threshold to count as meaningful growth */
|
|
20
|
+
const GROWTH_STEP = 1;
|
|
21
|
+
/** Maximum stabilization nudge per dimension (awareness, not correction) */
|
|
22
|
+
const STABILIZE_MAX = 1.5;
|
|
23
|
+
/** Fraction of sustained gain that becomes new baseline */
|
|
24
|
+
const GROWTH_BASELINE_RATIO = 0.1;
|
|
25
|
+
const NO_SIGNAL = {
|
|
26
|
+
kind: null, dimensions: [], magnitude: 0,
|
|
27
|
+
stabilize: null, baselineShift: null, description: null,
|
|
28
|
+
};
|
|
29
|
+
// ── Core ────────────────────────────────────────────────────
|
|
30
|
+
/**
|
|
31
|
+
* Detect trajectory patterns from recent state history.
|
|
32
|
+
* Pure function — no side effects, no persistence.
|
|
33
|
+
*/
|
|
34
|
+
export function detectTrajectory(history, baseline) {
|
|
35
|
+
if (history.length < MIN_WINDOW)
|
|
36
|
+
return NO_SIGNAL;
|
|
37
|
+
const window = history.slice(-MIN_WINDOW);
|
|
38
|
+
const declining = [];
|
|
39
|
+
const growing = [];
|
|
40
|
+
for (const dim of DIMENSION_KEYS) {
|
|
41
|
+
const values = window.map(s => s.state[dim]);
|
|
42
|
+
const deltas = [];
|
|
43
|
+
for (let i = 1; i < values.length; i++) {
|
|
44
|
+
deltas.push(values[i] - values[i - 1]);
|
|
45
|
+
}
|
|
46
|
+
if (deltas.every(d => d < DECLINE_STEP)) {
|
|
47
|
+
declining.push(dim);
|
|
48
|
+
}
|
|
49
|
+
if (deltas.every(d => d > GROWTH_STEP) && values[values.length - 1] > baseline[dim]) {
|
|
50
|
+
growing.push(dim);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// ── Spiral: 2+ dimensions declining together ──
|
|
54
|
+
if (declining.length >= 2) {
|
|
55
|
+
const totalDrop = declining.reduce((sum, dim) => {
|
|
56
|
+
const vals = window.map(s => s.state[dim]);
|
|
57
|
+
return sum + Math.abs(vals[vals.length - 1] - vals[0]);
|
|
58
|
+
}, 0);
|
|
59
|
+
const stabilize = {};
|
|
60
|
+
for (const dim of declining) {
|
|
61
|
+
stabilize[dim] = STABILIZE_MAX;
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
kind: "spiral",
|
|
65
|
+
dimensions: declining,
|
|
66
|
+
magnitude: Math.min(1, totalDrop / 40),
|
|
67
|
+
stabilize,
|
|
68
|
+
baselineShift: null,
|
|
69
|
+
description: `spiral: ${declining.join("+")} declining ${window.length} turns`,
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// ── Single dimension decline ──
|
|
73
|
+
if (declining.length === 1) {
|
|
74
|
+
const dim = declining[0];
|
|
75
|
+
const vals = window.map(s => s.state[dim]);
|
|
76
|
+
const drop = Math.abs(vals[vals.length - 1] - vals[0]);
|
|
77
|
+
return {
|
|
78
|
+
kind: "decline",
|
|
79
|
+
dimensions: declining,
|
|
80
|
+
magnitude: Math.min(1, drop / 20),
|
|
81
|
+
stabilize: { [dim]: STABILIZE_MAX * 0.5 },
|
|
82
|
+
baselineShift: null,
|
|
83
|
+
description: `${String(dim)} declining ${window.length} turns (-${drop.toFixed(1)})`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
// ── Growth: sustained increase above baseline ──
|
|
87
|
+
if (growing.length > 0) {
|
|
88
|
+
const baselineShift = {};
|
|
89
|
+
for (const dim of growing) {
|
|
90
|
+
const vals = window.map(s => s.state[dim]);
|
|
91
|
+
const gain = vals[vals.length - 1] - vals[0];
|
|
92
|
+
baselineShift[dim] = gain * GROWTH_BASELINE_RATIO;
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
kind: "growth",
|
|
96
|
+
dimensions: growing,
|
|
97
|
+
magnitude: Math.min(1, growing.length / 4),
|
|
98
|
+
stabilize: null,
|
|
99
|
+
baselineShift,
|
|
100
|
+
description: `growth: ${growing.join("+")} sustained increase`,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
return NO_SIGNAL;
|
|
104
|
+
}
|
package/openclaw.plugin.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"id": "psyche-ai",
|
|
3
3
|
"name": "Artificial Psyche",
|
|
4
4
|
"description": "AI-first subjectivity kernel for agents with continuous appraisal, relation dynamics, and adaptive reply loops",
|
|
5
|
-
"version": "11.
|
|
5
|
+
"version": "11.7.0",
|
|
6
6
|
"configSchema": {
|
|
7
7
|
"type": "object",
|
|
8
8
|
"additionalProperties": false,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "psyche-ai",
|
|
3
|
-
"version": "11.
|
|
3
|
+
"version": "11.7.0",
|
|
4
4
|
"description": "AI-first subjectivity kernel for agents with continuous appraisal, relation dynamics, and adaptive reply loops",
|
|
5
5
|
"mcpName": "io.github.Shangri-la-0428/psyche-ai",
|
|
6
6
|
"type": "module",
|