@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,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Encrypted storage interface for The Architect's persistence layer.
|
|
3
|
+
*
|
|
4
|
+
* Implementations must ensure all stored values are encrypted at rest.
|
|
5
|
+
* The persistence module stores serialized JSON strings via this interface
|
|
6
|
+
* and trusts the adapter to handle encryption transparently.
|
|
7
|
+
*/
|
|
8
|
+
export interface EncryptedStorage {
|
|
9
|
+
get(key: string): Promise<string | null>;
|
|
10
|
+
set(key: string, value: string): Promise<void>;
|
|
11
|
+
delete(key: string): Promise<void>;
|
|
12
|
+
exists(key: string): Promise<boolean>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* In-memory implementation of EncryptedStorage for development and testing.
|
|
16
|
+
* Data is NOT encrypted — use only in non-production environments.
|
|
17
|
+
*/
|
|
18
|
+
export declare class InMemoryEncryptedStorage implements EncryptedStorage {
|
|
19
|
+
private store;
|
|
20
|
+
get(key: string): Promise<string | null>;
|
|
21
|
+
set(key: string, value: string): Promise<void>;
|
|
22
|
+
delete(key: string): Promise<void>;
|
|
23
|
+
exists(key: string): Promise<boolean>;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Adapter that wraps Auxiora's Vault as an EncryptedStorage implementation.
|
|
27
|
+
*
|
|
28
|
+
* The Vault must be unlocked before use. All values are AES-256-GCM encrypted
|
|
29
|
+
* on disk via the vault's own encryption layer.
|
|
30
|
+
*
|
|
31
|
+
* Usage:
|
|
32
|
+
* const vault = new Vault();
|
|
33
|
+
* await vault.unlock(password);
|
|
34
|
+
* const storage = new VaultStorageAdapter(vault);
|
|
35
|
+
* const persistence = new ArchitectPersistence(storage);
|
|
36
|
+
*/
|
|
37
|
+
export declare class VaultStorageAdapter implements EncryptedStorage {
|
|
38
|
+
private vault;
|
|
39
|
+
constructor(vault: VaultLike);
|
|
40
|
+
get(key: string): Promise<string | null>;
|
|
41
|
+
set(key: string, value: string): Promise<void>;
|
|
42
|
+
delete(key: string): Promise<void>;
|
|
43
|
+
exists(key: string): Promise<boolean>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Minimal interface matching Auxiora's Vault class.
|
|
47
|
+
* Allows the adapter to work without a hard dependency on the vault package.
|
|
48
|
+
*/
|
|
49
|
+
export interface VaultLike {
|
|
50
|
+
get(name: string): string | undefined;
|
|
51
|
+
add(name: string, value: string): Promise<void>;
|
|
52
|
+
remove(name: string): Promise<boolean>;
|
|
53
|
+
has(name: string): boolean;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=persistence-adapter.d.ts.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-memory implementation of EncryptedStorage for development and testing.
|
|
3
|
+
* Data is NOT encrypted — use only in non-production environments.
|
|
4
|
+
*/
|
|
5
|
+
export class InMemoryEncryptedStorage {
|
|
6
|
+
store = new Map();
|
|
7
|
+
async get(key) {
|
|
8
|
+
return this.store.get(key) ?? null;
|
|
9
|
+
}
|
|
10
|
+
async set(key, value) {
|
|
11
|
+
this.store.set(key, value);
|
|
12
|
+
}
|
|
13
|
+
async delete(key) {
|
|
14
|
+
this.store.delete(key);
|
|
15
|
+
}
|
|
16
|
+
async exists(key) {
|
|
17
|
+
return this.store.has(key);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Adapter that wraps Auxiora's Vault as an EncryptedStorage implementation.
|
|
22
|
+
*
|
|
23
|
+
* The Vault must be unlocked before use. All values are AES-256-GCM encrypted
|
|
24
|
+
* on disk via the vault's own encryption layer.
|
|
25
|
+
*
|
|
26
|
+
* Usage:
|
|
27
|
+
* const vault = new Vault();
|
|
28
|
+
* await vault.unlock(password);
|
|
29
|
+
* const storage = new VaultStorageAdapter(vault);
|
|
30
|
+
* const persistence = new ArchitectPersistence(storage);
|
|
31
|
+
*/
|
|
32
|
+
export class VaultStorageAdapter {
|
|
33
|
+
vault;
|
|
34
|
+
constructor(vault) {
|
|
35
|
+
this.vault = vault;
|
|
36
|
+
}
|
|
37
|
+
async get(key) {
|
|
38
|
+
return this.vault.get(key) ?? null;
|
|
39
|
+
}
|
|
40
|
+
async set(key, value) {
|
|
41
|
+
await this.vault.add(key, value);
|
|
42
|
+
}
|
|
43
|
+
async delete(key) {
|
|
44
|
+
await this.vault.remove(key);
|
|
45
|
+
}
|
|
46
|
+
async exists(key) {
|
|
47
|
+
return this.vault.has(key);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=persistence-adapter.js.map
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { ContextDomain } from '../schema.js';
|
|
2
|
+
import type { EncryptedStorage } from './persistence-adapter.js';
|
|
3
|
+
import { CorrectionStore } from './correction-store.js';
|
|
4
|
+
export interface ArchitectPreferences {
|
|
5
|
+
/** Serialized CorrectionStore (context detection learning data). */
|
|
6
|
+
corrections: string;
|
|
7
|
+
/** Serialized CustomWeights (user trait adjustments). */
|
|
8
|
+
customWeights?: string;
|
|
9
|
+
/** Serialized PreferenceHistory (timestamped preference changes). */
|
|
10
|
+
preferenceHistory?: string;
|
|
11
|
+
/** Serialized DecisionLog (cross-session decision tracking). */
|
|
12
|
+
decisionLog?: string;
|
|
13
|
+
/** Serialized FeedbackStore (response feedback collection). */
|
|
14
|
+
feedbackStore?: string;
|
|
15
|
+
/** Whether to show the context indicator pill in the chat UI. */
|
|
16
|
+
showContextIndicator: boolean;
|
|
17
|
+
/** Whether to show the sources/provenance button in the chat UI. */
|
|
18
|
+
showSourcesButton: boolean;
|
|
19
|
+
/** Whether to auto-detect context from messages. */
|
|
20
|
+
autoDetectContext: boolean;
|
|
21
|
+
/** User-set default context override (null = auto-detect). */
|
|
22
|
+
defaultContext: ContextDomain | null;
|
|
23
|
+
/** Per-domain usage counts (local analytics, never transmitted). */
|
|
24
|
+
contextUsageHistory: Record<ContextDomain, number>;
|
|
25
|
+
/** Total number of interactions with The Architect. */
|
|
26
|
+
totalInteractions: number;
|
|
27
|
+
/** Timestamp of first use. */
|
|
28
|
+
firstUsed: number;
|
|
29
|
+
/** Timestamp of last use. */
|
|
30
|
+
lastUsed: number;
|
|
31
|
+
/** Schema version for migration support. */
|
|
32
|
+
version: number;
|
|
33
|
+
}
|
|
34
|
+
export declare class ArchitectPersistence {
|
|
35
|
+
private storage;
|
|
36
|
+
private static STORAGE_KEY;
|
|
37
|
+
constructor(storage: EncryptedStorage);
|
|
38
|
+
/** Load preferences from encrypted storage. Returns defaults if none exist. */
|
|
39
|
+
load(): Promise<ArchitectPreferences>;
|
|
40
|
+
/** Save preferences to encrypted storage. Updates lastUsed automatically. */
|
|
41
|
+
save(prefs: ArchitectPreferences): Promise<void>;
|
|
42
|
+
/** Increment usage count for a domain and total interactions. */
|
|
43
|
+
recordUsage(domain: ContextDomain): Promise<void>;
|
|
44
|
+
/** Update the corrections field from a CorrectionStore instance. */
|
|
45
|
+
saveCorrections(store: CorrectionStore): Promise<void>;
|
|
46
|
+
/** Get the top N most-used context domains, sorted by usage descending. */
|
|
47
|
+
getMostUsedContexts(topN: number): Promise<ContextDomain[]>;
|
|
48
|
+
/** Delete all stored Architect data (user privacy). */
|
|
49
|
+
clearAll(): Promise<void>;
|
|
50
|
+
/** Export all data as JSON string (user data portability). */
|
|
51
|
+
exportAll(): Promise<string>;
|
|
52
|
+
/** Handle version upgrades for stored preferences. */
|
|
53
|
+
private migrate;
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=persistence.d.ts.map
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { CorrectionStore } from './correction-store.js';
|
|
2
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
3
|
+
// Constants
|
|
4
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
5
|
+
const CURRENT_VERSION = 2;
|
|
6
|
+
const ALL_DOMAINS = [
|
|
7
|
+
'security_review', 'code_engineering', 'architecture_design', 'debugging',
|
|
8
|
+
'team_leadership', 'one_on_one', 'sales_pitch', 'negotiation',
|
|
9
|
+
'marketing_content', 'strategic_planning', 'crisis_management',
|
|
10
|
+
'creative_work', 'writing_content', 'decision_making',
|
|
11
|
+
'learning_research', 'personal_development', 'general',
|
|
12
|
+
];
|
|
13
|
+
function emptyUsageHistory() {
|
|
14
|
+
const history = {};
|
|
15
|
+
for (const domain of ALL_DOMAINS) {
|
|
16
|
+
history[domain] = 0;
|
|
17
|
+
}
|
|
18
|
+
return history;
|
|
19
|
+
}
|
|
20
|
+
function createDefaults() {
|
|
21
|
+
const now = Date.now();
|
|
22
|
+
return {
|
|
23
|
+
corrections: new CorrectionStore().serialize(),
|
|
24
|
+
showContextIndicator: true,
|
|
25
|
+
showSourcesButton: true,
|
|
26
|
+
autoDetectContext: true,
|
|
27
|
+
defaultContext: null,
|
|
28
|
+
contextUsageHistory: emptyUsageHistory(),
|
|
29
|
+
totalInteractions: 0,
|
|
30
|
+
firstUsed: now,
|
|
31
|
+
lastUsed: now,
|
|
32
|
+
version: CURRENT_VERSION,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
36
|
+
// ArchitectPersistence
|
|
37
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
38
|
+
export class ArchitectPersistence {
|
|
39
|
+
storage;
|
|
40
|
+
static STORAGE_KEY = 'architect_preferences';
|
|
41
|
+
constructor(storage) {
|
|
42
|
+
this.storage = storage;
|
|
43
|
+
}
|
|
44
|
+
/** Load preferences from encrypted storage. Returns defaults if none exist. */
|
|
45
|
+
async load() {
|
|
46
|
+
const raw = await this.storage.get(ArchitectPersistence.STORAGE_KEY);
|
|
47
|
+
if (raw === null) {
|
|
48
|
+
return createDefaults();
|
|
49
|
+
}
|
|
50
|
+
const prefs = JSON.parse(raw);
|
|
51
|
+
return this.migrate(prefs);
|
|
52
|
+
}
|
|
53
|
+
/** Save preferences to encrypted storage. Updates lastUsed automatically. */
|
|
54
|
+
async save(prefs) {
|
|
55
|
+
prefs.lastUsed = Date.now();
|
|
56
|
+
await this.storage.set(ArchitectPersistence.STORAGE_KEY, JSON.stringify(prefs));
|
|
57
|
+
}
|
|
58
|
+
/** Increment usage count for a domain and total interactions. */
|
|
59
|
+
async recordUsage(domain) {
|
|
60
|
+
const prefs = await this.load();
|
|
61
|
+
prefs.contextUsageHistory[domain] = (prefs.contextUsageHistory[domain] ?? 0) + 1;
|
|
62
|
+
prefs.totalInteractions++;
|
|
63
|
+
await this.save(prefs);
|
|
64
|
+
}
|
|
65
|
+
/** Update the corrections field from a CorrectionStore instance. */
|
|
66
|
+
async saveCorrections(store) {
|
|
67
|
+
const prefs = await this.load();
|
|
68
|
+
prefs.corrections = store.serialize();
|
|
69
|
+
await this.save(prefs);
|
|
70
|
+
}
|
|
71
|
+
/** Get the top N most-used context domains, sorted by usage descending. */
|
|
72
|
+
async getMostUsedContexts(topN) {
|
|
73
|
+
const prefs = await this.load();
|
|
74
|
+
return Object.entries(prefs.contextUsageHistory)
|
|
75
|
+
.filter(([, count]) => count > 0)
|
|
76
|
+
.sort(([, a], [, b]) => b - a)
|
|
77
|
+
.slice(0, topN)
|
|
78
|
+
.map(([domain]) => domain);
|
|
79
|
+
}
|
|
80
|
+
/** Delete all stored Architect data (user privacy). */
|
|
81
|
+
async clearAll() {
|
|
82
|
+
await this.storage.delete(ArchitectPersistence.STORAGE_KEY);
|
|
83
|
+
}
|
|
84
|
+
/** Export all data as JSON string (user data portability). */
|
|
85
|
+
async exportAll() {
|
|
86
|
+
const prefs = await this.load();
|
|
87
|
+
return JSON.stringify(prefs, null, 2);
|
|
88
|
+
}
|
|
89
|
+
/** Handle version upgrades for stored preferences. */
|
|
90
|
+
async migrate(prefs) {
|
|
91
|
+
if (prefs.version === CURRENT_VERSION) {
|
|
92
|
+
return prefs;
|
|
93
|
+
}
|
|
94
|
+
// Version 0 → 1: add missing fields with defaults
|
|
95
|
+
if (prefs.version === 0 || prefs.version === undefined) {
|
|
96
|
+
const defaults = createDefaults();
|
|
97
|
+
prefs.showContextIndicator ??= defaults.showContextIndicator;
|
|
98
|
+
prefs.showSourcesButton ??= defaults.showSourcesButton;
|
|
99
|
+
prefs.autoDetectContext ??= defaults.autoDetectContext;
|
|
100
|
+
prefs.defaultContext ??= defaults.defaultContext;
|
|
101
|
+
prefs.contextUsageHistory ??= defaults.contextUsageHistory;
|
|
102
|
+
prefs.totalInteractions ??= defaults.totalInteractions;
|
|
103
|
+
prefs.firstUsed ??= defaults.firstUsed;
|
|
104
|
+
prefs.lastUsed ??= defaults.lastUsed;
|
|
105
|
+
prefs.corrections ??= defaults.corrections;
|
|
106
|
+
// Ensure all domains exist in usage history
|
|
107
|
+
for (const domain of ALL_DOMAINS) {
|
|
108
|
+
prefs.contextUsageHistory[domain] ??= 0;
|
|
109
|
+
}
|
|
110
|
+
prefs.version = 1;
|
|
111
|
+
}
|
|
112
|
+
// Version 1 → 2: add self-awareness modules (preference history, decision log, feedback store)
|
|
113
|
+
if (prefs.version === 1) {
|
|
114
|
+
prefs.preferenceHistory ??= undefined;
|
|
115
|
+
prefs.decisionLog ??= undefined;
|
|
116
|
+
prefs.feedbackStore ??= undefined;
|
|
117
|
+
prefs.version = CURRENT_VERSION;
|
|
118
|
+
}
|
|
119
|
+
await this.save(prefs);
|
|
120
|
+
return prefs;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=persistence.js.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { TraitMix, ContextDomain } from '../schema.js';
|
|
2
|
+
export interface PreferenceEntry {
|
|
3
|
+
trait: keyof TraitMix;
|
|
4
|
+
offset: number;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
context: ContextDomain | null;
|
|
7
|
+
source: 'user' | 'preset' | 'feedback';
|
|
8
|
+
reason?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface PreferenceConflict {
|
|
11
|
+
trait: keyof TraitMix;
|
|
12
|
+
entries: PreferenceEntry[];
|
|
13
|
+
resolution: number;
|
|
14
|
+
strategy: 'recency' | 'context';
|
|
15
|
+
}
|
|
16
|
+
export declare class PreferenceHistory {
|
|
17
|
+
private entries;
|
|
18
|
+
private maxEntries;
|
|
19
|
+
/** Record a preference change (called by CustomWeights wrapper). */
|
|
20
|
+
record(entry: Omit<PreferenceEntry, 'timestamp'>): void;
|
|
21
|
+
/**
|
|
22
|
+
* Get the effective offset for a trait, using recency-weighted resolution.
|
|
23
|
+
*
|
|
24
|
+
* 1. If a context-scoped entry exists for the current domain, use it
|
|
25
|
+
* (strategy: 'context').
|
|
26
|
+
* 2. Otherwise, use exponential recency weighting: recent entries count
|
|
27
|
+
* more (decay factor 0.8 per entry) (strategy: 'recency').
|
|
28
|
+
* 3. Entries older than 30 days decay to 10 % weight.
|
|
29
|
+
*/
|
|
30
|
+
getEffectiveOffset(trait: keyof TraitMix, currentDomain?: ContextDomain): number;
|
|
31
|
+
/**
|
|
32
|
+
* Detect conflicts: entries for the same trait that pull in opposite
|
|
33
|
+
* directions. Returns conflicts with the resolved value and strategy used.
|
|
34
|
+
*/
|
|
35
|
+
detectConflicts(): PreferenceConflict[];
|
|
36
|
+
/** Get history for a specific trait, most recent first. */
|
|
37
|
+
getTraitHistory(trait: keyof TraitMix): PreferenceEntry[];
|
|
38
|
+
/** Serialize for encrypted storage. */
|
|
39
|
+
serialize(): string;
|
|
40
|
+
/** Deserialize from encrypted storage. Validates entry shapes defensively. */
|
|
41
|
+
static deserialize(data: string): PreferenceHistory;
|
|
42
|
+
/** Clear all preference history (user data deletion). */
|
|
43
|
+
clear(): void;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=preference-history.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preference-history.d.ts","sourceRoot":"","sources":["preference-history.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAM5D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,QAAQ,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,aAAa,GAAG,IAAI,CAAC;IAC9B,MAAM,EAAE,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;IACvC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,MAAM,QAAQ,CAAC;IACtB,OAAO,EAAE,eAAe,EAAE,CAAC;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,SAAS,GAAG,SAAS,CAAC;CACjC;AAmBD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,UAAU,CAAO;IAIzB,oEAAoE;IACpE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,eAAe,EAAE,WAAW,CAAC,GAAG,IAAI;IASvD;;;;;;;;OAQG;IACH,kBAAkB,CAChB,KAAK,EAAE,MAAM,QAAQ,EACrB,aAAa,CAAC,EAAE,aAAa,GAC5B,MAAM;IA0CT;;;OAGG;IACH,eAAe,IAAI,kBAAkB,EAAE;IAoCvC,2DAA2D;IAC3D,eAAe,CAAC,KAAK,EAAE,MAAM,QAAQ,GAAG,eAAe,EAAE;IAQzD,uCAAuC;IACvC,SAAS,IAAI,MAAM;IAInB,8EAA8E;IAC9E,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB;IAqBnD,yDAAyD;IACzD,KAAK,IAAI,IAAI;CAGd"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
2
|
+
// Constants
|
|
3
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
/** Exponential decay factor per entry (most recent = 1, next = 0.8, etc.). */
|
|
5
|
+
const RECENCY_DECAY = 0.8;
|
|
6
|
+
/** Entries older than this (ms) decay to 10 % weight. */
|
|
7
|
+
const AGE_THRESHOLD_MS = 30 * 24 * 60 * 60 * 1000; // 30 days
|
|
8
|
+
/** Minimum weight for entries older than AGE_THRESHOLD_MS. */
|
|
9
|
+
const OLD_ENTRY_WEIGHT = 0.1;
|
|
10
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
11
|
+
// PreferenceHistory
|
|
12
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
13
|
+
export class PreferenceHistory {
|
|
14
|
+
entries = [];
|
|
15
|
+
maxEntries = 200;
|
|
16
|
+
// ── Record ──────────────────────────────────────────────────────────────
|
|
17
|
+
/** Record a preference change (called by CustomWeights wrapper). */
|
|
18
|
+
record(entry) {
|
|
19
|
+
this.entries.push({ ...entry, timestamp: Date.now() });
|
|
20
|
+
if (this.entries.length > this.maxEntries) {
|
|
21
|
+
this.entries = this.entries.slice(this.entries.length - this.maxEntries);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
// ── Effective offset ────────────────────────────────────────────────────
|
|
25
|
+
/**
|
|
26
|
+
* Get the effective offset for a trait, using recency-weighted resolution.
|
|
27
|
+
*
|
|
28
|
+
* 1. If a context-scoped entry exists for the current domain, use it
|
|
29
|
+
* (strategy: 'context').
|
|
30
|
+
* 2. Otherwise, use exponential recency weighting: recent entries count
|
|
31
|
+
* more (decay factor 0.8 per entry) (strategy: 'recency').
|
|
32
|
+
* 3. Entries older than 30 days decay to 10 % weight.
|
|
33
|
+
*/
|
|
34
|
+
getEffectiveOffset(trait, currentDomain) {
|
|
35
|
+
const traitEntries = this.entries.filter(e => e.trait === trait);
|
|
36
|
+
if (traitEntries.length === 0)
|
|
37
|
+
return 0;
|
|
38
|
+
// Strategy 1: context-scoped match
|
|
39
|
+
if (currentDomain) {
|
|
40
|
+
const contextEntries = traitEntries.filter(e => e.context === currentDomain);
|
|
41
|
+
if (contextEntries.length > 0) {
|
|
42
|
+
// Use the most recent context-scoped entry
|
|
43
|
+
return contextEntries[contextEntries.length - 1].offset;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Strategy 2: recency-weighted average
|
|
47
|
+
const now = Date.now();
|
|
48
|
+
const sorted = [...traitEntries].sort((a, b) => b.timestamp - a.timestamp); // most recent first
|
|
49
|
+
let weightedSum = 0;
|
|
50
|
+
let totalWeight = 0;
|
|
51
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
52
|
+
let weight = Math.pow(RECENCY_DECAY, i);
|
|
53
|
+
// Age decay: entries older than 30 days get capped at 10 %
|
|
54
|
+
const ageMs = now - sorted[i].timestamp;
|
|
55
|
+
if (ageMs > AGE_THRESHOLD_MS) {
|
|
56
|
+
weight *= OLD_ENTRY_WEIGHT;
|
|
57
|
+
}
|
|
58
|
+
weightedSum += sorted[i].offset * weight;
|
|
59
|
+
totalWeight += weight;
|
|
60
|
+
}
|
|
61
|
+
return totalWeight > 0 ? weightedSum / totalWeight : 0;
|
|
62
|
+
}
|
|
63
|
+
// ── Conflict detection ──────────────────────────────────────────────────
|
|
64
|
+
/**
|
|
65
|
+
* Detect conflicts: entries for the same trait that pull in opposite
|
|
66
|
+
* directions. Returns conflicts with the resolved value and strategy used.
|
|
67
|
+
*/
|
|
68
|
+
detectConflicts() {
|
|
69
|
+
const byTrait = new Map();
|
|
70
|
+
for (const entry of this.entries) {
|
|
71
|
+
const existing = byTrait.get(entry.trait);
|
|
72
|
+
if (existing) {
|
|
73
|
+
existing.push(entry);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
byTrait.set(entry.trait, [entry]);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const conflicts = [];
|
|
80
|
+
for (const [trait, entries] of byTrait) {
|
|
81
|
+
if (entries.length < 2)
|
|
82
|
+
continue;
|
|
83
|
+
const hasPositive = entries.some(e => e.offset > 0);
|
|
84
|
+
const hasNegative = entries.some(e => e.offset < 0);
|
|
85
|
+
if (hasPositive && hasNegative) {
|
|
86
|
+
const resolution = this.getEffectiveOffset(trait);
|
|
87
|
+
conflicts.push({
|
|
88
|
+
trait,
|
|
89
|
+
entries: [...entries],
|
|
90
|
+
resolution,
|
|
91
|
+
strategy: 'recency',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return conflicts;
|
|
96
|
+
}
|
|
97
|
+
// ── Trait history ───────────────────────────────────────────────────────
|
|
98
|
+
/** Get history for a specific trait, most recent first. */
|
|
99
|
+
getTraitHistory(trait) {
|
|
100
|
+
return this.entries
|
|
101
|
+
.filter(e => e.trait === trait)
|
|
102
|
+
.sort((a, b) => b.timestamp - a.timestamp);
|
|
103
|
+
}
|
|
104
|
+
// ── Serialization ─────────────────────────────────────────────────────
|
|
105
|
+
/** Serialize for encrypted storage. */
|
|
106
|
+
serialize() {
|
|
107
|
+
return JSON.stringify({ entries: this.entries });
|
|
108
|
+
}
|
|
109
|
+
/** Deserialize from encrypted storage. Validates entry shapes defensively. */
|
|
110
|
+
static deserialize(data) {
|
|
111
|
+
const history = new PreferenceHistory();
|
|
112
|
+
try {
|
|
113
|
+
const parsed = JSON.parse(data);
|
|
114
|
+
if (Array.isArray(parsed.entries)) {
|
|
115
|
+
history.entries = parsed.entries.filter((e) => typeof e === 'object' && e !== null &&
|
|
116
|
+
typeof e.trait === 'string' &&
|
|
117
|
+
typeof e.offset === 'number' &&
|
|
118
|
+
typeof e.timestamp === 'number');
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
// Corrupt data — return empty history
|
|
123
|
+
}
|
|
124
|
+
return history;
|
|
125
|
+
}
|
|
126
|
+
// ── Lifecycle ──────────────────────────────────────────────────────────
|
|
127
|
+
/** Clear all preference history (user data deletion). */
|
|
128
|
+
clear() {
|
|
129
|
+
this.entries = [];
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=preference-history.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"preference-history.js","sourceRoot":"","sources":["preference-history.ts"],"names":[],"mappings":"AAsBA,+EAA+E;AAC/E,YAAY;AACZ,+EAA+E;AAE/E,8EAA8E;AAC9E,MAAM,aAAa,GAAG,GAAG,CAAC;AAE1B,yDAAyD;AACzD,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,UAAU;AAE7D,8DAA8D;AAC9D,MAAM,gBAAgB,GAAG,GAAG,CAAC;AAE7B,+EAA+E;AAC/E,oBAAoB;AACpB,+EAA+E;AAE/E,MAAM,OAAO,iBAAiB;IACpB,OAAO,GAAsB,EAAE,CAAC;IAChC,UAAU,GAAG,GAAG,CAAC;IAEzB,2EAA2E;IAE3E,oEAAoE;IACpE,MAAM,CAAC,KAAyC;QAC9C,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACvD,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,EAAE,CAAC;YAC1C,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED,2EAA2E;IAE3E;;;;;;;;OAQG;IACH,kBAAkB,CAChB,KAAqB,EACrB,aAA6B;QAE7B,MAAM,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC;QACjE,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,CAAC,CAAC;QAExC,mCAAmC;QACnC,IAAI,aAAa,EAAE,CAAC;YAClB,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,CACxC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,aAAa,CACjC,CAAC;YACF,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC9B,2CAA2C;gBAC3C,OAAO,cAAc,CAAC,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC;YAC1D,CAAC;QACH,CAAC;QAED,uCAAuC;QACvC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,MAAM,GAAG,CAAC,GAAG,YAAY,CAAC,CAAC,IAAI,CACnC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CACpC,CAAC,CAAC,oBAAoB;QAEvB,IAAI,WAAW,GAAG,CAAC,CAAC;QACpB,IAAI,WAAW,GAAG,CAAC,CAAC;QAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACvC,IAAI,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC;YAExC,2DAA2D;YAC3D,MAAM,KAAK,GAAG,GAAG,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;YACxC,IAAI,KAAK,GAAG,gBAAgB,EAAE,CAAC;gBAC7B,MAAM,IAAI,gBAAgB,CAAC;YAC7B,CAAC;YAED,WAAW,IAAI,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,MAAM,CAAC;YACzC,WAAW,IAAI,MAAM,CAAC;QACxB,CAAC;QAED,OAAO,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,WAAW,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;IACzD,CAAC;IAED,2EAA2E;IAE3E;;;OAGG;IACH,eAAe;QACb,MAAM,OAAO,GAAG,IAAI,GAAG,EAAqC,CAAC;QAE7D,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC1C,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACvB,CAAC;iBAAM,CAAC;gBACN,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;QAED,MAAM,SAAS,GAAyB,EAAE,CAAC;QAE3C,KAAK,MAAM,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,OAAO,EAAE,CAAC;YACvC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;gBAAE,SAAS;YAEjC,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YACpD,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAEpD,IAAI,WAAW,IAAI,WAAW,EAAE,CAAC;gBAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;gBAClD,SAAS,CAAC,IAAI,CAAC;oBACb,KAAK;oBACL,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC;oBACrB,UAAU;oBACV,QAAQ,EAAE,SAAS;iBACpB,CAAC,CAAC;YACL,CAAC;QACH,CAAC;QAED,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,2EAA2E;IAE3E,2DAA2D;IAC3D,eAAe,CAAC,KAAqB;QACnC,OAAO,IAAI,CAAC,OAAO;aAChB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC;aAC9B,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,CAAC,CAAC;IAC/C,CAAC;IAED,yEAAyE;IAEzE,uCAAuC;IACvC,SAAS;QACP,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,8EAA8E;IAC9E,MAAM,CAAC,WAAW,CAAC,IAAY;QAC7B,MAAM,OAAO,GAAG,IAAI,iBAAiB,EAAE,CAAC;QACxC,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;YAC3D,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC;gBAClC,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CACrC,CAAC,CAAC,EAAwB,EAAE,CAC1B,OAAO,CAAC,KAAK,QAAQ,IAAI,CAAC,KAAK,IAAI;oBACnC,OAAQ,CAAqB,CAAC,KAAK,KAAK,QAAQ;oBAChD,OAAQ,CAAqB,CAAC,MAAM,KAAK,QAAQ;oBACjD,OAAQ,CAAqB,CAAC,SAAS,KAAK,QAAQ,CACvD,CAAC;YACJ,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,sCAAsC;QACxC,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,0EAA0E;IAE1E,yDAAyD;IACzD,KAAK;QACH,IAAI,CAAC,OAAO,GAAG,EAAE,CAAC;IACpB,CAAC;CACF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { TraitMix, TaskContext, TraitSource } from '../schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* Assembles a context-specific prompt modifier from the current trait mix.
|
|
4
|
+
*
|
|
5
|
+
* Selects the top 10 weighted traits, generates a weight-scaled behavioral
|
|
6
|
+
* instruction for each, and composes them into a prompt block that sits
|
|
7
|
+
* between the base personality prompt and the user message.
|
|
8
|
+
*/
|
|
9
|
+
export declare function assemblePromptModifier(mix: TraitMix, context: TaskContext): string;
|
|
10
|
+
/**
|
|
11
|
+
* Returns the SOURCE_MAP entries for the top N weighted traits in the mix.
|
|
12
|
+
* Useful for transparency — explaining *why* the personality is behaving
|
|
13
|
+
* a certain way and which historical minds are driving the response.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getActiveSources(mix: TraitMix, topN?: number): TraitSource[];
|
|
16
|
+
//# sourceMappingURL=prompt-assembler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-assembler.d.ts","sourceRoot":"","sources":["prompt-assembler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAQvE;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,GAAG,MAAM,CA6BlF;AAMD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,GAAE,MAAW,GAAG,WAAW,EAAE,CAQhF"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { TRAIT_TO_INSTRUCTION } from './trait-to-instruction.js';
|
|
2
|
+
import { SOURCE_MAP } from './source-map.js';
|
|
3
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
4
|
+
// Prompt modifier assembly
|
|
5
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
6
|
+
/**
|
|
7
|
+
* Assembles a context-specific prompt modifier from the current trait mix.
|
|
8
|
+
*
|
|
9
|
+
* Selects the top 10 weighted traits, generates a weight-scaled behavioral
|
|
10
|
+
* instruction for each, and composes them into a prompt block that sits
|
|
11
|
+
* between the base personality prompt and the user message.
|
|
12
|
+
*/
|
|
13
|
+
export function assemblePromptModifier(mix, context) {
|
|
14
|
+
const entries = Object.entries(mix);
|
|
15
|
+
// Sort by weight descending, take top 10
|
|
16
|
+
const top = entries
|
|
17
|
+
.sort((a, b) => b[1] - a[1])
|
|
18
|
+
.slice(0, 10);
|
|
19
|
+
const instructions = [];
|
|
20
|
+
for (const [key, value] of top) {
|
|
21
|
+
const fn = TRAIT_TO_INSTRUCTION[key];
|
|
22
|
+
if (fn) {
|
|
23
|
+
instructions.push(fn(value, context));
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return [
|
|
27
|
+
'## Current Context Adaptation',
|
|
28
|
+
'',
|
|
29
|
+
`You are operating in a **${formatDomain(context.domain)}** context.`,
|
|
30
|
+
`The user's emotional state appears **${context.emotionalRegister}**.`,
|
|
31
|
+
`Stakes: **${context.stakes}**. Complexity: **${context.complexity}**.`,
|
|
32
|
+
'',
|
|
33
|
+
'For this interaction, emphasize:',
|
|
34
|
+
'',
|
|
35
|
+
...instructions.map((i) => `- ${i}`),
|
|
36
|
+
'',
|
|
37
|
+
`Tone: warmth=${mix.warmth.toFixed(1)}, urgency=${mix.urgency.toFixed(1)}, humor=${mix.humor.toFixed(1)}, depth=${mix.verbosity.toFixed(1)}`,
|
|
38
|
+
].join('\n');
|
|
39
|
+
}
|
|
40
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
// Active source retrieval
|
|
42
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
43
|
+
/**
|
|
44
|
+
* Returns the SOURCE_MAP entries for the top N weighted traits in the mix.
|
|
45
|
+
* Useful for transparency — explaining *why* the personality is behaving
|
|
46
|
+
* a certain way and which historical minds are driving the response.
|
|
47
|
+
*/
|
|
48
|
+
export function getActiveSources(mix, topN = 10) {
|
|
49
|
+
const entries = Object.entries(mix);
|
|
50
|
+
return entries
|
|
51
|
+
.sort((a, b) => b[1] - a[1])
|
|
52
|
+
.slice(0, topN)
|
|
53
|
+
.map(([key]) => SOURCE_MAP[key])
|
|
54
|
+
.filter(Boolean);
|
|
55
|
+
}
|
|
56
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
57
|
+
// Helpers
|
|
58
|
+
// ────────────────────────────────────────────────────────────────────────────
|
|
59
|
+
/** Converts a snake_case domain key to a human-readable label. */
|
|
60
|
+
function formatDomain(domain) {
|
|
61
|
+
return domain
|
|
62
|
+
.split('_')
|
|
63
|
+
.map((w) => w.charAt(0).toUpperCase() + w.slice(1))
|
|
64
|
+
.join(' ');
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=prompt-assembler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-assembler.js","sourceRoot":"","sources":["prompt-assembler.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAE7C,+EAA+E;AAC/E,2BAA2B;AAC3B,+EAA+E;AAE/E;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,GAAa,EAAE,OAAoB;IACxE,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAoC,CAAC;IAEvE,yCAAyC;IACzC,MAAM,GAAG,GAAG,OAAO;SAChB,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAEhB,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,GAAG,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;QACrC,IAAI,EAAE,EAAE,CAAC;YACP,YAAY,CAAC,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,OAAO;QACL,+BAA+B;QAC/B,EAAE;QACF,4BAA4B,YAAY,CAAC,OAAO,CAAC,MAAM,CAAC,aAAa;QACrE,wCAAwC,OAAO,CAAC,iBAAiB,KAAK;QACtE,aAAa,OAAO,CAAC,MAAM,qBAAqB,OAAO,CAAC,UAAU,KAAK;QACvE,EAAE;QACF,kCAAkC;QAClC,EAAE;QACF,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,EAAE;QACF,gBAAgB,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,WAAW,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;KAC7I,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED,+EAA+E;AAC/E,0BAA0B;AAC1B,+EAA+E;AAE/E;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAa,EAAE,OAAe,EAAE;IAC/D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAoC,CAAC;IAEvE,OAAO,OAAO;SACX,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;SAC3B,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC;SACd,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;SAC/B,MAAM,CAAC,OAAO,CAAC,CAAC;AACrB,CAAC;AAED,+EAA+E;AAC/E,UAAU;AACV,+EAA+E;AAE/E,kEAAkE;AAClE,SAAS,YAAY,CAAC,MAAc;IAClC,OAAO,MAAM;SACV,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;SAClD,IAAI,CAAC,GAAG,CAAC,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { TaskContext, ContextDomain } from '../schema.js';
|
|
2
|
+
import type { CorrectionStore } from './correction-store.js';
|
|
3
|
+
export interface ContextRecommendation {
|
|
4
|
+
suggestedDomain: ContextDomain;
|
|
5
|
+
reason: string;
|
|
6
|
+
confidence: number;
|
|
7
|
+
source: 'correction_pattern' | 'low_confidence' | 'usage_pattern';
|
|
8
|
+
}
|
|
9
|
+
export declare class ContextRecommender {
|
|
10
|
+
/**
|
|
11
|
+
* Analyze the detected context and determine if a recommendation should
|
|
12
|
+
* be shown. Returns null if auto-detection seems right; otherwise returns
|
|
13
|
+
* a recommendation with a human-readable reason and confidence score.
|
|
14
|
+
*
|
|
15
|
+
* Priority order:
|
|
16
|
+
* 1. Correction-based (learned from user overrides)
|
|
17
|
+
* 2. Low-confidence (ambiguous detection, close runner-up)
|
|
18
|
+
* 3. Usage-pattern (general detected but history is concentrated)
|
|
19
|
+
*/
|
|
20
|
+
shouldRecommend(detectedContext: TaskContext, correctionStore: CorrectionStore, usageHistory: Record<ContextDomain, number>, userMessage?: string): ContextRecommendation | null;
|
|
21
|
+
private correctionBased;
|
|
22
|
+
private lowConfidence;
|
|
23
|
+
private usagePattern;
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=recommender.d.ts.map
|