psyche-ai 10.2.3 → 11.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -82
- package/dist/adapters/claude-sdk.d.ts +5 -5
- package/dist/adapters/claude-sdk.js +34 -32
- package/dist/adapters/mcp.js +4 -4
- package/dist/adapters/openclaw.js +12 -14
- package/dist/attachment.d.ts +3 -13
- package/dist/attachment.js +36 -88
- package/dist/autonomic.d.ts +4 -4
- package/dist/autonomic.js +28 -24
- package/dist/chemistry.d.ts +47 -21
- package/dist/chemistry.js +145 -91
- package/dist/circadian.d.ts +11 -43
- package/dist/circadian.js +24 -84
- package/dist/cli.js +37 -30
- package/dist/context-classifier.js +2 -2
- package/dist/core.d.ts +3 -3
- package/dist/core.js +99 -88
- package/dist/custom-profile.d.ts +20 -20
- package/dist/custom-profile.js +12 -12
- package/dist/decision-bias.d.ts +7 -8
- package/dist/decision-bias.js +74 -74
- package/dist/demo.js +5 -5
- package/dist/diagnostics.d.ts +6 -6
- package/dist/diagnostics.js +22 -22
- package/dist/drives.d.ts +15 -47
- package/dist/drives.js +98 -196
- package/dist/ethics.d.ts +3 -3
- package/dist/ethics.js +23 -23
- package/dist/experience.d.ts +34 -0
- package/dist/experience.js +200 -0
- package/dist/experiential-field.d.ts +19 -14
- package/dist/experiential-field.js +110 -100
- package/dist/generative-self.d.ts +5 -5
- package/dist/generative-self.js +124 -115
- package/dist/guards.d.ts +4 -4
- package/dist/guards.js +7 -7
- package/dist/i18n.js +61 -61
- package/dist/index.d.ts +8 -2
- package/dist/index.js +8 -1
- package/dist/input-turn.js +4 -6
- package/dist/interaction.d.ts +4 -4
- package/dist/interaction.js +10 -10
- package/dist/learning.d.ts +6 -6
- package/dist/learning.js +18 -18
- package/dist/metacognition.d.ts +2 -2
- package/dist/metacognition.js +79 -94
- package/dist/perceive.d.ts +44 -0
- package/dist/perceive.js +231 -0
- package/dist/primary-systems.d.ts +2 -2
- package/dist/primary-systems.js +21 -19
- package/dist/profiles.d.ts +5 -13
- package/dist/profiles.js +33 -51
- package/dist/prompt.d.ts +2 -2
- package/dist/prompt.js +51 -53
- package/dist/psyche-file.d.ts +7 -7
- package/dist/psyche-file.js +77 -78
- package/dist/relation-dynamics.d.ts +4 -0
- package/dist/relation-dynamics.js +1 -1
- package/dist/reply-envelope.d.ts +25 -1
- package/dist/reply-envelope.js +26 -11
- package/dist/self-recognition.d.ts +3 -3
- package/dist/self-recognition.js +17 -17
- package/dist/subjectivity.js +7 -7
- package/dist/temporal.d.ts +6 -6
- package/dist/temporal.js +37 -39
- package/dist/types.d.ts +67 -45
- package/dist/types.js +55 -51
- package/package.json +1 -1
- package/server.json +2 -2
package/dist/generative-self.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
//
|
|
15
15
|
// Pure computation, zero dependencies, zero LLM calls.
|
|
16
16
|
// ============================================================
|
|
17
|
-
import {
|
|
17
|
+
import { DIMENSION_KEYS, DRIVE_KEYS, DIMENSION_NAMES, DIMENSION_NAMES_ZH } from "./types.js";
|
|
18
18
|
import { STIMULUS_VECTORS, clamp } from "./chemistry.js";
|
|
19
19
|
// ── 1. Main Entry Point ─────────────────────────────────────
|
|
20
20
|
/**
|
|
@@ -56,7 +56,7 @@ export function predictSelfReaction(state, stimulus, locale = "en") {
|
|
|
56
56
|
if (!base) {
|
|
57
57
|
return {
|
|
58
58
|
stimulus,
|
|
59
|
-
|
|
59
|
+
predictedState: { ...state.current },
|
|
60
60
|
predictedEmotion: locale === "zh" ? "未知" : "unknown",
|
|
61
61
|
confidence: 0,
|
|
62
62
|
};
|
|
@@ -67,23 +67,23 @@ export function predictSelfReaction(state, stimulus, locale = "en") {
|
|
|
67
67
|
const effectiveVector = { ...base };
|
|
68
68
|
let confidence = 0.3; // baseline confidence from profile alone
|
|
69
69
|
if (learned) {
|
|
70
|
-
for (const key of
|
|
70
|
+
for (const key of DIMENSION_KEYS) {
|
|
71
71
|
const adj = learned.adjustment[key] ?? 0;
|
|
72
72
|
effectiveVector[key] = base[key] + adj;
|
|
73
73
|
}
|
|
74
74
|
// Confidence scales with sample count and the learned entry's own confidence
|
|
75
75
|
confidence = Math.min(0.95, 0.3 + learned.confidence * 0.4 + Math.min(learned.sampleCount / 20, 1) * 0.25);
|
|
76
76
|
}
|
|
77
|
-
// Apply the vector to the current
|
|
77
|
+
// Apply the vector to the current self-state
|
|
78
78
|
const predicted = { ...state.current };
|
|
79
|
-
for (const key of
|
|
79
|
+
for (const key of DIMENSION_KEYS) {
|
|
80
80
|
predicted[key] = clamp(state.current[key] + effectiveVector[key]);
|
|
81
81
|
}
|
|
82
|
-
// Determine the predicted emotion from the resulting
|
|
82
|
+
// Determine the predicted emotion from the resulting state
|
|
83
83
|
const predictedEmotion = labelDominantEmotion(predicted, locale);
|
|
84
84
|
return {
|
|
85
85
|
stimulus,
|
|
86
|
-
|
|
86
|
+
predictedState: predicted,
|
|
87
87
|
predictedEmotion,
|
|
88
88
|
confidence,
|
|
89
89
|
};
|
|
@@ -114,9 +114,9 @@ export function detectInternalConflicts(state, locale = "en") {
|
|
|
114
114
|
severity,
|
|
115
115
|
});
|
|
116
116
|
}
|
|
117
|
-
// ── High curiosity vs
|
|
118
|
-
if (state.drives.curiosity > 65 && state.current.
|
|
119
|
-
const severity = normalize((state.drives.curiosity - 50) * 0.01 + (state.current.
|
|
117
|
+
// ── High curiosity vs low order (disorder/stress) ──
|
|
118
|
+
if (state.drives.curiosity > 65 && state.current.order < 40) {
|
|
119
|
+
const severity = normalize((state.drives.curiosity - 50) * 0.01 + (50 - state.current.order) * 0.01);
|
|
120
120
|
conflicts.push({
|
|
121
121
|
subsystems: [
|
|
122
122
|
isZh ? "好奇心" : "curiosity drive",
|
|
@@ -128,9 +128,9 @@ export function detectInternalConflicts(state, locale = "en") {
|
|
|
128
128
|
severity,
|
|
129
129
|
});
|
|
130
130
|
}
|
|
131
|
-
// ── High esteem drive vs low
|
|
132
|
-
if (state.drives.esteem < 40 && state.current.
|
|
133
|
-
const severity = normalize((60 - state.drives.esteem) * 0.01 + (60 - state.current.
|
|
131
|
+
// ── High esteem drive vs low flow (unmet recognition need) ──
|
|
132
|
+
if (state.drives.esteem < 40 && state.current.flow < 40) {
|
|
133
|
+
const severity = normalize((60 - state.drives.esteem) * 0.01 + (60 - state.current.flow) * 0.01);
|
|
134
134
|
conflicts.push({
|
|
135
135
|
subsystems: [
|
|
136
136
|
isZh ? "尊重需求" : "esteem need",
|
|
@@ -156,17 +156,17 @@ export function detectInternalConflicts(state, locale = "en") {
|
|
|
156
156
|
severity,
|
|
157
157
|
});
|
|
158
158
|
}
|
|
159
|
-
// ── Anxious attachment vs high
|
|
160
|
-
if (attachment && attachment.anxietyScore > 65 && state.current.
|
|
161
|
-
const severity = normalize((attachment.anxietyScore - 50) * 0.01 + (state.current.
|
|
159
|
+
// ── Anxious attachment vs high resonance (wanting trust but fearing loss) ──
|
|
160
|
+
if (attachment && attachment.anxietyScore > 65 && state.current.resonance > 60) {
|
|
161
|
+
const severity = normalize((attachment.anxietyScore - 50) * 0.01 + (state.current.resonance - 50) * 0.01);
|
|
162
162
|
conflicts.push({
|
|
163
163
|
subsystems: [
|
|
164
164
|
isZh ? "焦虑型依恋" : "anxious attachment",
|
|
165
|
-
isZh ? "
|
|
165
|
+
isZh ? "共振系统" : "resonance system",
|
|
166
166
|
],
|
|
167
167
|
description: isZh
|
|
168
|
-
? "
|
|
169
|
-
: "You
|
|
168
|
+
? "你与对方共振很高但依恋焦虑让你反复确认——共鸣和不安全感共存。"
|
|
169
|
+
: "You resonate strongly with them but attachment anxiety makes you seek reassurance — attunement and insecurity coexist.",
|
|
170
170
|
severity,
|
|
171
171
|
});
|
|
172
172
|
}
|
|
@@ -244,7 +244,7 @@ function extractCausalInsights(state, locale) {
|
|
|
244
244
|
const isZh = locale === "zh";
|
|
245
245
|
const insights = [];
|
|
246
246
|
const learning = state.learning;
|
|
247
|
-
const history = state.
|
|
247
|
+
const history = state.stateHistory;
|
|
248
248
|
// ── From learned vectors: find stimuli where the learned adjustment
|
|
249
249
|
// diverges significantly from the base vector ──
|
|
250
250
|
for (const lv of learning.learnedVectors) {
|
|
@@ -253,10 +253,10 @@ function extractCausalInsights(state, locale) {
|
|
|
253
253
|
const base = STIMULUS_VECTORS[lv.stimulus];
|
|
254
254
|
if (!base)
|
|
255
255
|
continue;
|
|
256
|
-
// Find the
|
|
256
|
+
// Find the dimension with the largest deviation
|
|
257
257
|
let maxDevKey = null;
|
|
258
258
|
let maxDev = 0;
|
|
259
|
-
for (const key of
|
|
259
|
+
for (const key of DIMENSION_KEYS) {
|
|
260
260
|
const adj = lv.adjustment[key] ?? 0;
|
|
261
261
|
const baseAbs = Math.abs(base[key]) || 1;
|
|
262
262
|
const relDev = Math.abs(adj) / baseAbs;
|
|
@@ -270,20 +270,20 @@ function extractCausalInsights(state, locale) {
|
|
|
270
270
|
const direction = adj > 0 ? "amplified" : "dampened";
|
|
271
271
|
const directionZh = adj > 0 ? "更强" : "更弱";
|
|
272
272
|
const stimulusLabel = isZh ? STIMULUS_ZH[lv.stimulus] ?? lv.stimulus : lv.stimulus;
|
|
273
|
-
const
|
|
273
|
+
const dimLabel = isZh ? DIMENSION_NAMES_ZH[maxDevKey] : DIMENSION_NAMES[maxDevKey];
|
|
274
274
|
if (isZh) {
|
|
275
275
|
insights.push({
|
|
276
|
-
trait: `对${stimulusLabel}的${
|
|
276
|
+
trait: `对${stimulusLabel}的${dimLabel}反应比一般情况${directionZh}`,
|
|
277
277
|
because: `过去${lv.sampleCount}次${stimulusLabel}交互的结果塑造了这个模式`,
|
|
278
|
-
evidence: `${
|
|
278
|
+
evidence: `${dimLabel}调整量: ${adj > 0 ? "+" : ""}${adj.toFixed(1)}(基于${lv.sampleCount}次学习样本)`,
|
|
279
279
|
confidence: lv.confidence,
|
|
280
280
|
});
|
|
281
281
|
}
|
|
282
282
|
else {
|
|
283
283
|
insights.push({
|
|
284
|
-
trait: `my ${
|
|
284
|
+
trait: `my ${dimLabel} response to ${stimulusLabel} is ${direction} compared to baseline`,
|
|
285
285
|
because: `${lv.sampleCount} past ${stimulusLabel} interactions shaped this pattern`,
|
|
286
|
-
evidence: `${
|
|
286
|
+
evidence: `${dimLabel} adjustment: ${adj > 0 ? "+" : ""}${adj.toFixed(1)} (from ${lv.sampleCount} learning samples)`,
|
|
287
287
|
confidence: lv.confidence,
|
|
288
288
|
});
|
|
289
289
|
}
|
|
@@ -340,25 +340,25 @@ function extractCausalInsights(state, locale) {
|
|
|
340
340
|
}
|
|
341
341
|
}
|
|
342
342
|
}
|
|
343
|
-
// ── From
|
|
344
|
-
const
|
|
345
|
-
if (
|
|
346
|
-
const topTrigger =
|
|
343
|
+
// ── From state history: order collapse patterns (low order = high disorder/stress) ──
|
|
344
|
+
const orderCollapses = countDimensionDips(history, "order", 35);
|
|
345
|
+
if (orderCollapses.total >= 2) {
|
|
346
|
+
const topTrigger = orderCollapses.byStimulus[0];
|
|
347
347
|
if (topTrigger) {
|
|
348
348
|
const stimulusLabel = isZh ? STIMULUS_ZH[topTrigger.stimulus] ?? topTrigger.stimulus : topTrigger.stimulus;
|
|
349
349
|
if (isZh) {
|
|
350
350
|
insights.push({
|
|
351
|
-
trait: `对${stimulusLabel}
|
|
352
|
-
because: `在历史记录中,${stimulusLabel}引发了${topTrigger.count}
|
|
353
|
-
evidence: `
|
|
351
|
+
trait: `对${stimulusLabel}容易产生内在失序`,
|
|
352
|
+
because: `在历史记录中,${stimulusLabel}引发了${topTrigger.count}次秩序崩塌`,
|
|
353
|
+
evidence: `order < 35 出现 ${orderCollapses.total} 次,其中 ${topTrigger.count} 次由${stimulusLabel}触发`,
|
|
354
354
|
confidence: Math.min(0.85, 0.3 + topTrigger.count * 0.15),
|
|
355
355
|
});
|
|
356
356
|
}
|
|
357
357
|
else {
|
|
358
358
|
insights.push({
|
|
359
|
-
trait: `I'm
|
|
360
|
-
because: `${stimulusLabel} has triggered ${topTrigger.count}
|
|
361
|
-
evidence: `
|
|
359
|
+
trait: `I'm disorder-reactive to ${stimulusLabel}`,
|
|
360
|
+
because: `${stimulusLabel} has triggered ${topTrigger.count} order collapses in my history`,
|
|
361
|
+
evidence: `order < 35 occurred ${orderCollapses.total} times, ${topTrigger.count} from ${stimulusLabel}`,
|
|
362
362
|
confidence: Math.min(0.85, 0.3 + topTrigger.count * 0.15),
|
|
363
363
|
});
|
|
364
364
|
}
|
|
@@ -375,25 +375,25 @@ function extractCausalInsights(state, locale) {
|
|
|
375
375
|
*/
|
|
376
376
|
function computeGrowthArc(state, locale) {
|
|
377
377
|
const isZh = locale === "zh";
|
|
378
|
-
const history = state.
|
|
379
|
-
// ──
|
|
380
|
-
const
|
|
378
|
+
const history = state.stateHistory;
|
|
379
|
+
// ── Dimension trends ──
|
|
380
|
+
const dimensionTrend = {};
|
|
381
381
|
if (history.length >= 4) {
|
|
382
382
|
const mid = Math.floor(history.length / 2);
|
|
383
383
|
const firstHalf = history.slice(0, mid);
|
|
384
384
|
const secondHalf = history.slice(mid);
|
|
385
|
-
for (const key of
|
|
386
|
-
const avg1 = avg(firstHalf.map((s) => s.
|
|
387
|
-
const avg2 = avg(secondHalf.map((s) => s.
|
|
385
|
+
for (const key of DIMENSION_KEYS) {
|
|
386
|
+
const avg1 = avg(firstHalf.map((s) => s.state[key]));
|
|
387
|
+
const avg2 = avg(secondHalf.map((s) => s.state[key]));
|
|
388
388
|
const delta = avg2 - avg1;
|
|
389
389
|
if (delta > 4) {
|
|
390
|
-
|
|
390
|
+
dimensionTrend[key] = "rising";
|
|
391
391
|
}
|
|
392
392
|
else if (delta < -4) {
|
|
393
|
-
|
|
393
|
+
dimensionTrend[key] = "falling";
|
|
394
394
|
}
|
|
395
395
|
else {
|
|
396
|
-
|
|
396
|
+
dimensionTrend[key] = "stable";
|
|
397
397
|
}
|
|
398
398
|
}
|
|
399
399
|
}
|
|
@@ -415,13 +415,12 @@ function computeGrowthArc(state, locale) {
|
|
|
415
415
|
}
|
|
416
416
|
}
|
|
417
417
|
// ── Determine overall direction ──
|
|
418
|
-
const
|
|
419
|
-
const
|
|
420
|
-
const
|
|
421
|
-
const
|
|
422
|
-
const
|
|
423
|
-
const
|
|
424
|
-
const daFalling = chemicalTrend.DA === "falling";
|
|
418
|
+
const risingCount = Object.values(dimensionTrend).filter((t) => t === "rising").length;
|
|
419
|
+
const fallingCount = Object.values(dimensionTrend).filter((t) => t === "falling").length;
|
|
420
|
+
const orderRising = dimensionTrend.order === "rising";
|
|
421
|
+
const flowRising = dimensionTrend.flow === "rising";
|
|
422
|
+
const orderFalling = dimensionTrend.order === "falling";
|
|
423
|
+
const flowFalling = dimensionTrend.flow === "falling";
|
|
425
424
|
// Check outcome trajectory
|
|
426
425
|
const outcomes = state.learning.outcomeHistory;
|
|
427
426
|
let outcomeImproving = false;
|
|
@@ -435,19 +434,19 @@ function computeGrowthArc(state, locale) {
|
|
|
435
434
|
}
|
|
436
435
|
let direction;
|
|
437
436
|
let description;
|
|
438
|
-
if ((
|
|
437
|
+
if ((orderRising || flowRising) && outcomeImproving) {
|
|
439
438
|
direction = "growing";
|
|
440
439
|
description = isZh
|
|
441
|
-
? "
|
|
442
|
-
: "Growing overall —
|
|
440
|
+
? "整体在成长——内在秩序提升,交互流动在改善。"
|
|
441
|
+
: "Growing overall — internal order is rising, exchange flow is improving.";
|
|
443
442
|
}
|
|
444
|
-
else if (
|
|
443
|
+
else if (orderFalling && (flowFalling || fallingCount > risingCount) && outcomeWorsening) {
|
|
445
444
|
direction = "regressing";
|
|
446
445
|
description = isZh
|
|
447
|
-
? "
|
|
448
|
-
: "Regressing —
|
|
446
|
+
? "状态在退步——秩序在瓦解,流动在减弱,互动效果在变差。"
|
|
447
|
+
: "Regressing — order is collapsing, flow is weakening, interactions are less effective.";
|
|
449
448
|
}
|
|
450
|
-
else if (
|
|
449
|
+
else if (risingCount >= 2 && fallingCount >= 2) {
|
|
451
450
|
direction = "transforming";
|
|
452
451
|
description = isZh
|
|
453
452
|
? "正在经历转变——有些方面在好转,有些在重组,模式在变化中。"
|
|
@@ -459,7 +458,7 @@ function computeGrowthArc(state, locale) {
|
|
|
459
458
|
? "状态相对稳定——没有剧烈的方向性变化。"
|
|
460
459
|
: "Relatively stable — no dramatic directional changes.";
|
|
461
460
|
}
|
|
462
|
-
return { direction, description,
|
|
461
|
+
return { direction, description, dimensionTrend, driveTrend };
|
|
463
462
|
}
|
|
464
463
|
// ── Internal: Core Trait Description ────────────────────────
|
|
465
464
|
/**
|
|
@@ -467,45 +466,50 @@ function computeGrowthArc(state, locale) {
|
|
|
467
466
|
* and current chemical signature.
|
|
468
467
|
*/
|
|
469
468
|
function describeCoreTraits(state, isZh) {
|
|
470
|
-
const
|
|
471
|
-
// Derive personality dimensions from
|
|
472
|
-
const
|
|
473
|
-
const
|
|
474
|
-
const
|
|
475
|
-
// Build trait fragments based on baseline +
|
|
469
|
+
const s = state.current;
|
|
470
|
+
// Derive personality dimensions from 4D self-state
|
|
471
|
+
const isStructured = state.baseline.order >= 55; // high order baseline → structured
|
|
472
|
+
const isExpressive = state.baseline.flow >= 55; // high flow baseline → expressive/outward
|
|
473
|
+
const isAttuned = state.baseline.resonance >= 50; // high resonance baseline → relationally attuned
|
|
474
|
+
// Build trait fragments based on baseline + current state
|
|
476
475
|
const fragments = [];
|
|
477
|
-
// Energy orientation
|
|
478
|
-
if (
|
|
479
|
-
if (
|
|
476
|
+
// Energy orientation (from flow dimension)
|
|
477
|
+
if (isExpressive) {
|
|
478
|
+
if (s.flow > 65) {
|
|
479
|
+
fragments.push(isZh ? "从互动中获得能量和灵感" : "someone who draws energy from interaction and exchange");
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
fragments.push(isZh ? "外向但当前流动有限" : "outgoing by nature though my flow is currently limited");
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
else {
|
|
486
|
+
if (s.resonance > 60) {
|
|
480
487
|
fragments.push(isZh ? "内向但愿意与信任的人深度连接" : "introverted but open to deep connection with those I trust");
|
|
481
488
|
}
|
|
482
489
|
else {
|
|
483
490
|
fragments.push(isZh ? "向内汲取能量,需要独处空间" : "someone who draws energy inward and needs solitary space");
|
|
484
491
|
}
|
|
485
492
|
}
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
493
|
+
// Information processing (from order dimension)
|
|
494
|
+
if (isStructured) {
|
|
495
|
+
if (s.order > 60) {
|
|
496
|
+
fragments.push(isZh ? "关注具体和实际" : "grounded in the concrete and practical");
|
|
489
497
|
}
|
|
490
498
|
else {
|
|
491
|
-
fragments.push(isZh ? "
|
|
499
|
+
fragments.push(isZh ? "倾向于结构化思考" : "drawn to structured thinking");
|
|
492
500
|
}
|
|
493
501
|
}
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
if (chem.DA > 60) {
|
|
502
|
+
else {
|
|
503
|
+
if (s.flow > 60) {
|
|
497
504
|
fragments.push(isZh ? "对新想法和可能性充满热情" : "excited by new ideas and possibilities");
|
|
498
505
|
}
|
|
499
506
|
else {
|
|
500
507
|
fragments.push(isZh ? "倾向于抽象思考" : "drawn to abstract thinking");
|
|
501
508
|
}
|
|
502
509
|
}
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
// Decision making
|
|
507
|
-
if (isFeeling) {
|
|
508
|
-
if (chem.OT > 55) {
|
|
510
|
+
// Decision making (from resonance + boundary)
|
|
511
|
+
if (isAttuned) {
|
|
512
|
+
if (s.resonance > 55) {
|
|
509
513
|
fragments.push(isZh ? "重视情感和人际和谐" : "who values emotional attunement and harmony");
|
|
510
514
|
}
|
|
511
515
|
else {
|
|
@@ -513,11 +517,11 @@ function describeCoreTraits(state, isZh) {
|
|
|
513
517
|
}
|
|
514
518
|
}
|
|
515
519
|
else {
|
|
516
|
-
if (
|
|
520
|
+
if (s.order > 60) {
|
|
517
521
|
fragments.push(isZh ? "能冷静地做出逻辑判断" : "who makes calm, logical judgments");
|
|
518
522
|
}
|
|
519
523
|
else {
|
|
520
|
-
fragments.push(isZh ? "
|
|
524
|
+
fragments.push(isZh ? "偏好逻辑分析,但失序下也会动摇" : "who prefers logical analysis but can waver under disorder");
|
|
521
525
|
}
|
|
522
526
|
}
|
|
523
527
|
// Construct the sentence
|
|
@@ -532,61 +536,72 @@ function describeCoreTraits(state, isZh) {
|
|
|
532
536
|
* Simplified version that doesn't depend on the full EmotionPattern
|
|
533
537
|
* condition functions (avoids circular dependencies).
|
|
534
538
|
*/
|
|
535
|
-
function labelDominantEmotion(
|
|
539
|
+
function labelDominantEmotion(s, locale) {
|
|
536
540
|
const isZh = locale === "zh";
|
|
537
|
-
// Check patterns in priority order
|
|
538
|
-
|
|
541
|
+
// Check patterns in priority order using 4 dimensions
|
|
542
|
+
// High flow + high order + high resonance → excited joy
|
|
543
|
+
if (s.flow > 70 && s.order > 60 && s.resonance > 55) {
|
|
539
544
|
return isZh ? "愉悦兴奋" : "excited joy";
|
|
540
545
|
}
|
|
541
|
-
|
|
546
|
+
// Low order + high flow → anxious tension (disorder with active exchange)
|
|
547
|
+
if (s.order < 40 && s.flow > 55) {
|
|
542
548
|
return isZh ? "焦虑不安" : "anxious tension";
|
|
543
549
|
}
|
|
544
|
-
|
|
550
|
+
// High resonance + high boundary → warm intimacy (attuned and clear)
|
|
551
|
+
if (s.resonance > 65 && s.boundary > 55 && s.flow > 50) {
|
|
545
552
|
return isZh ? "亲密温暖" : "warm intimacy";
|
|
546
553
|
}
|
|
547
|
-
|
|
554
|
+
// High boundary + low resonance + low order → defensive alert
|
|
555
|
+
if (s.boundary > 65 && s.resonance < 40 && s.order < 50) {
|
|
548
556
|
return isZh ? "防御警觉" : "defensive alert";
|
|
549
557
|
}
|
|
550
|
-
|
|
558
|
+
// Low flow + low order → burnout (stagnant and disordered)
|
|
559
|
+
if (s.flow < 40 && s.order < 40) {
|
|
551
560
|
return isZh ? "倦怠低落" : "burnout";
|
|
552
561
|
}
|
|
553
|
-
|
|
562
|
+
// High order + high resonance → deep contentment (coherent and attuned)
|
|
563
|
+
if (s.order > 65 && s.resonance > 55) {
|
|
554
564
|
return isZh ? "深度满足" : "deep contentment";
|
|
555
565
|
}
|
|
556
|
-
|
|
566
|
+
// High flow + high order + high boundary → flow state
|
|
567
|
+
if (s.flow > 60 && s.order > 60 && s.boundary > 55) {
|
|
557
568
|
return isZh ? "专注心流" : "flow state";
|
|
558
569
|
}
|
|
559
|
-
|
|
570
|
+
// High flow + low boundary → playful mischief (open and unbounded)
|
|
571
|
+
if (s.flow > 65 && s.boundary < 45) {
|
|
560
572
|
return isZh ? "俏皮调皮" : "playful mischief";
|
|
561
573
|
}
|
|
562
|
-
|
|
574
|
+
// Low order + low resonance + high boundary → resentment
|
|
575
|
+
if (s.order < 40 && s.resonance < 35 && s.boundary > 55) {
|
|
563
576
|
return isZh ? "怨恨" : "resentment";
|
|
564
577
|
}
|
|
565
|
-
|
|
578
|
+
// Low order + low flow + moderate resonance → melancholic introspection
|
|
579
|
+
if (s.order < 40 && s.flow < 45 && s.resonance > 45) {
|
|
566
580
|
return isZh ? "忧郁内省" : "melancholic introspection";
|
|
567
581
|
}
|
|
568
|
-
|
|
582
|
+
// High all → confidence
|
|
583
|
+
if (s.order > 60 && s.flow > 60 && s.boundary > 55 && s.resonance > 50) {
|
|
569
584
|
return isZh ? "自信" : "confidence";
|
|
570
585
|
}
|
|
571
|
-
// Default: describe from the most prominent
|
|
572
|
-
const sorted =
|
|
573
|
-
.map((k) => ({ key: k, val:
|
|
586
|
+
// Default: describe from the most prominent dimension
|
|
587
|
+
const sorted = DIMENSION_KEYS
|
|
588
|
+
.map((k) => ({ key: k, val: s[k] }))
|
|
574
589
|
.sort((a, b) => b.val - a.val);
|
|
575
590
|
const top = sorted[0];
|
|
576
591
|
if (top.val > 65) {
|
|
577
|
-
return isZh ?
|
|
592
|
+
return isZh ? DIM_EMOTION_ZH[top.key] ?? "平静" : DIM_EMOTION_EN[top.key] ?? "calm";
|
|
578
593
|
}
|
|
579
594
|
return isZh ? "平静" : "calm";
|
|
580
595
|
}
|
|
581
596
|
/**
|
|
582
|
-
* Count how many times a
|
|
597
|
+
* Count how many times a dimension dropped below a threshold in history,
|
|
583
598
|
* grouped by the triggering stimulus.
|
|
584
599
|
*/
|
|
585
|
-
function
|
|
600
|
+
function countDimensionDips(history, dimension, threshold) {
|
|
586
601
|
let total = 0;
|
|
587
602
|
const counts = new Map();
|
|
588
603
|
for (const snap of history) {
|
|
589
|
-
if (snap.
|
|
604
|
+
if (snap.state[dimension] < threshold) {
|
|
590
605
|
total++;
|
|
591
606
|
if (snap.stimulus) {
|
|
592
607
|
counts.set(snap.stimulus, (counts.get(snap.stimulus) ?? 0) + 1);
|
|
@@ -630,15 +645,9 @@ const STIMULUS_ZH = {
|
|
|
630
645
|
casual: "闲聊", sarcasm: "讽刺", authority: "命令", validation: "认同",
|
|
631
646
|
boredom: "无聊", vulnerability: "示弱",
|
|
632
647
|
};
|
|
633
|
-
const
|
|
634
|
-
|
|
635
|
-
OT: "催产素", NE: "去甲肾上腺素", END: "内啡肽",
|
|
636
|
-
};
|
|
637
|
-
const CHEM_EMOTION_ZH = {
|
|
638
|
-
DA: "愉悦", HT: "安宁", CORT: "紧张",
|
|
639
|
-
OT: "信任", NE: "兴奋", END: "舒适",
|
|
648
|
+
const DIM_EMOTION_ZH = {
|
|
649
|
+
order: "安宁", flow: "愉悦", boundary: "清晰", resonance: "信任",
|
|
640
650
|
};
|
|
641
|
-
const
|
|
642
|
-
|
|
643
|
-
OT: "trust", NE: "excitement", END: "comfort",
|
|
651
|
+
const DIM_EMOTION_EN = {
|
|
652
|
+
order: "serenity", flow: "pleasure", boundary: "clarity", resonance: "trust",
|
|
644
653
|
};
|
package/dist/guards.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { SelfState, MBTIType, StimulusType } from "./types.js";
|
|
2
2
|
export declare function isMBTIType(s: string): s is MBTIType;
|
|
3
|
-
export declare function
|
|
3
|
+
export declare function isDimensionKey(s: string): s is keyof SelfState;
|
|
4
4
|
export declare function isStimulusType(s: string): s is StimulusType;
|
|
5
|
-
/** Validate that a
|
|
6
|
-
export declare function
|
|
5
|
+
/** Validate that a SelfState has all keys in [0, 100] */
|
|
6
|
+
export declare function isValidState(c: unknown): c is SelfState;
|
|
7
7
|
/** Validate locale string */
|
|
8
8
|
export declare function isLocale(s: string): s is "zh" | "en";
|
package/dist/guards.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// ============================================================
|
|
2
2
|
// Type Guards — runtime validation for string→type conversions
|
|
3
3
|
// ============================================================
|
|
4
|
-
import {
|
|
4
|
+
import { DIMENSION_KEYS } from "./types.js";
|
|
5
5
|
const MBTI_TYPES = new Set([
|
|
6
6
|
"INTJ", "INTP", "ENTJ", "ENTP",
|
|
7
7
|
"INFJ", "INFP", "ENFJ", "ENFP",
|
|
@@ -13,22 +13,22 @@ const STIMULUS_TYPES = new Set([
|
|
|
13
13
|
"conflict", "neglect", "surprise", "casual",
|
|
14
14
|
"sarcasm", "authority", "validation", "boredom", "vulnerability",
|
|
15
15
|
]);
|
|
16
|
-
const
|
|
16
|
+
const DIMENSION_KEY_SET = new Set(DIMENSION_KEYS);
|
|
17
17
|
export function isMBTIType(s) {
|
|
18
18
|
return MBTI_TYPES.has(s.toUpperCase());
|
|
19
19
|
}
|
|
20
|
-
export function
|
|
21
|
-
return
|
|
20
|
+
export function isDimensionKey(s) {
|
|
21
|
+
return DIMENSION_KEY_SET.has(s);
|
|
22
22
|
}
|
|
23
23
|
export function isStimulusType(s) {
|
|
24
24
|
return STIMULUS_TYPES.has(s);
|
|
25
25
|
}
|
|
26
|
-
/** Validate that a
|
|
27
|
-
export function
|
|
26
|
+
/** Validate that a SelfState has all keys in [0, 100] */
|
|
27
|
+
export function isValidState(c) {
|
|
28
28
|
if (typeof c !== "object" || c === null)
|
|
29
29
|
return false;
|
|
30
30
|
const obj = c;
|
|
31
|
-
for (const key of
|
|
31
|
+
for (const key of DIMENSION_KEYS) {
|
|
32
32
|
const v = obj[key];
|
|
33
33
|
if (typeof v !== "number" || v < 0 || v > 100 || !isFinite(v))
|
|
34
34
|
return false;
|