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
|
@@ -4,7 +4,8 @@
|
|
|
4
4
|
// Moves the system from "what am I feeling?" toward
|
|
5
5
|
// "what just happened between us, and what is still unresolved?"
|
|
6
6
|
// ============================================================
|
|
7
|
-
import { DEFAULT_DYADIC_FIELD } from "./types.js";
|
|
7
|
+
import { DEFAULT_DYADIC_FIELD, DEFAULT_RELATIONSHIP } from "./types.js";
|
|
8
|
+
import { computeAppraisalAxes, mergeAppraisalResidue } from "./appraisal.js";
|
|
8
9
|
function clamp01(v) {
|
|
9
10
|
return Math.max(0, Math.min(1, v));
|
|
10
11
|
}
|
|
@@ -255,6 +256,72 @@ export function computeRelationMove(text, opts) {
|
|
|
255
256
|
}
|
|
256
257
|
return { type, intensity: score };
|
|
257
258
|
}
|
|
259
|
+
export function resolveRelationContext(state, userId) {
|
|
260
|
+
const key = userId ?? "_default";
|
|
261
|
+
const relationship = state.relationships[key]
|
|
262
|
+
?? state.relationships._default
|
|
263
|
+
?? state.relationships[Object.keys(state.relationships)[0]]
|
|
264
|
+
?? DEFAULT_RELATIONSHIP;
|
|
265
|
+
const field = state.dyadicFields?.[key]
|
|
266
|
+
?? state.dyadicFields?._default
|
|
267
|
+
?? DEFAULT_DYADIC_FIELD;
|
|
268
|
+
const pendingSignals = state.pendingRelationSignals?.[key]
|
|
269
|
+
?? state.pendingRelationSignals?._default
|
|
270
|
+
?? [];
|
|
271
|
+
return {
|
|
272
|
+
key,
|
|
273
|
+
relationship,
|
|
274
|
+
field,
|
|
275
|
+
pendingSignals,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
export function applyRelationalTurn(state, text, opts) {
|
|
279
|
+
const now = opts.now ?? new Date().toISOString();
|
|
280
|
+
const relationContext = resolveRelationContext(state, opts.userId);
|
|
281
|
+
const appraisalAxes = computeAppraisalAxes(text, {
|
|
282
|
+
mode: opts.mode,
|
|
283
|
+
stimulus: opts.stimulus,
|
|
284
|
+
previous: state.subjectResidue?.axes,
|
|
285
|
+
});
|
|
286
|
+
const relationMove = computeRelationMove(text, {
|
|
287
|
+
appraisal: appraisalAxes,
|
|
288
|
+
stimulus: opts.stimulus,
|
|
289
|
+
mode: opts.mode,
|
|
290
|
+
field: relationContext.field,
|
|
291
|
+
relationship: relationContext.relationship,
|
|
292
|
+
});
|
|
293
|
+
const delayedRelation = evolvePendingRelationSignals(relationContext.pendingSignals, relationMove, appraisalAxes, { mode: opts.mode });
|
|
294
|
+
const field = evolveDyadicField(relationContext.field, relationMove, appraisalAxes, {
|
|
295
|
+
mode: opts.mode,
|
|
296
|
+
now,
|
|
297
|
+
delayedPressure: delayedRelation.delayedPressure,
|
|
298
|
+
});
|
|
299
|
+
return {
|
|
300
|
+
state: {
|
|
301
|
+
...state,
|
|
302
|
+
subjectResidue: {
|
|
303
|
+
axes: mergeAppraisalResidue(state.subjectResidue?.axes, appraisalAxes, opts.mode),
|
|
304
|
+
updatedAt: now,
|
|
305
|
+
},
|
|
306
|
+
dyadicFields: {
|
|
307
|
+
...(state.dyadicFields ?? {}),
|
|
308
|
+
[relationContext.key]: field,
|
|
309
|
+
},
|
|
310
|
+
pendingRelationSignals: {
|
|
311
|
+
...(state.pendingRelationSignals ?? {}),
|
|
312
|
+
[relationContext.key]: delayedRelation.signals,
|
|
313
|
+
},
|
|
314
|
+
},
|
|
315
|
+
appraisalAxes,
|
|
316
|
+
relationMove,
|
|
317
|
+
delayedPressure: delayedRelation.delayedPressure,
|
|
318
|
+
relationContext: {
|
|
319
|
+
...relationContext,
|
|
320
|
+
field,
|
|
321
|
+
pendingSignals: delayedRelation.signals,
|
|
322
|
+
},
|
|
323
|
+
};
|
|
324
|
+
}
|
|
258
325
|
export function evolveDyadicField(previous, move, appraisal, opts) {
|
|
259
326
|
const prev = previous ?? DEFAULT_DYADIC_FIELD;
|
|
260
327
|
const baseline = DEFAULT_DYADIC_FIELD;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { AppraisalAxes, GenerationControls, Locale, PolicyModifiers, PsycheState, ResolvedRelationContext, ResponseContract, StimulusType, SubjectivityKernel } from "./types.js";
|
|
2
|
+
export interface ReplyEnvelope {
|
|
3
|
+
policyModifiers: PolicyModifiers;
|
|
4
|
+
subjectivityKernel: SubjectivityKernel;
|
|
5
|
+
responseContract: ResponseContract;
|
|
6
|
+
generationControls: GenerationControls;
|
|
7
|
+
policyContext: string;
|
|
8
|
+
subjectivityContext: string;
|
|
9
|
+
responseContractContext: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function deriveReplyEnvelope(state: PsycheState, appraisal: AppraisalAxes, opts: {
|
|
12
|
+
locale: Locale;
|
|
13
|
+
userText?: string;
|
|
14
|
+
algorithmStimulus?: StimulusType | null;
|
|
15
|
+
personalityIntensity?: number;
|
|
16
|
+
relationContext?: ResolvedRelationContext;
|
|
17
|
+
}): ReplyEnvelope;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Reply Envelope — unified host-facing reply ABI derivation
|
|
3
|
+
//
|
|
4
|
+
// Keeps the hot path narrow by deriving reply-facing structures
|
|
5
|
+
// from one state snapshot and one resolved relation context.
|
|
6
|
+
// ============================================================
|
|
7
|
+
import { buildPolicyContext, computePolicyModifiers } from "./decision-bias.js";
|
|
8
|
+
import { deriveGenerationControls } from "./host-controls.js";
|
|
9
|
+
import { buildResponseContractContext, computeResponseContract } from "./response-contract.js";
|
|
10
|
+
import { buildSubjectivityContext, computeSubjectivityKernel } from "./subjectivity.js";
|
|
11
|
+
export function deriveReplyEnvelope(state, appraisal, opts) {
|
|
12
|
+
const policyModifiers = computePolicyModifiers(state);
|
|
13
|
+
const subjectivityKernel = computeSubjectivityKernel(state, policyModifiers, appraisal, opts.relationContext);
|
|
14
|
+
const responseContract = computeResponseContract(subjectivityKernel, {
|
|
15
|
+
locale: opts.locale,
|
|
16
|
+
userText: opts.userText,
|
|
17
|
+
algorithmStimulus: opts.algorithmStimulus,
|
|
18
|
+
personalityIntensity: opts.personalityIntensity,
|
|
19
|
+
});
|
|
20
|
+
const generationControls = deriveGenerationControls({
|
|
21
|
+
responseContract,
|
|
22
|
+
policyModifiers,
|
|
23
|
+
});
|
|
24
|
+
const policyContext = buildPolicyContext(policyModifiers, opts.locale, state.drives);
|
|
25
|
+
const subjectivityContext = buildSubjectivityContext(subjectivityKernel, opts.locale);
|
|
26
|
+
const responseContractContext = buildResponseContractContext(responseContract, opts.locale);
|
|
27
|
+
return {
|
|
28
|
+
policyModifiers,
|
|
29
|
+
subjectivityKernel,
|
|
30
|
+
responseContract,
|
|
31
|
+
generationControls,
|
|
32
|
+
policyContext,
|
|
33
|
+
subjectivityContext,
|
|
34
|
+
responseContractContext,
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -8,11 +8,63 @@ const EMOTIONAL_STIMULI = new Set(["vulnerability", "intimacy", "neglect"]);
|
|
|
8
8
|
function clampInt(v, min, max) {
|
|
9
9
|
return Math.max(min, Math.min(max, Math.round(v)));
|
|
10
10
|
}
|
|
11
|
-
function
|
|
11
|
+
function deriveReplyProfile(kernel) {
|
|
12
|
+
const taskFocused = kernel.taskPlane.focus >= 0.62;
|
|
13
|
+
const disciplined = kernel.taskPlane.discipline >= 0.72;
|
|
14
|
+
if (taskFocused && disciplined) {
|
|
15
|
+
return { replyProfile: "work", replyProfileBasis: "task-focus+discipline" };
|
|
16
|
+
}
|
|
17
|
+
if (taskFocused) {
|
|
18
|
+
return { replyProfile: "work", replyProfileBasis: "task-focus" };
|
|
19
|
+
}
|
|
20
|
+
if (disciplined) {
|
|
21
|
+
return { replyProfile: "work", replyProfileBasis: "discipline" };
|
|
22
|
+
}
|
|
23
|
+
return { replyProfile: "private", replyProfileBasis: "default-private" };
|
|
24
|
+
}
|
|
25
|
+
function computeLengthBudget(locale, userText, replyProfile, expressionMode, kernel) {
|
|
12
26
|
const len = userText.length;
|
|
13
27
|
let maxSentences = 2;
|
|
14
28
|
let maxChars;
|
|
15
|
-
if (
|
|
29
|
+
if (replyProfile === "work") {
|
|
30
|
+
if (locale === "zh") {
|
|
31
|
+
if (len <= 10) {
|
|
32
|
+
maxSentences = 2;
|
|
33
|
+
maxChars = 36;
|
|
34
|
+
}
|
|
35
|
+
else if (len <= 40) {
|
|
36
|
+
maxSentences = 3;
|
|
37
|
+
maxChars = clampInt(len * 2.4, 48, 220);
|
|
38
|
+
}
|
|
39
|
+
else if (len <= 120) {
|
|
40
|
+
maxSentences = 5;
|
|
41
|
+
maxChars = clampInt(len * 1.9, 120, 420);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
maxSentences = 6;
|
|
45
|
+
maxChars = clampInt(len * 1.5, 180, 720);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
if (len <= 16) {
|
|
50
|
+
maxSentences = 2;
|
|
51
|
+
maxChars = 48;
|
|
52
|
+
}
|
|
53
|
+
else if (len <= 60) {
|
|
54
|
+
maxSentences = 3;
|
|
55
|
+
maxChars = clampInt(len * 2.3, 64, 280);
|
|
56
|
+
}
|
|
57
|
+
else if (len <= 180) {
|
|
58
|
+
maxSentences = 5;
|
|
59
|
+
maxChars = clampInt(len * 1.8, 140, 520);
|
|
60
|
+
}
|
|
61
|
+
else {
|
|
62
|
+
maxSentences = 6;
|
|
63
|
+
maxChars = clampInt(len * 1.45, 220, 900);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (locale === "zh") {
|
|
16
68
|
if (len <= 6) {
|
|
17
69
|
maxSentences = 1;
|
|
18
70
|
maxChars = 15;
|
|
@@ -49,39 +101,81 @@ function computeLengthBudget(locale, userText, expressionMode, kernel) {
|
|
|
49
101
|
}
|
|
50
102
|
}
|
|
51
103
|
if (expressionMode === "brief") {
|
|
52
|
-
maxSentences =
|
|
53
|
-
|
|
104
|
+
maxSentences = replyProfile === "work"
|
|
105
|
+
? Math.max(2, Math.min(maxSentences, 4))
|
|
106
|
+
: Math.max(1, Math.min(maxSentences, 2));
|
|
107
|
+
maxChars = maxChars !== undefined
|
|
108
|
+
? clampInt(maxChars * (replyProfile === "work" ? 0.9 : 0.85), replyProfile === "work" ? 36 : 10, maxChars)
|
|
109
|
+
: maxChars;
|
|
54
110
|
}
|
|
55
111
|
else if (expressionMode === "expansive") {
|
|
56
|
-
maxSentences = Math.min(4, maxSentences + 1);
|
|
57
|
-
maxChars = maxChars !== undefined
|
|
112
|
+
maxSentences = Math.min(replyProfile === "work" ? 6 : 4, maxSentences + 1);
|
|
113
|
+
maxChars = maxChars !== undefined
|
|
114
|
+
? clampInt(maxChars * 1.1, maxChars, Math.max(maxChars, replyProfile === "work" ? 900 : 260))
|
|
115
|
+
: maxChars;
|
|
58
116
|
}
|
|
59
117
|
if (kernel?.taskPlane.focus && kernel.taskPlane.focus > 0.72) {
|
|
60
|
-
|
|
61
|
-
|
|
118
|
+
if (replyProfile === "work") {
|
|
119
|
+
maxSentences = Math.max(2, maxSentences);
|
|
120
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 1.05, 48, Math.max(maxChars, 720)) : 160;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
maxSentences = Math.max(1, Math.min(maxSentences, 2));
|
|
124
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.82, 10, maxChars) : maxChars;
|
|
125
|
+
}
|
|
62
126
|
}
|
|
63
127
|
if (kernel?.subjectPlane.guardedness && kernel.subjectPlane.guardedness > 0.72) {
|
|
64
|
-
|
|
65
|
-
|
|
128
|
+
if (replyProfile === "work") {
|
|
129
|
+
maxSentences = Math.max(2, Math.min(maxSentences, 3));
|
|
130
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.88, 84, maxChars) : 112;
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
maxSentences = 1;
|
|
134
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.72, 8, maxChars) : 18;
|
|
135
|
+
}
|
|
66
136
|
}
|
|
67
137
|
if (kernel?.ambiguityPlane.expressionInhibition && kernel.ambiguityPlane.expressionInhibition > 0.66) {
|
|
68
|
-
|
|
69
|
-
|
|
138
|
+
if (replyProfile === "work") {
|
|
139
|
+
maxSentences = Math.max(2, Math.min(maxSentences, 3));
|
|
140
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.9, 96, maxChars) : 136;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
maxSentences = 1;
|
|
144
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.76, 8, maxChars) : 18;
|
|
145
|
+
}
|
|
70
146
|
}
|
|
71
147
|
if (kernel?.relationPlane.silentCarry && kernel.relationPlane.silentCarry > 0.54) {
|
|
72
|
-
maxSentences = Math.max(1, Math.min(maxSentences, 2));
|
|
73
|
-
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.82, 8, maxChars) : 20;
|
|
148
|
+
maxSentences = Math.max(replyProfile === "work" ? 2 : 1, Math.min(maxSentences, replyProfile === "work" ? 3 : 2));
|
|
149
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.82, replyProfile === "work" ? 96 : 8, maxChars) : (replyProfile === "work" ? 136 : 20);
|
|
74
150
|
}
|
|
75
151
|
if (kernel?.relationPlane.hysteresis && kernel.relationPlane.hysteresis > 0.64) {
|
|
76
|
-
|
|
77
|
-
|
|
152
|
+
if (replyProfile === "work") {
|
|
153
|
+
maxSentences = Math.max(2, Math.min(maxSentences, 3));
|
|
154
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.84, 104, maxChars) : 144;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
maxSentences = 1;
|
|
158
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.78, 8, maxChars) : 18;
|
|
159
|
+
}
|
|
78
160
|
}
|
|
79
161
|
if (kernel?.relationPlane.repairFriction && kernel.relationPlane.repairFriction > 0.62) {
|
|
80
|
-
|
|
81
|
-
|
|
162
|
+
if (replyProfile === "work") {
|
|
163
|
+
maxSentences = Math.max(2, Math.min(maxSentences, 3));
|
|
164
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.82, 96, maxChars) : 128;
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
maxSentences = 1;
|
|
168
|
+
maxChars = maxChars !== undefined ? clampInt(maxChars * 0.74, 8, maxChars) : 16;
|
|
169
|
+
}
|
|
82
170
|
}
|
|
83
171
|
return { maxSentences, maxChars };
|
|
84
172
|
}
|
|
173
|
+
function buildStimulusReportingGuide(locale) {
|
|
174
|
+
if (locale === "zh") {
|
|
175
|
+
return "stimulus速记:闲聊casual/命令authority/认同validation/示弱vulnerability/冷淡neglect/批评criticism";
|
|
176
|
+
}
|
|
177
|
+
return "stimulus map: chat=casual / command=authority / agreement=validation / vulnerable=vulnerability / cold=neglect / criticism=criticism";
|
|
178
|
+
}
|
|
85
179
|
function detectToneParticles(userText, locale) {
|
|
86
180
|
if (locale !== "zh")
|
|
87
181
|
return "natural";
|
|
@@ -100,9 +194,15 @@ export function computeResponseContract(kernel, opts) {
|
|
|
100
194
|
const locale = opts?.locale ?? "zh";
|
|
101
195
|
const userText = opts?.userText ?? "";
|
|
102
196
|
const personalityIntensity = opts?.personalityIntensity ?? 0.7;
|
|
197
|
+
const { replyProfile, replyProfileBasis } = deriveReplyProfile(kernel);
|
|
103
198
|
const { maxSentences, maxChars } = userText.length > 0
|
|
104
|
-
? computeLengthBudget(locale, userText, kernel.expressionMode, kernel)
|
|
105
|
-
: {
|
|
199
|
+
? computeLengthBudget(locale, userText, replyProfile, kernel.expressionMode, kernel)
|
|
200
|
+
: {
|
|
201
|
+
maxSentences: replyProfile === "work"
|
|
202
|
+
? (kernel.expressionMode === "expansive" ? 5 : 3)
|
|
203
|
+
: kernel.expressionMode === "brief" ? 1 : kernel.expressionMode === "expansive" ? 3 : 2,
|
|
204
|
+
maxChars: replyProfile === "work" ? 160 : undefined,
|
|
205
|
+
};
|
|
106
206
|
let updateMode = "none";
|
|
107
207
|
if (kernel.taskPlane.focus > 0.72) {
|
|
108
208
|
updateMode = "none";
|
|
@@ -165,6 +265,8 @@ export function computeResponseContract(kernel, opts) {
|
|
|
165
265
|
initiativeMode = "reactive";
|
|
166
266
|
}
|
|
167
267
|
return {
|
|
268
|
+
replyProfile,
|
|
269
|
+
replyProfileBasis,
|
|
168
270
|
maxSentences,
|
|
169
271
|
maxChars,
|
|
170
272
|
expressionMode: kernel.expressionMode,
|
|
@@ -177,9 +279,26 @@ export function computeResponseContract(kernel, opts) {
|
|
|
177
279
|
updateMode,
|
|
178
280
|
};
|
|
179
281
|
}
|
|
282
|
+
function describeReplyProfileBasis(basis, locale) {
|
|
283
|
+
if (locale === "zh") {
|
|
284
|
+
switch (basis) {
|
|
285
|
+
case "task-focus":
|
|
286
|
+
return "因:聚焦";
|
|
287
|
+
case "discipline":
|
|
288
|
+
return "因:纪律";
|
|
289
|
+
case "task-focus+discipline":
|
|
290
|
+
return "因:聚焦+纪律";
|
|
291
|
+
default:
|
|
292
|
+
return "因:默认私人";
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return `basis:${basis}`;
|
|
296
|
+
}
|
|
180
297
|
export function buildResponseContractContext(contract, locale = "zh") {
|
|
181
298
|
if (locale === "zh") {
|
|
182
299
|
const parts = [];
|
|
300
|
+
parts.push(contract.replyProfile === "work" ? "工作面" : "私人面");
|
|
301
|
+
parts.push(describeReplyProfileBasis(contract.replyProfileBasis, locale));
|
|
183
302
|
const shape = contract.maxChars
|
|
184
303
|
? `${contract.maxSentences === 1 ? "1句内" : `最多${contract.maxSentences}句`},≤${contract.maxChars}字`
|
|
185
304
|
: `${contract.maxSentences === 1 ? "1句内" : `最多${contract.maxSentences}句`}`;
|
|
@@ -207,14 +326,18 @@ export function buildResponseContractContext(contract, locale = "zh") {
|
|
|
207
326
|
if (contract.emojiLimit > 0)
|
|
208
327
|
parts.push(`表情≤${contract.emojiLimit}`);
|
|
209
328
|
if (contract.updateMode === "stimulus")
|
|
210
|
-
parts.push(
|
|
329
|
+
parts.push(buildStimulusReportingGuide(locale));
|
|
211
330
|
else if (contract.updateMode === "empathy")
|
|
212
331
|
parts.push("对方谈感受时再报empathy");
|
|
213
|
-
else if (contract.updateMode === "stimulus+empathy")
|
|
214
|
-
parts.push(
|
|
332
|
+
else if (contract.updateMode === "stimulus+empathy") {
|
|
333
|
+
parts.push(buildStimulusReportingGuide(locale));
|
|
334
|
+
parts.push("对方谈感受时再报empathy");
|
|
335
|
+
}
|
|
215
336
|
return `[回应契约] ${parts.join(";")}。`;
|
|
216
337
|
}
|
|
217
338
|
const parts = [];
|
|
339
|
+
parts.push(contract.replyProfile === "work" ? "work surface" : "private surface");
|
|
340
|
+
parts.push(describeReplyProfileBasis(contract.replyProfileBasis, locale));
|
|
218
341
|
const shape = contract.maxChars
|
|
219
342
|
? `${contract.maxSentences === 1 ? "1 sentence" : `up to ${contract.maxSentences} sentences`}, <= ${contract.maxChars} chars`
|
|
220
343
|
: `${contract.maxSentences === 1 ? "1 sentence" : `up to ${contract.maxSentences} sentences`}`;
|
|
@@ -240,10 +363,12 @@ export function buildResponseContractContext(contract, locale = "zh") {
|
|
|
240
363
|
if (contract.emojiLimit > 0)
|
|
241
364
|
parts.push(`emoji <= ${contract.emojiLimit}`);
|
|
242
365
|
if (contract.updateMode === "stimulus")
|
|
243
|
-
parts.push(
|
|
366
|
+
parts.push(buildStimulusReportingGuide(locale));
|
|
244
367
|
else if (contract.updateMode === "empathy")
|
|
245
368
|
parts.push("report empathy only when feelings are shared");
|
|
246
|
-
else if (contract.updateMode === "stimulus+empathy")
|
|
247
|
-
parts.push(
|
|
369
|
+
else if (contract.updateMode === "stimulus+empathy") {
|
|
370
|
+
parts.push(buildStimulusReportingGuide(locale));
|
|
371
|
+
parts.push("report empathy only when feelings are shared");
|
|
372
|
+
}
|
|
248
373
|
return `[Reply Contract] ${parts.join(", ")}.`;
|
|
249
374
|
}
|
package/dist/subjectivity.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type { AppraisalAxes, Locale, PolicyModifiers, PsycheState, SubjectivityKernel } from "./types.js";
|
|
2
|
-
export declare function computeSubjectivityKernel(state: PsycheState, policyModifiers?: PolicyModifiers, appraisal?: AppraisalAxes,
|
|
1
|
+
import type { AppraisalAxes, Locale, PolicyModifiers, PsycheState, SubjectivityKernel, ResolvedRelationContext } from "./types.js";
|
|
2
|
+
export declare function computeSubjectivityKernel(state: PsycheState, policyModifiers?: PolicyModifiers, appraisal?: AppraisalAxes, relationContextOrUserId?: ResolvedRelationContext | string): SubjectivityKernel;
|
|
3
3
|
export declare function buildSubjectivityContext(kernel: SubjectivityKernel, locale?: Locale): string;
|
package/dist/subjectivity.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { DEFAULT_APPRAISAL_AXES, DEFAULT_DYADIC_FIELD, DRIVE_KEYS } from "./types.js";
|
|
8
8
|
import { computeAttentionWeights, computeDecisionBias, computePolicyModifiers } from "./decision-bias.js";
|
|
9
9
|
import { getResidueIntensity } from "./appraisal.js";
|
|
10
|
-
import { getLoopPressure } from "./relation-dynamics.js";
|
|
10
|
+
import { getLoopPressure, resolveRelationContext } from "./relation-dynamics.js";
|
|
11
11
|
function clamp01(v) {
|
|
12
12
|
return Math.max(0, Math.min(1, v));
|
|
13
13
|
}
|
|
@@ -47,10 +47,11 @@ function pickAttentionAnchor(state, tension, warmth) {
|
|
|
47
47
|
candidates.sort((a, b) => b[1] - a[1]);
|
|
48
48
|
return candidates[0][0];
|
|
49
49
|
}
|
|
50
|
-
function computeRelationPlane(state, appraisal,
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
|
|
50
|
+
function computeRelationPlane(state, appraisal, relationContext) {
|
|
51
|
+
const rel = relationContext?.relationship
|
|
52
|
+
?? state.relationships._default
|
|
53
|
+
?? state.relationships[Object.keys(state.relationships)[0]];
|
|
54
|
+
const field = relationContext?.field ?? DEFAULT_DYADIC_FIELD;
|
|
54
55
|
const loopPressure = getLoopPressure(field);
|
|
55
56
|
const closeness = wavg([
|
|
56
57
|
field.perceivedCloseness,
|
|
@@ -112,9 +113,8 @@ function computeRelationPlane(state, appraisal, userId) {
|
|
|
112
113
|
lastMove: field.lastMove,
|
|
113
114
|
};
|
|
114
115
|
}
|
|
115
|
-
function computeAmbiguityPlane(state, appraisal, relationPlane,
|
|
116
|
-
const
|
|
117
|
-
const pendingSignals = state.pendingRelationSignals?.[key] ?? state.pendingRelationSignals?._default ?? [];
|
|
116
|
+
function computeAmbiguityPlane(state, appraisal, relationPlane, relationContext) {
|
|
117
|
+
const pendingSignals = relationContext?.pendingSignals ?? [];
|
|
118
118
|
const pendingPressure = clamp01(pendingSignals.reduce((sum, signal) => sum + signal.intensity * (signal.readyInTurns > 0 ? 0.55 : 0.35), 0));
|
|
119
119
|
const baseConflict = wavg([
|
|
120
120
|
Math.min(relationPlane.closeness, Math.max(relationPlane.loopPressure, appraisal.selfPreservation)),
|
|
@@ -219,13 +219,22 @@ function computeSubjectPlane(state, warmth, guard, appraisal, relationPlane) {
|
|
|
219
219
|
residue: residueIntensity,
|
|
220
220
|
};
|
|
221
221
|
}
|
|
222
|
-
|
|
222
|
+
function normalizeRelationContext(state, relationContextOrUserId) {
|
|
223
|
+
if (!relationContextOrUserId)
|
|
224
|
+
return resolveRelationContext(state);
|
|
225
|
+
if (typeof relationContextOrUserId === "string") {
|
|
226
|
+
return resolveRelationContext(state, relationContextOrUserId);
|
|
227
|
+
}
|
|
228
|
+
return relationContextOrUserId;
|
|
229
|
+
}
|
|
230
|
+
export function computeSubjectivityKernel(state, policyModifiers = computePolicyModifiers(state), appraisal = state.subjectResidue?.axes ?? DEFAULT_APPRAISAL_AXES, relationContextOrUserId) {
|
|
231
|
+
const relationContext = normalizeRelationContext(state, relationContextOrUserId);
|
|
223
232
|
const c = state.current;
|
|
224
|
-
const rel =
|
|
233
|
+
const rel = relationContext?.relationship
|
|
225
234
|
?? state.relationships._default
|
|
226
235
|
?? state.relationships[Object.keys(state.relationships)[0]];
|
|
227
|
-
const relationPlane = computeRelationPlane(state, appraisal,
|
|
228
|
-
const ambiguityPlane = computeAmbiguityPlane(state, appraisal, relationPlane,
|
|
236
|
+
const relationPlane = computeRelationPlane(state, appraisal, relationContext);
|
|
237
|
+
const ambiguityPlane = computeAmbiguityPlane(state, appraisal, relationPlane, relationContext);
|
|
229
238
|
const bias = computeDecisionBias(state);
|
|
230
239
|
const energySignal = state.energyBudgets
|
|
231
240
|
? (norm(state.energyBudgets.attention)
|
package/dist/temporal.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare function predictNextStimulus(emotionalHistory: ChemicalSnapshot[]
|
|
|
25
25
|
* High-probability positive prediction -> DA/OT micro-rise.
|
|
26
26
|
* High-probability negative prediction -> CORT micro-rise.
|
|
27
27
|
*/
|
|
28
|
-
export declare function generateAnticipation(predictions: StimulusPrediction[],
|
|
28
|
+
export declare function generateAnticipation(predictions: StimulusPrediction[], _currentChemistry: ChemicalState): AnticipationState;
|
|
29
29
|
/**
|
|
30
30
|
* Compute disappointment/surprise when actual stimulus differs from prediction.
|
|
31
31
|
* Returns additional chemistry delta beyond the normal stimulus response.
|
|
@@ -35,4 +35,4 @@ export declare function computeSurpriseEffect(anticipated: AnticipationState, ac
|
|
|
35
35
|
* Evaluate if the last interaction would have gone better with different chemistry.
|
|
36
36
|
* Runs a counterfactual: "what if my chemistry had been at baseline?"
|
|
37
37
|
*/
|
|
38
|
-
export declare function computeRegret(preInteractionState: PsycheState, postInteractionState: PsycheState, outcomeScore: number,
|
|
38
|
+
export declare function computeRegret(preInteractionState: PsycheState, postInteractionState: PsycheState, outcomeScore: number, _appliedStimulus: StimulusType | null): RegretEntry | null;
|
package/dist/temporal.js
CHANGED
|
@@ -142,7 +142,7 @@ function buildPhasePrior(weights) {
|
|
|
142
142
|
* High-probability positive prediction -> DA/OT micro-rise.
|
|
143
143
|
* High-probability negative prediction -> CORT micro-rise.
|
|
144
144
|
*/
|
|
145
|
-
export function generateAnticipation(predictions,
|
|
145
|
+
export function generateAnticipation(predictions, _currentChemistry) {
|
|
146
146
|
const anticipation = {};
|
|
147
147
|
for (const key of CHEMICAL_KEYS) {
|
|
148
148
|
anticipation[key] = 0;
|
|
@@ -231,7 +231,7 @@ const CHEMICAL_DESCRIPTIONS = {
|
|
|
231
231
|
* Evaluate if the last interaction would have gone better with different chemistry.
|
|
232
232
|
* Runs a counterfactual: "what if my chemistry had been at baseline?"
|
|
233
233
|
*/
|
|
234
|
-
export function computeRegret(preInteractionState, postInteractionState, outcomeScore,
|
|
234
|
+
export function computeRegret(preInteractionState, postInteractionState, outcomeScore, _appliedStimulus) {
|
|
235
235
|
// Only generate regret for bad outcomes
|
|
236
236
|
if (outcomeScore >= -0.2) {
|
|
237
237
|
return null;
|
package/dist/types.d.ts
CHANGED
|
@@ -27,12 +27,18 @@ export declare const DRIVE_NAMES_ZH: Record<DriveType, string>;
|
|
|
27
27
|
/** Human-readable names for each chemical */
|
|
28
28
|
export declare const CHEMICAL_NAMES: Record<keyof ChemicalState, string>;
|
|
29
29
|
export declare const CHEMICAL_NAMES_ZH: Record<keyof ChemicalState, string>;
|
|
30
|
+
export interface ChemicalRuntimeSpec {
|
|
31
|
+
normalMin: number;
|
|
32
|
+
normalMax: number;
|
|
33
|
+
halfLifeHours: number;
|
|
34
|
+
}
|
|
30
35
|
/** Decay speed category */
|
|
31
36
|
export type DecaySpeed = "fast" | "medium" | "slow";
|
|
32
37
|
/** Decay factor per chemical (applied per hour) */
|
|
33
38
|
export declare const DECAY_FACTORS: Record<DecaySpeed, number>;
|
|
34
39
|
/** Which chemicals decay at which speed */
|
|
35
40
|
export declare const CHEMICAL_DECAY_SPEED: Record<keyof ChemicalState, DecaySpeed>;
|
|
41
|
+
export declare const CHEMICAL_RUNTIME_SPECS: Record<keyof ChemicalState, ChemicalRuntimeSpec>;
|
|
36
42
|
/** Psyche operating mode */
|
|
37
43
|
export type PsycheMode = "natural" | "work" | "companion";
|
|
38
44
|
/** Big Five personality traits (0-100 each) */
|
|
@@ -87,6 +93,8 @@ export interface ChemicalSnapshot {
|
|
|
87
93
|
stimulus: StimulusType | null;
|
|
88
94
|
dominantEmotion: string | null;
|
|
89
95
|
timestamp: string;
|
|
96
|
+
semanticSummary?: string;
|
|
97
|
+
semanticPoints?: string[];
|
|
90
98
|
intensity?: number;
|
|
91
99
|
valence?: number;
|
|
92
100
|
isCoreMemory?: boolean;
|
|
@@ -166,11 +174,30 @@ export declare const MAX_DEFENSE_PATTERNS = 10;
|
|
|
166
174
|
export type RegulationStrategyType = "reappraisal" | "strategic-expression" | "self-soothing";
|
|
167
175
|
/** Defense mechanism type */
|
|
168
176
|
export type DefenseMechanismType = "rationalization" | "projection" | "sublimation" | "avoidance";
|
|
177
|
+
/** Which internal metric a regulation action is trying to pull back toward target */
|
|
178
|
+
export type RegulationTargetMetric = keyof ChemicalState | "emotional-confidence";
|
|
179
|
+
/** Whether the last regulation action is helping */
|
|
180
|
+
export type RegulationFeedbackEffect = "converging" | "holding" | "diverging";
|
|
181
|
+
export interface RegulationFeedback {
|
|
182
|
+
strategy: RegulationStrategyType;
|
|
183
|
+
targetMetric: RegulationTargetMetric;
|
|
184
|
+
effect: RegulationFeedbackEffect;
|
|
185
|
+
gapBefore: number;
|
|
186
|
+
gapNow: number;
|
|
187
|
+
}
|
|
169
188
|
/** Record of a past regulation attempt */
|
|
170
189
|
export interface RegulationRecord {
|
|
171
190
|
strategy: RegulationStrategyType;
|
|
172
191
|
timestamp: string;
|
|
173
192
|
effective: boolean;
|
|
193
|
+
action?: string;
|
|
194
|
+
horizonTurns?: number;
|
|
195
|
+
remainingTurns?: number;
|
|
196
|
+
targetMetric?: RegulationTargetMetric;
|
|
197
|
+
targetValue?: number;
|
|
198
|
+
gapBefore?: number;
|
|
199
|
+
gapLatest?: number;
|
|
200
|
+
effect?: RegulationFeedbackEffect;
|
|
174
201
|
}
|
|
175
202
|
/** Tracked defense pattern frequency */
|
|
176
203
|
export interface DefensePatternRecord {
|
|
@@ -185,6 +212,7 @@ export interface MetacognitiveState {
|
|
|
185
212
|
/** Running average of emotional confidence across assessments */
|
|
186
213
|
avgEmotionalConfidence: number;
|
|
187
214
|
totalAssessments: number;
|
|
215
|
+
lastRegulationFeedback?: RegulationFeedback | null;
|
|
188
216
|
}
|
|
189
217
|
/** Default empty metacognitive state */
|
|
190
218
|
export declare const DEFAULT_METACOGNITIVE_STATE: MetacognitiveState;
|
|
@@ -365,6 +393,13 @@ export interface DyadicFieldState {
|
|
|
365
393
|
lastMove: RelationMoveType;
|
|
366
394
|
updatedAt: string;
|
|
367
395
|
}
|
|
396
|
+
/** Resolved per-partner view used across the hot path */
|
|
397
|
+
export interface ResolvedRelationContext {
|
|
398
|
+
key: string;
|
|
399
|
+
relationship: RelationshipState;
|
|
400
|
+
field: DyadicFieldState;
|
|
401
|
+
pendingSignals: PendingRelationSignalState[];
|
|
402
|
+
}
|
|
368
403
|
export declare const DEFAULT_DYADIC_FIELD: DyadicFieldState;
|
|
369
404
|
export interface AmbiguityPlaneState {
|
|
370
405
|
/** How confidently the system should name what is happening */
|
|
@@ -463,6 +498,10 @@ export interface SubjectivityKernel {
|
|
|
463
498
|
* in a compact, host-consumable form.
|
|
464
499
|
*/
|
|
465
500
|
export interface ResponseContract {
|
|
501
|
+
/** Which conversational surface this turn belongs to */
|
|
502
|
+
replyProfile: "work" | "private";
|
|
503
|
+
/** Why the current turn was classified into that conversational surface */
|
|
504
|
+
replyProfileBasis: "task-focus" | "discipline" | "task-focus+discipline" | "default-private";
|
|
466
505
|
/** Maximum suggested sentence count */
|
|
467
506
|
maxSentences: number;
|
|
468
507
|
/** Maximum suggested character count, when a concrete cap is available */
|
package/dist/types.js
CHANGED
|
@@ -56,6 +56,17 @@ export const CHEMICAL_DECAY_SPEED = {
|
|
|
56
56
|
NE: "fast",
|
|
57
57
|
END: "fast",
|
|
58
58
|
};
|
|
59
|
+
function decayHalfLifeHours(decayPerHour) {
|
|
60
|
+
return Math.log(0.5) / Math.log(decayPerHour);
|
|
61
|
+
}
|
|
62
|
+
export const CHEMICAL_RUNTIME_SPECS = {
|
|
63
|
+
DA: { normalMin: 35, normalMax: 75, halfLifeHours: decayHalfLifeHours(DECAY_FACTORS.medium) },
|
|
64
|
+
HT: { normalMin: 40, normalMax: 75, halfLifeHours: decayHalfLifeHours(DECAY_FACTORS.slow) },
|
|
65
|
+
CORT: { normalMin: 20, normalMax: 55, halfLifeHours: decayHalfLifeHours(DECAY_FACTORS.medium) },
|
|
66
|
+
OT: { normalMin: 35, normalMax: 75, halfLifeHours: decayHalfLifeHours(DECAY_FACTORS.slow) },
|
|
67
|
+
NE: { normalMin: 30, normalMax: 70, halfLifeHours: decayHalfLifeHours(DECAY_FACTORS.fast) },
|
|
68
|
+
END: { normalMin: 30, normalMax: 70, halfLifeHours: decayHalfLifeHours(DECAY_FACTORS.fast) },
|
|
69
|
+
};
|
|
59
70
|
/** Default attachment for new relationships */
|
|
60
71
|
export const DEFAULT_ATTACHMENT = {
|
|
61
72
|
style: "secure",
|
|
@@ -95,6 +106,7 @@ export const DEFAULT_METACOGNITIVE_STATE = {
|
|
|
95
106
|
defensePatterns: [],
|
|
96
107
|
avgEmotionalConfidence: 0.5,
|
|
97
108
|
totalAssessments: 0,
|
|
109
|
+
lastRegulationFeedback: null,
|
|
98
110
|
};
|
|
99
111
|
// ── Personhood Types (v6) ────────────────────────────────────
|
|
100
112
|
/** Max causal insights to persist */
|
package/llms.txt
CHANGED