@auxiora/personality 1.0.0 → 1.3.1
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/__tests__/architect-awareness-collector.test.d.ts +2 -0
- package/dist/__tests__/architect-awareness-collector.test.d.ts.map +1 -0
- package/dist/__tests__/architect-awareness-collector.test.js +57 -0
- package/dist/__tests__/architect-awareness-collector.test.js.map +1 -0
- package/dist/__tests__/architect-bridge.test.d.ts +2 -0
- package/dist/__tests__/architect-bridge.test.d.ts.map +1 -0
- package/dist/__tests__/architect-bridge.test.js +59 -0
- package/dist/__tests__/architect-bridge.test.js.map +1 -0
- package/dist/__tests__/soul-bias-parser.test.d.ts +2 -0
- package/dist/__tests__/soul-bias-parser.test.d.ts.map +1 -0
- package/dist/__tests__/soul-bias-parser.test.js +47 -0
- package/dist/__tests__/soul-bias-parser.test.js.map +1 -0
- package/dist/architect-awareness-collector.d.ts +20 -0
- package/dist/architect-awareness-collector.d.ts.map +1 -0
- package/dist/architect-awareness-collector.js +41 -0
- package/dist/architect-awareness-collector.js.map +1 -0
- package/dist/architect-bridge.d.ts +35 -0
- package/dist/architect-bridge.d.ts.map +1 -0
- package/dist/architect-bridge.js +70 -0
- package/dist/architect-bridge.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -0
- package/dist/index.js.map +1 -1
- package/dist/marketplace/schema.d.ts +6 -6
- package/dist/soul-bias-parser.d.ts +10 -0
- package/dist/soul-bias-parser.d.ts.map +1 -0
- package/dist/soul-bias-parser.js +48 -0
- package/dist/soul-bias-parser.js.map +1 -0
- package/lib/context-detector.d.ts +23 -0
- package/lib/context-detector.js +275 -0
- package/lib/context-profiles.d.ts +3 -0
- package/lib/context-profiles.js +550 -0
- package/lib/conversation-context.d.ts +70 -0
- package/lib/conversation-context.js +144 -0
- package/lib/conversation-export.d.ts +77 -0
- package/lib/conversation-export.js +254 -0
- package/lib/correction-store.d.ts +53 -0
- package/lib/correction-store.js +185 -0
- package/lib/custom-weights.d.ts +49 -0
- package/lib/custom-weights.js +181 -0
- package/lib/decision-log.d.ts +41 -0
- package/lib/decision-log.js +145 -0
- package/lib/emotional-overrides.d.ts +14 -0
- package/lib/emotional-overrides.js +86 -0
- package/lib/emotional-tracker.d.ts +41 -0
- package/lib/emotional-tracker.js +210 -0
- package/lib/feedback-store.d.ts +45 -0
- package/lib/feedback-store.js +152 -0
- package/lib/index.d.ts +204 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +620 -0
- package/lib/index.js.map +1 -0
- package/lib/persistence-adapter.d.ts +55 -0
- package/lib/persistence-adapter.js +50 -0
- package/lib/persistence.d.ts +55 -0
- package/lib/persistence.js +123 -0
- package/lib/preference-history.d.ts +45 -0
- package/lib/preference-history.js +132 -0
- package/lib/prompt-assembler.d.ts +16 -0
- package/lib/prompt-assembler.js +66 -0
- package/lib/recommender.d.ts +25 -0
- package/lib/recommender.js +125 -0
- package/lib/schema.d.ts +177 -0
- package/lib/schema.d.ts.map +1 -0
- package/lib/schema.js +2 -0
- package/lib/schema.js.map +1 -0
- package/lib/source-map.d.ts +9 -0
- package/lib/source-map.js +223 -0
- package/lib/system-prompt.d.ts +2 -0
- package/lib/system-prompt.js +102 -0
- package/lib/the-architect/context-detector.d.ts +23 -0
- package/lib/the-architect/context-detector.d.ts.map +1 -0
- package/lib/the-architect/context-detector.js +275 -0
- package/lib/the-architect/context-detector.js.map +1 -0
- package/lib/the-architect/context-profiles.d.ts +3 -0
- package/lib/the-architect/context-profiles.d.ts.map +1 -0
- package/lib/the-architect/context-profiles.js +550 -0
- package/lib/the-architect/context-profiles.js.map +1 -0
- package/lib/the-architect/conversation-context.d.ts +70 -0
- package/lib/the-architect/conversation-context.js +144 -0
- package/lib/the-architect/conversation-context.js.map +1 -0
- package/lib/the-architect/conversation-export.d.ts +77 -0
- package/lib/the-architect/conversation-export.js +254 -0
- package/lib/the-architect/correction-store.d.ts +53 -0
- package/lib/the-architect/correction-store.d.ts.map +1 -0
- package/lib/the-architect/correction-store.js +185 -0
- package/lib/the-architect/correction-store.js.map +1 -0
- package/lib/the-architect/custom-weights.d.ts +49 -0
- package/lib/the-architect/custom-weights.js +181 -0
- package/lib/the-architect/decision-log.d.ts +41 -0
- package/lib/the-architect/decision-log.d.ts.map +1 -0
- package/lib/the-architect/decision-log.js +145 -0
- package/lib/the-architect/decision-log.js.map +1 -0
- package/lib/the-architect/emotional-overrides.d.ts +14 -0
- package/lib/the-architect/emotional-overrides.d.ts.map +1 -0
- package/lib/the-architect/emotional-overrides.js +86 -0
- package/lib/the-architect/emotional-overrides.js.map +1 -0
- package/lib/the-architect/emotional-tracker.d.ts +41 -0
- package/lib/the-architect/emotional-tracker.js +210 -0
- package/lib/the-architect/feedback-store.d.ts +45 -0
- package/lib/the-architect/feedback-store.d.ts.map +1 -0
- package/lib/the-architect/feedback-store.js +152 -0
- package/lib/the-architect/feedback-store.js.map +1 -0
- package/lib/the-architect/index.d.ts +199 -0
- package/lib/the-architect/index.d.ts.map +1 -0
- package/lib/the-architect/index.js +606 -0
- package/lib/the-architect/index.js.map +1 -0
- package/lib/the-architect/persistence-adapter.d.ts +55 -0
- package/lib/the-architect/persistence-adapter.js +50 -0
- package/lib/the-architect/persistence.d.ts +55 -0
- package/lib/the-architect/persistence.js +123 -0
- package/lib/the-architect/preference-history.d.ts +45 -0
- package/lib/the-architect/preference-history.d.ts.map +1 -0
- package/lib/the-architect/preference-history.js +132 -0
- package/lib/the-architect/preference-history.js.map +1 -0
- package/lib/the-architect/prompt-assembler.d.ts +16 -0
- package/lib/the-architect/prompt-assembler.d.ts.map +1 -0
- package/lib/the-architect/prompt-assembler.js +66 -0
- package/lib/the-architect/prompt-assembler.js.map +1 -0
- package/lib/the-architect/recommender.d.ts +25 -0
- package/lib/the-architect/recommender.js +125 -0
- package/lib/the-architect/source-map.d.ts +9 -0
- package/lib/the-architect/source-map.d.ts.map +1 -0
- package/lib/the-architect/source-map.js +223 -0
- package/lib/the-architect/source-map.js.map +1 -0
- package/lib/the-architect/system-prompt.d.ts +2 -0
- package/lib/the-architect/system-prompt.d.ts.map +1 -0
- package/lib/the-architect/system-prompt.js +102 -0
- package/lib/the-architect/system-prompt.js.map +1 -0
- package/lib/the-architect/trait-to-instruction.d.ts +12 -0
- package/lib/the-architect/trait-to-instruction.d.ts.map +1 -0
- package/lib/the-architect/trait-to-instruction.js +330 -0
- package/lib/the-architect/trait-to-instruction.js.map +1 -0
- package/lib/trait-to-instruction.d.ts +12 -0
- package/lib/trait-to-instruction.js +330 -0
- package/lib/user-model-synthesizer.d.ts +100 -0
- package/lib/user-model-synthesizer.js +224 -0
- package/package.json +15 -3
- package/modes/advisor.md +0 -24
- package/modes/analyst.md +0 -25
- package/modes/companion.md +0 -24
- package/modes/legal.md +0 -1188
- package/modes/operator.md +0 -24
- package/modes/roast.md +0 -24
- package/modes/socratic.md +0 -24
- package/modes/writer.md +0 -23
- package/src/__tests__/builder.test.ts +0 -78
- package/src/__tests__/conversation-builder.test.ts +0 -386
- package/src/__tests__/escalation.test.ts +0 -172
- package/src/__tests__/manager.test.ts +0 -141
- package/src/__tests__/parser.test.ts +0 -101
- package/src/__tests__/security-floor.test.ts +0 -212
- package/src/builder.ts +0 -75
- package/src/conversation-builder.ts +0 -279
- package/src/escalation.ts +0 -162
- package/src/index.ts +0 -55
- package/src/manager.ts +0 -119
- package/src/marketplace/__tests__/scanner.test.ts +0 -159
- package/src/marketplace/__tests__/schema.test.ts +0 -269
- package/src/marketplace/scanner.ts +0 -85
- package/src/marketplace/schema.ts +0 -141
- package/src/modes/__tests__/mode-detector.test.ts +0 -149
- package/src/modes/__tests__/mode-loader.test.ts +0 -143
- package/src/modes/__tests__/prompt-assembler.test.ts +0 -291
- package/src/modes/mode-detector.ts +0 -84
- package/src/modes/mode-loader.ts +0 -105
- package/src/modes/prompt-assembler.ts +0 -278
- package/src/modes/types.ts +0 -67
- package/src/parser.ts +0 -132
- package/src/security-floor.ts +0 -147
- package/src/types.ts +0 -27
- package/src/voice-profiles.ts +0 -88
- package/templates/chill.md +0 -30
- package/templates/creative.md +0 -29
- package/templates/friendly.md +0 -28
- package/templates/mentor.md +0 -31
- package/templates/minimal.md +0 -24
- package/templates/professional.md +0 -28
- package/templates/technical.md +0 -30
- package/tsconfig.json +0 -12
- package/tsconfig.tsbuildinfo +0 -1
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Constants
|
|
3
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
/** Number of consecutive same-domain detections required to establish a theme. */
|
|
5
|
+
const THEME_LOCK_THRESHOLD = 3;
|
|
6
|
+
/** Confidence threshold for a new domain to override an existing theme. */
|
|
7
|
+
const THEME_OVERRIDE_CONFIDENCE = 0.7;
|
|
8
|
+
/** Crisis always takes over — no theme can suppress it. */
|
|
9
|
+
const CRISIS_DOMAIN = 'crisis_management';
|
|
10
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
// ConversationContext
|
|
12
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
/**
|
|
14
|
+
* Maintains context awareness across a full conversation, not just per-message.
|
|
15
|
+
*
|
|
16
|
+
* If the conversation is about security architecture, a brief tangent about
|
|
17
|
+
* lunch shouldn't reset the context to "general." The class tracks a
|
|
18
|
+
* conversation *theme* that locks after 3+ consistent detections and only
|
|
19
|
+
* shifts when a new domain arrives with high confidence.
|
|
20
|
+
*
|
|
21
|
+
* CRITICAL: Crisis context (`crisis_management`) ALWAYS overrides the
|
|
22
|
+
* conversation theme. If the user suddenly says "we just got breached,"
|
|
23
|
+
* crisis takes over immediately regardless of theme.
|
|
24
|
+
*/
|
|
25
|
+
export class ConversationContext {
|
|
26
|
+
history = [];
|
|
27
|
+
dominantDomain = 'general';
|
|
28
|
+
domainStreak = 0;
|
|
29
|
+
conversationTheme = null;
|
|
30
|
+
// ── Recording ───────────────────────────────────────────────────────────
|
|
31
|
+
/**
|
|
32
|
+
* Record a new context detection. Updates streak tracking and may
|
|
33
|
+
* auto-establish a conversation theme after enough consistent detections.
|
|
34
|
+
*/
|
|
35
|
+
recordDetection(message, domain, confidence) {
|
|
36
|
+
this.history.push({
|
|
37
|
+
message,
|
|
38
|
+
domain,
|
|
39
|
+
confidence,
|
|
40
|
+
timestamp: Date.now(),
|
|
41
|
+
});
|
|
42
|
+
// Update streak tracking
|
|
43
|
+
if (domain === this.dominantDomain) {
|
|
44
|
+
this.domainStreak++;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
this.dominantDomain = domain;
|
|
48
|
+
this.domainStreak = 1;
|
|
49
|
+
}
|
|
50
|
+
// Auto-establish theme after THEME_LOCK_THRESHOLD consecutive detections
|
|
51
|
+
if (this.conversationTheme === null &&
|
|
52
|
+
this.domainStreak >= THEME_LOCK_THRESHOLD &&
|
|
53
|
+
this.dominantDomain !== 'general') {
|
|
54
|
+
this.conversationTheme = this.dominantDomain;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
// ── Effective domain ────────────────────────────────────────────────────
|
|
58
|
+
/**
|
|
59
|
+
* Get the effective domain considering conversation history.
|
|
60
|
+
*
|
|
61
|
+
* Rules:
|
|
62
|
+
* 1. Crisis ALWAYS wins — bypasses any theme.
|
|
63
|
+
* 2. If a theme is set and the new detection is 'general' or low confidence,
|
|
64
|
+
* return the theme (the tangent doesn't break it).
|
|
65
|
+
* 3. If a theme is set and the new detection is a DIFFERENT specific domain
|
|
66
|
+
* with high confidence (> 0.7), update the theme to the new domain.
|
|
67
|
+
* 4. If no theme is set, return the raw detection unchanged.
|
|
68
|
+
*/
|
|
69
|
+
getEffectiveDomain(currentDetection, currentConfidence) {
|
|
70
|
+
// Rule 1: Crisis always overrides
|
|
71
|
+
if (currentDetection === CRISIS_DOMAIN) {
|
|
72
|
+
this.conversationTheme = CRISIS_DOMAIN;
|
|
73
|
+
return CRISIS_DOMAIN;
|
|
74
|
+
}
|
|
75
|
+
// No theme → raw detection
|
|
76
|
+
if (this.conversationTheme === null) {
|
|
77
|
+
return currentDetection;
|
|
78
|
+
}
|
|
79
|
+
// Theme is set — evaluate the new detection
|
|
80
|
+
if (currentDetection === 'general' || currentConfidence < THEME_OVERRIDE_CONFIDENCE) {
|
|
81
|
+
// Low-signal message: theme holds
|
|
82
|
+
return this.conversationTheme;
|
|
83
|
+
}
|
|
84
|
+
if (currentDetection !== this.conversationTheme) {
|
|
85
|
+
// High-confidence different domain: shift the theme
|
|
86
|
+
this.conversationTheme = currentDetection;
|
|
87
|
+
}
|
|
88
|
+
return this.conversationTheme;
|
|
89
|
+
}
|
|
90
|
+
// ── Manual control ──────────────────────────────────────────────────────
|
|
91
|
+
/** Explicitly set conversation theme (user override). */
|
|
92
|
+
setTheme(domain) {
|
|
93
|
+
this.conversationTheme = domain;
|
|
94
|
+
}
|
|
95
|
+
/** Clear theme — returns to pure auto-detection. */
|
|
96
|
+
clearTheme() {
|
|
97
|
+
this.conversationTheme = null;
|
|
98
|
+
}
|
|
99
|
+
// ── Introspection ──────────────────────────────────────────────────────
|
|
100
|
+
/** Get conversation summary with theme, distribution, and streak info. */
|
|
101
|
+
getSummary() {
|
|
102
|
+
const distribution = {};
|
|
103
|
+
for (const record of this.history) {
|
|
104
|
+
distribution[record.domain] = (distribution[record.domain] ?? 0) + 1;
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
theme: this.conversationTheme,
|
|
108
|
+
messageCount: this.history.length,
|
|
109
|
+
domainDistribution: distribution,
|
|
110
|
+
currentStreak: {
|
|
111
|
+
domain: this.dominantDomain,
|
|
112
|
+
count: this.domainStreak,
|
|
113
|
+
},
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// ── Lifecycle ──────────────────────────────────────────────────────────
|
|
117
|
+
/** Reset for a new conversation — clears all state. */
|
|
118
|
+
reset() {
|
|
119
|
+
this.history = [];
|
|
120
|
+
this.dominantDomain = 'general';
|
|
121
|
+
this.domainStreak = 0;
|
|
122
|
+
this.conversationTheme = null;
|
|
123
|
+
}
|
|
124
|
+
// ── Persistence ──────────────────────────────────────────────────────
|
|
125
|
+
/** Serialize state for vault persistence. Caps history at 50 records. */
|
|
126
|
+
serialize() {
|
|
127
|
+
return {
|
|
128
|
+
theme: this.conversationTheme,
|
|
129
|
+
dominantDomain: this.dominantDomain,
|
|
130
|
+
domainStreak: this.domainStreak,
|
|
131
|
+
history: this.history.slice(-50),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/** Restore a ConversationContext from previously serialized state. */
|
|
135
|
+
static restore(state) {
|
|
136
|
+
const ctx = new ConversationContext();
|
|
137
|
+
ctx.conversationTheme = state.theme;
|
|
138
|
+
ctx.dominantDomain = state.dominantDomain;
|
|
139
|
+
ctx.domainStreak = state.domainStreak;
|
|
140
|
+
ctx.history = [...state.history];
|
|
141
|
+
return ctx;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=conversation-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"conversation-context.js","sourceRoot":"","sources":["conversation-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { ContextDomain, EmotionalRegister, TraitSource } from '../schema.js';
|
|
2
|
+
import type { EmotionalTrajectory } from './emotional-tracker.js';
|
|
3
|
+
import type { ContextRecommendation } from './recommender.js';
|
|
4
|
+
export interface ChatMessage {
|
|
5
|
+
role: 'user' | 'assistant';
|
|
6
|
+
content: string;
|
|
7
|
+
timestamp: number;
|
|
8
|
+
/** Personality engine output attached to assistant messages. */
|
|
9
|
+
metadata?: AssistantMetadata;
|
|
10
|
+
}
|
|
11
|
+
export interface AssistantMetadata {
|
|
12
|
+
domain: ContextDomain;
|
|
13
|
+
emotionalRegister: EmotionalRegister;
|
|
14
|
+
emotionalTrajectory?: EmotionalTrajectory;
|
|
15
|
+
conversationTheme?: ContextDomain;
|
|
16
|
+
corrected?: boolean;
|
|
17
|
+
originalDomain?: ContextDomain;
|
|
18
|
+
confidence?: number;
|
|
19
|
+
stakes: string;
|
|
20
|
+
complexity: string;
|
|
21
|
+
activeTraits: TraitSource[];
|
|
22
|
+
customWeightsApplied?: Partial<Record<string, number>>;
|
|
23
|
+
recommendation?: ContextRecommendation;
|
|
24
|
+
}
|
|
25
|
+
export interface ExportedMessage {
|
|
26
|
+
role: 'user' | 'assistant';
|
|
27
|
+
content: string;
|
|
28
|
+
timestamp: number;
|
|
29
|
+
context?: {
|
|
30
|
+
domain: ContextDomain;
|
|
31
|
+
emotionalRegister: EmotionalRegister;
|
|
32
|
+
emotionalTrajectory?: EmotionalTrajectory;
|
|
33
|
+
conversationTheme?: ContextDomain;
|
|
34
|
+
corrected?: boolean;
|
|
35
|
+
originalDomain?: ContextDomain;
|
|
36
|
+
confidence?: number;
|
|
37
|
+
stakes: string;
|
|
38
|
+
complexity: string;
|
|
39
|
+
};
|
|
40
|
+
activeTraits?: Array<{
|
|
41
|
+
traitName: string;
|
|
42
|
+
weight: number;
|
|
43
|
+
sourceName: string;
|
|
44
|
+
}>;
|
|
45
|
+
customWeightsApplied?: Partial<Record<string, number>>;
|
|
46
|
+
recommendation?: ContextRecommendation;
|
|
47
|
+
}
|
|
48
|
+
export interface ExportedConversation {
|
|
49
|
+
id: string;
|
|
50
|
+
title: string;
|
|
51
|
+
exportedAt: number;
|
|
52
|
+
messageCount: number;
|
|
53
|
+
messages: ExportedMessage[];
|
|
54
|
+
summary: {
|
|
55
|
+
dominantContexts: Array<{
|
|
56
|
+
domain: ContextDomain;
|
|
57
|
+
percentage: number;
|
|
58
|
+
}>;
|
|
59
|
+
emotionalArc: EmotionalRegister[];
|
|
60
|
+
correctionsApplied: number;
|
|
61
|
+
uniqueSourcesReferenced: string[];
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
export declare class ConversationExporter {
|
|
65
|
+
/**
|
|
66
|
+
* Build an export from conversation messages with their metadata.
|
|
67
|
+
*/
|
|
68
|
+
export(messages: ChatMessage[], conversationId: string): ExportedConversation;
|
|
69
|
+
/** Export to JSON string. */
|
|
70
|
+
toJSON(conversation: ExportedConversation): string;
|
|
71
|
+
/** Export to Markdown (human-readable report). */
|
|
72
|
+
toMarkdown(conversation: ExportedConversation): string;
|
|
73
|
+
/** Export to CSV (one row per assistant message for analysis). */
|
|
74
|
+
toCSV(conversation: ExportedConversation): string;
|
|
75
|
+
private buildSummary;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=conversation-export.d.ts.map
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Helpers
|
|
3
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
/** Human-readable label for a domain. */
|
|
5
|
+
function domainLabel(domain) {
|
|
6
|
+
return domain
|
|
7
|
+
.split('_')
|
|
8
|
+
.map(w => w.charAt(0).toUpperCase() + w.slice(1))
|
|
9
|
+
.join(' ');
|
|
10
|
+
}
|
|
11
|
+
/** Domain emoji for markdown output. */
|
|
12
|
+
const DOMAIN_EMOJI = {
|
|
13
|
+
security_review: '🛡️',
|
|
14
|
+
code_engineering: '💻',
|
|
15
|
+
architecture_design: '🏗️',
|
|
16
|
+
debugging: '🔍',
|
|
17
|
+
team_leadership: '👥',
|
|
18
|
+
one_on_one: '🤝',
|
|
19
|
+
sales_pitch: '💰',
|
|
20
|
+
negotiation: '🤝',
|
|
21
|
+
marketing_content: '📣',
|
|
22
|
+
strategic_planning: '📊',
|
|
23
|
+
crisis_management: '🚨',
|
|
24
|
+
creative_work: '🎨',
|
|
25
|
+
writing_content: '✍️',
|
|
26
|
+
decision_making: '⚖️',
|
|
27
|
+
learning_research: '📚',
|
|
28
|
+
personal_development: '🌱',
|
|
29
|
+
general: '💬',
|
|
30
|
+
};
|
|
31
|
+
/** Escape a CSV field value — wraps in quotes if it contains commas, quotes, or newlines. */
|
|
32
|
+
function csvEscape(value) {
|
|
33
|
+
if (value.includes(',') || value.includes('"') || value.includes('\n') || value.includes('\r')) {
|
|
34
|
+
return '"' + value.replace(/"/g, '""') + '"';
|
|
35
|
+
}
|
|
36
|
+
return value;
|
|
37
|
+
}
|
|
38
|
+
/** Auto-generate a title from the first user message. */
|
|
39
|
+
function generateTitle(messages) {
|
|
40
|
+
const firstUser = messages.find(m => m.role === 'user');
|
|
41
|
+
if (!firstUser)
|
|
42
|
+
return 'Empty Conversation';
|
|
43
|
+
const text = firstUser.content.trim();
|
|
44
|
+
if (text.length <= 60)
|
|
45
|
+
return text;
|
|
46
|
+
return text.slice(0, 57) + '...';
|
|
47
|
+
}
|
|
48
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
49
|
+
// ConversationExporter
|
|
50
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
51
|
+
export class ConversationExporter {
|
|
52
|
+
/**
|
|
53
|
+
* Build an export from conversation messages with their metadata.
|
|
54
|
+
*/
|
|
55
|
+
export(messages, conversationId) {
|
|
56
|
+
const exportedMessages = messages.map(msg => {
|
|
57
|
+
if (msg.role === 'user' || !msg.metadata) {
|
|
58
|
+
return { role: msg.role, content: msg.content, timestamp: msg.timestamp };
|
|
59
|
+
}
|
|
60
|
+
const meta = msg.metadata;
|
|
61
|
+
return {
|
|
62
|
+
role: msg.role,
|
|
63
|
+
content: msg.content,
|
|
64
|
+
timestamp: msg.timestamp,
|
|
65
|
+
context: {
|
|
66
|
+
domain: meta.domain,
|
|
67
|
+
emotionalRegister: meta.emotionalRegister,
|
|
68
|
+
emotionalTrajectory: meta.emotionalTrajectory,
|
|
69
|
+
conversationTheme: meta.conversationTheme,
|
|
70
|
+
corrected: meta.corrected,
|
|
71
|
+
originalDomain: meta.originalDomain,
|
|
72
|
+
confidence: meta.confidence,
|
|
73
|
+
stakes: meta.stakes,
|
|
74
|
+
complexity: meta.complexity,
|
|
75
|
+
},
|
|
76
|
+
activeTraits: meta.activeTraits.map(t => ({
|
|
77
|
+
traitName: t.traitKey,
|
|
78
|
+
weight: parseFloat(t.traitKey), // placeholder — actual weight comes from the mix
|
|
79
|
+
sourceName: t.sourceName,
|
|
80
|
+
})),
|
|
81
|
+
customWeightsApplied: meta.customWeightsApplied,
|
|
82
|
+
recommendation: meta.recommendation,
|
|
83
|
+
};
|
|
84
|
+
});
|
|
85
|
+
// Fix activeTraits weight: we don't have the actual mix weight here, so
|
|
86
|
+
// we set weight from the trait data as-is. The caller provides the
|
|
87
|
+
// full trait source which already has behavioralInstruction etc.
|
|
88
|
+
// For export, we'll use a default weight of 1.0 for active traits since
|
|
89
|
+
// they were deemed active by the threshold in getActiveSources.
|
|
90
|
+
for (const msg of exportedMessages) {
|
|
91
|
+
if (msg.activeTraits) {
|
|
92
|
+
for (const trait of msg.activeTraits) {
|
|
93
|
+
trait.weight = 1.0;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
const summary = this.buildSummary(exportedMessages);
|
|
98
|
+
return {
|
|
99
|
+
id: conversationId,
|
|
100
|
+
title: generateTitle(messages),
|
|
101
|
+
exportedAt: Date.now(),
|
|
102
|
+
messageCount: messages.length,
|
|
103
|
+
messages: exportedMessages,
|
|
104
|
+
summary,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
/** Export to JSON string. */
|
|
108
|
+
toJSON(conversation) {
|
|
109
|
+
return JSON.stringify(conversation, null, 2);
|
|
110
|
+
}
|
|
111
|
+
/** Export to Markdown (human-readable report). */
|
|
112
|
+
toMarkdown(conversation) {
|
|
113
|
+
const lines = [];
|
|
114
|
+
// Header
|
|
115
|
+
lines.push(`# Conversation: ${conversation.title}`);
|
|
116
|
+
lines.push('');
|
|
117
|
+
const date = new Date(conversation.exportedAt).toISOString().split('T')[0];
|
|
118
|
+
lines.push(`**Date:** ${date} | **Messages:** ${conversation.messageCount}`);
|
|
119
|
+
// Dominant contexts
|
|
120
|
+
if (conversation.summary.dominantContexts.length > 0) {
|
|
121
|
+
const contexts = conversation.summary.dominantContexts
|
|
122
|
+
.map(c => `${domainLabel(c.domain)} (${Math.round(c.percentage)}%)`)
|
|
123
|
+
.join(', ');
|
|
124
|
+
lines.push(`**Dominant contexts:** ${contexts}`);
|
|
125
|
+
}
|
|
126
|
+
// Sources referenced
|
|
127
|
+
if (conversation.summary.uniqueSourcesReferenced.length > 0) {
|
|
128
|
+
lines.push(`**Historical minds referenced:** ${conversation.summary.uniqueSourcesReferenced.join(', ')}`);
|
|
129
|
+
}
|
|
130
|
+
if (conversation.summary.correctionsApplied > 0) {
|
|
131
|
+
lines.push(`**Corrections applied:** ${conversation.summary.correctionsApplied}`);
|
|
132
|
+
}
|
|
133
|
+
lines.push('');
|
|
134
|
+
// Messages
|
|
135
|
+
for (const msg of conversation.messages) {
|
|
136
|
+
lines.push('---');
|
|
137
|
+
lines.push('');
|
|
138
|
+
if (msg.role === 'user') {
|
|
139
|
+
lines.push(`**You:** ${msg.content}`);
|
|
140
|
+
}
|
|
141
|
+
else {
|
|
142
|
+
// Build assistant header
|
|
143
|
+
const emoji = msg.context ? (DOMAIN_EMOJI[msg.context.domain] ?? '💬') : '💬';
|
|
144
|
+
const domainStr = msg.context ? domainLabel(msg.context.domain) : 'General';
|
|
145
|
+
const confidenceStr = msg.context?.confidence != null
|
|
146
|
+
? (msg.context.confidence >= 0.8 ? 'Confident' : msg.context.confidence >= 0.5 ? 'Moderate' : 'Low confidence')
|
|
147
|
+
: '';
|
|
148
|
+
const headerParts = [emoji, domainStr];
|
|
149
|
+
if (confidenceStr)
|
|
150
|
+
headerParts.push(`· ${confidenceStr}`);
|
|
151
|
+
lines.push(`**Architect** [${headerParts.join(' ')}]:`);
|
|
152
|
+
lines.push(msg.content);
|
|
153
|
+
// Active traits
|
|
154
|
+
if (msg.activeTraits && msg.activeTraits.length > 0) {
|
|
155
|
+
const traitList = msg.activeTraits
|
|
156
|
+
.slice(0, 8) // top 8 to avoid clutter
|
|
157
|
+
.map(t => `${formatTraitName(t.traitName)} (${t.sourceName})`)
|
|
158
|
+
.join(', ');
|
|
159
|
+
lines.push(`*Active: ${traitList}*`);
|
|
160
|
+
}
|
|
161
|
+
// Correction note
|
|
162
|
+
if (msg.context?.corrected && msg.context.originalDomain) {
|
|
163
|
+
lines.push(`*Corrected from ${domainLabel(msg.context.originalDomain)}*`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
lines.push('');
|
|
167
|
+
}
|
|
168
|
+
lines.push('---');
|
|
169
|
+
return lines.join('\n');
|
|
170
|
+
}
|
|
171
|
+
/** Export to CSV (one row per assistant message for analysis). */
|
|
172
|
+
toCSV(conversation) {
|
|
173
|
+
const headers = [
|
|
174
|
+
'timestamp', 'domain', 'emotion', 'trajectory', 'stakes', 'complexity', 'confidence',
|
|
175
|
+
'top_trait_1', 'top_trait_1_weight', 'top_trait_1_source',
|
|
176
|
+
'top_trait_2', 'top_trait_2_weight', 'top_trait_2_source',
|
|
177
|
+
'top_trait_3', 'top_trait_3_weight', 'top_trait_3_source',
|
|
178
|
+
'top_trait_4', 'top_trait_4_weight', 'top_trait_4_source',
|
|
179
|
+
'top_trait_5', 'top_trait_5_weight', 'top_trait_5_source',
|
|
180
|
+
'correction_applied', 'recommendation_shown',
|
|
181
|
+
];
|
|
182
|
+
const rows = [headers.join(',')];
|
|
183
|
+
for (const msg of conversation.messages) {
|
|
184
|
+
if (msg.role !== 'assistant' || !msg.context)
|
|
185
|
+
continue;
|
|
186
|
+
const traits = msg.activeTraits ?? [];
|
|
187
|
+
const top5 = traits.slice(0, 5);
|
|
188
|
+
const fields = [
|
|
189
|
+
String(msg.timestamp),
|
|
190
|
+
csvEscape(msg.context.domain),
|
|
191
|
+
csvEscape(msg.context.emotionalRegister),
|
|
192
|
+
csvEscape(msg.context.emotionalTrajectory ?? ''),
|
|
193
|
+
csvEscape(msg.context.stakes),
|
|
194
|
+
csvEscape(msg.context.complexity),
|
|
195
|
+
msg.context.confidence != null ? String(msg.context.confidence) : '',
|
|
196
|
+
];
|
|
197
|
+
// Top 5 traits (3 columns each)
|
|
198
|
+
for (let i = 0; i < 5; i++) {
|
|
199
|
+
if (i < top5.length) {
|
|
200
|
+
fields.push(csvEscape(top5[i].traitName));
|
|
201
|
+
fields.push(String(top5[i].weight));
|
|
202
|
+
fields.push(csvEscape(top5[i].sourceName));
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
fields.push('', '', '');
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
fields.push(msg.context.corrected ? 'true' : 'false');
|
|
209
|
+
fields.push(msg.recommendation ? 'true' : 'false');
|
|
210
|
+
rows.push(fields.join(','));
|
|
211
|
+
}
|
|
212
|
+
return rows.join('\n');
|
|
213
|
+
}
|
|
214
|
+
// ── Private ────────────────────────────────────────────────────────────
|
|
215
|
+
buildSummary(messages) {
|
|
216
|
+
const assistantMessages = messages.filter(m => m.role === 'assistant' && m.context);
|
|
217
|
+
// Dominant contexts
|
|
218
|
+
const domainCounts = new Map();
|
|
219
|
+
for (const msg of assistantMessages) {
|
|
220
|
+
const domain = msg.context.domain;
|
|
221
|
+
domainCounts.set(domain, (domainCounts.get(domain) ?? 0) + 1);
|
|
222
|
+
}
|
|
223
|
+
const totalAssistant = assistantMessages.length || 1;
|
|
224
|
+
const dominantContexts = Array.from(domainCounts.entries())
|
|
225
|
+
.map(([domain, count]) => ({ domain, percentage: (count / totalAssistant) * 100 }))
|
|
226
|
+
.sort((a, b) => b.percentage - a.percentage);
|
|
227
|
+
// Emotional arc — one emotion per assistant turn
|
|
228
|
+
const emotionalArc = assistantMessages
|
|
229
|
+
.map(m => m.context.emotionalRegister);
|
|
230
|
+
// Corrections applied
|
|
231
|
+
const correctionsApplied = assistantMessages
|
|
232
|
+
.filter(m => m.context.corrected === true).length;
|
|
233
|
+
// Unique sources
|
|
234
|
+
const sourceSet = new Set();
|
|
235
|
+
for (const msg of assistantMessages) {
|
|
236
|
+
if (msg.activeTraits) {
|
|
237
|
+
for (const trait of msg.activeTraits) {
|
|
238
|
+
sourceSet.add(trait.sourceName);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
const uniqueSourcesReferenced = Array.from(sourceSet).sort();
|
|
243
|
+
return { dominantContexts, emotionalArc, correctionsApplied, uniqueSourcesReferenced };
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
/** Format a camelCase trait key into human-readable form. */
|
|
247
|
+
function formatTraitName(key) {
|
|
248
|
+
// "adversarialThinking" → "Adversarial Thinking"
|
|
249
|
+
return key
|
|
250
|
+
.replace(/([A-Z])/g, ' $1')
|
|
251
|
+
.replace(/^./, c => c.toUpperCase())
|
|
252
|
+
.trim();
|
|
253
|
+
}
|
|
254
|
+
//# sourceMappingURL=conversation-export.js.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { ContextDomain, EmotionalRegister } from '../schema.js';
|
|
2
|
+
export interface DetectionCorrection {
|
|
3
|
+
id: string;
|
|
4
|
+
timestamp: number;
|
|
5
|
+
userMessage: string;
|
|
6
|
+
messageLength: number;
|
|
7
|
+
detectedDomain: ContextDomain;
|
|
8
|
+
correctedDomain: ContextDomain;
|
|
9
|
+
detectedEmotion: EmotionalRegister;
|
|
10
|
+
keywords: string[];
|
|
11
|
+
}
|
|
12
|
+
export interface CorrectionPattern {
|
|
13
|
+
keyword: string;
|
|
14
|
+
fromDomain: ContextDomain;
|
|
15
|
+
toDomain: ContextDomain;
|
|
16
|
+
occurrences: number;
|
|
17
|
+
confidence: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class CorrectionStore {
|
|
20
|
+
private corrections;
|
|
21
|
+
private patterns;
|
|
22
|
+
/** Record a new correction. Generates id/timestamp and extracts keywords. */
|
|
23
|
+
addCorrection(correction: Omit<DetectionCorrection, 'id' | 'timestamp' | 'keywords'>): void;
|
|
24
|
+
/** Get all stored corrections. */
|
|
25
|
+
getCorrections(): DetectionCorrection[];
|
|
26
|
+
/** Get correction patterns sorted by confidence descending. */
|
|
27
|
+
getPatterns(): CorrectionPattern[];
|
|
28
|
+
/**
|
|
29
|
+
* Given a message and detected domain, check if corrections suggest a
|
|
30
|
+
* different domain. Returns the corrected domain if pattern confidence
|
|
31
|
+
* > 0.6 and occurrences >= 3, else null.
|
|
32
|
+
*/
|
|
33
|
+
suggestCorrection(message: string, detectedDomain: ContextDomain): ContextDomain | null;
|
|
34
|
+
/** Recompute patterns from all stored corrections. */
|
|
35
|
+
private recomputePatterns;
|
|
36
|
+
/** Serialize for encrypted storage. */
|
|
37
|
+
serialize(): string;
|
|
38
|
+
/** Deserialize from encrypted storage. */
|
|
39
|
+
static deserialize(data: string): CorrectionStore;
|
|
40
|
+
/** Clear all corrections (user data deletion). */
|
|
41
|
+
clear(): void;
|
|
42
|
+
/** Stats for debugging. */
|
|
43
|
+
getStats(): {
|
|
44
|
+
totalCorrections: number;
|
|
45
|
+
topMisclassifications: Array<{
|
|
46
|
+
from: ContextDomain;
|
|
47
|
+
to: ContextDomain;
|
|
48
|
+
count: number;
|
|
49
|
+
}>;
|
|
50
|
+
correctionRate: Record<string, number>;
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=correction-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"correction-store.d.ts","sourceRoot":"","sources":["correction-store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAMrE,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,aAAa,CAAC;IAC9B,eAAe,EAAE,aAAa,CAAC;IAC/B,eAAe,EAAE,iBAAiB,CAAC;IACnC,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,aAAa,CAAC;IAC1B,QAAQ,EAAE,aAAa,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,CAAC;CACpB;AA0DD,qBAAa,eAAe;IAC1B,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,QAAQ,CAA2B;IAE3C,6EAA6E;IAC7E,aAAa,CACX,UAAU,EAAE,IAAI,CAAC,mBAAmB,EAAE,IAAI,GAAG,WAAW,GAAG,UAAU,CAAC,GACrE,IAAI;IAUP,kCAAkC;IAClC,cAAc,IAAI,mBAAmB,EAAE;IAIvC,+DAA+D;IAC/D,WAAW,IAAI,iBAAiB,EAAE;IAIlC;;;;OAIG;IACH,iBAAiB,CACf,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,aAAa,GAC5B,aAAa,GAAG,IAAI;IAoBvB,sDAAsD;IACtD,OAAO,CAAC,iBAAiB;IAwCzB,uCAAuC;IACvC,SAAS,IAAI,MAAM;IAOnB,0CAA0C;IAC1C,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe;IAWjD,kDAAkD;IAClD,KAAK,IAAI,IAAI;IAKb,2BAA2B;IAC3B,QAAQ,IAAI;QACV,gBAAgB,EAAE,MAAM,CAAC;QACzB,qBAAqB,EAAE,KAAK,CAAC;YAAE,IAAI,EAAE,aAAa,CAAC;YAAC,EAAE,EAAE,aAAa,CAAC;YAAC,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;QACxF,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;KACxC;CAoCF"}
|