psyche-ai 10.0.0 → 10.0.2

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/dist/appraisal.js CHANGED
@@ -4,7 +4,7 @@
4
4
  // Zero-LLM, low-latency detection of self-relevant semantic pressure.
5
5
  // These axes sit beneath prompt prose and above raw stimulus labels.
6
6
  // ============================================================
7
- import { DEFAULT_APPRAISAL_AXES } from "./types.js";
7
+ import { DEFAULT_APPRAISAL_AXES, MODE_PROFILES } from "./types.js";
8
8
  import { detectIntent } from "./classify.js";
9
9
  function clamp01(v) {
10
10
  return Math.max(0, Math.min(1, v));
@@ -334,7 +334,7 @@ export function mergeAppraisalResidue(previous, current, mode) {
334
334
  return next;
335
335
  }
336
336
  function getAxisDecay(key, mode, previousValue, currentValue) {
337
- let decay = mode === "work" ? 0.68 : mode === "companion" ? 0.86 : 0.78;
337
+ let decay = MODE_PROFILES[mode ?? "natural"].appraisalDecay;
338
338
  if (key === "identityThreat" || key === "abandonmentRisk" || key === "selfPreservation") {
339
339
  decay += 0.08;
340
340
  }
package/dist/core.js CHANGED
@@ -11,7 +11,7 @@
11
11
  //
12
12
  // Orchestrates: chemistry, classify, prompt, profiles, guards, learning
13
13
  // ============================================================
14
- import { DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ENERGY_BUDGETS, DEFAULT_TRAIT_DRIFT, DEFAULT_SUBJECT_RESIDUE, DEFAULT_DYADIC_FIELD } from "./types.js";
14
+ import { DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ENERGY_BUDGETS, DEFAULT_TRAIT_DRIFT, DEFAULT_SUBJECT_RESIDUE, DEFAULT_DYADIC_FIELD, MODE_PROFILES } from "./types.js";
15
15
  import { MemoryStorageAdapter } from "./storage.js";
16
16
  import { applyDecay, applyStimulus, applyContagion, clamp, describeEmotionalState } from "./chemistry.js";
17
17
  import { classifyStimulus, BuiltInClassifier, buildLLMClassifierPrompt, parseLLMClassification } from "./classify.js";
@@ -342,8 +342,9 @@ export class PsycheEngine {
342
342
  // hits ~1.7x harder than a 0.55 mild disagreement.
343
343
  // Maps [0.5, 1.0] → [0.6, 1.2] via linear interpolation.
344
344
  const confidenceIntensity = 0.6 + (primary.confidence - 0.5) * 1.2;
345
- const modeMultiplier = this.cfg.mode === "work" ? 0.3 : this.cfg.mode === "companion" ? 1.5 : 1.0;
346
- const effectiveMaxDelta = this.cfg.mode === "work" ? 5 : this.cfg.maxChemicalDelta;
345
+ const modeProfile = MODE_PROFILES[this.cfg.mode];
346
+ const modeMultiplier = modeProfile.chemistryMultiplier;
347
+ const effectiveMaxDelta = modeProfile.maxChemicalDelta ?? this.cfg.maxChemicalDelta;
347
348
  // v9: Habituation — count recent same-type stimuli in this session
348
349
  const recentSameCount = (state.emotionalHistory ?? [])
349
350
  .filter(s => s.stimulus === primary.type).length + 1; // +1 for current
@@ -9,25 +9,21 @@ function clampInt(v, min, max) {
9
9
  function estimateMaxTokens(contract) {
10
10
  if (!contract)
11
11
  return undefined;
12
+ // Derive from vibe tier (maxSentences) — aligned with what the prompt actually tells the LLM.
13
+ // No precise char counts in prompt means maxTokens is the only hard ceiling.
12
14
  let budget;
13
- if (contract.maxChars !== undefined) {
14
- budget = clampInt(contract.maxChars * 2.2, 64, 1024);
15
- }
16
- else if (contract.expressionMode === "brief") {
15
+ if (contract.maxSentences <= 1)
17
16
  budget = 96;
17
+ else if (contract.maxSentences <= 2)
18
+ budget = 192;
19
+ else if (contract.maxSentences <= 3)
20
+ budget = 320;
21
+ else
22
+ budget = 512;
23
+ // Work mode: tighter ceiling from internal maxChars when available
24
+ if (contract.replyProfile === "work" && contract.maxChars !== undefined) {
25
+ budget = Math.min(budget, clampInt(contract.maxChars * 2.2, 96, 1024));
18
26
  }
19
- else if (contract.expressionMode === "expansive") {
20
- budget = 640;
21
- }
22
- else {
23
- budget = 256;
24
- }
25
- if (contract.maxSentences <= 1)
26
- budget = Math.min(budget, 96);
27
- else if (contract.maxSentences === 2)
28
- budget = Math.min(budget, 160);
29
- else if (contract.maxSentences === 3)
30
- budget = Math.min(budget, 320);
31
27
  if (contract.initiativeMode === "reactive") {
32
28
  budget = clampInt(budget * 0.85, 64, 1024);
33
29
  }
package/dist/index.d.ts CHANGED
@@ -2,7 +2,8 @@ export { PsycheEngine } from "./core.js";
2
2
  export type { PsycheEngineConfig, ProcessInputResult, ProcessOutputResult, ProcessOutcomeResult } from "./core.js";
3
3
  export { FileStorageAdapter, MemoryStorageAdapter } from "./storage.js";
4
4
  export type { StorageAdapter } from "./storage.js";
5
- export type { PsycheState, ChemicalState, Locale, PsycheMode, StimulusType, MBTIType, WritebackSignalType, DelegateCapability, CapabilityGrant, RevocationCondition, DelegateAuthorization, } from "./types.js";
5
+ export type { PsycheState, ChemicalState, Locale, PsycheMode, StimulusType, MBTIType, WritebackSignalType, DelegateCapability, CapabilityGrant, RevocationCondition, DelegateAuthorization, ModeProfile, } from "./types.js";
6
+ export { MODE_PROFILES } from "./types.js";
6
7
  export { buildProtocolContext, buildCompactContext } from "./prompt.js";
7
8
  /** @deprecated Use buildCompactContext instead. Kept for backward compat. */
8
9
  export { buildDynamicContext } from "./prompt.js";
package/dist/index.js CHANGED
@@ -16,6 +16,7 @@
16
16
  export { PsycheEngine } from "./core.js";
17
17
  // ── Storage ─────────────────────────────────────────────────
18
18
  export { FileStorageAdapter, MemoryStorageAdapter } from "./storage.js";
19
+ export { MODE_PROFILES } from "./types.js";
19
20
  // ── Prompt context builders ─────────────────────────────────
20
21
  export { buildProtocolContext, buildCompactContext } from "./prompt.js";
21
22
  /** @deprecated Use buildCompactContext instead. Kept for backward compat. */
package/dist/prompt.js CHANGED
@@ -2,7 +2,7 @@
2
2
  // Prompt Injection — Build emotional context for LLM (v0.2)
3
3
  // Imperative protocol, behavior guides, i18n
4
4
  // ============================================================
5
- import { CHEMICAL_KEYS, CHEMICAL_NAMES_ZH, DRIVE_KEYS } from "./types.js";
5
+ import { CHEMICAL_KEYS, CHEMICAL_NAMES_ZH, DRIVE_KEYS, MODE_PROFILES } from "./types.js";
6
6
  import { getExpressionHint, getBehaviorGuide, detectEmotions } from "./chemistry.js";
7
7
  import { getRelationship } from "./psyche-file.js";
8
8
  import { t } from "./i18n.js";
@@ -672,11 +672,7 @@ export function isNearBaseline(state, threshold = 8) {
672
672
  return CHEMICAL_KEYS.every((key) => Math.abs(state.current[key] - state.baseline[key]) <= threshold);
673
673
  }
674
674
  export function getNearBaselineThreshold(mode) {
675
- if (mode === "work")
676
- return 20;
677
- if (mode === "companion")
678
- return 5;
679
- return 8; // natural
675
+ return MODE_PROFILES[mode ?? "natural"].nearBaselineThreshold;
680
676
  }
681
677
  // ── Behavioral Bias ─────────────────────────────────────────
682
678
  // Chemistry deviation → behavioral tendencies. No emotion labels.
@@ -698,7 +694,8 @@ export function deriveBehavioralBias(state, locale) {
698
694
  const dHT = current.HT - baseline.HT;
699
695
  const dNE = current.NE - baseline.NE;
700
696
  const dEND = current.END - baseline.END;
701
- if (dOT > 10)
697
+ const otThreshold = MODE_PROFILES[state.meta.mode ?? "natural"].otWarmthThreshold;
698
+ if (dOT > otThreshold)
702
699
  biases.push(isZh ? "倾向靠近,愿意多说" : "leaning closer, willing to share");
703
700
  else if (dOT < -10)
704
701
  biases.push(isZh ? "保持距离,不想多说" : "keeping distance, not inclined to share");
@@ -768,8 +765,8 @@ function buildUnifiedConstraints(state, locale, opts) {
768
765
  }
769
766
  else if (established) {
770
767
  lines.push(isZh
771
- ? "镜像对方风格。不贴不舔。有自尊。"
772
- : "Mirror their style. No people-pleasing. You have dignity.");
768
+ ? (opts.warmResume ? "放松,可以主动分享。有自尊。" : "镜像对方风格。不贴不舔。有自尊。")
769
+ : (opts.warmResume ? "Relax, you can initiate sharing. You have dignity." : "Mirror their style. No people-pleasing. You have dignity."));
773
770
  }
774
771
  else {
775
772
  if (isZh) {
@@ -786,19 +783,21 @@ function buildUnifiedConstraints(state, locale, opts) {
786
783
  : `${state.agreementStreak} agreements in a row. Pause — do you truly agree?`);
787
784
  }
788
785
  // ── Mirror constraints (if user text, skip for ultra-short) ──
786
+ // Vibe words, not precise numbers — LLMs turn hard limits into counting exercises.
789
787
  if (userText && userText.length >= 3) {
790
788
  const len = userText.length;
789
+ const profile = MODE_PROFILES[state.meta.mode ?? "natural"];
791
790
  if (isZh) {
792
791
  if (len <= 6)
793
- lines.push(`对方只发了${len}个字。你也简短回,不超过15字。`);
792
+ lines.push("对方发了很短的消息。你也简短回。");
794
793
  else if (len <= 20)
795
- lines.push(`对方说了一句话(${len}字)。你回一两句,不超过${Math.round(len * 1.5)}字。`);
794
+ lines.push("对方说了一句话。你回一两句,别比对方长太多。");
796
795
  else if (len <= 60)
797
- lines.push(`对方写了几句(${len}字)。你回两三句,不超过${Math.round(len * 1.2)}字。`);
796
+ lines.push("对方写了几句。你回两三句,篇幅相当。");
798
797
  else
799
- lines.push(`对方认真写了一段(${len}字)。你可以多说,但不要超过${len}字。`);
798
+ lines.push("对方认真写了一段。你可以多说,认真回应。");
800
799
  const mojiCount = (userText.match(/[呀啊呢吧嘛哦噢哈嘿嗯啦吗呐嗨]/g) || []).length;
801
- if (mojiCount >= 2)
800
+ if (mojiCount >= 2 || profile.toneParticlesDefault)
802
801
  lines.push("对方用了语气词,你也自然地用。");
803
802
  else if (mojiCount === 0 && len > 15)
804
803
  lines.push("对方措辞正式/干练,少用语气词。");
@@ -808,13 +807,13 @@ function buildUnifiedConstraints(state, locale, opts) {
808
807
  }
809
808
  else {
810
809
  if (len <= 10)
811
- lines.push(`They sent ${len} chars. Keep reply under 20 chars.`);
810
+ lines.push("Very short message. Keep your reply brief too.");
812
811
  else if (len <= 40)
813
- lines.push(`Short message (${len} chars). 1-2 sentences, under ${Math.round(len * 1.5)} chars.`);
812
+ lines.push("Short message. A sentence or two, don't over-extend.");
814
813
  else if (len <= 100)
815
- lines.push(`Medium message (${len} chars). 2-3 sentences, under ${Math.round(len * 1.2)} chars.`);
814
+ lines.push("Medium message. A few sentences, roughly matching their effort.");
816
815
  else
817
- lines.push(`Long message (${len} chars). Match their effort, don't exceed ${len} chars.`);
816
+ lines.push("Long message. Match their effort, respond thoughtfully.");
818
817
  }
819
818
  }
820
819
  // ── Reciprocity (only when extreme) ──
@@ -978,6 +977,7 @@ export function buildCompactContext(state, userId, opts) {
978
977
  established,
979
978
  intensity,
980
979
  investment,
980
+ warmResume: bridge?.continuityMode === "warm-resume",
981
981
  });
982
982
  if (unified)
983
983
  parts.push(unified);
@@ -4,7 +4,7 @@
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_APPRAISAL_AXES, DEFAULT_DYADIC_FIELD, DEFAULT_RELATIONSHIP } from "./types.js";
7
+ import { DEFAULT_APPRAISAL_AXES, DEFAULT_DYADIC_FIELD, DEFAULT_RELATIONSHIP, MODE_PROFILES } from "./types.js";
8
8
  import { computeAppraisalAxes, mergeAppraisalResidue } from "./appraisal.js";
9
9
  function clamp01(v) {
10
10
  return Math.max(0, Math.min(1, v));
@@ -164,7 +164,7 @@ function withLoop(loops, type, intensity) {
164
164
  .slice(0, 4);
165
165
  }
166
166
  function ageLoops(loops, mode) {
167
- const decay = mode === "work" ? 0.94 : 0.97;
167
+ const decay = MODE_PROFILES[mode ?? "natural"].relationDecay;
168
168
  return loops
169
169
  .map((loop) => ({
170
170
  ...loop,
@@ -737,7 +737,7 @@ export function evolveDyadicField(previous, move, appraisal, opts) {
737
737
  const now = opts?.now ?? new Date().toISOString();
738
738
  const delayedPressure = opts?.delayedPressure ?? 0;
739
739
  let openLoops = ageLoops(prev.openLoops, mode);
740
- const naturalDrift = mode === "work" ? 0.06 : 0.04;
740
+ const naturalDrift = MODE_PROFILES[mode ?? "natural"].relationDrift;
741
741
  // NOTE: repairFriction reads deprecated fields (repairFatigue, misattunementLoad,
742
742
  // backslidePressure). These feed internal field evolution only — they have no
743
743
  // downstream behavioral effect on prompt or policy output.
@@ -1069,7 +1069,7 @@ export function evolvePendingRelationSignals(previous, move, appraisal, opts) {
1069
1069
  const aged = (previous ?? [])
1070
1070
  .map((signal) => ({
1071
1071
  ...signal,
1072
- intensity: clamp01(signal.intensity * (mode === "work" ? 0.94 : 0.97)),
1072
+ intensity: clamp01(signal.intensity * MODE_PROFILES[mode ?? "natural"].relationDecay),
1073
1073
  readyInTurns: Math.max(0, signal.readyInTurns - 1),
1074
1074
  ttl: signal.ttl - 1,
1075
1075
  }))
@@ -1095,7 +1095,7 @@ export function evolvePendingRelationSignals(previous, move, appraisal, opts) {
1095
1095
  move: move.type,
1096
1096
  intensity: clamp01(move.intensity * (move.type === "repair" ? 0.42 : 0.54)),
1097
1097
  readyInTurns: move.type === "repair" ? 0 : 1,
1098
- ttl: mode === "work" ? 4 : 6,
1098
+ ttl: MODE_PROFILES[mode ?? "natural"].relationSignalTTL,
1099
1099
  });
1100
1100
  }
1101
1101
  return {
@@ -17,6 +17,7 @@ export function deriveReplyEnvelope(state, appraisal, opts) {
17
17
  algorithmStimulus: opts.algorithmStimulus,
18
18
  classificationConfidence: opts.classificationConfidence,
19
19
  personalityIntensity: opts.personalityIntensity,
20
+ mode: state.meta.mode,
20
21
  });
21
22
  const generationControls = deriveGenerationControls({
22
23
  responseContract,
@@ -5,5 +5,6 @@ export declare function computeResponseContract(kernel: SubjectivityKernel, opts
5
5
  algorithmStimulus?: StimulusType | null;
6
6
  classificationConfidence?: number;
7
7
  personalityIntensity?: number;
8
+ mode?: "natural" | "work" | "companion";
8
9
  }): ResponseContract;
9
10
  export declare function buildResponseContractContext(contract: ResponseContract, locale?: Locale): string;
@@ -4,6 +4,7 @@
4
4
  // Converts subjectivity + immediate message shape into a narrow reply ABI.
5
5
  // Pure, synchronous, and intended to replace verbose prompt rules.
6
6
  // ============================================================
7
+ import { MODE_PROFILES } from "./types.js";
7
8
  const EMOTIONAL_STIMULI = new Set(["vulnerability", "intimacy", "neglect"]);
8
9
  function clampInt(v, min, max) {
9
10
  return Math.max(min, Math.min(max, Math.round(v)));
@@ -199,6 +200,7 @@ export function computeResponseContract(kernel, opts) {
199
200
  const locale = opts?.locale ?? "zh";
200
201
  const userText = opts?.userText ?? "";
201
202
  const personalityIntensity = opts?.personalityIntensity ?? 0.7;
203
+ const profile = MODE_PROFILES[opts?.mode ?? "natural"];
202
204
  const { replyProfile, replyProfileBasis } = deriveReplyProfile(kernel);
203
205
  const classificationConfidence = opts?.classificationConfidence ?? 0;
204
206
  const overrideWindow = classificationConfidence >= 0.78
@@ -206,7 +208,7 @@ export function computeResponseContract(kernel, opts) {
206
208
  : classificationConfidence >= 0.62
207
209
  ? "balanced"
208
210
  : "wide";
209
- const { maxSentences, maxChars } = userText.length > 0
211
+ let { maxSentences, maxChars } = userText.length > 0
210
212
  ? computeLengthBudget(locale, userText, replyProfile, kernel.expressionMode, kernel)
211
213
  : {
212
214
  maxSentences: replyProfile === "work"
@@ -214,6 +216,12 @@ export function computeResponseContract(kernel, opts) {
214
216
  : kernel.expressionMode === "brief" ? 1 : kernel.expressionMode === "expansive" ? 3 : 2,
215
217
  maxChars: replyProfile === "work" ? 160 : undefined,
216
218
  };
219
+ // Mode-aware length adjustment: affects maxTokens ceiling (host layer).
220
+ // Prompt uses vibe words derived from maxSentences, not precise numbers.
221
+ if (maxChars !== undefined && profile.lengthMultiplier !== 1.0) {
222
+ maxChars = Math.round(maxChars * profile.lengthMultiplier);
223
+ }
224
+ maxSentences = Math.max(profile.minSentences, maxSentences);
217
225
  let updateMode = "none";
218
226
  if (kernel.taskPlane.focus > 0.72) {
219
227
  updateMode = "none";
@@ -287,7 +295,7 @@ export function computeResponseContract(kernel, opts) {
287
295
  boundaryMode,
288
296
  toneParticles: userText.length > 0 ? detectToneParticles(userText, locale) : "natural",
289
297
  emojiLimit: userText.length > 0 ? detectEmojiLimit(userText) : 0,
290
- authenticityMode: personalityIntensity >= 0.3 ? "strict" : "friendly",
298
+ authenticityMode: personalityIntensity >= 0.3 && !(profile.authenticityWhenWarm === "friendly" && socialDistance === "warm") ? "strict" : "friendly",
291
299
  updateMode,
292
300
  };
293
301
  }
@@ -319,16 +327,33 @@ function describeOverrideWindow(overrideWindow, locale) {
319
327
  }
320
328
  return `override:${overrideWindow}`;
321
329
  }
330
+ // Length vibe: soft directional cue, not a hard number.
331
+ // maxChars stays internal for host-controls maxTokens calculation.
332
+ function describeLengthVibe(maxSentences, locale) {
333
+ if (locale === "zh") {
334
+ if (maxSentences <= 1)
335
+ return "简短回";
336
+ if (maxSentences <= 2)
337
+ return "一两句";
338
+ if (maxSentences <= 3)
339
+ return "两三句";
340
+ return "可以展开";
341
+ }
342
+ if (maxSentences <= 1)
343
+ return "keep brief";
344
+ if (maxSentences <= 2)
345
+ return "a sentence or two";
346
+ if (maxSentences <= 3)
347
+ return "a few sentences";
348
+ return "feel free to elaborate";
349
+ }
322
350
  export function buildResponseContractContext(contract, locale = "zh") {
323
351
  if (locale === "zh") {
324
352
  const parts = [];
325
353
  parts.push(contract.replyProfile === "work" ? "工作" : "私人");
326
354
  parts.push(describeReplyProfileBasis(contract.replyProfileBasis, locale));
327
355
  parts.push(describeOverrideWindow(contract.overrideWindow, locale));
328
- const shape = contract.maxChars
329
- ? `${contract.maxSentences === 1 ? "1句内" : `${contract.maxSentences}句`}≤${contract.maxChars}字`
330
- : `${contract.maxSentences === 1 ? "1句内" : `${contract.maxSentences}句`}`;
331
- parts.push(shape);
356
+ parts.push(describeLengthVibe(contract.maxSentences, locale));
332
357
  if (contract.initiativeMode === "reactive")
333
358
  parts.push("少主动");
334
359
  else if (contract.initiativeMode === "proactive")
@@ -367,10 +392,7 @@ export function buildResponseContractContext(contract, locale = "zh") {
367
392
  parts.push(contract.replyProfile === "work" ? "work surface" : "private surface");
368
393
  parts.push(describeReplyProfileBasis(contract.replyProfileBasis, locale));
369
394
  parts.push(describeOverrideWindow(contract.overrideWindow, locale));
370
- const shape = contract.maxChars
371
- ? `${contract.maxSentences === 1 ? "1 sentence" : `up to ${contract.maxSentences} sentences`}, <= ${contract.maxChars} chars`
372
- : `${contract.maxSentences === 1 ? "1 sentence" : `up to ${contract.maxSentences} sentences`}`;
373
- parts.push(shape);
395
+ parts.push(describeLengthVibe(contract.maxSentences, locale));
374
396
  if (contract.initiativeMode === "reactive")
375
397
  parts.push("low initiative");
376
398
  else if (contract.initiativeMode === "proactive")
package/dist/types.d.ts CHANGED
@@ -41,6 +41,22 @@ export declare const CHEMICAL_DECAY_SPEED: Record<keyof ChemicalState, DecaySpee
41
41
  export declare const CHEMICAL_RUNTIME_SPECS: Record<keyof ChemicalState, ChemicalRuntimeSpec>;
42
42
  /** Psyche operating mode */
43
43
  export type PsycheMode = "natural" | "work" | "companion";
44
+ /** Mode profile — all mode-specific parameters in one place. */
45
+ export interface ModeProfile {
46
+ chemistryMultiplier: number;
47
+ maxChemicalDelta: number | null;
48
+ nearBaselineThreshold: number;
49
+ otWarmthThreshold: number;
50
+ lengthMultiplier: number;
51
+ minSentences: number;
52
+ authenticityWhenWarm: "strict" | "friendly";
53
+ toneParticlesDefault: boolean;
54
+ relationDecay: number;
55
+ relationDrift: number;
56
+ relationSignalTTL: number;
57
+ appraisalDecay: number;
58
+ }
59
+ export declare const MODE_PROFILES: Record<PsycheMode, ModeProfile>;
44
60
  /** Big Five personality traits (0-100 each) */
45
61
  export interface PersonalityTraits {
46
62
  openness: number;
package/dist/types.js CHANGED
@@ -67,6 +67,50 @@ export const CHEMICAL_RUNTIME_SPECS = {
67
67
  NE: { normalMin: 30, normalMax: 70, halfLifeHours: decayHalfLifeHours(DECAY_FACTORS.fast) },
68
68
  END: { normalMin: 30, normalMax: 70, halfLifeHours: decayHalfLifeHours(DECAY_FACTORS.fast) },
69
69
  };
70
+ export const MODE_PROFILES = {
71
+ work: {
72
+ chemistryMultiplier: 0.3,
73
+ maxChemicalDelta: 5,
74
+ nearBaselineThreshold: 20,
75
+ otWarmthThreshold: 10,
76
+ lengthMultiplier: 1.0,
77
+ minSentences: 1,
78
+ authenticityWhenWarm: "strict",
79
+ toneParticlesDefault: false,
80
+ relationDecay: 0.94,
81
+ relationDrift: 0.06,
82
+ relationSignalTTL: 4,
83
+ appraisalDecay: 0.68,
84
+ },
85
+ natural: {
86
+ chemistryMultiplier: 1.0,
87
+ maxChemicalDelta: null,
88
+ nearBaselineThreshold: 8,
89
+ otWarmthThreshold: 10,
90
+ lengthMultiplier: 1.0,
91
+ minSentences: 1,
92
+ authenticityWhenWarm: "strict",
93
+ toneParticlesDefault: false,
94
+ relationDecay: 0.97,
95
+ relationDrift: 0.04,
96
+ relationSignalTTL: 6,
97
+ appraisalDecay: 0.78,
98
+ },
99
+ companion: {
100
+ chemistryMultiplier: 1.5,
101
+ maxChemicalDelta: null,
102
+ nearBaselineThreshold: 5,
103
+ otWarmthThreshold: 5,
104
+ lengthMultiplier: 1.5,
105
+ minSentences: 2,
106
+ authenticityWhenWarm: "friendly",
107
+ toneParticlesDefault: true,
108
+ relationDecay: 0.97,
109
+ relationDrift: 0.04,
110
+ relationSignalTTL: 6,
111
+ appraisalDecay: 0.86,
112
+ },
113
+ };
70
114
  /** Default attachment for new relationships */
71
115
  export const DEFAULT_ATTACHMENT = {
72
116
  style: "secure",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "psyche-ai",
3
- "version": "10.0.0",
3
+ "version": "10.0.2",
4
4
  "description": "AI-first subjectivity kernel for agents with continuous appraisal, relation dynamics, and adaptive reply loops",
5
5
  "mcpName": "io.github.Shangri-la-0428/psyche-ai",
6
6
  "type": "module",