psyche-ai 9.2.5 → 9.2.7
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 +41 -11
- package/dist/adapters/http.js +24 -2
- package/dist/adapters/langchain.d.ts +4 -0
- package/dist/adapters/langchain.js +23 -1
- package/dist/adapters/mcp.js +4 -2
- package/dist/core.d.ts +15 -4
- package/dist/core.js +112 -68
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/prompt.js +2 -2
- package/dist/psyche-file.d.ts +5 -1
- package/dist/psyche-file.js +39 -1
- package/dist/relation-dynamics.d.ts +35 -1
- package/dist/relation-dynamics.js +497 -9
- package/dist/reply-envelope.d.ts +18 -0
- package/dist/reply-envelope.js +37 -0
- package/dist/response-contract.d.ts +1 -0
- package/dist/response-contract.js +47 -16
- package/dist/subjectivity.d.ts +2 -2
- package/dist/subjectivity.js +21 -12
- package/dist/types.d.ts +71 -0
- package/dist/types.js +3 -0
- package/llms.txt +1 -1
- package/package.json +16 -13
- package/server.json +1 -1
- package/README.en.md +0 -12
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
# Psyche —
|
|
1
|
+
# Psyche — 面向智能体的 AI-first 主观性内核
|
|
2
2
|
|
|
3
3
|
[](https://www.npmjs.com/package/psyche-ai)
|
|
4
|
-
[]()
|
|
5
5
|
[]()
|
|
6
6
|
[](LICENSE)
|
|
7
7
|
|
|
@@ -9,15 +9,26 @@
|
|
|
9
9
|
>
|
|
10
10
|
> 官网: [psyche.oasyce.com](https://psyche.oasyce.com)
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
Psyche 不是给模型贴一层“情绪 UI”。
|
|
13
13
|
|
|
14
|
-
|
|
14
|
+
它把持续 appraisal、关系动力学、自适应回应闭环和持久内在状态压成宿主可消费的控制面,让 AI 不是按 prompt 扮演人格,而是被状态真正改写后续几轮的行为分布。
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
**一句话:Psyche 是给智能体用的 subjectivity kernel。**
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
它不会额外调用模型做情绪推理。它只在本地计算化学状态、关系场和调节控制,然后把结果收敛成 `SubjectivityKernel`、`ResponseContract`、`GenerationControls` 这组窄 ABI。
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
## 一个项目,三个入口
|
|
21
|
+
|
|
22
|
+
- **安装包**: [`psyche-ai`](https://www.npmjs.com/package/psyche-ai)
|
|
23
|
+
- **源码仓库**: [`oasyce_psyche`](https://github.com/Shangri-la-0428/oasyce_psyche)
|
|
24
|
+
- **官网**: [psyche.oasyce.com](https://psyche.oasyce.com)
|
|
25
|
+
|
|
26
|
+
## 为什么它值得被看见
|
|
27
|
+
|
|
28
|
+
- **不是 persona prompt**:输入会留下持续主体偏置,不是一轮一清。
|
|
29
|
+
- **不是 sentiment classifier**:它建模的是连续 appraisal、关系动力学和修复摩擦。
|
|
30
|
+
- **不是纯记忆层**:它会改变后续的回应方式、长度、距离感和工作面/私人面切换。
|
|
31
|
+
- **不牺牲性能**:零额外模型调用,compact 注入约 `15-180 tokens`,热路径 quick benchmark 约 `p50 0.191ms / p95 1.05ms`。
|
|
21
32
|
|
|
22
33
|
---
|
|
23
34
|
|
|
@@ -131,8 +142,8 @@ npm view psyche-ai version
|
|
|
131
142
|
## 快速体验(不需要 LLM)
|
|
132
143
|
|
|
133
144
|
```bash
|
|
134
|
-
git clone https://github.com/Shangri-la-0428/
|
|
135
|
-
cd
|
|
145
|
+
git clone https://github.com/Shangri-la-0428/oasyce_psyche.git
|
|
146
|
+
cd oasyce_psyche && npm install && npx tsx examples/quickstart.ts
|
|
136
147
|
```
|
|
137
148
|
|
|
138
149
|
5 条消息,看化学值实时变化。夸它多巴胺飙升,骂它皮质醇飙升,冷落它催产素下降。
|
|
@@ -185,6 +196,25 @@ Psyche 现在更准确的目标,不是“模仿某种像人的风格”,而
|
|
|
185
196
|
**v8** 更像“内部丰富,但外部仍然克制”的人格中间件。
|
|
186
197
|
**v9.2** 则把目标推进到:让 AI 产生可持续、可恢复、可压制但不瞬间归零的主体偏置。
|
|
187
198
|
|
|
199
|
+
### 自适应回应闭环(v9.2.5)
|
|
200
|
+
|
|
201
|
+
在持续主体偏置之上,Psyche 又补了一层更实用的闭环:
|
|
202
|
+
|
|
203
|
+
- **双回应 profile**:自动区分 `work` / `private`,工作任务不再被私人模式的短句克制压扁
|
|
204
|
+
- **可观测依据**:`replyProfileBasis` 会告诉宿主当前为什么被判成工作面或私人面
|
|
205
|
+
- **可执行元认知**:不再只说“建议调整”,而是给出下一轮怎么降温、怎么收缩、怎么减少主动性
|
|
206
|
+
- **调节回看**:下一轮会评估上次调节是在 `converging`、`holding` 还是 `diverging`
|
|
207
|
+
- **语义记忆分层**:短对话保留一句 `semanticSummary`,长对话保留 `semanticPoints`,减少“只记住情绪,不记得聊了什么”
|
|
208
|
+
|
|
209
|
+
这让 Psyche 不只是“有内在状态”,而是开始像一个会自我调节、会回看偏差、会区分工作面和私人面的自适应系统。
|
|
210
|
+
|
|
211
|
+
在实现层,热路径也进一步收敛成两个节点:
|
|
212
|
+
|
|
213
|
+
- **ResolvedRelationContext**:每轮只解析一次当前关系视角,不再让 `core`、`subjectivity`、关系动力学各自重复 lookup
|
|
214
|
+
- **ReplyEnvelope**:把 `SubjectivityKernel`、`ResponseContract`、`GenerationControls` 统一导出成一个宿主控制面
|
|
215
|
+
|
|
216
|
+
这样做不是为了加抽象层,而是为了减少散装编排,让宿主稳定消费同一套行为 ABI。
|
|
217
|
+
|
|
188
218
|
### 内在世界
|
|
189
219
|
|
|
190
220
|
Psyche 给 AI 一个始终运转的内在自我——不是条件触发,而是每时每刻都在:
|
|
@@ -313,7 +343,7 @@ openclaw logs -f 2>&1 | grep Psyche
|
|
|
313
343
|
cat workspace-yu/psyche-state.json | python3 -m json.tool
|
|
314
344
|
|
|
315
345
|
# 诊断脚本
|
|
316
|
-
cd
|
|
346
|
+
cd oasyce_psyche && node scripts/diagnose.js
|
|
317
347
|
```
|
|
318
348
|
|
|
319
349
|
---
|
|
@@ -406,7 +436,7 @@ Psyche 核心引擎永久开源(MIT)。
|
|
|
406
436
|
```bash
|
|
407
437
|
npm install
|
|
408
438
|
npm run build
|
|
409
|
-
npm test #
|
|
439
|
+
npm test # 1291 tests
|
|
410
440
|
npm run typecheck # strict mode
|
|
411
441
|
```
|
|
412
442
|
|
package/dist/adapters/http.js
CHANGED
|
@@ -8,13 +8,31 @@
|
|
|
8
8
|
//
|
|
9
9
|
// Endpoints:
|
|
10
10
|
// POST /process-input { text, userId? } → { systemContext, dynamicContext, stimulus, policyModifiers?, subjectivityKernel?, responseContract?, generationControls?, policyContext }
|
|
11
|
-
// POST /process-output { text, userId? } → { cleanedText, stateChanged }
|
|
11
|
+
// POST /process-output { text, userId?, signals?, signalConfidence? } → { cleanedText, stateChanged }
|
|
12
12
|
// GET /state → PsycheState
|
|
13
13
|
// GET /protocol?locale=zh → { protocol }
|
|
14
14
|
//
|
|
15
15
|
// Zero dependencies — uses node:http only.
|
|
16
16
|
// ============================================================
|
|
17
17
|
import { createServer } from "node:http";
|
|
18
|
+
const VALID_WRITEBACK_SIGNALS = new Set([
|
|
19
|
+
"trust_up",
|
|
20
|
+
"trust_down",
|
|
21
|
+
"boundary_set",
|
|
22
|
+
"boundary_soften",
|
|
23
|
+
"repair_attempt",
|
|
24
|
+
"repair_landed",
|
|
25
|
+
"closeness_invite",
|
|
26
|
+
"withdrawal_mark",
|
|
27
|
+
"self_assertion",
|
|
28
|
+
"task_recenter",
|
|
29
|
+
]);
|
|
30
|
+
function parseSignals(value) {
|
|
31
|
+
if (!Array.isArray(value))
|
|
32
|
+
return undefined;
|
|
33
|
+
const parsed = value.filter((item) => (typeof item === "string" && VALID_WRITEBACK_SIGNALS.has(item)));
|
|
34
|
+
return parsed.length > 0 ? [...new Set(parsed)] : undefined;
|
|
35
|
+
}
|
|
18
36
|
// ── Server ───────────────────────────────────────────────────
|
|
19
37
|
/**
|
|
20
38
|
* Create an HTTP server that exposes PsycheEngine via REST API.
|
|
@@ -69,7 +87,11 @@ export function createPsycheServer(engine, opts) {
|
|
|
69
87
|
// POST /process-output
|
|
70
88
|
if (req.method === "POST" && url.pathname === "/process-output") {
|
|
71
89
|
const body = await readBody(req);
|
|
72
|
-
const result = await engine.processOutput(body.text ?? "", {
|
|
90
|
+
const result = await engine.processOutput(body.text ?? "", {
|
|
91
|
+
userId: body.userId,
|
|
92
|
+
signals: parseSignals(body.signals),
|
|
93
|
+
signalConfidence: typeof body.signalConfidence === "number" ? body.signalConfidence : undefined,
|
|
94
|
+
});
|
|
73
95
|
json(res, 200, result);
|
|
74
96
|
return;
|
|
75
97
|
}
|
|
@@ -28,6 +28,8 @@ import type { PsycheEngine } from "../core.js";
|
|
|
28
28
|
export declare class PsycheLangChain {
|
|
29
29
|
private readonly engine;
|
|
30
30
|
constructor(engine: PsycheEngine);
|
|
31
|
+
private readonly validSignals;
|
|
32
|
+
private parseSignals;
|
|
31
33
|
/**
|
|
32
34
|
* Get the system message to inject into the LLM call.
|
|
33
35
|
* Combines the protocol (cacheable) and dynamic context (per-turn).
|
|
@@ -59,5 +61,7 @@ export declare class PsycheLangChain {
|
|
|
59
61
|
*/
|
|
60
62
|
processResponse(text: string, opts?: {
|
|
61
63
|
userId?: string;
|
|
64
|
+
signals?: string[];
|
|
65
|
+
signalConfidence?: number;
|
|
62
66
|
}): Promise<string>;
|
|
63
67
|
}
|
|
@@ -43,6 +43,24 @@ export class PsycheLangChain {
|
|
|
43
43
|
constructor(engine) {
|
|
44
44
|
this.engine = engine;
|
|
45
45
|
}
|
|
46
|
+
validSignals = new Set([
|
|
47
|
+
"trust_up",
|
|
48
|
+
"trust_down",
|
|
49
|
+
"boundary_set",
|
|
50
|
+
"boundary_soften",
|
|
51
|
+
"repair_attempt",
|
|
52
|
+
"repair_landed",
|
|
53
|
+
"closeness_invite",
|
|
54
|
+
"withdrawal_mark",
|
|
55
|
+
"self_assertion",
|
|
56
|
+
"task_recenter",
|
|
57
|
+
]);
|
|
58
|
+
parseSignals(signals) {
|
|
59
|
+
if (!signals)
|
|
60
|
+
return undefined;
|
|
61
|
+
const parsed = signals.filter((signal) => this.validSignals.has(signal));
|
|
62
|
+
return parsed.length > 0 ? [...new Set(parsed)] : undefined;
|
|
63
|
+
}
|
|
46
64
|
/**
|
|
47
65
|
* Get the system message to inject into the LLM call.
|
|
48
66
|
* Combines the protocol (cacheable) and dynamic context (per-turn).
|
|
@@ -80,7 +98,11 @@ export class PsycheLangChain {
|
|
|
80
98
|
* Call this AFTER the LLM invocation, before showing output to the user.
|
|
81
99
|
*/
|
|
82
100
|
async processResponse(text, opts) {
|
|
83
|
-
const result = await this.engine.processOutput(text,
|
|
101
|
+
const result = await this.engine.processOutput(text, {
|
|
102
|
+
userId: opts?.userId,
|
|
103
|
+
signals: this.parseSignals(opts?.signals),
|
|
104
|
+
signalConfidence: opts?.signalConfidence,
|
|
105
|
+
});
|
|
84
106
|
return result.cleanedText;
|
|
85
107
|
}
|
|
86
108
|
}
|
package/dist/adapters/mcp.js
CHANGED
|
@@ -174,9 +174,11 @@ server.tool("process_output", "Process the LLM's response through the emotional
|
|
|
174
174
|
"emotional contagion. Call this AFTER generating a response.", {
|
|
175
175
|
text: z.string().describe("The LLM's response text"),
|
|
176
176
|
userId: z.string().optional().describe("Optional user ID"),
|
|
177
|
-
|
|
177
|
+
signals: z.array(z.string()).optional().describe("Optional sparse writeback signals from the host"),
|
|
178
|
+
signalConfidence: z.number().min(0).max(1).optional().describe("Optional confidence for the supplied signals"),
|
|
179
|
+
}, async ({ text, userId, signals, signalConfidence }) => {
|
|
178
180
|
const eng = await getEngine();
|
|
179
|
-
const result = await eng.processOutput(text, { userId });
|
|
181
|
+
const result = await eng.processOutput(text, { userId, signals: signals, signalConfidence });
|
|
180
182
|
return {
|
|
181
183
|
content: [{
|
|
182
184
|
type: "text",
|
package/dist/core.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PsycheState, StimulusType, Locale, MBTIType, OutcomeScore, PsycheMode, PersonalityTraits, PolicyModifiers, ClassifierProvider, SubjectivityKernel, ResponseContract, GenerationControls } from "./types.js";
|
|
1
|
+
import type { PsycheState, StimulusType, Locale, MBTIType, OutcomeScore, PsycheMode, PersonalityTraits, PolicyModifiers, ClassifierProvider, SubjectivityKernel, ResponseContract, GenerationControls, SessionBridgeState, WritebackCalibrationFeedback, WritebackSignalType } from "./types.js";
|
|
2
2
|
import type { StorageAdapter } from "./storage.js";
|
|
3
3
|
import type { DiagnosticReport, SessionMetrics } from "./diagnostics.js";
|
|
4
4
|
export interface PsycheEngineConfig {
|
|
@@ -36,6 +36,8 @@ export interface ProcessInputResult {
|
|
|
36
36
|
dynamicContext: string;
|
|
37
37
|
/** Detected stimulus type from user input, null if none */
|
|
38
38
|
stimulus: StimulusType | null;
|
|
39
|
+
/** Confidence of the primary algorithmic stimulus guess, if any */
|
|
40
|
+
stimulusConfidence?: number;
|
|
39
41
|
/** v9: Structured behavioral policy modifiers — machine-readable "off baseline" signals */
|
|
40
42
|
policyModifiers?: PolicyModifiers;
|
|
41
43
|
/** v9.3: Compact machine-readable subjective state for AI-first hosts */
|
|
@@ -44,6 +46,10 @@ export interface ProcessInputResult {
|
|
|
44
46
|
responseContract?: ResponseContract;
|
|
45
47
|
/** v9.3: Mechanical host controls derived from the reply envelope */
|
|
46
48
|
generationControls?: GenerationControls;
|
|
49
|
+
/** v9.2.7: cold-start carry derived from persisted relation state */
|
|
50
|
+
sessionBridge?: SessionBridgeState | null;
|
|
51
|
+
/** v9.2.8: sparse writeback signals evaluated on the latest turn */
|
|
52
|
+
writebackFeedback?: WritebackCalibrationFeedback[];
|
|
47
53
|
/**
|
|
48
54
|
* v9: Ready-to-use LLM prompt fragment summarizing current behavioral policy.
|
|
49
55
|
*
|
|
@@ -65,6 +71,11 @@ export interface ProcessOutputResult {
|
|
|
65
71
|
/** Whether chemistry was meaningfully updated (contagion or psyche_update) */
|
|
66
72
|
stateChanged: boolean;
|
|
67
73
|
}
|
|
74
|
+
export interface ProcessOutputOptions {
|
|
75
|
+
userId?: string;
|
|
76
|
+
signals?: WritebackSignalType[];
|
|
77
|
+
signalConfidence?: number;
|
|
78
|
+
}
|
|
68
79
|
export interface ProcessOutcomeResult {
|
|
69
80
|
/** Outcome evaluation score (-1 to 1) */
|
|
70
81
|
outcomeScore: OutcomeScore;
|
|
@@ -89,6 +100,8 @@ export declare class PsycheEngine {
|
|
|
89
100
|
private lastReport;
|
|
90
101
|
/** URL for auto-submitting diagnostic reports */
|
|
91
102
|
private readonly feedbackUrl;
|
|
103
|
+
/** Most recent algorithmic stimulus read + confidence band */
|
|
104
|
+
private lastStimulusAssessment;
|
|
92
105
|
constructor(config: PsycheEngineConfig | undefined, storage: StorageAdapter);
|
|
93
106
|
/**
|
|
94
107
|
* Load or create initial state. Must be called before processInput/processOutput.
|
|
@@ -105,9 +118,7 @@ export declare class PsycheEngine {
|
|
|
105
118
|
* Phase 2: Process LLM output text.
|
|
106
119
|
* Parses <psyche_update> tags, applies contagion, strips tags.
|
|
107
120
|
*/
|
|
108
|
-
processOutput(text: string, opts?:
|
|
109
|
-
userId?: string;
|
|
110
|
-
}): Promise<ProcessOutputResult>;
|
|
121
|
+
processOutput(text: string, opts?: ProcessOutputOptions): Promise<ProcessOutputResult>;
|
|
111
122
|
/**
|
|
112
123
|
* Phase 3 (optional): Explicitly evaluate the outcome of the last interaction.
|
|
113
124
|
*
|
package/dist/core.js
CHANGED
|
@@ -24,7 +24,7 @@ import { checkForUpdate, getPackageVersion } from "./update.js";
|
|
|
24
24
|
import { DiagnosticCollector, generateReport, formatLogEntry, submitFeedback } from "./diagnostics.js";
|
|
25
25
|
import { evaluateOutcome, computeContextHash, updateLearnedVector, predictChemistry, recordPrediction, } from "./learning.js";
|
|
26
26
|
import { assessMetacognition, updateMetacognitiveState } from "./metacognition.js";
|
|
27
|
-
import { buildDecisionContext
|
|
27
|
+
import { buildDecisionContext } from "./decision-bias.js";
|
|
28
28
|
import { computeExperientialField } from "./experiential-field.js";
|
|
29
29
|
import { computeGenerativeSelf } from "./generative-self.js";
|
|
30
30
|
import { updateSharedIntentionality, buildSharedIntentionalityContext } from "./shared-intentionality.js";
|
|
@@ -32,11 +32,18 @@ import { assessEthics, buildEthicalContext } from "./ethics.js";
|
|
|
32
32
|
import { computeCircadianModulation, computeHomeostaticPressure, computeEnergyDepletion, computeEnergyRecovery } from "./circadian.js";
|
|
33
33
|
import { computeAutonomicResult } from "./autonomic.js";
|
|
34
34
|
import { computePrimarySystems, computeSystemInteractions, gatePrimarySystemsByAutonomic, describeBehavioralTendencies, } from "./primary-systems.js";
|
|
35
|
-
import {
|
|
36
|
-
import {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
35
|
+
import { applyRelationalTurn, applySessionBridge, applyWritebackSignals, createWritebackCalibrations, evaluateWritebackCalibrations } from "./relation-dynamics.js";
|
|
36
|
+
import { deriveReplyEnvelope } from "./reply-envelope.js";
|
|
37
|
+
function formatWritebackFeedbackNote(feedback, locale) {
|
|
38
|
+
const top = feedback?.[0];
|
|
39
|
+
if (!top)
|
|
40
|
+
return undefined;
|
|
41
|
+
if (locale === "zh") {
|
|
42
|
+
const effect = top.effect === "converging" ? "收敛" : top.effect === "diverging" ? "发散" : "持平";
|
|
43
|
+
return `写回:${top.signal} ${effect}。`;
|
|
44
|
+
}
|
|
45
|
+
return `Writeback: ${top.signal} ${top.effect}.`;
|
|
46
|
+
}
|
|
40
47
|
const NOOP_LOGGER = { info: () => { }, warn: () => { }, debug: () => { } };
|
|
41
48
|
const REPAIRING_STIMULI = new Set(["praise", "validation", "intimacy"]);
|
|
42
49
|
const RELATIONSHIP_DELTAS = {
|
|
@@ -130,6 +137,8 @@ export class PsycheEngine {
|
|
|
130
137
|
lastReport = null;
|
|
131
138
|
/** URL for auto-submitting diagnostic reports */
|
|
132
139
|
feedbackUrl;
|
|
140
|
+
/** Most recent algorithmic stimulus read + confidence band */
|
|
141
|
+
lastStimulusAssessment = null;
|
|
133
142
|
constructor(config = {}, storage) {
|
|
134
143
|
this.traits = config.traits;
|
|
135
144
|
this.classifier = config.classifier ?? new BuiltInClassifier();
|
|
@@ -193,7 +202,7 @@ export class PsycheEngine {
|
|
|
193
202
|
// All new fields are optional — no data migration needed
|
|
194
203
|
if (loaded.version < 9) {
|
|
195
204
|
loaded.version = 9;
|
|
196
|
-
console.log("\x1b[36m[Psyche]\x1b[0m 已从 v8 升级到 v9 — 新增:真实人格漂移、能量预算、习惯化、行为策略输出。详见 https://github.com/Shangri-la-0428/
|
|
205
|
+
console.log("\x1b[36m[Psyche]\x1b[0m 已从 v8 升级到 v9 — 新增:真实人格漂移、能量预算、习惯化、行为策略输出。详见 https://github.com/Shangri-la-0428/oasyce_psyche");
|
|
197
206
|
}
|
|
198
207
|
if (!loaded.dyadicFields) {
|
|
199
208
|
loaded.dyadicFields = {
|
|
@@ -207,6 +216,12 @@ export class PsycheEngine {
|
|
|
207
216
|
if (!loaded.pendingRelationSignals) {
|
|
208
217
|
loaded.pendingRelationSignals = { _default: [] };
|
|
209
218
|
}
|
|
219
|
+
if (!loaded.pendingWritebackCalibrations) {
|
|
220
|
+
loaded.pendingWritebackCalibrations = [];
|
|
221
|
+
}
|
|
222
|
+
if (!loaded.lastWritebackFeedback) {
|
|
223
|
+
loaded.lastWritebackFeedback = [];
|
|
224
|
+
}
|
|
210
225
|
this.state = loaded;
|
|
211
226
|
}
|
|
212
227
|
else {
|
|
@@ -222,6 +237,8 @@ export class PsycheEngine {
|
|
|
222
237
|
*/
|
|
223
238
|
async processInput(text, opts) {
|
|
224
239
|
let state = this.ensureInitialized();
|
|
240
|
+
let sessionBridge = null;
|
|
241
|
+
let writebackFeedback = [];
|
|
225
242
|
// ── Auto-learning: evaluate previous turn's outcome ──────
|
|
226
243
|
if (this.pendingPrediction && text.length > 0) {
|
|
227
244
|
const nextClassifications = classifyStimulus(text);
|
|
@@ -264,6 +281,9 @@ export class PsycheEngine {
|
|
|
264
281
|
}
|
|
265
282
|
// P12: Track session start for homeostatic pressure
|
|
266
283
|
if (!state.sessionStartedAt) {
|
|
284
|
+
const bridged = applySessionBridge(state, { userId: opts?.userId, now: now.toISOString() });
|
|
285
|
+
state = bridged.state;
|
|
286
|
+
sessionBridge = bridged.bridge;
|
|
267
287
|
state = { ...state, sessionStartedAt: now.toISOString() };
|
|
268
288
|
}
|
|
269
289
|
// Apply homeostatic pressure (fatigue from extended sessions)
|
|
@@ -314,6 +334,7 @@ export class PsycheEngine {
|
|
|
314
334
|
}
|
|
315
335
|
}
|
|
316
336
|
const primary = classifications[0];
|
|
337
|
+
const primaryConfidence = primary?.confidence ?? 0;
|
|
317
338
|
let current = state.current;
|
|
318
339
|
if (primary && primary.confidence >= 0.5) {
|
|
319
340
|
appliedStimulus = primary.type;
|
|
@@ -337,46 +358,30 @@ export class PsycheEngine {
|
|
|
337
358
|
if (appliedStimulus) {
|
|
338
359
|
state = applyRelationshipDrift(state, appliedStimulus, opts?.userId);
|
|
339
360
|
}
|
|
361
|
+
this.lastStimulusAssessment = {
|
|
362
|
+
stimulus: primary?.type ?? null,
|
|
363
|
+
confidence: primaryConfidence,
|
|
364
|
+
overrideWindow: primaryConfidence >= 0.78 ? "narrow" : primaryConfidence >= 0.62 ? "balanced" : "wide",
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
this.lastStimulusAssessment = {
|
|
369
|
+
stimulus: null,
|
|
370
|
+
confidence: 0,
|
|
371
|
+
overrideWindow: "wide",
|
|
372
|
+
};
|
|
340
373
|
}
|
|
341
374
|
// v9: Deplete energy budgets from this interaction turn
|
|
342
375
|
energyBudgets = computeEnergyDepletion(energyBudgets, appliedStimulus, isExtravert);
|
|
343
376
|
state = { ...state, energyBudgets };
|
|
344
|
-
const
|
|
377
|
+
const relationalTurn = applyRelationalTurn(state, text, {
|
|
345
378
|
mode: this.cfg.mode,
|
|
379
|
+
now: now.toISOString(),
|
|
346
380
|
stimulus: appliedStimulus,
|
|
347
|
-
|
|
381
|
+
userId: opts?.userId,
|
|
348
382
|
});
|
|
349
|
-
state =
|
|
350
|
-
|
|
351
|
-
subjectResidue: {
|
|
352
|
-
axes: mergeAppraisalResidue(state.subjectResidue?.axes, appraisalAxes, this.cfg.mode),
|
|
353
|
-
updatedAt: now.toISOString(),
|
|
354
|
-
},
|
|
355
|
-
};
|
|
356
|
-
const dyadKey = opts?.userId ?? "_default";
|
|
357
|
-
const relationMove = computeRelationMove(text, {
|
|
358
|
-
appraisal: appraisalAxes,
|
|
359
|
-
stimulus: appliedStimulus,
|
|
360
|
-
mode: this.cfg.mode,
|
|
361
|
-
field: state.dyadicFields?.[dyadKey],
|
|
362
|
-
relationship: state.relationships[dyadKey] ?? state.relationships._default,
|
|
363
|
-
});
|
|
364
|
-
const delayedRelation = evolvePendingRelationSignals(state.pendingRelationSignals?.[dyadKey], relationMove, appraisalAxes, { mode: this.cfg.mode });
|
|
365
|
-
state = {
|
|
366
|
-
...state,
|
|
367
|
-
dyadicFields: {
|
|
368
|
-
...(state.dyadicFields ?? {}),
|
|
369
|
-
[dyadKey]: evolveDyadicField(state.dyadicFields?.[dyadKey], relationMove, appraisalAxes, {
|
|
370
|
-
mode: this.cfg.mode,
|
|
371
|
-
now: now.toISOString(),
|
|
372
|
-
delayedPressure: delayedRelation.delayedPressure,
|
|
373
|
-
}),
|
|
374
|
-
},
|
|
375
|
-
pendingRelationSignals: {
|
|
376
|
-
...(state.pendingRelationSignals ?? {}),
|
|
377
|
-
[dyadKey]: delayedRelation.signals,
|
|
378
|
-
},
|
|
379
|
-
};
|
|
383
|
+
state = relationalTurn.state;
|
|
384
|
+
const appraisalAxes = relationalTurn.appraisalAxes;
|
|
380
385
|
// Conversation warmth: sustained interaction → gentle DA/OT rise, CORT drop
|
|
381
386
|
// Simulates the natural "warm glow" of being in continuous conversation
|
|
382
387
|
const turnsSoFar = (state.emotionalHistory ?? []).length;
|
|
@@ -392,6 +397,9 @@ export class PsycheEngine {
|
|
|
392
397
|
},
|
|
393
398
|
};
|
|
394
399
|
}
|
|
400
|
+
const writebackEvaluation = evaluateWritebackCalibrations(state);
|
|
401
|
+
state = writebackEvaluation.state;
|
|
402
|
+
writebackFeedback = writebackEvaluation.feedback;
|
|
395
403
|
// ── Locale (used by multiple subsystems below) ──────────
|
|
396
404
|
const locale = state.meta.locale ?? this.cfg.locale;
|
|
397
405
|
// ── P7+P10: Autonomic nervous system + Processing depth ────
|
|
@@ -468,7 +476,7 @@ export class PsycheEngine {
|
|
|
468
476
|
const constructionContext = {
|
|
469
477
|
autonomicState: autonomicResult.state,
|
|
470
478
|
stimulus: appliedStimulus,
|
|
471
|
-
relationshipPhase:
|
|
479
|
+
relationshipPhase: relationalTurn.relationContext.relationship.phase,
|
|
472
480
|
predictionError: state.learning.predictionHistory.length > 0
|
|
473
481
|
? state.learning.predictionHistory[state.learning.predictionHistory.length - 1].predictionError
|
|
474
482
|
: undefined,
|
|
@@ -548,26 +556,22 @@ export class PsycheEngine {
|
|
|
548
556
|
this.diagnosticCollector.recordInput(appliedStimulus, appliedStimulus ? 1.0 : 0.0, state.current, appraisalAxes);
|
|
549
557
|
}
|
|
550
558
|
// Build metacognitive and decision context strings
|
|
551
|
-
const
|
|
559
|
+
const writebackNote = formatWritebackFeedbackNote(writebackFeedback, locale);
|
|
560
|
+
const metacogNote = writebackNote
|
|
561
|
+
? [writebackNote, metacognitiveAssessment?.metacognitiveNote].filter(Boolean).join("\n")
|
|
562
|
+
: metacognitiveAssessment?.metacognitiveNote;
|
|
552
563
|
const decisionCtx = buildDecisionContext(state);
|
|
553
564
|
const ethicsCtx = ethicalAssessment ? buildEthicalContext(ethicalAssessment, locale) : undefined;
|
|
554
565
|
const sharedCtx = sharedState ? buildSharedIntentionalityContext(sharedState, locale) : undefined;
|
|
555
566
|
const experientialNarrative = experientialField?.narrative || undefined;
|
|
556
567
|
// v9: Compute structured policy modifiers
|
|
557
|
-
const
|
|
558
|
-
const subjectivityKernel = computeSubjectivityKernel(state, policyModifiers, appraisalAxes, opts?.userId);
|
|
559
|
-
const subjectivityCtx = buildSubjectivityContext(subjectivityKernel, locale);
|
|
560
|
-
const responseContract = computeResponseContract(subjectivityKernel, {
|
|
568
|
+
const replyEnvelope = deriveReplyEnvelope(state, appraisalAxes, {
|
|
561
569
|
locale,
|
|
562
570
|
userText: text || undefined,
|
|
563
571
|
algorithmStimulus: appliedStimulus,
|
|
572
|
+
classificationConfidence: this.lastStimulusAssessment?.confidence,
|
|
564
573
|
personalityIntensity: this.cfg.personalityIntensity,
|
|
565
|
-
|
|
566
|
-
const responseContractCtx = buildResponseContractContext(responseContract, locale);
|
|
567
|
-
const policyCtx = buildPolicyContext(policyModifiers, locale, state.drives);
|
|
568
|
-
const generationControls = deriveGenerationControls({
|
|
569
|
-
responseContract,
|
|
570
|
-
policyModifiers,
|
|
574
|
+
relationContext: relationalTurn.relationContext,
|
|
571
575
|
});
|
|
572
576
|
// P10: Append processing depth info to autonomic description when depth is low
|
|
573
577
|
let autonomicDesc;
|
|
@@ -595,16 +599,19 @@ export class PsycheEngine {
|
|
|
595
599
|
autonomicDescription: autonomicDesc,
|
|
596
600
|
autonomicState: autonomicResult.state,
|
|
597
601
|
primarySystemsDescription: primarySystemsDescription || undefined,
|
|
598
|
-
subjectivityContext:
|
|
599
|
-
responseContractContext:
|
|
600
|
-
policyContext:
|
|
602
|
+
subjectivityContext: replyEnvelope.subjectivityContext,
|
|
603
|
+
responseContractContext: replyEnvelope.responseContractContext,
|
|
604
|
+
policyContext: replyEnvelope.policyContext || undefined,
|
|
601
605
|
}),
|
|
602
606
|
stimulus: appliedStimulus,
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
607
|
+
stimulusConfidence: this.lastStimulusAssessment?.confidence,
|
|
608
|
+
policyModifiers: replyEnvelope.policyModifiers,
|
|
609
|
+
subjectivityKernel: replyEnvelope.subjectivityKernel,
|
|
610
|
+
responseContract: replyEnvelope.responseContract,
|
|
611
|
+
generationControls: replyEnvelope.generationControls,
|
|
612
|
+
sessionBridge,
|
|
613
|
+
writebackFeedback,
|
|
614
|
+
policyContext: replyEnvelope.policyContext,
|
|
608
615
|
};
|
|
609
616
|
}
|
|
610
617
|
return {
|
|
@@ -618,14 +625,17 @@ export class PsycheEngine {
|
|
|
618
625
|
autonomicDescription: autonomicDesc,
|
|
619
626
|
autonomicState: autonomicResult.state,
|
|
620
627
|
primarySystemsDescription: primarySystemsDescription || undefined,
|
|
621
|
-
policyContext:
|
|
628
|
+
policyContext: replyEnvelope.policyContext || undefined,
|
|
622
629
|
}),
|
|
623
630
|
stimulus: appliedStimulus,
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
631
|
+
stimulusConfidence: this.lastStimulusAssessment?.confidence,
|
|
632
|
+
policyModifiers: replyEnvelope.policyModifiers,
|
|
633
|
+
subjectivityKernel: replyEnvelope.subjectivityKernel,
|
|
634
|
+
responseContract: replyEnvelope.responseContract,
|
|
635
|
+
generationControls: replyEnvelope.generationControls,
|
|
636
|
+
sessionBridge,
|
|
637
|
+
writebackFeedback,
|
|
638
|
+
policyContext: replyEnvelope.policyContext,
|
|
629
639
|
};
|
|
630
640
|
}
|
|
631
641
|
/**
|
|
@@ -684,6 +694,8 @@ export class PsycheEngine {
|
|
|
684
694
|
// Anti-sycophancy: track agreement streak
|
|
685
695
|
state = updateAgreementStreak(state, text);
|
|
686
696
|
// Parse and merge <psyche_update> from LLM output
|
|
697
|
+
let combinedSignals = [];
|
|
698
|
+
let combinedSignalConfidence = opts?.signalConfidence;
|
|
687
699
|
if (text.includes("<psyche_update>")) {
|
|
688
700
|
const parseResult = parsePsycheUpdate(text, NOOP_LOGGER);
|
|
689
701
|
if (parseResult) {
|
|
@@ -691,7 +703,8 @@ export class PsycheEngine {
|
|
|
691
703
|
stateChanged = true;
|
|
692
704
|
// LLM-assisted classification: if algorithm didn't apply a stimulus
|
|
693
705
|
// but LLM classified one, retroactively apply chemistry + drives
|
|
694
|
-
|
|
706
|
+
const overrideAllowed = this.lastStimulusAssessment?.overrideWindow !== "narrow";
|
|
707
|
+
if (parseResult.llmStimulus && (!this._lastAlgorithmApplied || overrideAllowed)) {
|
|
695
708
|
state = {
|
|
696
709
|
...state,
|
|
697
710
|
drives: feedDrives(state.drives, parseResult.llmStimulus),
|
|
@@ -699,11 +712,38 @@ export class PsycheEngine {
|
|
|
699
712
|
const effectiveSensitivity = computeEffectiveSensitivity(getSensitivity(state.mbti), state.drives, parseResult.llmStimulus, state.traitDrift);
|
|
700
713
|
state = {
|
|
701
714
|
...state,
|
|
702
|
-
current: applyStimulus(state.current, parseResult.llmStimulus, effectiveSensitivity, this.cfg.maxChemicalDelta, NOOP_LOGGER),
|
|
715
|
+
current: applyStimulus(state.current, parseResult.llmStimulus, effectiveSensitivity * (overrideAllowed && this._lastAlgorithmApplied ? 0.8 : 1), this.cfg.maxChemicalDelta, NOOP_LOGGER),
|
|
703
716
|
};
|
|
704
717
|
}
|
|
718
|
+
if (parseResult.signals && parseResult.signals.length > 0) {
|
|
719
|
+
combinedSignals.push(...parseResult.signals);
|
|
720
|
+
combinedSignalConfidence = Math.max(combinedSignalConfidence ?? 0, parseResult.signalConfidence ?? 0);
|
|
721
|
+
}
|
|
705
722
|
}
|
|
706
723
|
}
|
|
724
|
+
if (opts?.signals && opts.signals.length > 0) {
|
|
725
|
+
combinedSignals.push(...opts.signals);
|
|
726
|
+
combinedSignalConfidence = Math.max(combinedSignalConfidence ?? 0, opts.signalConfidence ?? 0);
|
|
727
|
+
}
|
|
728
|
+
if (combinedSignals.length > 0) {
|
|
729
|
+
const dedupedSignals = [...new Set(combinedSignals)];
|
|
730
|
+
const pending = createWritebackCalibrations(state, dedupedSignals, {
|
|
731
|
+
userId: opts?.userId,
|
|
732
|
+
confidence: combinedSignalConfidence,
|
|
733
|
+
});
|
|
734
|
+
state = applyWritebackSignals(state, dedupedSignals, {
|
|
735
|
+
userId: opts?.userId,
|
|
736
|
+
confidence: combinedSignalConfidence,
|
|
737
|
+
});
|
|
738
|
+
state = {
|
|
739
|
+
...state,
|
|
740
|
+
pendingWritebackCalibrations: [
|
|
741
|
+
...(state.pendingWritebackCalibrations ?? []),
|
|
742
|
+
...pending,
|
|
743
|
+
].slice(-12),
|
|
744
|
+
};
|
|
745
|
+
stateChanged = true;
|
|
746
|
+
}
|
|
707
747
|
// Persist
|
|
708
748
|
this.state = state;
|
|
709
749
|
await this.storage.save(state);
|
|
@@ -889,6 +929,8 @@ export class PsycheEngine {
|
|
|
889
929
|
},
|
|
890
930
|
},
|
|
891
931
|
pendingRelationSignals: { _default: [] },
|
|
932
|
+
pendingWritebackCalibrations: [],
|
|
933
|
+
lastWritebackFeedback: [],
|
|
892
934
|
meta: {
|
|
893
935
|
agentName: name,
|
|
894
936
|
createdAt: now,
|
|
@@ -928,6 +970,8 @@ export class PsycheEngine {
|
|
|
928
970
|
},
|
|
929
971
|
},
|
|
930
972
|
pendingRelationSignals: { _default: [] },
|
|
973
|
+
pendingWritebackCalibrations: [],
|
|
974
|
+
lastWritebackFeedback: [],
|
|
931
975
|
relationships: opts?.preserveRelationships !== false
|
|
932
976
|
? state.relationships
|
|
933
977
|
: { _default: { ...DEFAULT_RELATIONSHIP } },
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { PsycheEngine } from "./core.js";
|
|
|
2
2
|
export type { PsycheEngineConfig, ProcessInputResult, ProcessOutputResult, ProcessOutcomeResult } from "./core.js";
|
|
3
3
|
export { FileStorageAdapter, MemoryStorageAdapter } from "./storage.js";
|
|
4
4
|
export type { StorageAdapter } from "./storage.js";
|
|
5
|
-
export type { PsycheState, MBTIType, Locale, StimulusType, ChemicalState, ChemicalSnapshot, SelfModel, RelationshipState, EmpathyEntry, EmotionPattern, DriveType, InnateDrives, LearningState, LearnedVectorAdjustment, PredictionRecord, OutcomeScore, OutcomeSignals, AttachmentStyle, AttachmentData, MetacognitiveState, RegulationRecord, DefensePatternRecord, RegulationStrategyType, DefenseMechanismType, PersonhoodState, PersistedCausalInsight, GrowthDirection, PersonalityTraits, PsycheMode, PolicyModifiers, SubjectivityKernel, ResponseContract, GenerationControls, AppraisalAxes, SubjectResidue, TaskPlaneState, SubjectPlaneState, RelationPlaneState, AmbiguityPlaneState, RelationMoveType, RelationMove, OpenLoopType, OpenLoopState, PendingRelationSignalState, DyadicFieldState, TraitDriftState, EnergyBudgets, ClassifierProvider, ClassifierContext, ClassificationResult, } from "./types.js";
|
|
5
|
+
export type { PsycheState, MBTIType, Locale, StimulusType, ChemicalState, ChemicalSnapshot, SelfModel, RelationshipState, EmpathyEntry, EmotionPattern, DriveType, InnateDrives, LearningState, LearnedVectorAdjustment, PredictionRecord, OutcomeScore, OutcomeSignals, AttachmentStyle, AttachmentData, MetacognitiveState, RegulationRecord, DefensePatternRecord, RegulationStrategyType, DefenseMechanismType, PersonhoodState, PersistedCausalInsight, GrowthDirection, PersonalityTraits, PsycheMode, PolicyModifiers, SubjectivityKernel, ResponseContract, GenerationControls, AppraisalAxes, SubjectResidue, TaskPlaneState, SubjectPlaneState, RelationPlaneState, AmbiguityPlaneState, RelationMoveType, RelationMove, OpenLoopType, OpenLoopState, PendingRelationSignalState, DyadicFieldState, SessionBridgeState, WritebackSignalType, WritebackSignalWeightMap, PendingWritebackCalibration, WritebackCalibrationFeedback, WritebackCalibrationMetric, TraitDriftState, EnergyBudgets, ClassifierProvider, ClassifierContext, ClassificationResult, } from "./types.js";
|
|
6
6
|
export { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ATTACHMENT, DRIVE_KEYS, DRIVE_NAMES_ZH, DEFAULT_TRAIT_DRIFT, DEFAULT_ENERGY_BUDGETS, DEFAULT_APPRAISAL_AXES, DEFAULT_SUBJECT_RESIDUE, DEFAULT_DYADIC_FIELD, } from "./types.js";
|
|
7
7
|
export { computeSelfReflection, computeEmotionalTendency, buildSelfReflectionContext } from "./self-recognition.js";
|
|
8
8
|
export type { SelfReflection } from "./self-recognition.js";
|
|
@@ -27,7 +27,7 @@ export { computeSubjectivityKernel, buildSubjectivityContext } from "./subjectiv
|
|
|
27
27
|
export { computeResponseContract, buildResponseContractContext } from "./response-contract.js";
|
|
28
28
|
export { deriveGenerationControls } from "./host-controls.js";
|
|
29
29
|
export { computeAppraisalAxes, mergeAppraisalResidue, getResidueIntensity } from "./appraisal.js";
|
|
30
|
-
export { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals, getLoopPressure } from "./relation-dynamics.js";
|
|
30
|
+
export { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals, getLoopPressure, applySessionBridge, applyWritebackSignals, createWritebackCalibrations, evaluateWritebackCalibrations, } from "./relation-dynamics.js";
|
|
31
31
|
export { computeExperientialField, computeCoherence, detectUnnamedEmotion, computeAffectCore } from "./experiential-field.js";
|
|
32
32
|
export type { ExperientialField, ExperientialQuality, ConstructionContext } from "./experiential-field.js";
|
|
33
33
|
export { computeGenerativeSelf, predictSelfReaction, detectInternalConflicts, buildIdentityNarrative } from "./generative-self.js";
|
package/dist/index.js
CHANGED
|
@@ -38,7 +38,7 @@ export { computeSubjectivityKernel, buildSubjectivityContext } from "./subjectiv
|
|
|
38
38
|
export { computeResponseContract, buildResponseContractContext } from "./response-contract.js";
|
|
39
39
|
export { deriveGenerationControls } from "./host-controls.js";
|
|
40
40
|
export { computeAppraisalAxes, mergeAppraisalResidue, getResidueIntensity } from "./appraisal.js";
|
|
41
|
-
export { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals, getLoopPressure } from "./relation-dynamics.js";
|
|
41
|
+
export { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals, getLoopPressure, applySessionBridge, applyWritebackSignals, createWritebackCalibrations, evaluateWritebackCalibrations, } from "./relation-dynamics.js";
|
|
42
42
|
// Experiential field (P6 + P8 Barrett construction)
|
|
43
43
|
export { computeExperientialField, computeCoherence, detectUnnamedEmotion, computeAffectCore } from "./experiential-field.js";
|
|
44
44
|
// Generative self (P6)
|
package/dist/prompt.js
CHANGED
|
@@ -468,8 +468,8 @@ function buildMirrorConstraints(userText, locale) {
|
|
|
468
468
|
function buildCompactSensingContext(_userText, locale, algorithmStimulus) {
|
|
469
469
|
if (locale === "zh") {
|
|
470
470
|
return algorithmStimulus
|
|
471
|
-
? `[情绪感知] 算法初判:${algorithmStimulus}
|
|
472
|
-
: `[情绪感知]
|
|
471
|
+
? `[情绪感知] 算法初判:${algorithmStimulus};你终判。`
|
|
472
|
+
: `[情绪感知] 情绪由你终判。`;
|
|
473
473
|
}
|
|
474
474
|
return algorithmStimulus
|
|
475
475
|
? `[Emotional Sensing] Algorithm hint: ${algorithmStimulus}; final tonal read is yours.`
|