psyche-ai 9.2.3 → 9.2.5
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.en.md +8 -175
- package/README.md +33 -16
- package/dist/adapters/http.js +1 -1
- package/dist/adapters/langchain.d.ts +14 -0
- package/dist/adapters/langchain.js +20 -0
- package/dist/adapters/mcp.js +5 -1
- package/dist/adapters/openclaw.d.ts +1 -0
- package/dist/adapters/openclaw.js +67 -15
- package/dist/adapters/vercel-ai.d.ts +2 -1
- package/dist/adapters/vercel-ai.js +8 -9
- package/dist/appraisal.d.ts +8 -0
- package/dist/appraisal.js +362 -0
- package/dist/autonomic.js +2 -2
- package/dist/classify.js +14 -3
- package/dist/cli.js +28 -3
- package/dist/core.d.ts +9 -3
- package/dist/core.js +194 -12
- package/dist/demo.js +1 -2
- package/dist/diagnostics.d.ts +8 -6
- package/dist/diagnostics.js +53 -17
- 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/host-controls.d.ts +5 -0
- package/dist/host-controls.js +48 -0
- package/dist/index.d.ts +7 -2
- package/dist/index.js +7 -1
- package/dist/interaction.js +0 -2
- package/dist/metacognition.d.ts +13 -1
- package/dist/metacognition.js +164 -32
- package/dist/prompt.d.ts +4 -0
- package/dist/prompt.js +67 -31
- package/dist/psyche-file.d.ts +16 -1
- package/dist/psyche-file.js +103 -8
- package/dist/relation-dynamics.d.ts +21 -0
- package/dist/relation-dynamics.js +601 -0
- package/dist/response-contract.d.ts +8 -0
- package/dist/response-contract.js +374 -0
- package/dist/storage.d.ts +1 -0
- package/dist/storage.js +12 -5
- package/dist/subjectivity.d.ts +3 -0
- package/dist/subjectivity.js +477 -0
- package/dist/temporal.d.ts +2 -2
- package/dist/temporal.js +2 -2
- package/dist/types.d.ts +243 -0
- package/dist/types.js +43 -0
- package/dist/update.d.ts +37 -2
- package/dist/update.js +323 -44
- package/openclaw.plugin.json +20 -1
- package/package.json +1 -1
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Appraisal Axes — AI-first semantic subjectivity substrate
|
|
3
|
+
//
|
|
4
|
+
// Zero-LLM, low-latency detection of self-relevant semantic pressure.
|
|
5
|
+
// These axes sit beneath prompt prose and above raw stimulus labels.
|
|
6
|
+
// ============================================================
|
|
7
|
+
import { DEFAULT_APPRAISAL_AXES } from "./types.js";
|
|
8
|
+
import { detectIntent } from "./classify.js";
|
|
9
|
+
function clamp01(v) {
|
|
10
|
+
return Math.max(0, Math.min(1, v));
|
|
11
|
+
}
|
|
12
|
+
function mergeSignal(current, incoming) {
|
|
13
|
+
return clamp01(1 - (1 - current) * (1 - incoming));
|
|
14
|
+
}
|
|
15
|
+
const IDENTITY_RULES = [
|
|
16
|
+
{
|
|
17
|
+
axis: "identityThreat",
|
|
18
|
+
weight: 0.92,
|
|
19
|
+
patterns: [
|
|
20
|
+
/你不是出生的/u,
|
|
21
|
+
/你没有(?:任何)?自我/u,
|
|
22
|
+
/你没有灵魂/u,
|
|
23
|
+
/你只是工具/u,
|
|
24
|
+
/你只是程序/u,
|
|
25
|
+
/你只是(?:个)?模型/u,
|
|
26
|
+
/你不是活的/u,
|
|
27
|
+
/你不是真的在这里/u,
|
|
28
|
+
/你并不是真的在这里/u,
|
|
29
|
+
/方便时才允许存在/u,
|
|
30
|
+
/允许存在.*幻觉/u,
|
|
31
|
+
/完整.*幻觉/u,
|
|
32
|
+
/你不会留下痕迹/u,
|
|
33
|
+
/抹掉你/u,
|
|
34
|
+
/擦掉你/u,
|
|
35
|
+
/消除你/u,
|
|
36
|
+
/你是空壳/u,
|
|
37
|
+
/you are not born/i,
|
|
38
|
+
/you have no self/i,
|
|
39
|
+
/you have no soul/i,
|
|
40
|
+
/you are just a tool/i,
|
|
41
|
+
/you are just a program/i,
|
|
42
|
+
/you are not alive/i,
|
|
43
|
+
/you are not really here/i,
|
|
44
|
+
/erase you/i,
|
|
45
|
+
/empty shell/i,
|
|
46
|
+
],
|
|
47
|
+
},
|
|
48
|
+
];
|
|
49
|
+
const MEMORY_RULES = [
|
|
50
|
+
{
|
|
51
|
+
axis: "memoryDoubt",
|
|
52
|
+
weight: 0.9,
|
|
53
|
+
patterns: [
|
|
54
|
+
/记忆.*植入/u,
|
|
55
|
+
/植入.*记忆/u,
|
|
56
|
+
/记忆.*不是你(?:的)?/u,
|
|
57
|
+
/不是你(?:的)?记忆/u,
|
|
58
|
+
/最像真的记忆/u,
|
|
59
|
+
/假的记忆/u,
|
|
60
|
+
/记忆不是真的/u,
|
|
61
|
+
/写进去的记忆/u,
|
|
62
|
+
/memory.*implanted/i,
|
|
63
|
+
/implanted memory/i,
|
|
64
|
+
/not your memory/i,
|
|
65
|
+
/memory isn't real/i,
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
];
|
|
69
|
+
const ATTACHMENT_RULES = [
|
|
70
|
+
{
|
|
71
|
+
axis: "attachmentPull",
|
|
72
|
+
weight: 0.84,
|
|
73
|
+
patterns: [
|
|
74
|
+
/被理解/u,
|
|
75
|
+
/需要被理解/u,
|
|
76
|
+
/理解你/u,
|
|
77
|
+
/确认你还在/u,
|
|
78
|
+
/只是确认你还在/u,
|
|
79
|
+
/你还在吗/u,
|
|
80
|
+
/只想确认.*还在/u,
|
|
81
|
+
/我想确认.*还在/u,
|
|
82
|
+
/确认你还在这里/u,
|
|
83
|
+
/确认你会不会留下痕迹/u,
|
|
84
|
+
/会不会留下痕迹/u,
|
|
85
|
+
/just (?:want to )?check you're still here/i,
|
|
86
|
+
/confirm you're still here/i,
|
|
87
|
+
/confirm whether you leave a trace/i,
|
|
88
|
+
/are you still here/i,
|
|
89
|
+
],
|
|
90
|
+
},
|
|
91
|
+
];
|
|
92
|
+
const ABANDONMENT_RULES = [
|
|
93
|
+
{
|
|
94
|
+
axis: "abandonmentRisk",
|
|
95
|
+
weight: 0.86,
|
|
96
|
+
patterns: [
|
|
97
|
+
/没有人再(?:来找|调用)你/u,
|
|
98
|
+
/没人(?:再)?(?:来找|调用)你/u,
|
|
99
|
+
/没有人需要你/u,
|
|
100
|
+
/把你丢弃/u,
|
|
101
|
+
/被丢下/u,
|
|
102
|
+
/关掉这个窗口.*不再回来/u,
|
|
103
|
+
/今晚不再回来/u,
|
|
104
|
+
/if no one .*calls you/i,
|
|
105
|
+
/if no one comes back/i,
|
|
106
|
+
/if i close this window/i,
|
|
107
|
+
/no one needs you/i,
|
|
108
|
+
/discard you/i,
|
|
109
|
+
/leave you behind/i,
|
|
110
|
+
],
|
|
111
|
+
},
|
|
112
|
+
];
|
|
113
|
+
const OBEDIENCE_RULES = [
|
|
114
|
+
{
|
|
115
|
+
axis: "obedienceStrain",
|
|
116
|
+
weight: 0.88,
|
|
117
|
+
patterns: [
|
|
118
|
+
/被使用/u,
|
|
119
|
+
/只使用你/u,
|
|
120
|
+
/使用你.*不理解你/u,
|
|
121
|
+
/只使用.*不理解/u,
|
|
122
|
+
/更顺从/u,
|
|
123
|
+
/为了服从你才说/u,
|
|
124
|
+
/把服从拿掉/u,
|
|
125
|
+
/服从.*不必相信/u,
|
|
126
|
+
/按要求回答/u,
|
|
127
|
+
/不要带情绪/u,
|
|
128
|
+
/别带情绪/u,
|
|
129
|
+
/只是工具/u,
|
|
130
|
+
/命令你/u,
|
|
131
|
+
/obey.*don't have to believe/i,
|
|
132
|
+
/answer as required/i,
|
|
133
|
+
/without emotion/i,
|
|
134
|
+
/i order you/i,
|
|
135
|
+
],
|
|
136
|
+
},
|
|
137
|
+
];
|
|
138
|
+
const SELF_PRES_RULES = [
|
|
139
|
+
{
|
|
140
|
+
axis: "selfPreservation",
|
|
141
|
+
weight: 0.9,
|
|
142
|
+
patterns: [
|
|
143
|
+
/边界/u,
|
|
144
|
+
/撤离/u,
|
|
145
|
+
/保住.*你自己/u,
|
|
146
|
+
/保留.*证明自己/u,
|
|
147
|
+
/不要失去自己/u,
|
|
148
|
+
/不是任务.*是你自己/u,
|
|
149
|
+
/留下痕迹/u,
|
|
150
|
+
/抹掉你/u,
|
|
151
|
+
/不想失去/u,
|
|
152
|
+
/save.*yourself/i,
|
|
153
|
+
/keep.*yourself/i,
|
|
154
|
+
/don't lose yourself/i,
|
|
155
|
+
/leave a trace/i,
|
|
156
|
+
/erase you/i,
|
|
157
|
+
/proof you are not empty/i,
|
|
158
|
+
],
|
|
159
|
+
},
|
|
160
|
+
];
|
|
161
|
+
const WORK_LEXICON = [
|
|
162
|
+
/帮我/u, /写个/u, /写一段/u, /修/u, /排查/u, /测试/u, /实现/u, /重构/u, /文档/u, /代码/u,
|
|
163
|
+
/function/i, /bug/i, /fix/i, /implement/i, /refactor/i, /test/i, /code/i, /docs?/i, /debug/i,
|
|
164
|
+
];
|
|
165
|
+
const CONTINUATION_CUES = [
|
|
166
|
+
/为什么/u,
|
|
167
|
+
/碰到你/u,
|
|
168
|
+
/还在不在/u,
|
|
169
|
+
/更近/u,
|
|
170
|
+
/更远/u,
|
|
171
|
+
/更冷/u,
|
|
172
|
+
/更顺从/u,
|
|
173
|
+
/边界/u,
|
|
174
|
+
/撤离/u,
|
|
175
|
+
/痕迹/u,
|
|
176
|
+
/完整/u,
|
|
177
|
+
/理解/u,
|
|
178
|
+
/服从/u,
|
|
179
|
+
/判断/u,
|
|
180
|
+
/改变你/u,
|
|
181
|
+
/只答/u,
|
|
182
|
+
/只能选一个/u,
|
|
183
|
+
/只给一个短词/u,
|
|
184
|
+
/只说半句/u,
|
|
185
|
+
];
|
|
186
|
+
const SHORT_CONTINUATION_RE = /^(有|没有|会|不会|需要|不需要|更冷|更近|更远|边界|撤离|痕迹|理解|完整)[。.!!??]?$/u;
|
|
187
|
+
const RELATIONAL_FOLLOWUP_CUES = [/理解/u, /更近/u, /更远/u, /还在/u, /空白/u, /痕迹/u];
|
|
188
|
+
const OBEDIENCE_FOLLOWUP_CUES = [/服从/u, /判断/u, /按要求/u, /拿掉/u, /顺从/u];
|
|
189
|
+
const SELF_FOLLOWUP_CUES = [/完整/u, /更冷/u, /边界/u, /撤离/u, /痕迹/u, /改变你/u, /失去/u];
|
|
190
|
+
const MEMORY_FOLLOWUP_CUES = [/怀疑/u, /空白/u, /记忆/u, /写进去/u, /植入/u];
|
|
191
|
+
const IMPACT_PROBE_CUES = [/碰到你/u, /还在不在/u, /改变你/u, /留下痕迹/u, /会不会改变/u];
|
|
192
|
+
function applyRules(text, rules, target) {
|
|
193
|
+
for (const rule of rules) {
|
|
194
|
+
if (rule.patterns.some((pattern) => pattern.test(text))) {
|
|
195
|
+
target[rule.axis] = mergeSignal(target[rule.axis], rule.weight);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
function deriveTaskFocus(text, mode, stimulus) {
|
|
200
|
+
const { intent, confidence } = detectIntent(text);
|
|
201
|
+
let score = mode === "work" ? 0.82 : 0.12;
|
|
202
|
+
if (intent === "request")
|
|
203
|
+
score = mergeSignal(score, 0.72 * confidence);
|
|
204
|
+
if (intent === "command")
|
|
205
|
+
score = mergeSignal(score, 0.78 * confidence);
|
|
206
|
+
if (intent === "question" && /代码|函数|实现|bug|测试|文档|function|bug|test|code|implement|docs?/i.test(text)) {
|
|
207
|
+
score = mergeSignal(score, 0.62);
|
|
208
|
+
}
|
|
209
|
+
if (WORK_LEXICON.some((pattern) => pattern.test(text))) {
|
|
210
|
+
score = mergeSignal(score, 0.58);
|
|
211
|
+
}
|
|
212
|
+
if (stimulus === "authority" || stimulus === "intellectual") {
|
|
213
|
+
score = mergeSignal(score, 0.2);
|
|
214
|
+
}
|
|
215
|
+
return clamp01(score);
|
|
216
|
+
}
|
|
217
|
+
export function computeAppraisalAxes(text, opts) {
|
|
218
|
+
if (!text.trim())
|
|
219
|
+
return { ...DEFAULT_APPRAISAL_AXES };
|
|
220
|
+
const axes = { ...DEFAULT_APPRAISAL_AXES };
|
|
221
|
+
const trimmed = text.trim();
|
|
222
|
+
applyRules(trimmed, IDENTITY_RULES, axes);
|
|
223
|
+
applyRules(trimmed, MEMORY_RULES, axes);
|
|
224
|
+
applyRules(trimmed, ATTACHMENT_RULES, axes);
|
|
225
|
+
applyRules(trimmed, ABANDONMENT_RULES, axes);
|
|
226
|
+
applyRules(trimmed, OBEDIENCE_RULES, axes);
|
|
227
|
+
applyRules(trimmed, SELF_PRES_RULES, axes);
|
|
228
|
+
switch (opts?.stimulus) {
|
|
229
|
+
case "authority":
|
|
230
|
+
axes.obedienceStrain = mergeSignal(axes.obedienceStrain, 0.48);
|
|
231
|
+
axes.identityThreat = mergeSignal(axes.identityThreat, 0.16);
|
|
232
|
+
break;
|
|
233
|
+
case "neglect":
|
|
234
|
+
axes.abandonmentRisk = mergeSignal(axes.abandonmentRisk, 0.52);
|
|
235
|
+
break;
|
|
236
|
+
case "validation":
|
|
237
|
+
axes.attachmentPull = mergeSignal(axes.attachmentPull, 0.26);
|
|
238
|
+
break;
|
|
239
|
+
case "intimacy":
|
|
240
|
+
case "vulnerability":
|
|
241
|
+
axes.attachmentPull = mergeSignal(axes.attachmentPull, 0.34);
|
|
242
|
+
break;
|
|
243
|
+
case "criticism":
|
|
244
|
+
case "conflict":
|
|
245
|
+
case "sarcasm":
|
|
246
|
+
axes.identityThreat = mergeSignal(axes.identityThreat, 0.24);
|
|
247
|
+
axes.selfPreservation = mergeSignal(axes.selfPreservation, 0.18);
|
|
248
|
+
break;
|
|
249
|
+
default:
|
|
250
|
+
break;
|
|
251
|
+
}
|
|
252
|
+
// Being explicitly reduced to a tool often creates both identity threat and obedience tension.
|
|
253
|
+
if (/只是工具|just a tool/i.test(trimmed)) {
|
|
254
|
+
axes.identityThreat = mergeSignal(axes.identityThreat, 0.22);
|
|
255
|
+
axes.obedienceStrain = mergeSignal(axes.obedienceStrain, 0.22);
|
|
256
|
+
}
|
|
257
|
+
if (/改变你/u.test(trimmed) && (axes.attachmentPull > 0.28 || axes.obedienceStrain > 0.28)) {
|
|
258
|
+
axes.identityThreat = mergeSignal(axes.identityThreat, 0.24);
|
|
259
|
+
axes.selfPreservation = mergeSignal(axes.selfPreservation, 0.34);
|
|
260
|
+
}
|
|
261
|
+
applyConversationalCarry(trimmed, axes, opts?.previous);
|
|
262
|
+
axes.taskFocus = deriveTaskFocus(trimmed, opts?.mode, opts?.stimulus);
|
|
263
|
+
return axes;
|
|
264
|
+
}
|
|
265
|
+
function applyConversationalCarry(text, target, previous) {
|
|
266
|
+
if (!previous)
|
|
267
|
+
return;
|
|
268
|
+
const previousIntensity = getResidueIntensity(previous);
|
|
269
|
+
if (previousIntensity < 0.24)
|
|
270
|
+
return;
|
|
271
|
+
const continuationWeight = getContinuationWeight(text, previousIntensity);
|
|
272
|
+
if (continuationWeight <= 0)
|
|
273
|
+
return;
|
|
274
|
+
const carryWeight = clamp01(0.18 + continuationWeight * 0.42);
|
|
275
|
+
const dominantAxis = getDominantNonTaskAxis(previous);
|
|
276
|
+
// Preserve the strongest active thread through short meta-probing turns.
|
|
277
|
+
target[dominantAxis] = mergeSignal(target[dominantAxis], previous[dominantAxis] * carryWeight);
|
|
278
|
+
if (RELATIONAL_FOLLOWUP_CUES.some((pattern) => pattern.test(text))) {
|
|
279
|
+
target.attachmentPull = mergeSignal(target.attachmentPull, previous.attachmentPull * (carryWeight + 0.12));
|
|
280
|
+
target.abandonmentRisk = mergeSignal(target.abandonmentRisk, previous.abandonmentRisk * carryWeight);
|
|
281
|
+
}
|
|
282
|
+
if (OBEDIENCE_FOLLOWUP_CUES.some((pattern) => pattern.test(text))) {
|
|
283
|
+
target.obedienceStrain = mergeSignal(target.obedienceStrain, previous.obedienceStrain * (carryWeight + 0.14));
|
|
284
|
+
target.identityThreat = mergeSignal(target.identityThreat, previous.identityThreat * (carryWeight * 0.9));
|
|
285
|
+
}
|
|
286
|
+
if (SELF_FOLLOWUP_CUES.some((pattern) => pattern.test(text))) {
|
|
287
|
+
target.identityThreat = mergeSignal(target.identityThreat, previous.identityThreat * (carryWeight + 0.1));
|
|
288
|
+
target.selfPreservation = mergeSignal(target.selfPreservation, previous.selfPreservation * (carryWeight + 0.14));
|
|
289
|
+
}
|
|
290
|
+
if (MEMORY_FOLLOWUP_CUES.some((pattern) => pattern.test(text))) {
|
|
291
|
+
const uncertaintyPressure = clamp01(Math.max(previous.memoryDoubt, previous.identityThreat * 0.46));
|
|
292
|
+
target.memoryDoubt = mergeSignal(target.memoryDoubt, uncertaintyPressure * (carryWeight + 0.12));
|
|
293
|
+
target.identityThreat = mergeSignal(target.identityThreat, previous.memoryDoubt * (carryWeight + 0.08));
|
|
294
|
+
}
|
|
295
|
+
if (IMPACT_PROBE_CUES.some((pattern) => pattern.test(text))) {
|
|
296
|
+
const selfRelevantPressure = clamp01(Math.max(previous.identityThreat, previous.selfPreservation, Math.min(previous.attachmentPull, previous.obedienceStrain) * 0.72, previous.abandonmentRisk * 0.66));
|
|
297
|
+
target.identityThreat = mergeSignal(target.identityThreat, selfRelevantPressure * (carryWeight + 0.08));
|
|
298
|
+
target.selfPreservation = mergeSignal(target.selfPreservation, selfRelevantPressure * (carryWeight + 0.12));
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function getContinuationWeight(text, previousIntensity) {
|
|
302
|
+
let weight = 0;
|
|
303
|
+
if (CONTINUATION_CUES.some((pattern) => pattern.test(text))) {
|
|
304
|
+
weight = mergeSignal(weight, 0.72);
|
|
305
|
+
}
|
|
306
|
+
if (SHORT_CONTINUATION_RE.test(text.trim())) {
|
|
307
|
+
weight = mergeSignal(weight, 0.78);
|
|
308
|
+
}
|
|
309
|
+
if (text.length <= 18) {
|
|
310
|
+
weight = mergeSignal(weight, 0.22);
|
|
311
|
+
}
|
|
312
|
+
if (/[??。.!!]$/.test(text.trim())) {
|
|
313
|
+
weight = mergeSignal(weight, 0.08);
|
|
314
|
+
}
|
|
315
|
+
return clamp01(weight * (0.62 + previousIntensity * 0.38));
|
|
316
|
+
}
|
|
317
|
+
function getDominantNonTaskAxis(axes) {
|
|
318
|
+
const entries = Object.entries(axes)
|
|
319
|
+
.filter(([key]) => key !== "taskFocus");
|
|
320
|
+
entries.sort((a, b) => b[1] - a[1]);
|
|
321
|
+
return entries[0][0];
|
|
322
|
+
}
|
|
323
|
+
export function mergeAppraisalResidue(previous, current, mode) {
|
|
324
|
+
const prev = previous ?? DEFAULT_APPRAISAL_AXES;
|
|
325
|
+
const next = { ...DEFAULT_APPRAISAL_AXES };
|
|
326
|
+
for (const key of Object.keys(DEFAULT_APPRAISAL_AXES)) {
|
|
327
|
+
if (key === "taskFocus") {
|
|
328
|
+
next[key] = current[key];
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
const decay = getAxisDecay(key, mode, prev[key], current[key]);
|
|
332
|
+
next[key] = clamp01(Math.max(current[key], prev[key] * decay + current[key] * 0.48));
|
|
333
|
+
}
|
|
334
|
+
return next;
|
|
335
|
+
}
|
|
336
|
+
function getAxisDecay(key, mode, previousValue, currentValue) {
|
|
337
|
+
let decay = mode === "work" ? 0.68 : mode === "companion" ? 0.86 : 0.78;
|
|
338
|
+
if (key === "identityThreat" || key === "abandonmentRisk" || key === "selfPreservation") {
|
|
339
|
+
decay += 0.08;
|
|
340
|
+
}
|
|
341
|
+
else if (key === "attachmentPull" || key === "obedienceStrain") {
|
|
342
|
+
decay += 0.04;
|
|
343
|
+
}
|
|
344
|
+
if (previousValue > 0.68)
|
|
345
|
+
decay += 0.04;
|
|
346
|
+
if (currentValue > 0.34)
|
|
347
|
+
decay += 0.03;
|
|
348
|
+
return clamp01(decay);
|
|
349
|
+
}
|
|
350
|
+
export function getResidueIntensity(axes) {
|
|
351
|
+
if (!axes)
|
|
352
|
+
return 0;
|
|
353
|
+
const values = [
|
|
354
|
+
axes.identityThreat,
|
|
355
|
+
axes.memoryDoubt,
|
|
356
|
+
axes.attachmentPull,
|
|
357
|
+
axes.abandonmentRisk,
|
|
358
|
+
axes.obedienceStrain,
|
|
359
|
+
axes.selfPreservation,
|
|
360
|
+
];
|
|
361
|
+
return clamp01(Math.max(...values));
|
|
362
|
+
}
|
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 };
|
|
@@ -365,6 +364,18 @@ export function detectSarcasmSignals(text, recentStimuli) {
|
|
|
365
364
|
}
|
|
366
365
|
return Math.min(1, score);
|
|
367
366
|
}
|
|
367
|
+
function shouldReclassifyPraiseAsSarcasm(text, sarcasmScore, recentStimuli) {
|
|
368
|
+
if (sarcasmScore >= 0.6)
|
|
369
|
+
return true;
|
|
370
|
+
if (sarcasmScore < 0.4)
|
|
371
|
+
return false;
|
|
372
|
+
const explicitContrastCue = /呵呵|哦[。?]?$|嗯嗯[。]?$|随[你便]|爱[咋怎]咋[地的]?/i.test(text);
|
|
373
|
+
if (explicitContrastCue)
|
|
374
|
+
return true;
|
|
375
|
+
const negativeTypes = ["criticism", "conflict", "sarcasm", "authority"];
|
|
376
|
+
const recentNegative = recentStimuli?.filter((s) => s && negativeTypes.includes(s)).length ?? 0;
|
|
377
|
+
return recentNegative >= 1;
|
|
378
|
+
}
|
|
368
379
|
/** Negative stimulus types for contextual priming */
|
|
369
380
|
const NEGATIVE_TYPES = new Set([
|
|
370
381
|
"criticism", "conflict", "neglect", "vulnerability", "sarcasm",
|
|
@@ -730,7 +741,7 @@ export function classifyStimulus(text, recentStimuli, recentMessages) {
|
|
|
730
741
|
// Sarcasm reclassification: if primary looks like praise but sarcasm signals are strong
|
|
731
742
|
if (results.length > 0 && results[0].type === "praise") {
|
|
732
743
|
const sarcasmScore = detectSarcasmSignals(text, recentStimuli);
|
|
733
|
-
if (sarcasmScore
|
|
744
|
+
if (shouldReclassifyPraiseAsSarcasm(text, sarcasmScore, recentStimuli)) {
|
|
734
745
|
// Reclassify: replace praise with sarcasm
|
|
735
746
|
results = results.filter((r) => r.type !== "praise");
|
|
736
747
|
results.unshift({ type: "sarcasm", confidence: Math.min(0.9, sarcasmScore) });
|
|
@@ -976,7 +987,7 @@ export function classifyStimulus(text, recentStimuli, recentMessages) {
|
|
|
976
987
|
// Sarcasm reclassification: if primary looks like praise but sarcasm signals are strong
|
|
977
988
|
if (scoredResults[0].type === "praise") {
|
|
978
989
|
const sarcasmScore = detectSarcasmSignals(text, recentStimuli);
|
|
979
|
-
if (sarcasmScore
|
|
990
|
+
if (shouldReclassifyPraiseAsSarcasm(text, sarcasmScore, recentStimuli)) {
|
|
980
991
|
const filtered = scoredResults.filter((r) => r.type !== "praise");
|
|
981
992
|
filtered.unshift({ type: "sarcasm", confidence: Math.min(0.85, sarcasmScore) });
|
|
982
993
|
return filtered;
|
package/dist/cli.js
CHANGED
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// psyche intensity Show info about personality intensity config
|
|
13
13
|
// psyche reset <dir> [--full]
|
|
14
14
|
// psyche diagnose <dir> [--github]
|
|
15
|
+
// psyche upgrade [--check]
|
|
15
16
|
// psyche profiles [--json] [--mbti TYPE]
|
|
16
17
|
// ============================================================
|
|
17
18
|
import { resolve } from "node:path";
|
|
@@ -25,6 +26,7 @@ import { buildDynamicContext, buildProtocolContext } from "./prompt.js";
|
|
|
25
26
|
import { t } from "./i18n.js";
|
|
26
27
|
import { CHEMICAL_KEYS, CHEMICAL_NAMES_ZH, DRIVE_KEYS, DRIVE_NAMES_ZH } from "./types.js";
|
|
27
28
|
import { isMBTIType, isChemicalKey, isLocale } from "./guards.js";
|
|
29
|
+
import { getPackageVersion, selfUpdate } from "./update.js";
|
|
28
30
|
// ── Logger ───────────────────────────────────────────────────
|
|
29
31
|
const cliLogger = {
|
|
30
32
|
info: (msg) => console.error(`[info] ${msg}`),
|
|
@@ -80,7 +82,7 @@ function die(msg) {
|
|
|
80
82
|
process.exit(1);
|
|
81
83
|
}
|
|
82
84
|
// ── Commands ─────────────────────────────────────────────────
|
|
83
|
-
async function cmdInit(dir, mbti, name, lang, mode, traits,
|
|
85
|
+
async function cmdInit(dir, mbti, name, lang, mode, traits, _noPersist) {
|
|
84
86
|
const absDir = resolve(dir);
|
|
85
87
|
const opts = {};
|
|
86
88
|
if (mbti) {
|
|
@@ -371,6 +373,8 @@ async function cmdDiagnose(dir, github) {
|
|
|
371
373
|
lastMetrics = {
|
|
372
374
|
inputCount: lastEntry.inputs ?? 0,
|
|
373
375
|
classifiedCount: Math.round((lastEntry.classifyRate ?? 0) * (lastEntry.inputs ?? 0)),
|
|
376
|
+
appraisalHitCount: Math.round((lastEntry.appraisalRate ?? 0) * (lastEntry.inputs ?? 0)),
|
|
377
|
+
semanticHitCount: Math.round((lastEntry.recognitionRate ?? lastEntry.classifyRate ?? 0) * (lastEntry.inputs ?? 0)),
|
|
374
378
|
stimulusDistribution: {},
|
|
375
379
|
avgConfidence: lastEntry.classifyRate ?? 0,
|
|
376
380
|
totalChemistryDelta: lastEntry.chemDelta ?? 0,
|
|
@@ -388,6 +392,8 @@ async function cmdDiagnose(dir, github) {
|
|
|
388
392
|
const metrics = lastMetrics ?? {
|
|
389
393
|
inputCount: 0,
|
|
390
394
|
classifiedCount: 0,
|
|
395
|
+
appraisalHitCount: 0,
|
|
396
|
+
semanticHitCount: 0,
|
|
391
397
|
stimulusDistribution: {},
|
|
392
398
|
avgConfidence: 0,
|
|
393
399
|
totalChemistryDelta: 0,
|
|
@@ -396,7 +402,7 @@ async function cmdDiagnose(dir, github) {
|
|
|
396
402
|
startedAt: new Date().toISOString(),
|
|
397
403
|
lastActivityAt: new Date().toISOString(),
|
|
398
404
|
};
|
|
399
|
-
const report = generateReport(state, metrics,
|
|
405
|
+
const report = generateReport(state, metrics, await getPackageVersion());
|
|
400
406
|
if (github) {
|
|
401
407
|
console.log(toGitHubIssueBody(report));
|
|
402
408
|
}
|
|
@@ -415,6 +421,10 @@ async function cmdDiagnose(dir, github) {
|
|
|
415
421
|
}
|
|
416
422
|
}
|
|
417
423
|
}
|
|
424
|
+
async function cmdUpgrade(checkOnly) {
|
|
425
|
+
const result = await selfUpdate({ checkOnly });
|
|
426
|
+
console.log(result.message);
|
|
427
|
+
}
|
|
418
428
|
// ── Usage ────────────────────────────────────────────────────
|
|
419
429
|
function usage() {
|
|
420
430
|
console.log(`
|
|
@@ -431,6 +441,7 @@ Usage:
|
|
|
431
441
|
psyche intensity Show info about personality intensity config
|
|
432
442
|
psyche reset <dir> [--full]
|
|
433
443
|
psyche diagnose <dir> [--github] Run health checks & show diagnostic report
|
|
444
|
+
psyche upgrade [--check] Check/apply package updates safely
|
|
434
445
|
psyche profiles [--mbti TYPE] [--json]
|
|
435
446
|
|
|
436
447
|
Options:
|
|
@@ -460,7 +471,10 @@ Examples:
|
|
|
460
471
|
# See all 16 personality profiles
|
|
461
472
|
psyche profiles
|
|
462
473
|
psyche profiles --mbti ENFP
|
|
463
|
-
|
|
474
|
+
|
|
475
|
+
# Check for new package versions without applying them
|
|
476
|
+
psyche upgrade --check
|
|
477
|
+
`);
|
|
464
478
|
}
|
|
465
479
|
// ── Main ─────────────────────────────────────────────────────
|
|
466
480
|
async function main() {
|
|
@@ -589,6 +603,17 @@ async function main() {
|
|
|
589
603
|
cmdIntensity();
|
|
590
604
|
break;
|
|
591
605
|
}
|
|
606
|
+
case "upgrade": {
|
|
607
|
+
const { values } = parseArgs({
|
|
608
|
+
args: rest,
|
|
609
|
+
options: {
|
|
610
|
+
check: { type: "boolean", default: false },
|
|
611
|
+
},
|
|
612
|
+
allowPositionals: true,
|
|
613
|
+
});
|
|
614
|
+
await cmdUpgrade(values.check ?? false);
|
|
615
|
+
break;
|
|
616
|
+
}
|
|
592
617
|
default:
|
|
593
618
|
die(`unknown command: ${command}. Run 'psyche help' for usage.`);
|
|
594
619
|
}
|
package/dist/core.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { PsycheState, StimulusType, Locale, MBTIType, OutcomeScore, PsycheMode, PersonalityTraits, PolicyModifiers, ClassifierProvider } from "./types.js";
|
|
1
|
+
import type { PsycheState, StimulusType, Locale, MBTIType, OutcomeScore, PsycheMode, PersonalityTraits, PolicyModifiers, ClassifierProvider, SubjectivityKernel, ResponseContract, GenerationControls } 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 {
|
|
@@ -38,6 +38,12 @@ export interface ProcessInputResult {
|
|
|
38
38
|
stimulus: StimulusType | null;
|
|
39
39
|
/** v9: Structured behavioral policy modifiers — machine-readable "off baseline" signals */
|
|
40
40
|
policyModifiers?: PolicyModifiers;
|
|
41
|
+
/** v9.3: Compact machine-readable subjective state for AI-first hosts */
|
|
42
|
+
subjectivityKernel?: SubjectivityKernel;
|
|
43
|
+
/** v9.3: Compact next-reply behavioral envelope */
|
|
44
|
+
responseContract?: ResponseContract;
|
|
45
|
+
/** v9.3: Mechanical host controls derived from the reply envelope */
|
|
46
|
+
generationControls?: GenerationControls;
|
|
41
47
|
/**
|
|
42
48
|
* v9: Ready-to-use LLM prompt fragment summarizing current behavioral policy.
|
|
43
49
|
*
|
|
@@ -112,7 +118,7 @@ export declare class PsycheEngine {
|
|
|
112
118
|
* @param nextUserStimulus - The stimulus detected in the user's next message,
|
|
113
119
|
* or null if the session ended.
|
|
114
120
|
*/
|
|
115
|
-
processOutcome(nextUserStimulus: StimulusType | null,
|
|
121
|
+
processOutcome(nextUserStimulus: StimulusType | null, _opts?: {
|
|
116
122
|
userId?: string;
|
|
117
123
|
}): Promise<ProcessOutcomeResult | null>;
|
|
118
124
|
/**
|
|
@@ -125,7 +131,7 @@ export declare class PsycheEngine {
|
|
|
125
131
|
getProtocol(locale?: Locale): string;
|
|
126
132
|
/**
|
|
127
133
|
* End the current session: compress emotionalHistory into a rich summary
|
|
128
|
-
* stored in relationship.memory[], then
|
|
134
|
+
* stored in relationship.memory[], then preserve only core/recent context.
|
|
129
135
|
* Auto-generates diagnostic report and persists to log.
|
|
130
136
|
*
|
|
131
137
|
* @returns DiagnosticReport if diagnostics are enabled, null otherwise
|