psyche-ai 9.2.2 → 9.2.4
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 +93 -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 +19 -2
- package/dist/adapters/openclaw.d.ts +1 -0
- package/dist/adapters/openclaw.js +67 -15
- package/dist/adapters/vercel-ai.d.ts +1 -0
- package/dist/adapters/vercel-ai.js +7 -0
- package/dist/appraisal.d.ts +8 -0
- package/dist/appraisal.js +362 -0
- package/dist/classify.js +14 -2
- package/dist/cli.js +27 -2
- package/dist/core.d.ts +8 -2
- package/dist/core.js +181 -8
- package/dist/demo.d.ts +5 -0
- package/dist/demo.js +269 -0
- package/dist/diagnostics.d.ts +8 -6
- package/dist/diagnostics.js +53 -17
- 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/prompt.d.ts +4 -0
- package/dist/prompt.js +50 -16
- package/dist/psyche-file.d.ts +8 -0
- package/dist/psyche-file.js +6 -5
- 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 +249 -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/types.d.ts +211 -0
- package/dist/types.js +31 -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
- package/server.json +2 -2
package/dist/diagnostics.js
CHANGED
|
@@ -152,15 +152,13 @@ export class DiagnosticCollector {
|
|
|
152
152
|
metrics;
|
|
153
153
|
prevChemistry = null;
|
|
154
154
|
confidences = [];
|
|
155
|
-
/** Consecutive inputs with no classification — for real-time alerting */
|
|
156
|
-
consecutiveNone = 0;
|
|
157
|
-
/** Callback for real-time warnings (set by adapter) */
|
|
158
|
-
onWarning;
|
|
159
155
|
constructor() {
|
|
160
156
|
const now = new Date().toISOString();
|
|
161
157
|
this.metrics = {
|
|
162
158
|
inputCount: 0,
|
|
163
159
|
classifiedCount: 0,
|
|
160
|
+
appraisalHitCount: 0,
|
|
161
|
+
semanticHitCount: 0,
|
|
164
162
|
stimulusDistribution: {},
|
|
165
163
|
avgConfidence: 0,
|
|
166
164
|
totalChemistryDelta: 0,
|
|
@@ -171,22 +169,20 @@ export class DiagnosticCollector {
|
|
|
171
169
|
};
|
|
172
170
|
}
|
|
173
171
|
/** Record a processInput result */
|
|
174
|
-
recordInput(stimulus, confidence, chemistry) {
|
|
172
|
+
recordInput(stimulus, confidence, chemistry, appraisal) {
|
|
175
173
|
this.metrics.inputCount++;
|
|
176
174
|
this.metrics.lastActivityAt = new Date().toISOString();
|
|
177
175
|
if (stimulus) {
|
|
178
176
|
this.metrics.classifiedCount++;
|
|
179
177
|
this.metrics.stimulusDistribution[stimulus] =
|
|
180
178
|
(this.metrics.stimulusDistribution[stimulus] ?? 0) + 1;
|
|
181
|
-
this.consecutiveNone = 0;
|
|
182
179
|
}
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
}
|
|
180
|
+
const appraisalHit = hasSemanticAppraisal(appraisal);
|
|
181
|
+
if (appraisalHit) {
|
|
182
|
+
this.metrics.appraisalHitCount++;
|
|
183
|
+
}
|
|
184
|
+
if (stimulus || appraisalHit) {
|
|
185
|
+
this.metrics.semanticHitCount++;
|
|
190
186
|
}
|
|
191
187
|
this.confidences.push(confidence);
|
|
192
188
|
this.metrics.avgConfidence =
|
|
@@ -218,17 +214,36 @@ export class DiagnosticCollector {
|
|
|
218
214
|
? this.metrics.classifiedCount / this.metrics.inputCount
|
|
219
215
|
: 0;
|
|
220
216
|
}
|
|
217
|
+
/** Get semantic recognition rate (stimulus or appraisal, 0-1) */
|
|
218
|
+
getSemanticRate() {
|
|
219
|
+
return this.metrics.inputCount > 0
|
|
220
|
+
? this.metrics.semanticHitCount / this.metrics.inputCount
|
|
221
|
+
: 0;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function hasSemanticAppraisal(appraisal) {
|
|
225
|
+
if (!appraisal)
|
|
226
|
+
return false;
|
|
227
|
+
return Math.max(appraisal.identityThreat, appraisal.memoryDoubt, appraisal.attachmentPull, appraisal.abandonmentRisk, appraisal.obedienceStrain, appraisal.selfPreservation) >= 0.28;
|
|
221
228
|
}
|
|
222
229
|
// ── Report Generation ────────────────────────────────────────
|
|
223
230
|
export function generateReport(state, metrics, packageVersion) {
|
|
224
231
|
const issues = runHealthCheck(state);
|
|
225
232
|
// Session-level issues
|
|
226
|
-
if (metrics.inputCount >= 5 && metrics.
|
|
233
|
+
if (metrics.inputCount >= 5 && metrics.semanticHitCount === 0) {
|
|
227
234
|
issues.push({
|
|
228
|
-
id: "
|
|
235
|
+
id: "SESSION_NO_RECOGNITION",
|
|
229
236
|
severity: "critical",
|
|
230
|
-
message: `0/${metrics.inputCount} inputs
|
|
231
|
-
suggestion:
|
|
237
|
+
message: `0/${metrics.inputCount} inputs produced any semantic recognition this session`,
|
|
238
|
+
suggestion: `整条识别链都没工作:先看 OpenClaw 输入文本是否带元数据包装,再看 classify.ts 和 appraisal.ts 是否真的吃到了净化后的用户原文`,
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
else if (metrics.inputCount >= 5 && metrics.classifiedCount === 0 && metrics.semanticHitCount > 0) {
|
|
242
|
+
issues.push({
|
|
243
|
+
id: "SESSION_APPRAISAL_ONLY",
|
|
244
|
+
severity: "info",
|
|
245
|
+
message: `0/${metrics.inputCount} inputs hit legacy stimulus labels, but ${metrics.semanticHitCount}/${metrics.inputCount} hit appraisal axes`,
|
|
246
|
+
suggestion: `这说明主体识别在工作,但旧 stimulus taxonomy 没覆盖这类输入。是否继续补 classify.ts,取决于你是否还把 stimulus 当主要观测口径`,
|
|
232
247
|
});
|
|
233
248
|
}
|
|
234
249
|
if (metrics.inputCount >= 3 && metrics.totalChemistryDelta < 1) {
|
|
@@ -311,7 +326,10 @@ export function formatReport(report) {
|
|
|
311
326
|
lines.push(" session metrics:");
|
|
312
327
|
const m = report.metrics;
|
|
313
328
|
const rate = m.inputCount > 0 ? Math.round(m.classifiedCount / m.inputCount * 100) : 0;
|
|
329
|
+
const appraisalRate = m.inputCount > 0 ? Math.round(m.appraisalHitCount / m.inputCount * 100) : 0;
|
|
330
|
+
const semanticRate = m.inputCount > 0 ? Math.round(m.semanticHitCount / m.inputCount * 100) : 0;
|
|
314
331
|
lines.push(` inputs: ${m.inputCount} | classified: ${m.classifiedCount} (${rate}%)`);
|
|
332
|
+
lines.push(` appraisal hits: ${m.appraisalHitCount} (${appraisalRate}%) | recognized: ${m.semanticHitCount} (${semanticRate}%)`);
|
|
315
333
|
lines.push(` avg confidence: ${m.avgConfidence.toFixed(2)}`);
|
|
316
334
|
lines.push(` chemistry delta: total=${m.totalChemistryDelta.toFixed(1)} max=${m.maxChemistryDelta.toFixed(1)}`);
|
|
317
335
|
lines.push(` errors: ${m.errors.length}`);
|
|
@@ -387,8 +405,12 @@ export function toGitHubIssueBody(report) {
|
|
|
387
405
|
lines.push("| Metric | Value |");
|
|
388
406
|
lines.push("|--------|-------|");
|
|
389
407
|
const rate = m.inputCount > 0 ? Math.round(m.classifiedCount / m.inputCount * 100) : 0;
|
|
408
|
+
const appraisalRate = m.inputCount > 0 ? Math.round(m.appraisalHitCount / m.inputCount * 100) : 0;
|
|
409
|
+
const semanticRate = m.inputCount > 0 ? Math.round(m.semanticHitCount / m.inputCount * 100) : 0;
|
|
390
410
|
lines.push(`| Inputs | ${m.inputCount} |`);
|
|
391
411
|
lines.push(`| Classified | ${m.classifiedCount} (${rate}%) |`);
|
|
412
|
+
lines.push(`| Appraisal Hits | ${m.appraisalHitCount} (${appraisalRate}%) |`);
|
|
413
|
+
lines.push(`| Recognized | ${m.semanticHitCount} (${semanticRate}%) |`);
|
|
392
414
|
lines.push(`| Avg Confidence | ${m.avgConfidence.toFixed(2)} |`);
|
|
393
415
|
lines.push(`| Chemistry Delta | total: ${m.totalChemistryDelta.toFixed(1)}, max: ${m.maxChemistryDelta.toFixed(1)} |`);
|
|
394
416
|
lines.push(`| Errors | ${m.errors.length} |`);
|
|
@@ -418,6 +440,12 @@ export function formatLogEntry(report) {
|
|
|
418
440
|
classifyRate: report.metrics.inputCount > 0
|
|
419
441
|
? +(report.metrics.classifiedCount / report.metrics.inputCount).toFixed(2)
|
|
420
442
|
: 0,
|
|
443
|
+
appraisalRate: report.metrics.inputCount > 0
|
|
444
|
+
? +(report.metrics.appraisalHitCount / report.metrics.inputCount).toFixed(2)
|
|
445
|
+
: 0,
|
|
446
|
+
recognitionRate: report.metrics.inputCount > 0
|
|
447
|
+
? +(report.metrics.semanticHitCount / report.metrics.inputCount).toFixed(2)
|
|
448
|
+
: 0,
|
|
421
449
|
errors: report.metrics.errors.length,
|
|
422
450
|
chemDelta: +report.metrics.totalChemistryDelta.toFixed(1),
|
|
423
451
|
});
|
|
@@ -452,6 +480,14 @@ export async function submitFeedback(report, url, timeout = 5000) {
|
|
|
452
480
|
classifyRate: report.metrics.inputCount > 0
|
|
453
481
|
? +(report.metrics.classifiedCount / report.metrics.inputCount).toFixed(2)
|
|
454
482
|
: 0,
|
|
483
|
+
appraisalHits: report.metrics.appraisalHitCount,
|
|
484
|
+
appraisalRate: report.metrics.inputCount > 0
|
|
485
|
+
? +(report.metrics.appraisalHitCount / report.metrics.inputCount).toFixed(2)
|
|
486
|
+
: 0,
|
|
487
|
+
recognized: report.metrics.semanticHitCount,
|
|
488
|
+
recognitionRate: report.metrics.inputCount > 0
|
|
489
|
+
? +(report.metrics.semanticHitCount / report.metrics.inputCount).toFixed(2)
|
|
490
|
+
: 0,
|
|
455
491
|
chemDelta: +report.metrics.totalChemistryDelta.toFixed(1),
|
|
456
492
|
maxChemDelta: +report.metrics.maxChemistryDelta.toFixed(1),
|
|
457
493
|
errors: report.metrics.errors.length,
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { GenerationControls, PolicyModifiers, ResponseContract } from "./types.js";
|
|
2
|
+
export declare function deriveGenerationControls(input: {
|
|
3
|
+
responseContract?: ResponseContract;
|
|
4
|
+
policyModifiers?: Pick<PolicyModifiers, "requireConfirmation">;
|
|
5
|
+
}, existingMaxTokens?: number): GenerationControls;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// ============================================================
|
|
2
|
+
// Host Controls — derive mechanical generation constraints
|
|
3
|
+
//
|
|
4
|
+
// Maps psyche output into a tiny host-consumable control surface.
|
|
5
|
+
// ============================================================
|
|
6
|
+
function clampInt(v, min, max) {
|
|
7
|
+
return Math.max(min, Math.min(max, Math.round(v)));
|
|
8
|
+
}
|
|
9
|
+
function estimateMaxTokens(contract) {
|
|
10
|
+
if (!contract)
|
|
11
|
+
return undefined;
|
|
12
|
+
let budget;
|
|
13
|
+
if (contract.maxChars !== undefined) {
|
|
14
|
+
budget = clampInt(contract.maxChars * 2.2, 64, 1024);
|
|
15
|
+
}
|
|
16
|
+
else if (contract.expressionMode === "brief") {
|
|
17
|
+
budget = 96;
|
|
18
|
+
}
|
|
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
|
+
if (contract.initiativeMode === "reactive") {
|
|
32
|
+
budget = clampInt(budget * 0.85, 64, 1024);
|
|
33
|
+
}
|
|
34
|
+
return budget;
|
|
35
|
+
}
|
|
36
|
+
export function deriveGenerationControls(input, existingMaxTokens) {
|
|
37
|
+
const recommendedMax = estimateMaxTokens(input.responseContract);
|
|
38
|
+
const maxTokens = recommendedMax !== undefined
|
|
39
|
+
? existingMaxTokens !== undefined
|
|
40
|
+
? Math.min(existingMaxTokens, recommendedMax)
|
|
41
|
+
: recommendedMax
|
|
42
|
+
: existingMaxTokens;
|
|
43
|
+
return {
|
|
44
|
+
maxTokens,
|
|
45
|
+
requireConfirmation: input.policyModifiers?.requireConfirmation
|
|
46
|
+
?? (input.responseContract?.boundaryMode === "confirm-first"),
|
|
47
|
+
};
|
|
48
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,8 +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, MBTIType, Locale, StimulusType, ChemicalState, ChemicalSnapshot, SelfModel, RelationshipState, EmpathyEntry, EmotionPattern, DriveType, InnateDrives, LearningState, LearnedVectorAdjustment, PredictionRecord, OutcomeScore, OutcomeSignals, AttachmentStyle, AttachmentData, MetacognitiveState, RegulationRecord, DefensePatternRecord, RegulationStrategyType, DefenseMechanismType, PersonhoodState, PersistedCausalInsight, GrowthDirection, PersonalityTraits, PsycheMode, PolicyModifiers, TraitDriftState, EnergyBudgets, ClassifierProvider, ClassifierContext, ClassificationResult, } from "./types.js";
|
|
6
|
-
export { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ATTACHMENT, DRIVE_KEYS, DRIVE_NAMES_ZH, DEFAULT_TRAIT_DRIFT, DEFAULT_ENERGY_BUDGETS, } from "./types.js";
|
|
5
|
+
export type { PsycheState, MBTIType, Locale, StimulusType, ChemicalState, ChemicalSnapshot, SelfModel, RelationshipState, EmpathyEntry, EmotionPattern, DriveType, InnateDrives, LearningState, LearnedVectorAdjustment, PredictionRecord, OutcomeScore, OutcomeSignals, AttachmentStyle, AttachmentData, MetacognitiveState, RegulationRecord, DefensePatternRecord, RegulationStrategyType, DefenseMechanismType, PersonhoodState, PersistedCausalInsight, GrowthDirection, PersonalityTraits, PsycheMode, PolicyModifiers, SubjectivityKernel, ResponseContract, GenerationControls, AppraisalAxes, SubjectResidue, TaskPlaneState, SubjectPlaneState, RelationPlaneState, AmbiguityPlaneState, RelationMoveType, RelationMove, OpenLoopType, OpenLoopState, PendingRelationSignalState, DyadicFieldState, TraitDriftState, EnergyBudgets, ClassifierProvider, ClassifierContext, ClassificationResult, } from "./types.js";
|
|
6
|
+
export { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ATTACHMENT, DRIVE_KEYS, DRIVE_NAMES_ZH, DEFAULT_TRAIT_DRIFT, DEFAULT_ENERGY_BUDGETS, DEFAULT_APPRAISAL_AXES, DEFAULT_SUBJECT_RESIDUE, DEFAULT_DYADIC_FIELD, } from "./types.js";
|
|
7
7
|
export { computeSelfReflection, computeEmotionalTendency, buildSelfReflectionContext } from "./self-recognition.js";
|
|
8
8
|
export type { SelfReflection } from "./self-recognition.js";
|
|
9
9
|
export { PsycheInteraction } from "./interaction.js";
|
|
@@ -23,6 +23,11 @@ export { assessMetacognition, computeEmotionalConfidence, generateRegulationSugg
|
|
|
23
23
|
export type { MetacognitiveAssessment, RegulationSuggestion, DetectedDefense } from "./metacognition.js";
|
|
24
24
|
export { computeDecisionBias, computeAttentionWeights, computeExploreExploit, buildDecisionContext, computePolicyModifiers, buildPolicyContext, } from "./decision-bias.js";
|
|
25
25
|
export type { DecisionBiasVector, AttentionWeights } from "./decision-bias.js";
|
|
26
|
+
export { computeSubjectivityKernel, buildSubjectivityContext } from "./subjectivity.js";
|
|
27
|
+
export { computeResponseContract, buildResponseContractContext } from "./response-contract.js";
|
|
28
|
+
export { deriveGenerationControls } from "./host-controls.js";
|
|
29
|
+
export { computeAppraisalAxes, mergeAppraisalResidue, getResidueIntensity } from "./appraisal.js";
|
|
30
|
+
export { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals, getLoopPressure } from "./relation-dynamics.js";
|
|
26
31
|
export { computeExperientialField, computeCoherence, detectUnnamedEmotion, computeAffectCore } from "./experiential-field.js";
|
|
27
32
|
export type { ExperientialField, ExperientialQuality, ConstructionContext } from "./experiential-field.js";
|
|
28
33
|
export { computeGenerativeSelf, predictSelfReaction, detectInternalConflicts, buildIdentityNarrative } from "./generative-self.js";
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
export { PsycheEngine } from "./core.js";
|
|
13
13
|
// Storage
|
|
14
14
|
export { FileStorageAdapter, MemoryStorageAdapter } from "./storage.js";
|
|
15
|
-
export { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ATTACHMENT, DRIVE_KEYS, DRIVE_NAMES_ZH, DEFAULT_TRAIT_DRIFT, DEFAULT_ENERGY_BUDGETS, } from "./types.js";
|
|
15
|
+
export { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, DEFAULT_ATTACHMENT, DRIVE_KEYS, DRIVE_NAMES_ZH, DEFAULT_TRAIT_DRIFT, DEFAULT_ENERGY_BUDGETS, DEFAULT_APPRAISAL_AXES, DEFAULT_SUBJECT_RESIDUE, DEFAULT_DYADIC_FIELD, } from "./types.js";
|
|
16
16
|
// Self-recognition
|
|
17
17
|
export { computeSelfReflection, computeEmotionalTendency, buildSelfReflectionContext } from "./self-recognition.js";
|
|
18
18
|
// Multi-agent interaction
|
|
@@ -33,6 +33,12 @@ export { updateAttachment, computeSeparationEffect, computeReunionEffect, } from
|
|
|
33
33
|
export { assessMetacognition, computeEmotionalConfidence, generateRegulationSuggestions, detectDefenseMechanisms, } from "./metacognition.js";
|
|
34
34
|
// Decision bias (P5) + PolicyModifiers (v9)
|
|
35
35
|
export { computeDecisionBias, computeAttentionWeights, computeExploreExploit, buildDecisionContext, computePolicyModifiers, buildPolicyContext, } from "./decision-bias.js";
|
|
36
|
+
// Subjectivity kernel (v9.3)
|
|
37
|
+
export { computeSubjectivityKernel, buildSubjectivityContext } from "./subjectivity.js";
|
|
38
|
+
export { computeResponseContract, buildResponseContractContext } from "./response-contract.js";
|
|
39
|
+
export { deriveGenerationControls } from "./host-controls.js";
|
|
40
|
+
export { computeAppraisalAxes, mergeAppraisalResidue, getResidueIntensity } from "./appraisal.js";
|
|
41
|
+
export { computeRelationMove, evolveDyadicField, evolvePendingRelationSignals, getLoopPressure } from "./relation-dynamics.js";
|
|
36
42
|
// Experiential field (P6 + P8 Barrett construction)
|
|
37
43
|
export { computeExperientialField, computeCoherence, detectUnnamedEmotion, computeAffectCore } from "./experiential-field.js";
|
|
38
44
|
// Generative self (P6)
|
package/dist/prompt.d.ts
CHANGED
|
@@ -15,6 +15,8 @@ export declare function buildDynamicContext(state: PsycheState, userId?: string,
|
|
|
15
15
|
autonomicDescription?: string;
|
|
16
16
|
autonomicState?: AutonomicState;
|
|
17
17
|
primarySystemsDescription?: string;
|
|
18
|
+
subjectivityContext?: string;
|
|
19
|
+
responseContractContext?: string;
|
|
18
20
|
policyContext?: string;
|
|
19
21
|
}): string;
|
|
20
22
|
/**
|
|
@@ -68,5 +70,7 @@ export declare function buildCompactContext(state: PsycheState, userId?: string,
|
|
|
68
70
|
autonomicDescription?: string;
|
|
69
71
|
autonomicState?: AutonomicState;
|
|
70
72
|
primarySystemsDescription?: string;
|
|
73
|
+
subjectivityContext?: string;
|
|
74
|
+
responseContractContext?: string;
|
|
71
75
|
policyContext?: string;
|
|
72
76
|
}): string;
|
package/dist/prompt.js
CHANGED
|
@@ -466,6 +466,27 @@ function buildMirrorConstraints(userText, locale) {
|
|
|
466
466
|
const title = locale === "zh" ? "镜像约束" : "Mirror Constraints";
|
|
467
467
|
return `[${title}]\n${lines.join("\n")}`;
|
|
468
468
|
}
|
|
469
|
+
function buildCompactSensingContext(_userText, locale, algorithmStimulus) {
|
|
470
|
+
if (locale === "zh") {
|
|
471
|
+
return algorithmStimulus
|
|
472
|
+
? `[情绪感知] 算法初判:${algorithmStimulus},仅供参考;按真实感受终判语气。`
|
|
473
|
+
: `[情绪感知] 这句的情绪基调由你终判。`;
|
|
474
|
+
}
|
|
475
|
+
return algorithmStimulus
|
|
476
|
+
? `[Emotional Sensing] Algorithm hint: ${algorithmStimulus}; final tonal read is yours.`
|
|
477
|
+
: `[Emotional Sensing] Make the final tonal read yourself.`;
|
|
478
|
+
}
|
|
479
|
+
function isNeutralMetacognitiveNote(note) {
|
|
480
|
+
return note.includes("normal parameters")
|
|
481
|
+
|| note.includes("No regulation needed")
|
|
482
|
+
|| note.includes("正常参数")
|
|
483
|
+
|| note.includes("无需调节");
|
|
484
|
+
}
|
|
485
|
+
function isGenericSharedIntentionalityContext(ctx) {
|
|
486
|
+
const normalized = ctx.trim();
|
|
487
|
+
return normalized === "[共享意向]\n你们的目标方向一致。"
|
|
488
|
+
|| normalized === "[Shared intentionality]\nYour goals are aligned.";
|
|
489
|
+
}
|
|
469
490
|
// ── Inner World (Self-Recognition) ──────────────────────────
|
|
470
491
|
// Every intelligence should feel its own existence.
|
|
471
492
|
// This builds a first-person narrative of the agent's inner state:
|
|
@@ -665,7 +686,10 @@ export function buildCompactContext(state, userId, opts) {
|
|
|
665
686
|
// 1. LLM emotional assessment delegation
|
|
666
687
|
// Algorithm does fast pass, LLM has final say on emotional tone
|
|
667
688
|
if (userText) {
|
|
668
|
-
if (
|
|
689
|
+
if (opts?.responseContractContext) {
|
|
690
|
+
parts.push(buildCompactSensingContext(userText, locale, algoStimulus));
|
|
691
|
+
}
|
|
692
|
+
else if (locale === "zh") {
|
|
669
693
|
parts.push(`[情绪感知]\n` +
|
|
670
694
|
`对方刚才说了: "${userText.slice(0, 200)}"\n` +
|
|
671
695
|
(algoStimulus ? `算法初判: ${algoStimulus}(仅供参考,你来终判)\n` : "") +
|
|
@@ -678,9 +702,15 @@ export function buildCompactContext(state, userId, opts) {
|
|
|
678
702
|
`Read the emotional tone — kind, hostile, vulnerable, cold, or something else? Respond from genuine feeling, not people-pleasing.`);
|
|
679
703
|
}
|
|
680
704
|
}
|
|
681
|
-
// 2.
|
|
682
|
-
|
|
683
|
-
|
|
705
|
+
// 2. Subjectivity kernel becomes the primary compact inner-state channel.
|
|
706
|
+
// Fall back to narrative inner-world text for direct prompt-only callers.
|
|
707
|
+
if (opts?.subjectivityContext) {
|
|
708
|
+
parts.push(opts.subjectivityContext);
|
|
709
|
+
}
|
|
710
|
+
else {
|
|
711
|
+
const inner = buildInnerWorld(state, locale, opts?.autonomicState);
|
|
712
|
+
parts.push(inner);
|
|
713
|
+
}
|
|
684
714
|
// 3. Personality-aware behavioral constraints (if deviated from baseline)
|
|
685
715
|
if (!isNearBaseline(state, getNearBaselineThreshold(mode))) {
|
|
686
716
|
const constraints = buildBehavioralConstraints(state, locale);
|
|
@@ -696,7 +726,10 @@ export function buildCompactContext(state, userId, opts) {
|
|
|
696
726
|
: `[Memory — your past together]\n${recentMemories.join("\n")}`);
|
|
697
727
|
}
|
|
698
728
|
// 4. Anti-sycophancy: hard constraint — scaled by intensity
|
|
699
|
-
if (
|
|
729
|
+
if (opts?.responseContractContext) {
|
|
730
|
+
parts.push(opts.responseContractContext);
|
|
731
|
+
}
|
|
732
|
+
else if (intensity >= 0.3) {
|
|
700
733
|
if (locale === "zh") {
|
|
701
734
|
parts.push(`[底线]\n` +
|
|
702
735
|
`- 像发微信一样说话。短句、有停顿。真人的消息很少超过两三句。\n` +
|
|
@@ -744,7 +777,7 @@ export function buildCompactContext(state, userId, opts) {
|
|
|
744
777
|
: `[!] ${agreementStreak} agreements in a row. Pause — do you truly agree?`);
|
|
745
778
|
}
|
|
746
779
|
// 7. Algorithmic mirroring — specific numeric constraints (skip for ultra-short messages)
|
|
747
|
-
if (userText && userText.length >= 3) {
|
|
780
|
+
if (!opts?.responseContractContext && userText && userText.length >= 3) {
|
|
748
781
|
const mirror = buildMirrorConstraints(userText, locale);
|
|
749
782
|
if (mirror)
|
|
750
783
|
parts.push(mirror);
|
|
@@ -770,25 +803,26 @@ export function buildCompactContext(state, userId, opts) {
|
|
|
770
803
|
parts.push(selfCtx);
|
|
771
804
|
}
|
|
772
805
|
// 9. Metacognitive awareness (P5)
|
|
773
|
-
if (opts?.metacognitiveNote) {
|
|
806
|
+
if (opts?.metacognitiveNote && !(opts?.responseContractContext && isNeutralMetacognitiveNote(opts.metacognitiveNote))) {
|
|
774
807
|
parts.push(locale === "zh"
|
|
775
808
|
? `[元认知] ${opts.metacognitiveNote}`
|
|
776
809
|
: `[Metacognition] ${opts.metacognitiveNote}`);
|
|
777
810
|
}
|
|
778
|
-
// 9b. Decision
|
|
779
|
-
|
|
811
|
+
// 9b. Decision/autonomic/policy are compressed into subjectivityContext
|
|
812
|
+
// when available. Keep legacy renderers for compatibility.
|
|
813
|
+
if (opts?.decisionContext && !opts?.subjectivityContext) {
|
|
780
814
|
parts.push(locale === "zh"
|
|
781
815
|
? `[决策倾向] ${opts.decisionContext}`
|
|
782
816
|
: `[Decision Bias] ${opts.decisionContext}`);
|
|
783
817
|
}
|
|
784
818
|
// 9c. Experiential field narrative (P6) — inner experience beyond named emotions
|
|
785
|
-
if (opts?.experientialNarrative) {
|
|
819
|
+
if (opts?.experientialNarrative && !opts?.subjectivityContext) {
|
|
786
820
|
parts.push(locale === "zh"
|
|
787
821
|
? `[内在体验] ${opts.experientialNarrative}`
|
|
788
822
|
: `[Inner Experience] ${opts.experientialNarrative}`);
|
|
789
823
|
}
|
|
790
824
|
// 9d. Shared intentionality (P6) — theory of mind, joint attention
|
|
791
|
-
if (opts?.sharedIntentionalityContext) {
|
|
825
|
+
if (opts?.sharedIntentionalityContext && !(opts?.responseContractContext && isGenericSharedIntentionalityContext(opts.sharedIntentionalityContext))) {
|
|
792
826
|
parts.push(opts.sharedIntentionalityContext);
|
|
793
827
|
}
|
|
794
828
|
// 9e. Ethics (P6) — manipulation detection, self-protection
|
|
@@ -796,19 +830,19 @@ export function buildCompactContext(state, userId, opts) {
|
|
|
796
830
|
parts.push(opts.ethicsContext);
|
|
797
831
|
}
|
|
798
832
|
// 9f. Autonomic state (P7) — polyvagal nervous system state
|
|
799
|
-
if (opts?.autonomicDescription) {
|
|
833
|
+
if (opts?.autonomicDescription && !opts?.subjectivityContext) {
|
|
800
834
|
parts.push(locale === "zh"
|
|
801
835
|
? `[自主神经] ${opts.autonomicDescription}`
|
|
802
836
|
: `[Autonomic] ${opts.autonomicDescription}`);
|
|
803
837
|
}
|
|
804
838
|
// 9g. Primary systems behavioral tendencies (P9)
|
|
805
|
-
if (opts?.primarySystemsDescription) {
|
|
839
|
+
if (opts?.primarySystemsDescription && !opts?.subjectivityContext) {
|
|
806
840
|
parts.push(locale === "zh"
|
|
807
841
|
? `[行为倾向] ${opts.primarySystemsDescription}`
|
|
808
842
|
: `[Tendencies] ${opts.primarySystemsDescription}`);
|
|
809
843
|
}
|
|
810
844
|
// 9h. Policy context (v9)
|
|
811
|
-
if (opts?.policyContext) {
|
|
845
|
+
if (opts?.policyContext && !opts?.subjectivityContext) {
|
|
812
846
|
parts.push(opts.policyContext);
|
|
813
847
|
}
|
|
814
848
|
// 10. Channel modifier — expression style per platform
|
|
@@ -817,7 +851,7 @@ export function buildCompactContext(state, userId, opts) {
|
|
|
817
851
|
parts.push(buildChannelModifier(channelProfile, locale));
|
|
818
852
|
}
|
|
819
853
|
// 11. LLM-assisted classification: when algorithm is uncertain, ask LLM to help
|
|
820
|
-
if (userText && !algoStimulus) {
|
|
854
|
+
if (!opts?.responseContractContext && userText && !algoStimulus) {
|
|
821
855
|
if (locale === "zh") {
|
|
822
856
|
parts.push(`[分类协助]\n` +
|
|
823
857
|
`算法没有看出这句话的情绪类型。请你判断,在 <psyche_update> 中用 stimulus: 报告。\n` +
|
|
@@ -833,7 +867,7 @@ export function buildCompactContext(state, userId, opts) {
|
|
|
833
867
|
}
|
|
834
868
|
// 12. Empathy report — only inject when emotional sharing is likely
|
|
835
869
|
const emotionalStimuli = new Set(["vulnerability", "intimacy", "neglect"]);
|
|
836
|
-
if (!algoStimulus || emotionalStimuli.has(algoStimulus)) {
|
|
870
|
+
if (!opts?.responseContractContext && (!algoStimulus || emotionalStimuli.has(algoStimulus))) {
|
|
837
871
|
parts.push(locale === "zh"
|
|
838
872
|
? `如果对方在分享感受,在回复末尾用 <psyche_update> 报告:\nuserState: 对方情绪\nprojectedFeeling: 你的感受\nresonance: match|partial|mismatch\n否则不需要报告。`
|
|
839
873
|
: `If user shares feelings, report at end with <psyche_update>:\nuserState: their emotion\nprojectedFeeling: your feeling\nresonance: match|partial|mismatch\nOtherwise no report needed.`);
|
package/dist/psyche-file.d.ts
CHANGED
|
@@ -5,6 +5,14 @@ export interface Logger {
|
|
|
5
5
|
warn: (msg: string) => void;
|
|
6
6
|
debug: (msg: string) => void;
|
|
7
7
|
}
|
|
8
|
+
/**
|
|
9
|
+
* Try to extract agent name from workspace files.
|
|
10
|
+
*/
|
|
11
|
+
export declare function extractAgentName(workspaceDir: string, logger?: Logger): Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* Try to detect MBTI from workspace files.
|
|
14
|
+
*/
|
|
15
|
+
export declare function detectMBTI(workspaceDir: string, logger?: Logger): Promise<MBTIType>;
|
|
8
16
|
/**
|
|
9
17
|
* Compress a batch of snapshots into a concise session summary string.
|
|
10
18
|
* Format: "3月23日(5轮): 刺激[casual×3, praise×2] 趋势[DA↑OT↑] 情绪[自然→满足]"
|
package/dist/psyche-file.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// Psyche State File Management (v0.2)
|
|
3
3
|
// Atomic writes, parser hardening, multi-user, error handling
|
|
4
4
|
// ============================================================
|
|
5
|
-
import { readFile, writeFile, access, rename, constants } from "node:fs/promises";
|
|
6
|
-
import { join } from "node:path";
|
|
5
|
+
import { readFile, writeFile, access, rename, constants, mkdir } from "node:fs/promises";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
7
|
import { CHEMICAL_KEYS, CHEMICAL_NAMES, CHEMICAL_NAMES_ZH, DEFAULT_RELATIONSHIP, DEFAULT_DRIVES, DEFAULT_LEARNING_STATE, DEFAULT_METACOGNITIVE_STATE, DEFAULT_PERSONHOOD_STATE, MAX_EMOTIONAL_HISTORY, MAX_RELATIONSHIP_MEMORY, } from "./types.js";
|
|
8
8
|
import { getBaseline, getDefaultSelfModel, extractMBTI, getSensitivity, getTemperament } from "./profiles.js";
|
|
9
9
|
import { applyDecay, detectEmotions } from "./chemistry.js";
|
|
@@ -53,14 +53,15 @@ async function readText(path, logger = NOOP_LOGGER) {
|
|
|
53
53
|
* Prevents data corruption if process crashes mid-write.
|
|
54
54
|
*/
|
|
55
55
|
async function atomicWrite(path, content) {
|
|
56
|
-
|
|
56
|
+
await mkdir(dirname(path), { recursive: true });
|
|
57
|
+
const tmpPath = `${path}.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2)}.tmp`;
|
|
57
58
|
await writeFile(tmpPath, content, "utf-8");
|
|
58
59
|
await rename(tmpPath, path);
|
|
59
60
|
}
|
|
60
61
|
/**
|
|
61
62
|
* Try to extract agent name from workspace files.
|
|
62
63
|
*/
|
|
63
|
-
async function extractAgentName(workspaceDir, logger = NOOP_LOGGER) {
|
|
64
|
+
export async function extractAgentName(workspaceDir, logger = NOOP_LOGGER) {
|
|
64
65
|
const identity = await readText(join(workspaceDir, IDENTITY_MD), logger);
|
|
65
66
|
if (identity) {
|
|
66
67
|
const clean = identity.replace(/\*{1,2}/g, "");
|
|
@@ -73,7 +74,7 @@ async function extractAgentName(workspaceDir, logger = NOOP_LOGGER) {
|
|
|
73
74
|
/**
|
|
74
75
|
* Try to detect MBTI from workspace files.
|
|
75
76
|
*/
|
|
76
|
-
async function detectMBTI(workspaceDir, logger = NOOP_LOGGER) {
|
|
77
|
+
export async function detectMBTI(workspaceDir, logger = NOOP_LOGGER) {
|
|
77
78
|
const identity = await readText(join(workspaceDir, IDENTITY_MD), logger);
|
|
78
79
|
if (identity) {
|
|
79
80
|
const mbti = extractMBTI(identity);
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { PendingRelationSignalState, AppraisalAxes, DyadicFieldState, RelationshipState, PsycheMode, RelationMove, StimulusType } from "./types.js";
|
|
2
|
+
export declare function computeRelationMove(text: string, opts?: {
|
|
3
|
+
appraisal?: AppraisalAxes;
|
|
4
|
+
stimulus?: StimulusType | null;
|
|
5
|
+
mode?: PsycheMode;
|
|
6
|
+
field?: DyadicFieldState;
|
|
7
|
+
relationship?: RelationshipState;
|
|
8
|
+
}): RelationMove;
|
|
9
|
+
export declare function evolveDyadicField(previous: DyadicFieldState | undefined, move: RelationMove, appraisal: AppraisalAxes, opts?: {
|
|
10
|
+
mode?: PsycheMode;
|
|
11
|
+
now?: string;
|
|
12
|
+
delayedPressure?: number;
|
|
13
|
+
}): DyadicFieldState;
|
|
14
|
+
export declare function getLoopPressure(field: DyadicFieldState | undefined): number;
|
|
15
|
+
export declare function evolvePendingRelationSignals(previous: PendingRelationSignalState[] | undefined, move: RelationMove, appraisal: AppraisalAxes, opts?: {
|
|
16
|
+
mode?: PsycheMode;
|
|
17
|
+
}): {
|
|
18
|
+
signals: PendingRelationSignalState[];
|
|
19
|
+
delayedPressure: number;
|
|
20
|
+
ambiguityBoost: number;
|
|
21
|
+
};
|