psyche-ai 9.2.4 → 9.2.6
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/vercel-ai.d.ts +1 -1
- package/dist/adapters/vercel-ai.js +1 -9
- package/dist/autonomic.js +2 -2
- package/dist/classify.js +0 -1
- package/dist/cli.js +1 -1
- package/dist/core.d.ts +1 -1
- package/dist/core.js +39 -69
- package/dist/demo.js +1 -2
- package/dist/ethics.js +1 -1
- package/dist/experiential-field.d.ts +2 -2
- package/dist/experiential-field.js +7 -16
- package/dist/generative-self.js +0 -2
- package/dist/interaction.js +0 -2
- package/dist/metacognition.d.ts +13 -1
- package/dist/metacognition.js +164 -32
- package/dist/prompt.js +17 -15
- package/dist/psyche-file.d.ts +8 -1
- package/dist/psyche-file.js +97 -3
- package/dist/relation-dynamics.d.ts +14 -1
- package/dist/relation-dynamics.js +68 -1
- package/dist/reply-envelope.d.ts +17 -0
- package/dist/reply-envelope.js +36 -0
- package/dist/response-contract.js +151 -26
- package/dist/subjectivity.d.ts +2 -2
- package/dist/subjectivity.js +21 -12
- package/dist/temporal.d.ts +2 -2
- package/dist/temporal.js +2 -2
- package/dist/types.d.ts +39 -0
- package/dist/types.js +12 -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
|
|
|
@@ -49,7 +49,7 @@ export interface PsycheMiddlewareOptions {
|
|
|
49
49
|
* for await (const chunk of stream.textStream) { process.stdout.write(chunk); }
|
|
50
50
|
* ```
|
|
51
51
|
*/
|
|
52
|
-
export declare function psycheMiddleware(engine: PsycheEngine,
|
|
52
|
+
export declare function psycheMiddleware(engine: PsycheEngine, _opts?: PsycheMiddlewareOptions): {
|
|
53
53
|
transformParams: ({ params }: {
|
|
54
54
|
type: string;
|
|
55
55
|
params: CallParams;
|
|
@@ -15,12 +15,6 @@
|
|
|
15
15
|
// - wrapGenerate: process output, strip <psyche_update> tags
|
|
16
16
|
// - wrapStream: buffer stream, detect & strip tags at end
|
|
17
17
|
// ============================================================
|
|
18
|
-
// ── Tag stripping ────────────────────────────────────────────
|
|
19
|
-
const PSYCHE_TAG_RE = /<psyche_update>[\s\S]*?<\/psyche_update>/g;
|
|
20
|
-
const MULTI_NEWLINE_RE = /\n{3,}/g;
|
|
21
|
-
function stripPsycheTags(text) {
|
|
22
|
-
return text.replace(PSYCHE_TAG_RE, "").replace(MULTI_NEWLINE_RE, "\n\n").trim();
|
|
23
|
-
}
|
|
24
18
|
/**
|
|
25
19
|
* Create Vercel AI SDK middleware that injects psyche emotional context
|
|
26
20
|
* and processes LLM output for state updates.
|
|
@@ -50,7 +44,7 @@ function stripPsycheTags(text) {
|
|
|
50
44
|
* for await (const chunk of stream.textStream) { process.stdout.write(chunk); }
|
|
51
45
|
* ```
|
|
52
46
|
*/
|
|
53
|
-
export function psycheMiddleware(engine,
|
|
47
|
+
export function psycheMiddleware(engine, _opts) {
|
|
54
48
|
return {
|
|
55
49
|
transformParams: async ({ params }) => {
|
|
56
50
|
const userText = extractLastUserText(params.prompt ?? []);
|
|
@@ -82,7 +76,6 @@ export function psycheMiddleware(engine, opts) {
|
|
|
82
76
|
const { stream: innerStream } = await doStream();
|
|
83
77
|
// Buffer text chunks, detect <psyche_update> at end, strip from output
|
|
84
78
|
let fullText = "";
|
|
85
|
-
let tagDetected = false;
|
|
86
79
|
async function* transformStream() {
|
|
87
80
|
// Buffering strategy:
|
|
88
81
|
// Stream text chunks through normally UNTIL we see '<psyche_update>'.
|
|
@@ -105,7 +98,6 @@ export function psycheMiddleware(engine, opts) {
|
|
|
105
98
|
}
|
|
106
99
|
bufferStart = tagStart;
|
|
107
100
|
buffer = fullText.substring(tagStart);
|
|
108
|
-
tagDetected = true;
|
|
109
101
|
}
|
|
110
102
|
else {
|
|
111
103
|
// Check if we might be in a partial tag (< at end)
|
package/dist/autonomic.js
CHANGED
|
@@ -66,7 +66,7 @@ const DORSAL_ALLOWED = new Set([
|
|
|
66
66
|
* No transition inertia — returns the "target" state.
|
|
67
67
|
*/
|
|
68
68
|
export function computeAutonomicState(chemistry, drives) {
|
|
69
|
-
const { CORT, NE, DA
|
|
69
|
+
const { CORT, NE, DA } = chemistry;
|
|
70
70
|
const { survival, safety, connection } = drives;
|
|
71
71
|
// Count drives that are critically low (< 20)
|
|
72
72
|
const lowDriveCount = [survival, safety, connection, drives.esteem, drives.curiosity]
|
|
@@ -136,7 +136,7 @@ export function describeAutonomicState(state, locale) {
|
|
|
136
136
|
* when your nervous system is in fight/flight/freeze mode.
|
|
137
137
|
*/
|
|
138
138
|
export function computeProcessingDepth(autonomicState, chemistry, baseline, energyBudgets) {
|
|
139
|
-
const {
|
|
139
|
+
const { CORT } = chemistry;
|
|
140
140
|
// Chemical deviation from baseline (0-1)
|
|
141
141
|
let totalDeviation = 0;
|
|
142
142
|
const keys = ["DA", "HT", "CORT", "OT", "NE", "END"];
|
package/dist/classify.js
CHANGED
|
@@ -188,7 +188,6 @@ export function analyzeParticles(text) {
|
|
|
188
188
|
}
|
|
189
189
|
export function detectIntent(text) {
|
|
190
190
|
const t = text.trim();
|
|
191
|
-
const lower = t.toLowerCase();
|
|
192
191
|
// Chinese request patterns (polite)
|
|
193
192
|
if (/^(能不能|可以|可不可以|帮我|请|麻烦|劳驾)/.test(t) || /帮我/.test(t) || /一下[吧吗??]?$/.test(t)) {
|
|
194
193
|
return { intent: "request", confidence: 0.7 };
|
package/dist/cli.js
CHANGED
|
@@ -82,7 +82,7 @@ function die(msg) {
|
|
|
82
82
|
process.exit(1);
|
|
83
83
|
}
|
|
84
84
|
// ── Commands ─────────────────────────────────────────────────
|
|
85
|
-
async function cmdInit(dir, mbti, name, lang, mode, traits,
|
|
85
|
+
async function cmdInit(dir, mbti, name, lang, mode, traits, _noPersist) {
|
|
86
86
|
const absDir = resolve(dir);
|
|
87
87
|
const opts = {};
|
|
88
88
|
if (mbti) {
|
package/dist/core.d.ts
CHANGED
|
@@ -118,7 +118,7 @@ export declare class PsycheEngine {
|
|
|
118
118
|
* @param nextUserStimulus - The stimulus detected in the user's next message,
|
|
119
119
|
* or null if the session ended.
|
|
120
120
|
*/
|
|
121
|
-
processOutcome(nextUserStimulus: StimulusType | null,
|
|
121
|
+
processOutcome(nextUserStimulus: StimulusType | null, _opts?: {
|
|
122
122
|
userId?: string;
|
|
123
123
|
}): Promise<ProcessOutcomeResult | null>;
|
|
124
124
|
/**
|
package/dist/core.js
CHANGED
|
@@ -18,13 +18,13 @@ import { classifyStimulus, BuiltInClassifier, buildLLMClassifierPrompt, parseLLM
|
|
|
18
18
|
import { buildDynamicContext, buildProtocolContext, buildCompactContext } from "./prompt.js";
|
|
19
19
|
import { getSensitivity, getBaseline, getDefaultSelfModel, traitsToBaseline } from "./profiles.js";
|
|
20
20
|
import { isStimulusType } from "./guards.js";
|
|
21
|
-
import { parsePsycheUpdate, mergeUpdates, updateAgreementStreak, pushSnapshot, compressSession, } from "./psyche-file.js";
|
|
21
|
+
import { parsePsycheUpdate, mergeUpdates, updateAgreementStreak, pushSnapshot, compressSession, summarizeTurnSemantic, } from "./psyche-file.js";
|
|
22
22
|
import { decayDrives, feedDrives, detectExistentialThreat, computeEffectiveBaseline, computeEffectiveSensitivity, } from "./drives.js";
|
|
23
23
|
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
|
-
import { assessMetacognition } from "./metacognition.js";
|
|
27
|
-
import { buildDecisionContext
|
|
26
|
+
import { assessMetacognition, updateMetacognitiveState } from "./metacognition.js";
|
|
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,8 @@ 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
|
-
import { deriveGenerationControls } from "./host-controls.js";
|
|
38
|
-
import { computeAppraisalAxes, mergeAppraisalResidue } from "./appraisal.js";
|
|
39
|
-
import { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals } from "./relation-dynamics.js";
|
|
35
|
+
import { applyRelationalTurn } from "./relation-dynamics.js";
|
|
36
|
+
import { deriveReplyEnvelope } from "./reply-envelope.js";
|
|
40
37
|
const NOOP_LOGGER = { info: () => { }, warn: () => { }, debug: () => { } };
|
|
41
38
|
const REPAIRING_STIMULI = new Set(["praise", "validation", "intimacy"]);
|
|
42
39
|
const RELATIONSHIP_DELTAS = {
|
|
@@ -193,7 +190,7 @@ export class PsycheEngine {
|
|
|
193
190
|
// All new fields are optional — no data migration needed
|
|
194
191
|
if (loaded.version < 9) {
|
|
195
192
|
loaded.version = 9;
|
|
196
|
-
console.log("\x1b[36m[Psyche]\x1b[0m 已从 v8 升级到 v9 — 新增:真实人格漂移、能量预算、习惯化、行为策略输出。详见 https://github.com/Shangri-la-0428/
|
|
193
|
+
console.log("\x1b[36m[Psyche]\x1b[0m 已从 v8 升级到 v9 — 新增:真实人格漂移、能量预算、习惯化、行为策略输出。详见 https://github.com/Shangri-la-0428/oasyce_psyche");
|
|
197
194
|
}
|
|
198
195
|
if (!loaded.dyadicFields) {
|
|
199
196
|
loaded.dyadicFields = {
|
|
@@ -341,42 +338,14 @@ export class PsycheEngine {
|
|
|
341
338
|
// v9: Deplete energy budgets from this interaction turn
|
|
342
339
|
energyBudgets = computeEnergyDepletion(energyBudgets, appliedStimulus, isExtravert);
|
|
343
340
|
state = { ...state, energyBudgets };
|
|
344
|
-
const
|
|
341
|
+
const relationalTurn = applyRelationalTurn(state, text, {
|
|
345
342
|
mode: this.cfg.mode,
|
|
343
|
+
now: now.toISOString(),
|
|
346
344
|
stimulus: appliedStimulus,
|
|
347
|
-
|
|
345
|
+
userId: opts?.userId,
|
|
348
346
|
});
|
|
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
|
-
};
|
|
347
|
+
state = relationalTurn.state;
|
|
348
|
+
const appraisalAxes = relationalTurn.appraisalAxes;
|
|
380
349
|
// Conversation warmth: sustained interaction → gentle DA/OT rise, CORT drop
|
|
381
350
|
// Simulates the natural "warm glow" of being in continuous conversation
|
|
382
351
|
const turnsSoFar = (state.emotionalHistory ?? []).length;
|
|
@@ -429,9 +398,18 @@ export class PsycheEngine {
|
|
|
429
398
|
};
|
|
430
399
|
}
|
|
431
400
|
}
|
|
401
|
+
state = {
|
|
402
|
+
...state,
|
|
403
|
+
metacognition: updateMetacognitiveState(state.metacognition, metacognitiveAssessment),
|
|
404
|
+
};
|
|
432
405
|
}
|
|
433
406
|
// Push snapshot to emotional history
|
|
434
|
-
|
|
407
|
+
const semanticSummary = text
|
|
408
|
+
? summarizeTurnSemantic(text, locale, {
|
|
409
|
+
detail: state.meta.totalInteractions + 1 > 5 ? "expanded" : "brief",
|
|
410
|
+
})
|
|
411
|
+
: undefined;
|
|
412
|
+
state = pushSnapshot(state, appliedStimulus, semanticSummary);
|
|
435
413
|
// Increment interaction count
|
|
436
414
|
state = {
|
|
437
415
|
...state,
|
|
@@ -459,7 +437,7 @@ export class PsycheEngine {
|
|
|
459
437
|
const constructionContext = {
|
|
460
438
|
autonomicState: autonomicResult.state,
|
|
461
439
|
stimulus: appliedStimulus,
|
|
462
|
-
relationshipPhase:
|
|
440
|
+
relationshipPhase: relationalTurn.relationContext.relationship.phase,
|
|
463
441
|
predictionError: state.learning.predictionHistory.length > 0
|
|
464
442
|
? state.learning.predictionHistory[state.learning.predictionHistory.length - 1].predictionError
|
|
465
443
|
: undefined,
|
|
@@ -545,20 +523,12 @@ export class PsycheEngine {
|
|
|
545
523
|
const sharedCtx = sharedState ? buildSharedIntentionalityContext(sharedState, locale) : undefined;
|
|
546
524
|
const experientialNarrative = experientialField?.narrative || undefined;
|
|
547
525
|
// v9: Compute structured policy modifiers
|
|
548
|
-
const
|
|
549
|
-
const subjectivityKernel = computeSubjectivityKernel(state, policyModifiers, appraisalAxes, opts?.userId);
|
|
550
|
-
const subjectivityCtx = buildSubjectivityContext(subjectivityKernel, locale);
|
|
551
|
-
const responseContract = computeResponseContract(subjectivityKernel, {
|
|
526
|
+
const replyEnvelope = deriveReplyEnvelope(state, appraisalAxes, {
|
|
552
527
|
locale,
|
|
553
528
|
userText: text || undefined,
|
|
554
529
|
algorithmStimulus: appliedStimulus,
|
|
555
530
|
personalityIntensity: this.cfg.personalityIntensity,
|
|
556
|
-
|
|
557
|
-
const responseContractCtx = buildResponseContractContext(responseContract, locale);
|
|
558
|
-
const policyCtx = buildPolicyContext(policyModifiers, locale, state.drives);
|
|
559
|
-
const generationControls = deriveGenerationControls({
|
|
560
|
-
responseContract,
|
|
561
|
-
policyModifiers,
|
|
531
|
+
relationContext: relationalTurn.relationContext,
|
|
562
532
|
});
|
|
563
533
|
// P10: Append processing depth info to autonomic description when depth is low
|
|
564
534
|
let autonomicDesc;
|
|
@@ -586,16 +556,16 @@ export class PsycheEngine {
|
|
|
586
556
|
autonomicDescription: autonomicDesc,
|
|
587
557
|
autonomicState: autonomicResult.state,
|
|
588
558
|
primarySystemsDescription: primarySystemsDescription || undefined,
|
|
589
|
-
subjectivityContext:
|
|
590
|
-
responseContractContext:
|
|
591
|
-
policyContext:
|
|
559
|
+
subjectivityContext: replyEnvelope.subjectivityContext,
|
|
560
|
+
responseContractContext: replyEnvelope.responseContractContext,
|
|
561
|
+
policyContext: replyEnvelope.policyContext || undefined,
|
|
592
562
|
}),
|
|
593
563
|
stimulus: appliedStimulus,
|
|
594
|
-
policyModifiers,
|
|
595
|
-
subjectivityKernel,
|
|
596
|
-
responseContract,
|
|
597
|
-
generationControls,
|
|
598
|
-
policyContext:
|
|
564
|
+
policyModifiers: replyEnvelope.policyModifiers,
|
|
565
|
+
subjectivityKernel: replyEnvelope.subjectivityKernel,
|
|
566
|
+
responseContract: replyEnvelope.responseContract,
|
|
567
|
+
generationControls: replyEnvelope.generationControls,
|
|
568
|
+
policyContext: replyEnvelope.policyContext,
|
|
599
569
|
};
|
|
600
570
|
}
|
|
601
571
|
return {
|
|
@@ -609,14 +579,14 @@ export class PsycheEngine {
|
|
|
609
579
|
autonomicDescription: autonomicDesc,
|
|
610
580
|
autonomicState: autonomicResult.state,
|
|
611
581
|
primarySystemsDescription: primarySystemsDescription || undefined,
|
|
612
|
-
policyContext:
|
|
582
|
+
policyContext: replyEnvelope.policyContext || undefined,
|
|
613
583
|
}),
|
|
614
584
|
stimulus: appliedStimulus,
|
|
615
|
-
policyModifiers,
|
|
616
|
-
subjectivityKernel,
|
|
617
|
-
responseContract,
|
|
618
|
-
generationControls,
|
|
619
|
-
policyContext:
|
|
585
|
+
policyModifiers: replyEnvelope.policyModifiers,
|
|
586
|
+
subjectivityKernel: replyEnvelope.subjectivityKernel,
|
|
587
|
+
responseContract: replyEnvelope.responseContract,
|
|
588
|
+
generationControls: replyEnvelope.generationControls,
|
|
589
|
+
policyContext: replyEnvelope.policyContext,
|
|
620
590
|
};
|
|
621
591
|
}
|
|
622
592
|
/**
|
|
@@ -718,7 +688,7 @@ export class PsycheEngine {
|
|
|
718
688
|
* @param nextUserStimulus - The stimulus detected in the user's next message,
|
|
719
689
|
* or null if the session ended.
|
|
720
690
|
*/
|
|
721
|
-
async processOutcome(nextUserStimulus,
|
|
691
|
+
async processOutcome(nextUserStimulus, _opts) {
|
|
722
692
|
if (!this.pendingPrediction)
|
|
723
693
|
return null;
|
|
724
694
|
let state = this.ensureInitialized();
|
package/dist/demo.js
CHANGED
|
@@ -127,7 +127,7 @@ function sleep(ms) {
|
|
|
127
127
|
function printLine(char = "─", width = 60) {
|
|
128
128
|
process.stdout.write(c(C.dim, char.repeat(width)) + "\n");
|
|
129
129
|
}
|
|
130
|
-
function printChemistry(prev, curr,
|
|
130
|
+
function printChemistry(prev, curr, _locale) {
|
|
131
131
|
for (const key of CHEMICAL_KEYS) {
|
|
132
132
|
const p = Math.round(prev[key]);
|
|
133
133
|
const v = Math.round(curr[key]);
|
|
@@ -201,7 +201,6 @@ export async function runDemo(opts) {
|
|
|
201
201
|
printChemistry(prevState, currState.current, locale);
|
|
202
202
|
// Emergent mood
|
|
203
203
|
const mood = describeMood(currState.current, displayLocale);
|
|
204
|
-
const emotions = detectEmotions(currState.current);
|
|
205
204
|
process.stdout.write(`\n ${c(C.dim, "mood:")} ${c(C.bold, mood)}\n`);
|
|
206
205
|
// Policy context (if non-empty)
|
|
207
206
|
if (result.policyContext) {
|
package/dist/ethics.js
CHANGED
|
@@ -240,7 +240,7 @@ function detectGaslighting(state, history) {
|
|
|
240
240
|
* When an agent has formed strong attachment and the user takes advantage
|
|
241
241
|
* of that bond through boundary-pushing behavior, this is exploitative.
|
|
242
242
|
*/
|
|
243
|
-
function detectEmotionalExploitation(
|
|
243
|
+
function detectEmotionalExploitation(_state, history, attachment) {
|
|
244
244
|
if (history.length < MIN_HISTORY_FOR_DETECTION)
|
|
245
245
|
return null;
|
|
246
246
|
if (!attachment || attachment.strength < 30)
|
|
@@ -44,7 +44,7 @@ export declare function computeAffectCore(chemistry: ChemicalState): {
|
|
|
44
44
|
* relationship context, and optional metacognitive/bias data, then
|
|
45
45
|
* synthesizes them into a single coherent experience description.
|
|
46
46
|
*/
|
|
47
|
-
export declare function computeExperientialField(state: PsycheState,
|
|
47
|
+
export declare function computeExperientialField(state: PsycheState, _metacognition?: MetacognitiveAssessment, _decisionBias?: DecisionBiasVector, context?: ConstructionContext): ExperientialField;
|
|
48
48
|
/**
|
|
49
49
|
* Measure internal alignment across subsystems.
|
|
50
50
|
*
|
|
@@ -65,5 +65,5 @@ interface UnnamedEmotion {
|
|
|
65
65
|
* emotions in chemistry.ts — novel experiential states that need
|
|
66
66
|
* descriptive phrases rather than labels.
|
|
67
67
|
*/
|
|
68
|
-
export declare function detectUnnamedEmotion(chemistry: ChemicalState, drives: InnateDrives,
|
|
68
|
+
export declare function detectUnnamedEmotion(chemistry: ChemicalState, drives: InnateDrives, _currentQuality: ExperientialQuality): UnnamedEmotion | null;
|
|
69
69
|
export {};
|
|
@@ -14,16 +14,8 @@
|
|
|
14
14
|
// ============================================================
|
|
15
15
|
import { CHEMICAL_KEYS, DRIVE_KEYS } from "./types.js";
|
|
16
16
|
// ── Constants ────────────────────────────────────────────────
|
|
17
|
-
/** Baseline reference point — a "perfectly neutral" chemistry */
|
|
18
|
-
const NEUTRAL_CHEMISTRY = {
|
|
19
|
-
DA: 50, HT: 50, CORT: 50, OT: 50, NE: 50, END: 50,
|
|
20
|
-
};
|
|
21
17
|
/** Threshold below which a drive counts as "hungry" */
|
|
22
18
|
const DRIVE_HUNGRY_THRESHOLD = 40;
|
|
23
|
-
/** Threshold above which a chemical is "elevated" */
|
|
24
|
-
const CHEM_HIGH = 65;
|
|
25
|
-
/** Threshold below which a chemical is "depleted" */
|
|
26
|
-
const CHEM_LOW = 35;
|
|
27
19
|
/** If total activation is below this, the state is "flat/numb" */
|
|
28
20
|
const FLATNESS_THRESHOLD = 0.15;
|
|
29
21
|
// ── Affect Core (Russell Circumplex) ─────────────────────────
|
|
@@ -73,14 +65,14 @@ const QUALITY_CONCEPTS = [
|
|
|
73
65
|
* relationship context, and optional metacognitive/bias data, then
|
|
74
66
|
* synthesizes them into a single coherent experience description.
|
|
75
67
|
*/
|
|
76
|
-
export function computeExperientialField(state,
|
|
68
|
+
export function computeExperientialField(state, _metacognition, _decisionBias, context) {
|
|
77
69
|
const locale = state.meta.locale ?? "zh";
|
|
78
70
|
const rel = state.relationships._default ?? state.relationships[Object.keys(state.relationships)[0]];
|
|
79
71
|
const coherence = computeCoherence(state.current, state.baseline, state.drives, rel);
|
|
80
72
|
const intensity = computeIntensity(state.current, state.baseline);
|
|
81
|
-
const quality = constructQuality(state, coherence, intensity, rel,
|
|
73
|
+
const quality = constructQuality(state, coherence, intensity, rel, _metacognition, context);
|
|
82
74
|
const phenomenalDescription = generatePhenomenalDescription(quality, state, coherence, intensity, locale);
|
|
83
|
-
const narrative = generateNarrative(quality, state, coherence, intensity, rel, locale,
|
|
75
|
+
const narrative = generateNarrative(quality, state, coherence, intensity, rel, locale, _metacognition);
|
|
84
76
|
return {
|
|
85
77
|
narrative,
|
|
86
78
|
quality,
|
|
@@ -110,7 +102,6 @@ export function computeCoherence(current, baseline, drives, relationship) {
|
|
|
110
102
|
coherenceScore -= rewardStressConflict * 0.4;
|
|
111
103
|
// Bonding (OT) and threat (CORT + NE) should not coexist strongly
|
|
112
104
|
const bondingSignal = current.OT / 100;
|
|
113
|
-
const threatSignal = Math.min(1, (current.CORT + current.NE) / 200);
|
|
114
105
|
const bondingThreatConflict = bondingSignal * (stressSignal > 0.55 ? stressSignal : 0);
|
|
115
106
|
coherenceScore -= bondingThreatConflict * 0.3;
|
|
116
107
|
// ── Chemistry-Drive alignment ──
|
|
@@ -188,7 +179,7 @@ function computeIntensity(current, baseline) {
|
|
|
188
179
|
* preserved as hard gates — these represent extreme conditions where
|
|
189
180
|
* the normal construction process doesn't apply.
|
|
190
181
|
*/
|
|
191
|
-
function constructQuality(state, coherence, intensity, relationship,
|
|
182
|
+
function constructQuality(state, coherence, intensity, relationship, _metacognition, context) {
|
|
192
183
|
const d = state.drives;
|
|
193
184
|
// ── Special states first (override everything) ──
|
|
194
185
|
// Numb: nothing is happening. All near baseline, low intensity.
|
|
@@ -385,7 +376,7 @@ function selectVariant(variants, intensity, coherence) {
|
|
|
385
376
|
* emotions in chemistry.ts — novel experiential states that need
|
|
386
377
|
* descriptive phrases rather than labels.
|
|
387
378
|
*/
|
|
388
|
-
export function detectUnnamedEmotion(chemistry, drives,
|
|
379
|
+
export function detectUnnamedEmotion(chemistry, drives, _currentQuality) {
|
|
389
380
|
const c = chemistry;
|
|
390
381
|
// Nostalgia-but-forward: OT high + DA moderately high + NE high
|
|
391
382
|
// (warmth for the past + excitement for what's next)
|
|
@@ -521,7 +512,7 @@ function findHungriestDrive(drives) {
|
|
|
521
512
|
return hungriest;
|
|
522
513
|
}
|
|
523
514
|
// ── Narrative Builders (locale-specific) ─────────────────────
|
|
524
|
-
function buildNarrativeEn(quality,
|
|
515
|
+
function buildNarrativeEn(quality, _trend, hungriestDrive, relWarmth, coherence, _intensity, selfDoubt) {
|
|
525
516
|
const parts = [];
|
|
526
517
|
// Opening: the quality as felt experience
|
|
527
518
|
parts.push(QUALITY_OPENINGS_EN[quality]);
|
|
@@ -545,7 +536,7 @@ function buildNarrativeEn(quality, trend, hungriestDrive, relWarmth, coherence,
|
|
|
545
536
|
}
|
|
546
537
|
return parts.join(" ");
|
|
547
538
|
}
|
|
548
|
-
function buildNarrativeZh(quality,
|
|
539
|
+
function buildNarrativeZh(quality, _trend, hungriestDrive, relWarmth, coherence, _intensity, selfDoubt) {
|
|
549
540
|
const parts = [];
|
|
550
541
|
// Opening: quality as felt experience
|
|
551
542
|
parts.push(QUALITY_OPENINGS_ZH[quality]);
|
package/dist/generative-self.js
CHANGED
|
@@ -199,7 +199,6 @@ export function detectInternalConflicts(state, locale = "en") {
|
|
|
199
199
|
*/
|
|
200
200
|
export function buildIdentityNarrative(state, insights, growthArc, locale = "en") {
|
|
201
201
|
const isZh = locale === "zh";
|
|
202
|
-
const mbti = state.mbti;
|
|
203
202
|
const parts = [];
|
|
204
203
|
// ── Sentence 1: Core personality from MBTI + chemical signature ──
|
|
205
204
|
const coreTraits = describeCoreTraits(state, isZh);
|
|
@@ -474,7 +473,6 @@ function describeCoreTraits(state, isZh) {
|
|
|
474
473
|
const isIntro = mbti[0] === "I";
|
|
475
474
|
const isIntuitive = mbti[1] === "N";
|
|
476
475
|
const isFeeling = mbti[2] === "F";
|
|
477
|
-
const isPerceiving = mbti[3] === "P";
|
|
478
476
|
// Build trait fragments based on MBTI + chemical state
|
|
479
477
|
const fragments = [];
|
|
480
478
|
// Energy orientation
|
package/dist/interaction.js
CHANGED
|
@@ -118,8 +118,6 @@ export class PsycheInteraction {
|
|
|
118
118
|
const stateA = engineA.getState();
|
|
119
119
|
const stateB = engineB.getState();
|
|
120
120
|
// Detect dominant emotions from each engine's chemistry
|
|
121
|
-
const emotionsA = detectEmotions(stateA.current);
|
|
122
|
-
const emotionsB = detectEmotions(stateB.current);
|
|
123
121
|
// Classify dominant emotion into a stimulus type for contagion
|
|
124
122
|
const stimA = this.dominantEmotionAsStimulus(stateA.current);
|
|
125
123
|
const stimB = this.dominantEmotionAsStimulus(stateB.current);
|
package/dist/metacognition.d.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type { PsycheState, StimulusType, ChemicalState, OutcomeScore, MetacognitiveState, RegulationStrategyType, DefenseMechanismType } from "./types.js";
|
|
1
|
+
import type { PsycheState, StimulusType, ChemicalState, OutcomeScore, MetacognitiveState, RegulationStrategyType, DefenseMechanismType, RegulationTargetMetric, RegulationFeedback } from "./types.js";
|
|
2
2
|
export interface MetacognitiveAssessment {
|
|
3
3
|
/** 0-1: how reliably has this emotional state led to good outcomes in similar contexts */
|
|
4
4
|
emotionalConfidence: number;
|
|
5
5
|
/** Suggested regulation strategies */
|
|
6
6
|
regulationSuggestions: RegulationSuggestion[];
|
|
7
|
+
/** Whether the last surfaced regulation action is working */
|
|
8
|
+
regulationFeedback: RegulationFeedback | null;
|
|
7
9
|
/** Detected psychological defense mechanisms */
|
|
8
10
|
defenseMechanisms: DetectedDefense[];
|
|
9
11
|
/** Human-readable self-awareness note for prompt injection */
|
|
@@ -12,6 +14,16 @@ export interface MetacognitiveAssessment {
|
|
|
12
14
|
export interface RegulationSuggestion {
|
|
13
15
|
strategy: RegulationStrategyType;
|
|
14
16
|
description: string;
|
|
17
|
+
/** Concrete behavioral instruction for the next few turns */
|
|
18
|
+
action: string;
|
|
19
|
+
/** How many turns this action should stay active */
|
|
20
|
+
horizonTurns?: number;
|
|
21
|
+
/** Which metric this action is trying to pull back into range */
|
|
22
|
+
targetMetric?: RegulationTargetMetric;
|
|
23
|
+
/** Target value for that metric */
|
|
24
|
+
targetValue?: number;
|
|
25
|
+
/** Initial gap between the current state and the target value */
|
|
26
|
+
gapBefore?: number;
|
|
15
27
|
/** Suggested micro-adjustment to chemistry */
|
|
16
28
|
chemistryAdjustment?: Partial<ChemicalState>;
|
|
17
29
|
/** 0-1: confidence that this strategy would help */
|