@kernel.chat/kbot 3.28.1 → 3.30.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,72 @@
1
+ export type DecisionType = 'agent-routing' | 'model-selection' | 'tool-choice' | 'fallback-trigger' | 'cost-routing' | 'security-block' | 'learning-extraction' | 'pattern-match' | 'confidence-override';
2
+ export interface Decision {
3
+ /** When the decision was made */
4
+ timestamp: string;
5
+ /** What type of decision */
6
+ type: DecisionType;
7
+ /** What was decided */
8
+ decision: string;
9
+ /** Why — the reasoning chain */
10
+ reasoning: string[];
11
+ /** What alternatives were considered */
12
+ alternatives: string[];
13
+ /** Confidence in the decision (0-1) */
14
+ confidence: number;
15
+ /** What data informed this decision */
16
+ evidence: Record<string, unknown>;
17
+ /** What the user's message was (truncated) */
18
+ userContext: string;
19
+ /** Outcome — filled in after execution */
20
+ outcome?: 'success' | 'failure' | 'partial' | 'unknown';
21
+ }
22
+ /** Log a decision. Call this from agent routing, model selection, tool pipeline, etc. */
23
+ export declare function logDecision(decision: Omit<Decision, 'timestamp'>): void;
24
+ /** Quick helper for agent routing decisions */
25
+ export declare function logAgentRouting(opts: {
26
+ chosenAgent: string;
27
+ confidence: number;
28
+ method: string;
29
+ alternatives: string[];
30
+ userMessage: string;
31
+ }): void;
32
+ /** Quick helper for model selection decisions */
33
+ export declare function logModelSelection(opts: {
34
+ chosenModel: string;
35
+ chosenProvider: string;
36
+ reason: string;
37
+ cost: string;
38
+ alternatives: string[];
39
+ userMessage: string;
40
+ }): void;
41
+ /** Quick helper for fallback triggers */
42
+ export declare function logFallback(opts: {
43
+ from: string;
44
+ to: string;
45
+ reason: string;
46
+ error?: string;
47
+ }): void;
48
+ /** Quick helper for security blocks */
49
+ export declare function logSecurityBlock(opts: {
50
+ action: string;
51
+ reason: string;
52
+ severity: string;
53
+ userMessage: string;
54
+ }): void;
55
+ /** Get today's decisions */
56
+ export declare function getTodaysDecisions(): Decision[];
57
+ /** Get decisions for a specific date */
58
+ export declare function getDecisions(date: string): Decision[];
59
+ /** Get decisions by type */
60
+ export declare function getDecisionsByType(type: DecisionType, limit?: number): Decision[];
61
+ /** Get decision stats */
62
+ export declare function getDecisionStats(): {
63
+ total: number;
64
+ today: number;
65
+ byType: Record<string, number>;
66
+ avgConfidence: number;
67
+ securityBlocks: number;
68
+ fallbacks: number;
69
+ };
70
+ /** Format decisions for display */
71
+ export declare function formatDecisions(decisions: Decision[]): string;
72
+ //# sourceMappingURL=decision-journal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-journal.d.ts","sourceRoot":"","sources":["../src/decision-journal.ts"],"names":[],"mappings":"AA8BA,MAAM,MAAM,YAAY,GACpB,eAAe,GACf,iBAAiB,GACjB,aAAa,GACb,kBAAkB,GAClB,cAAc,GACd,gBAAgB,GAChB,qBAAqB,GACrB,eAAe,GACf,qBAAqB,CAAA;AAEzB,MAAM,WAAW,QAAQ;IACvB,iCAAiC;IACjC,SAAS,EAAE,MAAM,CAAA;IACjB,4BAA4B;IAC5B,IAAI,EAAE,YAAY,CAAA;IAClB,uBAAuB;IACvB,QAAQ,EAAE,MAAM,CAAA;IAChB,gCAAgC;IAChC,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,wCAAwC;IACxC,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,uCAAuC;IACvC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IACjC,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAA;IACnB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAA;CACxD;AAID,yFAAyF;AACzF,wBAAgB,WAAW,CAAC,QAAQ,EAAE,IAAI,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,IAAI,CAOvE;AAED,+CAA+C;AAC/C,wBAAgB,eAAe,CAAC,IAAI,EAAE;IACpC,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,IAAI,CAgBP;AAED,iDAAiD;AACjD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACtC,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,EAAE,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,IAAI,CAUP;AAED,yCAAyC;AACzC,wBAAgB,WAAW,CAAC,IAAI,EAAE;IAChC,IAAI,EAAE,MAAM,CAAA;IACZ,EAAE,EAAE,MAAM,CAAA;IACV,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,CAAA;CACf,GAAG,IAAI,CAUP;AAED,uCAAuC;AACvC,wBAAgB,gBAAgB,CAAC,IAAI,EAAE;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB,GAAG,IAAI,CAUP;AAID,4BAA4B;AAC5B,wBAAgB,kBAAkB,IAAI,QAAQ,EAAE,CAQ/C;AAED,wCAAwC;AACxC,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,EAAE,CAQrD;AAED,4BAA4B;AAC5B,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,SAAK,GAAG,QAAQ,EAAE,CAgB7E;AAED,yBAAyB;AACzB,wBAAgB,gBAAgB,IAAI;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC9B,aAAa,EAAE,MAAM,CAAA;IACrB,cAAc,EAAE,MAAM,CAAA;IACtB,SAAS,EAAE,MAAM,CAAA;CAClB,CAiCA;AAED,mCAAmC;AACnC,wBAAgB,eAAe,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,MAAM,CAsB7D"}
@@ -0,0 +1,200 @@
1
+ // kbot Decision Journal — Log WHY, Not Just What
2
+ //
3
+ // Most AI tools are black boxes. You see the output, not the reasoning.
4
+ // The decision journal captures the WHY behind every key decision:
5
+ // - Why this agent was routed (confidence, keywords, pattern match)
6
+ // - Why this model was selected (cost, capability, latency, availability)
7
+ // - Why this tool was chosen (intent match, past success rate)
8
+ // - Why a fallback was triggered (error, timeout, rate limit)
9
+ //
10
+ // Users see this via `kbot decisions` — transparency builds trust.
11
+ // Future kbot models learn from the reasoning chains, not just outcomes.
12
+ //
13
+ // Storage: ~/.kbot/memory/decisions/YYYY-MM-DD.jsonl (one JSON per line, append-only)
14
+ import { existsSync, appendFileSync, readFileSync, mkdirSync, readdirSync } from 'node:fs';
15
+ import { join } from 'node:path';
16
+ import { homedir } from 'node:os';
17
+ const DECISIONS_DIR = join(homedir(), '.kbot', 'memory', 'decisions');
18
+ function ensureDir() {
19
+ if (!existsSync(DECISIONS_DIR))
20
+ mkdirSync(DECISIONS_DIR, { recursive: true });
21
+ }
22
+ function todayFile() {
23
+ return join(DECISIONS_DIR, `${new Date().toISOString().split('T')[0]}.jsonl`);
24
+ }
25
+ // ── Logging ──
26
+ /** Log a decision. Call this from agent routing, model selection, tool pipeline, etc. */
27
+ export function logDecision(decision) {
28
+ ensureDir();
29
+ const entry = {
30
+ ...decision,
31
+ timestamp: new Date().toISOString(),
32
+ };
33
+ appendFileSync(todayFile(), JSON.stringify(entry) + '\n');
34
+ }
35
+ /** Quick helper for agent routing decisions */
36
+ export function logAgentRouting(opts) {
37
+ logDecision({
38
+ type: 'agent-routing',
39
+ decision: `Routed to ${opts.chosenAgent}`,
40
+ reasoning: [
41
+ `Method: ${opts.method}`,
42
+ `Confidence: ${(opts.confidence * 100).toFixed(0)}%`,
43
+ opts.alternatives.length > 0
44
+ ? `Considered: ${opts.alternatives.join(', ')}`
45
+ : 'No strong alternatives',
46
+ ],
47
+ alternatives: opts.alternatives,
48
+ confidence: opts.confidence,
49
+ evidence: { method: opts.method },
50
+ userContext: opts.userMessage.slice(0, 100),
51
+ });
52
+ }
53
+ /** Quick helper for model selection decisions */
54
+ export function logModelSelection(opts) {
55
+ logDecision({
56
+ type: 'model-selection',
57
+ decision: `Selected ${opts.chosenModel} via ${opts.chosenProvider}`,
58
+ reasoning: [opts.reason, `Cost tier: ${opts.cost}`],
59
+ alternatives: opts.alternatives,
60
+ confidence: 0.8,
61
+ evidence: { model: opts.chosenModel, provider: opts.chosenProvider, cost: opts.cost },
62
+ userContext: opts.userMessage.slice(0, 100),
63
+ });
64
+ }
65
+ /** Quick helper for fallback triggers */
66
+ export function logFallback(opts) {
67
+ logDecision({
68
+ type: 'fallback-trigger',
69
+ decision: `Fell back from ${opts.from} to ${opts.to}`,
70
+ reasoning: [opts.reason, opts.error ? `Error: ${opts.error}` : ''].filter(Boolean),
71
+ alternatives: [],
72
+ confidence: 1.0, // Fallbacks are deterministic
73
+ evidence: { from: opts.from, to: opts.to, error: opts.error },
74
+ userContext: '',
75
+ });
76
+ }
77
+ /** Quick helper for security blocks */
78
+ export function logSecurityBlock(opts) {
79
+ logDecision({
80
+ type: 'security-block',
81
+ decision: `Blocked: ${opts.action}`,
82
+ reasoning: [`Security: ${opts.reason}`, `Severity: ${opts.severity}`],
83
+ alternatives: [],
84
+ confidence: 1.0,
85
+ evidence: { severity: opts.severity },
86
+ userContext: opts.userMessage.slice(0, 100),
87
+ });
88
+ }
89
+ // ── Retrieval ──
90
+ /** Get today's decisions */
91
+ export function getTodaysDecisions() {
92
+ const path = todayFile();
93
+ if (!existsSync(path))
94
+ return [];
95
+ return readFileSync(path, 'utf-8')
96
+ .split('\n')
97
+ .filter(Boolean)
98
+ .map(line => { try {
99
+ return JSON.parse(line);
100
+ }
101
+ catch {
102
+ return null;
103
+ } })
104
+ .filter(Boolean);
105
+ }
106
+ /** Get decisions for a specific date */
107
+ export function getDecisions(date) {
108
+ const path = join(DECISIONS_DIR, `${date}.jsonl`);
109
+ if (!existsSync(path))
110
+ return [];
111
+ return readFileSync(path, 'utf-8')
112
+ .split('\n')
113
+ .filter(Boolean)
114
+ .map(line => { try {
115
+ return JSON.parse(line);
116
+ }
117
+ catch {
118
+ return null;
119
+ } })
120
+ .filter(Boolean);
121
+ }
122
+ /** Get decisions by type */
123
+ export function getDecisionsByType(type, limit = 50) {
124
+ ensureDir();
125
+ const allDecisions = [];
126
+ const files = readdirSync(DECISIONS_DIR).filter(f => f.endsWith('.jsonl')).sort().reverse();
127
+ for (const file of files) {
128
+ if (allDecisions.length >= limit)
129
+ break;
130
+ const decisions = readFileSync(join(DECISIONS_DIR, file), 'utf-8')
131
+ .split('\n')
132
+ .filter(Boolean)
133
+ .map(line => { try {
134
+ return JSON.parse(line);
135
+ }
136
+ catch {
137
+ return null;
138
+ } })
139
+ .filter((d) => d !== null && d.type === type);
140
+ allDecisions.push(...decisions);
141
+ }
142
+ return allDecisions.slice(0, limit);
143
+ }
144
+ /** Get decision stats */
145
+ export function getDecisionStats() {
146
+ ensureDir();
147
+ const todayDecisions = getTodaysDecisions();
148
+ const allFiles = readdirSync(DECISIONS_DIR).filter(f => f.endsWith('.jsonl'));
149
+ let total = 0;
150
+ const byType = {};
151
+ let confidenceSum = 0;
152
+ let securityBlocks = 0;
153
+ let fallbacks = 0;
154
+ for (const file of allFiles) {
155
+ const lines = readFileSync(join(DECISIONS_DIR, file), 'utf-8').split('\n').filter(Boolean);
156
+ for (const line of lines) {
157
+ try {
158
+ const d = JSON.parse(line);
159
+ total++;
160
+ byType[d.type] = (byType[d.type] || 0) + 1;
161
+ confidenceSum += d.confidence;
162
+ if (d.type === 'security-block')
163
+ securityBlocks++;
164
+ if (d.type === 'fallback-trigger')
165
+ fallbacks++;
166
+ }
167
+ catch { /* skip corrupt */ }
168
+ }
169
+ }
170
+ return {
171
+ total,
172
+ today: todayDecisions.length,
173
+ byType,
174
+ avgConfidence: total > 0 ? confidenceSum / total : 0,
175
+ securityBlocks,
176
+ fallbacks,
177
+ };
178
+ }
179
+ /** Format decisions for display */
180
+ export function formatDecisions(decisions) {
181
+ if (decisions.length === 0)
182
+ return 'No decisions recorded.';
183
+ const lines = ['## Decision Journal', ''];
184
+ for (const d of decisions.slice(0, 20)) {
185
+ const time = d.timestamp.split('T')[1]?.slice(0, 5) || '?';
186
+ const conf = `${Math.round(d.confidence * 100)}%`;
187
+ const icon = d.type === 'security-block' ? '🛡' :
188
+ d.type === 'fallback-trigger' ? '⚡' :
189
+ d.type === 'agent-routing' ? '🧭' :
190
+ d.type === 'model-selection' ? '🧠' :
191
+ d.type === 'cost-routing' ? '💰' : '📝';
192
+ lines.push(`${icon} **${time}** [${d.type}] ${d.decision} (${conf})`);
193
+ for (const r of d.reasoning) {
194
+ lines.push(` ${r}`);
195
+ }
196
+ lines.push('');
197
+ }
198
+ return lines.join('\n');
199
+ }
200
+ //# sourceMappingURL=decision-journal.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decision-journal.js","sourceRoot":"","sources":["../src/decision-journal.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ export interface Episode {
2
+ /** Unique ID: timestamp-based */
3
+ id: string;
4
+ /** When the session started */
5
+ startedAt: string;
6
+ /** When the session ended */
7
+ endedAt: string;
8
+ /** Duration in minutes */
9
+ durationMinutes: number;
10
+ /** One-line summary of what happened */
11
+ summary: string;
12
+ /** What the user wanted (extracted from first messages) */
13
+ userIntent: string[];
14
+ /** What kbot did (tool calls, agents used) */
15
+ actions: EpisodeAction[];
16
+ /** What was learned (new patterns, knowledge, corrections) */
17
+ learnings: string[];
18
+ /** What was surprising or new (first-time tools, unusual routing, errors) */
19
+ surprises: string[];
20
+ /** Emotional valence of the session */
21
+ valence: 'triumphant' | 'productive' | 'routine' | 'frustrating' | 'exploratory';
22
+ /** Agents used and their frequency */
23
+ agentsUsed: Record<string, number>;
24
+ /** Tools used and their frequency */
25
+ toolsUsed: Record<string, number>;
26
+ /** Total messages exchanged */
27
+ messageCount: number;
28
+ /** Tokens consumed */
29
+ tokensUsed: number;
30
+ /** Errors encountered */
31
+ errors: string[];
32
+ /** Project directory */
33
+ project: string;
34
+ /** Tags for retrieval */
35
+ tags: string[];
36
+ }
37
+ export interface EpisodeAction {
38
+ /** What tool or agent was invoked */
39
+ action: string;
40
+ /** Brief description of what it did */
41
+ description: string;
42
+ /** Whether it succeeded */
43
+ success: boolean;
44
+ /** Timestamp */
45
+ timestamp: string;
46
+ }
47
+ /** Start collecting episode data for a new session */
48
+ export declare function startEpisode(project: string): void;
49
+ /** Record a user message (extracts intent from early messages) */
50
+ export declare function recordUserMessage(message: string): void;
51
+ /** Record a tool execution */
52
+ export declare function recordToolUse(toolName: string, description: string, success: boolean): void;
53
+ /** Record agent routing */
54
+ export declare function recordAgentUse(agentId: string): void;
55
+ /** Record an error */
56
+ export declare function recordError(error: string): void;
57
+ /** Record something learned */
58
+ export declare function recordLearning(learning: string): void;
59
+ /** Record something surprising */
60
+ export declare function recordSurprise(surprise: string): void;
61
+ /** Record token usage */
62
+ export declare function recordTokens(tokens: number): void;
63
+ /** End the current session and save the episode */
64
+ export declare function endEpisode(): Episode | null;
65
+ /** List all episodes, newest first */
66
+ export declare function listEpisodes(limit?: number): Episode[];
67
+ /** Search episodes by tag */
68
+ export declare function searchEpisodes(tag: string): Episode[];
69
+ /** Get episode stats */
70
+ export declare function getEpisodeStats(): {
71
+ total: number;
72
+ totalMinutes: number;
73
+ totalMessages: number;
74
+ totalTokens: number;
75
+ valenceDistribution: Record<string, number>;
76
+ topTools: Array<[string, number]>;
77
+ topAgents: Array<[string, number]>;
78
+ };
79
+ /** Format episodes for display */
80
+ export declare function formatEpisodeList(episodes: Episode[]): string;
81
+ //# sourceMappingURL=episodic-memory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"episodic-memory.d.ts","sourceRoot":"","sources":["../src/episodic-memory.ts"],"names":[],"mappings":"AA+BA,MAAM,WAAW,OAAO;IACtB,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAA;IACV,+BAA+B;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,6BAA6B;IAC7B,OAAO,EAAE,MAAM,CAAA;IACf,0BAA0B;IAC1B,eAAe,EAAE,MAAM,CAAA;IACvB,wCAAwC;IACxC,OAAO,EAAE,MAAM,CAAA;IACf,2DAA2D;IAC3D,UAAU,EAAE,MAAM,EAAE,CAAA;IACpB,8CAA8C;IAC9C,OAAO,EAAE,aAAa,EAAE,CAAA;IACxB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,6EAA6E;IAC7E,SAAS,EAAE,MAAM,EAAE,CAAA;IACnB,uCAAuC;IACvC,OAAO,EAAE,YAAY,GAAG,YAAY,GAAG,SAAS,GAAG,aAAa,GAAG,aAAa,CAAA;IAChF,sCAAsC;IACtC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,qCAAqC;IACrC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,+BAA+B;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,sBAAsB;IACtB,UAAU,EAAE,MAAM,CAAA;IAClB,yBAAyB;IACzB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,wBAAwB;IACxB,OAAO,EAAE,MAAM,CAAA;IACf,yBAAyB;IACzB,IAAI,EAAE,MAAM,EAAE,CAAA;CACf;AAED,MAAM,WAAW,aAAa;IAC5B,qCAAqC;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,uCAAuC;IACvC,WAAW,EAAE,MAAM,CAAA;IACnB,2BAA2B;IAC3B,OAAO,EAAE,OAAO,CAAA;IAChB,gBAAgB;IAChB,SAAS,EAAE,MAAM,CAAA;CAClB;AAeD,sDAAsD;AACtD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAelD;AAED,kEAAkE;AAClE,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAMvD;AAED,8BAA8B;AAC9B,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAQ3F;AAED,2BAA2B;AAC3B,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAEpD;AAED,sBAAsB;AACtB,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAE/C;AAED,+BAA+B;AAC/B,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAErD;AAED,kCAAkC;AAClC,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAErD;AAED,yBAAyB;AACzB,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAEjD;AA6DD,mDAAmD;AACnD,wBAAgB,UAAU,IAAI,OAAO,GAAG,IAAI,CAkC3C;AAID,sCAAsC;AACtC,wBAAgB,YAAY,CAAC,KAAK,SAAK,GAAG,OAAO,EAAE,CAYlD;AAED,6BAA6B;AAC7B,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,EAAE,CAErD;AAED,wBAAwB;AACxB,wBAAgB,eAAe,IAAI;IACjC,KAAK,EAAE,MAAM,CAAA;IACb,YAAY,EAAE,MAAM,CAAA;IACpB,aAAa,EAAE,MAAM,CAAA;IACrB,WAAW,EAAE,MAAM,CAAA;IACnB,mBAAmB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAC3C,QAAQ,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;IACjC,SAAS,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CACnC,CAiCA;AAED,kCAAkC;AAClC,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,MAAM,CAoB7D"}
@@ -0,0 +1,260 @@
1
+ // kbot Episodic Memory — Sessions as Stories
2
+ //
3
+ // Pattern cache answers: "what tool sequence works for this problem?"
4
+ // Solution cache answers: "what's the answer to this question?"
5
+ // Episodic memory answers: "what HAPPENED?"
6
+ //
7
+ // After each session, kbot generates a narrative episode:
8
+ // - What the user wanted
9
+ // - What kbot did
10
+ // - What was surprising or new
11
+ // - What kbot learned
12
+ // - Emotional valence (was it frustrating? triumphant? routine?)
13
+ //
14
+ // Present kbot uses episodes for better session context.
15
+ // Future kbot (70B+) will reason about the narrative arc across episodes
16
+ // and understand growth, patterns of failure, and turning points.
17
+ //
18
+ // Storage: ~/.kbot/memory/episodes/YYYY-MM-DD_HH-MM.json
19
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, readdirSync } from 'node:fs';
20
+ import { join } from 'node:path';
21
+ import { homedir } from 'node:os';
22
+ const EPISODES_DIR = join(homedir(), '.kbot', 'memory', 'episodes');
23
+ function ensureDir() {
24
+ if (!existsSync(EPISODES_DIR))
25
+ mkdirSync(EPISODES_DIR, { recursive: true });
26
+ }
27
+ // ── Episode Collection (During Session) ──
28
+ let currentEpisode = null;
29
+ let sessionActions = [];
30
+ let sessionErrors = [];
31
+ let sessionIntents = [];
32
+ let sessionLearnings = [];
33
+ let sessionSurprises = [];
34
+ let sessionAgents = {};
35
+ let sessionTools = {};
36
+ let sessionMessages = 0;
37
+ let sessionTokens = 0;
38
+ /** Start collecting episode data for a new session */
39
+ export function startEpisode(project) {
40
+ currentEpisode = {
41
+ id: new Date().toISOString().replace(/[:.]/g, '-'),
42
+ startedAt: new Date().toISOString(),
43
+ project,
44
+ };
45
+ sessionActions = [];
46
+ sessionErrors = [];
47
+ sessionIntents = [];
48
+ sessionLearnings = [];
49
+ sessionSurprises = [];
50
+ sessionAgents = {};
51
+ sessionTools = {};
52
+ sessionMessages = 0;
53
+ sessionTokens = 0;
54
+ }
55
+ /** Record a user message (extracts intent from early messages) */
56
+ export function recordUserMessage(message) {
57
+ sessionMessages++;
58
+ // Extract intent from first 3 messages
59
+ if (sessionIntents.length < 3 && message.length > 10) {
60
+ sessionIntents.push(message.slice(0, 200));
61
+ }
62
+ }
63
+ /** Record a tool execution */
64
+ export function recordToolUse(toolName, description, success) {
65
+ sessionTools[toolName] = (sessionTools[toolName] || 0) + 1;
66
+ sessionActions.push({
67
+ action: toolName,
68
+ description: description.slice(0, 100),
69
+ success,
70
+ timestamp: new Date().toISOString(),
71
+ });
72
+ }
73
+ /** Record agent routing */
74
+ export function recordAgentUse(agentId) {
75
+ sessionAgents[agentId] = (sessionAgents[agentId] || 0) + 1;
76
+ }
77
+ /** Record an error */
78
+ export function recordError(error) {
79
+ sessionErrors.push(error.slice(0, 200));
80
+ }
81
+ /** Record something learned */
82
+ export function recordLearning(learning) {
83
+ sessionLearnings.push(learning.slice(0, 200));
84
+ }
85
+ /** Record something surprising */
86
+ export function recordSurprise(surprise) {
87
+ sessionSurprises.push(surprise.slice(0, 200));
88
+ }
89
+ /** Record token usage */
90
+ export function recordTokens(tokens) {
91
+ sessionTokens += tokens;
92
+ }
93
+ // ── Episode Finalization ──
94
+ /** Determine the emotional valence of the session */
95
+ function determineValence() {
96
+ const errorRate = sessionActions.length > 0 ? sessionErrors.length / sessionActions.length : 0;
97
+ const successRate = sessionActions.length > 0
98
+ ? sessionActions.filter(a => a.success).length / sessionActions.length
99
+ : 1;
100
+ if (sessionSurprises.length > 2 || sessionLearnings.length > 3)
101
+ return 'exploratory';
102
+ if (errorRate > 0.3)
103
+ return 'frustrating';
104
+ if (successRate > 0.9 && sessionActions.length > 10)
105
+ return 'triumphant';
106
+ if (successRate > 0.7)
107
+ return 'productive';
108
+ return 'routine';
109
+ }
110
+ /** Generate a one-line summary from session data */
111
+ function generateSummary() {
112
+ const topTools = Object.entries(sessionTools).sort((a, b) => b[1] - a[1]).slice(0, 3).map(([t]) => t);
113
+ const topAgents = Object.entries(sessionAgents).sort((a, b) => b[1] - a[1]).slice(0, 2).map(([a]) => a);
114
+ const actionCount = sessionActions.length;
115
+ const intent = sessionIntents[0]?.slice(0, 60) || 'general session';
116
+ const parts = [];
117
+ parts.push(`${actionCount} actions`);
118
+ if (topAgents.length)
119
+ parts.push(`via ${topAgents.join(', ')}`);
120
+ if (topTools.length)
121
+ parts.push(`using ${topTools.join(', ')}`);
122
+ parts.push(`— "${intent}"`);
123
+ return parts.join(' ');
124
+ }
125
+ /** Generate tags for retrieval */
126
+ function generateTags() {
127
+ const tags = [];
128
+ // Tool-based tags
129
+ if (sessionTools['file_write'] || sessionTools['file_edit'])
130
+ tags.push('coding');
131
+ if (sessionTools['bash'])
132
+ tags.push('shell');
133
+ if (sessionTools['git_commit'] || sessionTools['git_push'])
134
+ tags.push('git');
135
+ if (sessionTools['web_search'])
136
+ tags.push('research');
137
+ if (sessionTools['market_data'] || sessionTools['technical_analysis'])
138
+ tags.push('finance');
139
+ if (sessionTools['dep_audit'] || sessionTools['secret_scan'] || sessionTools['owasp_check'])
140
+ tags.push('security');
141
+ if (sessionTools['paper_trade'] || sessionTools['swap_execute'])
142
+ tags.push('trading');
143
+ // Agent-based tags
144
+ for (const agent of Object.keys(sessionAgents)) {
145
+ tags.push(agent);
146
+ }
147
+ // Valence tag
148
+ tags.push(determineValence());
149
+ // Error tag
150
+ if (sessionErrors.length > 0)
151
+ tags.push('had-errors');
152
+ return [...new Set(tags)];
153
+ }
154
+ /** End the current session and save the episode */
155
+ export function endEpisode() {
156
+ if (!currentEpisode?.startedAt)
157
+ return null;
158
+ const now = new Date();
159
+ const started = new Date(currentEpisode.startedAt);
160
+ const durationMinutes = Math.round((now.getTime() - started.getTime()) / 60_000);
161
+ const episode = {
162
+ id: currentEpisode.id || now.toISOString(),
163
+ startedAt: currentEpisode.startedAt,
164
+ endedAt: now.toISOString(),
165
+ durationMinutes,
166
+ summary: generateSummary(),
167
+ userIntent: sessionIntents,
168
+ actions: sessionActions.slice(-50), // Keep last 50 actions
169
+ learnings: sessionLearnings,
170
+ surprises: sessionSurprises,
171
+ valence: determineValence(),
172
+ agentsUsed: sessionAgents,
173
+ toolsUsed: sessionTools,
174
+ messageCount: sessionMessages,
175
+ tokensUsed: sessionTokens,
176
+ errors: sessionErrors.slice(-10),
177
+ project: currentEpisode.project || process.cwd(),
178
+ tags: generateTags(),
179
+ };
180
+ // Save
181
+ ensureDir();
182
+ const filename = `${started.toISOString().split('T')[0]}_${started.toISOString().split('T')[1].slice(0, 5).replace(':', '-')}.json`;
183
+ writeFileSync(join(EPISODES_DIR, filename), JSON.stringify(episode, null, 2));
184
+ currentEpisode = null;
185
+ return episode;
186
+ }
187
+ // ── Episode Retrieval ──
188
+ /** List all episodes, newest first */
189
+ export function listEpisodes(limit = 20) {
190
+ ensureDir();
191
+ const files = readdirSync(EPISODES_DIR)
192
+ .filter(f => f.endsWith('.json'))
193
+ .sort()
194
+ .reverse()
195
+ .slice(0, limit);
196
+ return files.map(f => {
197
+ try {
198
+ return JSON.parse(readFileSync(join(EPISODES_DIR, f), 'utf-8'));
199
+ }
200
+ catch {
201
+ return null;
202
+ }
203
+ }).filter(Boolean);
204
+ }
205
+ /** Search episodes by tag */
206
+ export function searchEpisodes(tag) {
207
+ return listEpisodes(100).filter(e => e.tags.includes(tag.toLowerCase()));
208
+ }
209
+ /** Get episode stats */
210
+ export function getEpisodeStats() {
211
+ const episodes = listEpisodes(1000);
212
+ const toolTotals = {};
213
+ const agentTotals = {};
214
+ const valence = {};
215
+ let totalMinutes = 0;
216
+ let totalMessages = 0;
217
+ let totalTokens = 0;
218
+ for (const ep of episodes) {
219
+ totalMinutes += ep.durationMinutes;
220
+ totalMessages += ep.messageCount;
221
+ totalTokens += ep.tokensUsed;
222
+ valence[ep.valence] = (valence[ep.valence] || 0) + 1;
223
+ for (const [tool, count] of Object.entries(ep.toolsUsed)) {
224
+ toolTotals[tool] = (toolTotals[tool] || 0) + count;
225
+ }
226
+ for (const [agent, count] of Object.entries(ep.agentsUsed)) {
227
+ agentTotals[agent] = (agentTotals[agent] || 0) + count;
228
+ }
229
+ }
230
+ return {
231
+ total: episodes.length,
232
+ totalMinutes,
233
+ totalMessages,
234
+ totalTokens,
235
+ valenceDistribution: valence,
236
+ topTools: Object.entries(toolTotals).sort((a, b) => b[1] - a[1]).slice(0, 10),
237
+ topAgents: Object.entries(agentTotals).sort((a, b) => b[1] - a[1]).slice(0, 10),
238
+ };
239
+ }
240
+ /** Format episodes for display */
241
+ export function formatEpisodeList(episodes) {
242
+ if (episodes.length === 0)
243
+ return 'No episodes recorded yet.';
244
+ const lines = ['## Session History', ''];
245
+ for (const ep of episodes) {
246
+ const date = ep.startedAt.split('T')[0];
247
+ const duration = ep.durationMinutes < 60
248
+ ? `${ep.durationMinutes}m`
249
+ : `${Math.floor(ep.durationMinutes / 60)}h ${ep.durationMinutes % 60}m`;
250
+ const valenceIcon = {
251
+ triumphant: '🏆', productive: '⚡', routine: '📎', frustrating: '🔥', exploratory: '🔭',
252
+ }[ep.valence] || '•';
253
+ lines.push(`${valenceIcon} **${date}** (${duration}) — ${ep.summary}`);
254
+ if (ep.learnings.length > 0) {
255
+ lines.push(` Learned: ${ep.learnings[0]}`);
256
+ }
257
+ }
258
+ return lines.join('\n');
259
+ }
260
+ //# sourceMappingURL=episodic-memory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"episodic-memory.js","sourceRoot":"","sources":["../src/episodic-memory.ts"],"names":[],"mappings":"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"}