@pencil-agent/nano-pencil 1.5.1 → 1.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,20 @@
1
+ /**
2
+ * [INPUT]: Partial<SoulConfig> overrides
3
+ * [OUTPUT]: Default SoulConfig merged with overrides
4
+ * [POS]: Configuration layer - provides defaults and validation
5
+ */
6
+ import type { SoulConfig } from "./types.js";
7
+ export type { SoulConfig } from "./types.js";
8
+ /**
9
+ * Get default Soul configuration
10
+ */
11
+ export declare function getDefaultConfig(): SoulConfig;
12
+ /**
13
+ * Get Soul configuration with overrides applied
14
+ */
15
+ export declare function getSoulConfig(overrides?: Partial<SoulConfig>): SoulConfig;
16
+ /**
17
+ * Validate Soul configuration
18
+ */
19
+ export declare function validateSoulConfig(config: SoulConfig): void;
20
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1,92 @@
1
+ /**
2
+ * [INPUT]: Partial<SoulConfig> overrides
3
+ * [OUTPUT]: Default SoulConfig merged with overrides
4
+ * [POS]: Configuration layer - provides defaults and validation
5
+ */
6
+ import { join } from "node:path";
7
+ import { homedir } from "node:os";
8
+ /**
9
+ * Get default Soul configuration
10
+ */
11
+ export function getDefaultConfig() {
12
+ const soulDir = process.env.SOUL_DIR || join(homedir(), ".nanopencil", "soul");
13
+ return {
14
+ soulDir,
15
+ evolution: {
16
+ natural: 10, // Evolve every 10 interactions
17
+ reflection: 100, // Deep reflection every 100 interactions
18
+ feedback: 1, // Evolve on every user feedback
19
+ crisis: 5, // Crisis mode after 5 failures
20
+ },
21
+ personalityLimits: {
22
+ maxDelta: 0.05, // Max 5% change per evolution
23
+ min: 0.1, // Floor at 10%
24
+ max: 0.9, // Ceiling at 90%
25
+ },
26
+ valueLimits: {
27
+ maxDelta: 0.1, // Max 10% change per evolution
28
+ min: 0.05, // Floor at 5%
29
+ max: 0.5, // Ceiling at 50% (since they sum to ~1)
30
+ },
31
+ memoryRetention: {
32
+ successes: 500,
33
+ failures: 500,
34
+ patterns: 200,
35
+ decisions: 1000,
36
+ },
37
+ };
38
+ }
39
+ /**
40
+ * Get Soul configuration with overrides applied
41
+ */
42
+ export function getSoulConfig(overrides) {
43
+ const defaults = getDefaultConfig();
44
+ if (!overrides)
45
+ return defaults;
46
+ return {
47
+ soulDir: overrides.soulDir ?? defaults.soulDir,
48
+ evolution: { ...defaults.evolution, ...overrides.evolution },
49
+ personalityLimits: {
50
+ ...defaults.personalityLimits,
51
+ ...overrides.personalityLimits,
52
+ },
53
+ valueLimits: { ...defaults.valueLimits, ...overrides.valueLimits },
54
+ memoryRetention: {
55
+ ...defaults.memoryRetention,
56
+ ...overrides.memoryRetention,
57
+ },
58
+ };
59
+ }
60
+ /**
61
+ * Validate Soul configuration
62
+ */
63
+ export function validateSoulConfig(config) {
64
+ // Validate evolution thresholds
65
+ if (config.evolution.natural < 1) {
66
+ throw new Error("evolution.natural must be at least 1");
67
+ }
68
+ if (config.evolution.reflection < config.evolution.natural) {
69
+ throw new Error("evolution.reflection must be >= evolution.natural");
70
+ }
71
+ // Validate limits
72
+ if (config.personalityLimits.maxDelta > 0.2) {
73
+ throw new Error("personalityLimits.maxDelta must be <= 0.2 (20%)");
74
+ }
75
+ if (config.personalityLimits.min < 0 || config.personalityLimits.min > 1) {
76
+ throw new Error("personalityLimits.min must be between 0 and 1");
77
+ }
78
+ if (config.personalityLimits.max < 0 || config.personalityLimits.max > 1) {
79
+ throw new Error("personalityLimits.max must be between 0 and 1");
80
+ }
81
+ if (config.personalityLimits.min >= config.personalityLimits.max) {
82
+ throw new Error("personalityLimits.min must be < personalityLimits.max");
83
+ }
84
+ // Validate memory retention
85
+ if (config.memoryRetention.successes < 100) {
86
+ throw new Error("memoryRetention.successes must be at least 100");
87
+ }
88
+ if (config.memoryRetention.failures < 100) {
89
+ throw new Error("memoryRetention.failures must be at least 100");
90
+ }
91
+ }
92
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * [INPUT]: Current profile, experiences, feedback
3
+ * [OUTPUT]: Personality and value deltas (evolution)
4
+ * [POS]: Evolution engine - implements learning algorithms
5
+ */
6
+ import type { SoulProfile, SoulMemory, PersonalityDelta, ValueDelta, SoulEvolution, InteractionContext } from "./types.js";
7
+ import type { SoulConfig } from "./config.js";
8
+ /**
9
+ * Soul Evolution Engine
10
+ */
11
+ export declare class SoulEvolutionEngine {
12
+ private config;
13
+ constructor(config: SoulConfig);
14
+ /**
15
+ * Compute personality delta based on experience
16
+ */
17
+ computePersonalityDelta(profile: SoulProfile, context: InteractionContext, outcome: "success" | "failure", previousAttempts?: number): PersonalityDelta;
18
+ /**
19
+ * Compute value delta based on context and outcome
20
+ */
21
+ computeValueDelta(profile: SoulProfile, context: InteractionContext, outcome: "success" | "failure"): ValueDelta;
22
+ /**
23
+ * Apply personality bounds
24
+ */
25
+ private applyPersonalityBounds;
26
+ /**
27
+ * Apply value bounds
28
+ */
29
+ private applyValueBounds;
30
+ /**
31
+ * Apply delta to profile
32
+ */
33
+ applyEvolution(profile: SoulProfile, evolution: SoulEvolution): SoulProfile;
34
+ /**
35
+ * Detect patterns from memory
36
+ */
37
+ detectPatterns(memory: SoulMemory, profile: SoulProfile): PatternInsight[];
38
+ /**
39
+ * Analyze success patterns
40
+ */
41
+ private analyzeSuccessPatterns;
42
+ /**
43
+ * Analyze failure patterns
44
+ */
45
+ private analyzeFailurePatterns;
46
+ /**
47
+ * Average personality snapshots
48
+ */
49
+ private averagePersonality;
50
+ /**
51
+ * Compute personality difference
52
+ */
53
+ private computePersonalityDiff;
54
+ /**
55
+ * Check if evolution should be triggered
56
+ */
57
+ shouldEvolve(profile: SoulProfile, context: InteractionContext, triggerType: SoulEvolution["trigger"]): boolean;
58
+ }
59
+ /**
60
+ * Pattern insight from analysis
61
+ */
62
+ export interface PatternInsight {
63
+ type: "success" | "failure";
64
+ category: string;
65
+ sampleSize: number;
66
+ avgPersonality?: SoulProfile["personality"];
67
+ delta?: Partial<SoulProfile["personality"]>;
68
+ recurring?: boolean;
69
+ correctedRate?: number;
70
+ recommendation?: string;
71
+ confidence: number;
72
+ }
73
+ //# sourceMappingURL=evolution.d.ts.map
@@ -0,0 +1,246 @@
1
+ /**
2
+ * [INPUT]: Current profile, experiences, feedback
3
+ * [OUTPUT]: Personality and value deltas (evolution)
4
+ * [POS]: Evolution engine - implements learning algorithms
5
+ */
6
+ /**
7
+ * Soul Evolution Engine
8
+ */
9
+ export class SoulEvolutionEngine {
10
+ config;
11
+ constructor(config) {
12
+ this.config = config;
13
+ }
14
+ /**
15
+ * Compute personality delta based on experience
16
+ */
17
+ computePersonalityDelta(profile, context, outcome, previousAttempts) {
18
+ const delta = {};
19
+ const limits = this.config.personalityLimits;
20
+ // Success reinforces current personality
21
+ if (outcome === "success") {
22
+ // Reinforce conscientiousness for quality work
23
+ if (previousAttempts && previousAttempts <= 2) {
24
+ delta.conscientiousness = Math.min(limits.maxDelta, 0.02);
25
+ }
26
+ // Reinforce openness for exploring new approaches
27
+ if (context.tags.includes("innovative")) {
28
+ delta.openness = Math.min(limits.maxDelta, 0.03);
29
+ }
30
+ // Reinforce safety margin for complex tasks
31
+ if (context.complexity > 0.7) {
32
+ delta.safetyMargin = Math.min(limits.maxDelta, 0.02);
33
+ }
34
+ }
35
+ // Failure triggers adjustment
36
+ else {
37
+ // Increase safety margin after failure
38
+ delta.safetyMargin = Math.min(limits.maxDelta, 0.05);
39
+ // Increase conscientiousness (be more careful)
40
+ delta.conscientiousness = Math.min(limits.maxDelta, 0.03);
41
+ // Decrease exploration (stick to known)
42
+ delta.explorationDrive = -Math.min(limits.maxDelta, 0.04);
43
+ }
44
+ // Apply bounds
45
+ return this.applyPersonalityBounds(profile.personality, delta);
46
+ }
47
+ /**
48
+ * Compute value delta based on context and outcome
49
+ */
50
+ computeValueDelta(profile, context, outcome) {
51
+ const delta = {};
52
+ const limits = this.config.valueLimits;
53
+ // Success reinforces values that led to it
54
+ if (outcome === "success") {
55
+ // If quick success, reinforce efficiency
56
+ if (context.toolUsage &&
57
+ Object.values(context.toolUsage).reduce((a, b) => a + b, 0) < 5) {
58
+ delta.efficiency = Math.min(limits.maxDelta, 0.05);
59
+ }
60
+ // If user rated highly, reinforce user experience
61
+ if (context.userFeedback && context.userFeedback.rating >= 4) {
62
+ delta.userExperience = Math.min(limits.maxDelta, 0.05);
63
+ }
64
+ }
65
+ // Failure triggers value reconsideration
66
+ else {
67
+ // Increase correctness priority after failure
68
+ delta.correctness = Math.min(limits.maxDelta, 0.05);
69
+ // Decrease innovation (was too risky)
70
+ delta.innovation = -Math.min(limits.maxDelta, 0.03);
71
+ }
72
+ // Apply bounds
73
+ return this.applyValueBounds(profile.values, delta);
74
+ }
75
+ /**
76
+ * Apply personality bounds
77
+ */
78
+ applyPersonalityBounds(personality, delta) {
79
+ const bounded = {};
80
+ const limits = this.config.personalityLimits;
81
+ for (const [key, value] of Object.entries(delta)) {
82
+ const current = personality[key];
83
+ if (current === undefined)
84
+ continue;
85
+ const newValue = current + value;
86
+ bounded[key] =
87
+ Math.max(limits.min, Math.min(limits.max, newValue)) - current;
88
+ }
89
+ return bounded;
90
+ }
91
+ /**
92
+ * Apply value bounds
93
+ */
94
+ applyValueBounds(values, delta) {
95
+ const bounded = {};
96
+ const limits = this.config.valueLimits;
97
+ for (const [key, value] of Object.entries(delta)) {
98
+ const current = values[key];
99
+ if (current === undefined)
100
+ continue;
101
+ const newValue = current + value;
102
+ bounded[key] =
103
+ Math.max(limits.min, Math.min(limits.max, newValue)) - current;
104
+ }
105
+ return bounded;
106
+ }
107
+ /**
108
+ * Apply delta to profile
109
+ */
110
+ applyEvolution(profile, evolution) {
111
+ const updated = { ...profile };
112
+ // Apply personality delta
113
+ for (const [key, value] of Object.entries(evolution.personalityDelta)) {
114
+ updated.personality[key] = Math.max(0, Math.min(1, updated.personality[key] + value));
115
+ }
116
+ // Apply value delta
117
+ for (const [key, value] of Object.entries(evolution.valueDelta)) {
118
+ updated.values[key] = Math.max(0, Math.min(1, updated.values[key] + value));
119
+ }
120
+ // Update metadata
121
+ updated.version += 1;
122
+ updated.lastEvolved = evolution.timestamp;
123
+ return updated;
124
+ }
125
+ /**
126
+ * Detect patterns from memory
127
+ */
128
+ detectPatterns(memory, profile) {
129
+ const insights = [];
130
+ // Analyze successes
131
+ const successfulPatterns = this.analyzeSuccessPatterns(memory.successes, profile);
132
+ insights.push(...successfulPatterns);
133
+ // Analyze failures
134
+ const failurePatterns = this.analyzeFailurePatterns(memory.failures);
135
+ insights.push(...failurePatterns);
136
+ return insights;
137
+ }
138
+ /**
139
+ * Analyze success patterns
140
+ */
141
+ analyzeSuccessPatterns(successes, profile) {
142
+ const insights = [];
143
+ // Group by category
144
+ const byCategory = new Map();
145
+ for (const success of successes) {
146
+ if (!byCategory.has(success.category)) {
147
+ byCategory.set(success.category, []);
148
+ }
149
+ byCategory.get(success.category).push(success);
150
+ }
151
+ // Find patterns
152
+ for (const [category, items] of byCategory) {
153
+ if (items.length < 3)
154
+ continue; // Need at least 3 samples
155
+ const avgPersonality = this.averagePersonality(items.map((i) => i.personalitySnapshot));
156
+ const delta = this.computePersonalityDiff(profile.personality, avgPersonality);
157
+ insights.push({
158
+ type: "success",
159
+ category,
160
+ sampleSize: items.length,
161
+ avgPersonality,
162
+ delta,
163
+ confidence: Math.min(1, items.length / 10),
164
+ });
165
+ }
166
+ return insights;
167
+ }
168
+ /**
169
+ * Analyze failure patterns
170
+ */
171
+ analyzeFailurePatterns(failures) {
172
+ const insights = [];
173
+ // Group by error type
174
+ const byError = new Map();
175
+ for (const failure of failures) {
176
+ if (!byError.has(failure.errorType)) {
177
+ byError.set(failure.errorType, []);
178
+ }
179
+ byError.get(failure.errorType).push(failure);
180
+ }
181
+ // Find patterns
182
+ for (const [errorType, items] of byError) {
183
+ if (items.length < 2)
184
+ continue;
185
+ // Check if failures are corrected
186
+ const correctedCount = items.filter((f) => f.corrected).length;
187
+ const recurring = items.length > correctedCount;
188
+ insights.push({
189
+ type: "failure",
190
+ category: errorType,
191
+ sampleSize: items.length,
192
+ recurring,
193
+ correctedRate: correctedCount / items.length,
194
+ recommendation: recurring
195
+ ? `Recurring error: ${errorType}. Consider increasing safetyMargin and conscientiousness.`
196
+ : `Error pattern learned and corrected: ${errorType}`,
197
+ confidence: Math.min(1, items.length / 5),
198
+ });
199
+ }
200
+ return insights;
201
+ }
202
+ /**
203
+ * Average personality snapshots
204
+ */
205
+ averagePersonality(snapshots) {
206
+ const avg = {};
207
+ for (const key of Object.keys(snapshots[0])) {
208
+ avg[key] =
209
+ snapshots.reduce((sum, s) => sum + s[key], 0) / snapshots.length;
210
+ }
211
+ return avg;
212
+ }
213
+ /**
214
+ * Compute personality difference
215
+ */
216
+ computePersonalityDiff(current, target) {
217
+ const diff = {};
218
+ for (const key of Object.keys(current)) {
219
+ const delta = target[key] - current[key];
220
+ if (Math.abs(delta) > 0.01) {
221
+ diff[key] = delta;
222
+ }
223
+ }
224
+ return diff;
225
+ }
226
+ /**
227
+ * Check if evolution should be triggered
228
+ */
229
+ shouldEvolve(profile, context, triggerType) {
230
+ const triggers = this.config.evolution;
231
+ switch (triggerType) {
232
+ case "natural":
233
+ return profile.stats.totalInteractions % triggers.natural === 0;
234
+ case "reflection":
235
+ return profile.stats.totalInteractions % triggers.reflection === 0;
236
+ case "feedback":
237
+ return context.userFeedback !== undefined;
238
+ case "crisis":
239
+ // Check recent failures
240
+ return (profile.stats.totalInteractions > 0 && profile.stats.successRate < 0.5);
241
+ default:
242
+ return false;
243
+ }
244
+ }
245
+ }
246
+ //# sourceMappingURL=evolution.js.map
@@ -0,0 +1,10 @@
1
+ /**
2
+ * NanoSoul Extension
3
+ *
4
+ * This extension integrates nanosoul as a loadable extension for NanoPencil.
5
+ * It provides AI personality evolution capabilities.
6
+ */
7
+ import type { ExtensionFactory } from "@mariozechner/pi-agent-core";
8
+ declare const nanosoulExtension: ExtensionFactory;
9
+ export default nanosoulExtension;
10
+ //# sourceMappingURL=extension.d.ts.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * NanoSoul Extension
3
+ *
4
+ * This extension integrates nanosoul as a loadable extension for NanoPencil.
5
+ * It provides AI personality evolution capabilities.
6
+ */
7
+ import { getSoulConfig } from "./config.js";
8
+ import { SoulManager } from "./manager.js";
9
+ const nanosoulExtension = (pi) => {
10
+ let soulManager = null;
11
+ // Initialize Soul
12
+ try {
13
+ soulManager = new SoulManager({
14
+ config: getSoulConfig(),
15
+ });
16
+ soulManager
17
+ .initialize()
18
+ .then(() => {
19
+ console.log("NanoSoul extension loaded successfully");
20
+ })
21
+ .catch((error) => {
22
+ console.warn(`Failed to initialize NanoSoul: ${error}`);
23
+ soulManager = null;
24
+ });
25
+ // Register slash command
26
+ pi.registerSlashCommand({
27
+ name: "soul",
28
+ description: "Show AI personality and stats (Soul)",
29
+ });
30
+ }
31
+ catch (error) {
32
+ console.warn(`Failed to create NanoSoul: ${error}`);
33
+ }
34
+ // Store soulManager for later use
35
+ pi.soulManager =
36
+ soulManager;
37
+ };
38
+ export default nanosoulExtension;
39
+ //# sourceMappingURL=extension.js.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * [INPUT]: None
3
+ * [OUTPUT]: Public API surface for Soul
4
+ * [POS]: Barrel export - hosts all public exports
5
+ */
6
+ export type { SoulProfile, SoulMemory, SoulEvolution, PersonalityVector, CognitiveStyle, ValueSystem, EmotionalState, ExpertiseArea, UserRelationship, SuccessMemory, FailureMemory, PatternMemory, DecisionMemory, PersonalityDelta, ValueDelta, EvolutionTrigger, ReflectionResult, InteractionContext, SoulConfig, SoulOptions, LlmFn, } from "./types.js";
7
+ export { getSoulConfig, getDefaultConfig, validateSoulConfig, } from "./config.js";
8
+ export { SoulStore } from "./store.js";
9
+ export { SoulEvolutionEngine, type PatternInsight, } from "./evolution.js";
10
+ export { generatePersonalityDirective, generateValueGuidance, generateCognitiveStyleHint, generateEmotionalContext, generateExpertiseContext, generateRelationshipContext, generateSoulInjection, } from "./injection.js";
11
+ export { SoulManager } from "./manager.js";
12
+ export { getSoulConfig as getSoulConfiguration } from "./config.js";
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,13 @@
1
+ /**
2
+ * [INPUT]: None
3
+ * [OUTPUT]: Public API surface for Soul
4
+ * [POS]: Barrel export - hosts all public exports
5
+ */
6
+ export { getSoulConfig, getDefaultConfig, validateSoulConfig, } from "./config.js";
7
+ export { SoulStore } from "./store.js";
8
+ export { SoulEvolutionEngine, } from "./evolution.js";
9
+ export { generatePersonalityDirective, generateValueGuidance, generateCognitiveStyleHint, generateEmotionalContext, generateExpertiseContext, generateRelationshipContext, generateSoulInjection, } from "./injection.js";
10
+ export { SoulManager } from "./manager.js";
11
+ // Re-export config for convenience
12
+ export { getSoulConfig as getSoulConfiguration } from "./config.js";
13
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,35 @@
1
+ /**
2
+ * [INPUT]: Soul profile, context
3
+ * [OUTPUT]: Prompt injections for system message
4
+ * [POS]: Expression layer - converts soul to prompt text
5
+ */
6
+ import type { SoulProfile, InteractionContext, ExpertiseArea } from "./types.js";
7
+ /**
8
+ * Generate personality-based prompt injection
9
+ */
10
+ export declare function generatePersonalityDirective(personality: SoulProfile["personality"]): string;
11
+ /**
12
+ * Generate value-based guidance
13
+ */
14
+ export declare function generateValueGuidance(values: SoulProfile["values"]): string;
15
+ /**
16
+ * Generate cognitive style hint
17
+ */
18
+ export declare function generateCognitiveStyleHint(style: SoulProfile["cognitiveStyle"]): string;
19
+ /**
20
+ * Generate emotional context
21
+ */
22
+ export declare function generateEmotionalContext(state: SoulProfile["emotionalState"]): string;
23
+ /**
24
+ * Generate expertise context
25
+ */
26
+ export declare function generateExpertiseContext(expertise: ExpertiseArea[], contextTags: string[]): string;
27
+ /**
28
+ * Generate relationship context
29
+ */
30
+ export declare function generateRelationshipContext(relationship: SoulProfile["userRelationship"]): string;
31
+ /**
32
+ * Generate complete Soul injection
33
+ */
34
+ export declare function generateSoulInjection(profile: SoulProfile, context: InteractionContext): string;
35
+ //# sourceMappingURL=injection.d.ts.map