@sesamespace/hivemind 0.8.13 → 0.10.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.
Files changed (54) hide show
  1. package/README.md +2 -1
  2. package/dist/{chunk-MLY4VFOO.js → chunk-BHCDOHSK.js} +3 -3
  3. package/dist/{chunk-PFZO67E2.js → chunk-DPLCEMEC.js} +2 -2
  4. package/dist/{chunk-HTLHMXAL.js → chunk-FBQBBAPZ.js} +2 -2
  5. package/dist/{chunk-NSTTILSN.js → chunk-FK6WYXRM.js} +79 -2
  6. package/dist/chunk-FK6WYXRM.js.map +1 -0
  7. package/dist/{chunk-LJHJGDKY.js → chunk-ICSJNKI6.js} +62 -2
  8. package/dist/chunk-ICSJNKI6.js.map +1 -0
  9. package/dist/{chunk-4Y7A25UG.js → chunk-IXBIAX76.js} +2 -2
  10. package/dist/{chunk-ZM7RK5YV.js → chunk-M3A2WRXM.js} +560 -37
  11. package/dist/chunk-M3A2WRXM.js.map +1 -0
  12. package/dist/commands/fleet.js +3 -3
  13. package/dist/commands/init.js +3 -3
  14. package/dist/commands/start.js +3 -3
  15. package/dist/commands/upgrade.js +1 -1
  16. package/dist/commands/watchdog.js +3 -3
  17. package/dist/dashboard.html +873 -131
  18. package/dist/index.js +2 -2
  19. package/dist/main.js +375 -7
  20. package/dist/main.js.map +1 -1
  21. package/dist/start.js +1 -1
  22. package/install.sh +162 -0
  23. package/package.json +24 -23
  24. package/packages/memory/Cargo.lock +6480 -0
  25. package/packages/memory/Cargo.toml +21 -0
  26. package/packages/memory/src/src/context.rs +179 -0
  27. package/packages/memory/src/src/embeddings.rs +51 -0
  28. package/packages/memory/src/src/main.rs +887 -0
  29. package/packages/memory/src/src/promotion.rs +808 -0
  30. package/packages/memory/src/src/scoring.rs +142 -0
  31. package/packages/memory/src/src/store.rs +460 -0
  32. package/packages/memory/src/src/tasks.rs +321 -0
  33. package/.pnpmrc.json +0 -1
  34. package/AUTO-DEBUG-DESIGN.md +0 -267
  35. package/DASHBOARD-PLAN.md +0 -206
  36. package/MEMORY-ENHANCEMENT-PLAN.md +0 -211
  37. package/TOOL-USE-DESIGN.md +0 -173
  38. package/dist/chunk-LJHJGDKY.js.map +0 -1
  39. package/dist/chunk-NSTTILSN.js.map +0 -1
  40. package/dist/chunk-ZM7RK5YV.js.map +0 -1
  41. package/docs/TOOL-PARITY-PLAN.md +0 -191
  42. package/src/memory/dashboard-integration.ts +0 -295
  43. package/src/memory/index.ts +0 -187
  44. package/src/memory/performance-test.ts +0 -208
  45. package/src/memory/processors/agent-sync.ts +0 -312
  46. package/src/memory/processors/command-learner.ts +0 -298
  47. package/src/memory/processors/memory-api-client.ts +0 -105
  48. package/src/memory/processors/message-flow-integration.ts +0 -168
  49. package/src/memory/processors/research-digester.ts +0 -204
  50. package/test-caitlin-access.md +0 -11
  51. /package/dist/{chunk-MLY4VFOO.js.map → chunk-BHCDOHSK.js.map} +0 -0
  52. /package/dist/{chunk-PFZO67E2.js.map → chunk-DPLCEMEC.js.map} +0 -0
  53. /package/dist/{chunk-HTLHMXAL.js.map → chunk-FBQBBAPZ.js.map} +0 -0
  54. /package/dist/{chunk-4Y7A25UG.js.map → chunk-IXBIAX76.js.map} +0 -0
@@ -1,298 +0,0 @@
1
- /**
2
- * Command Learner - Tracks successful command patterns and builds a knowledge base
3
- */
4
-
5
- import { BackgroundProcessor } from './background-processor';
6
- import { EventEmitter } from 'events';
7
-
8
- export interface CommandPattern {
9
- pattern: string;
10
- description: string;
11
- examples: CommandExample[];
12
- successRate: number;
13
- category: string;
14
- relatedCommands: string[];
15
- lastUsed: Date;
16
- usageCount: number;
17
- }
18
-
19
- export interface CommandExample {
20
- command: string;
21
- context: string;
22
- output?: string;
23
- success: boolean;
24
- timestamp: Date;
25
- }
26
-
27
- export class CommandLearner extends BackgroundProcessor {
28
- private patterns: Map<string, CommandPattern> = new Map();
29
- private recentCommands: CommandExample[] = [];
30
- private categoryIndex: Map<string, Set<string>> = new Map();
31
-
32
- constructor() {
33
- super('command-learner', 60000); // Process every minute
34
- }
35
-
36
- async process(): Promise<void> {
37
- // Analyze recent commands to extract patterns
38
- if (this.recentCommands.length >= 5) {
39
- await this.extractPatterns();
40
- }
41
-
42
- // Update success rates
43
- this.updateSuccessRates();
44
-
45
- // Emit current state
46
- this.emit('patterns-updated', {
47
- totalPatterns: this.patterns.size,
48
- categories: Array.from(this.categoryIndex.keys()),
49
- recentCommands: this.recentCommands.length
50
- });
51
- }
52
-
53
- /**
54
- * Track a command execution
55
- */
56
- async trackCommand(command: string, context: string, output?: string, success: boolean = true): Promise<void> {
57
- const example: CommandExample = {
58
- command,
59
- context,
60
- output: output?.substring(0, 1000), // Limit output size
61
- success,
62
- timestamp: new Date()
63
- };
64
-
65
- this.recentCommands.push(example);
66
-
67
- // Keep only last 100 commands
68
- if (this.recentCommands.length > 100) {
69
- this.recentCommands.shift();
70
- }
71
-
72
- // Check if this matches an existing pattern
73
- await this.matchToPattern(example);
74
- }
75
-
76
- private async extractPatterns(): Promise<void> {
77
- // Group commands by similarity
78
- const groups = this.groupSimilarCommands(this.recentCommands.slice(-20));
79
-
80
- for (const group of groups) {
81
- if (group.length >= 2) {
82
- const pattern = this.derivePattern(group);
83
- if (pattern) {
84
- this.patterns.set(pattern.pattern, pattern);
85
-
86
- // Index by category
87
- if (!this.categoryIndex.has(pattern.category)) {
88
- this.categoryIndex.set(pattern.category, new Set());
89
- }
90
- this.categoryIndex.get(pattern.category)!.add(pattern.pattern);
91
- }
92
- }
93
- }
94
- }
95
-
96
- private groupSimilarCommands(commands: CommandExample[]): CommandExample[][] {
97
- const groups: CommandExample[][] = [];
98
- const used = new Set<number>();
99
-
100
- for (let i = 0; i < commands.length; i++) {
101
- if (used.has(i)) continue;
102
-
103
- const group = [commands[i]];
104
- used.add(i);
105
-
106
- for (let j = i + 1; j < commands.length; j++) {
107
- if (used.has(j)) continue;
108
-
109
- if (this.areSimilar(commands[i].command, commands[j].command)) {
110
- group.push(commands[j]);
111
- used.add(j);
112
- }
113
- }
114
-
115
- if (group.length > 1) {
116
- groups.push(group);
117
- }
118
- }
119
-
120
- return groups;
121
- }
122
-
123
- private areSimilar(cmd1: string, cmd2: string): boolean {
124
- // Tokenize commands
125
- const tokens1 = cmd1.split(/\s+/);
126
- const tokens2 = cmd2.split(/\s+/);
127
-
128
- // Check if base command is the same
129
- if (tokens1[0] !== tokens2[0]) return false;
130
-
131
- // Check structural similarity
132
- if (Math.abs(tokens1.length - tokens2.length) > 2) return false;
133
-
134
- // Count matching tokens (excluding file paths and specific values)
135
- let matches = 0;
136
- for (let i = 0; i < Math.min(tokens1.length, tokens2.length); i++) {
137
- if (tokens1[i] === tokens2[i] ||
138
- (this.isVariable(tokens1[i]) && this.isVariable(tokens2[i]))) {
139
- matches++;
140
- }
141
- }
142
-
143
- return matches / Math.max(tokens1.length, tokens2.length) > 0.6;
144
- }
145
-
146
- private isVariable(token: string): boolean {
147
- // Detect tokens that are likely variables (paths, URLs, IDs, etc.)
148
- return token.includes('/') ||
149
- token.includes('.') ||
150
- token.match(/^[a-f0-9]{8,}$/i) !== null ||
151
- token.match(/^\d+$/) !== null;
152
- }
153
-
154
- private derivePattern(examples: CommandExample[]): CommandPattern | null {
155
- if (examples.length === 0) return null;
156
-
157
- const baseCmd = examples[0].command.split(/\s+/)[0];
158
- const category = this.categorizeCommand(baseCmd);
159
-
160
- // Find common structure
161
- const tokenizedExamples = examples.map(e => e.command.split(/\s+/));
162
- const patternTokens: string[] = [];
163
-
164
- for (let i = 0; i < tokenizedExamples[0].length; i++) {
165
- const tokensAtPosition = tokenizedExamples.map(t => t[i]).filter(Boolean);
166
-
167
- if (tokensAtPosition.every(t => t === tokensAtPosition[0])) {
168
- patternTokens.push(tokensAtPosition[0]);
169
- } else if (tokensAtPosition.every(t => this.isVariable(t))) {
170
- patternTokens.push('<variable>');
171
- } else {
172
- patternTokens.push('<option>');
173
- }
174
- }
175
-
176
- const pattern = patternTokens.join(' ');
177
- const successCount = examples.filter(e => e.success).length;
178
-
179
- return {
180
- pattern,
181
- description: this.generateDescription(pattern, examples),
182
- examples: examples.slice(0, 5), // Keep top 5 examples
183
- successRate: successCount / examples.length,
184
- category,
185
- relatedCommands: this.findRelatedCommands(baseCmd),
186
- lastUsed: new Date(Math.max(...examples.map(e => e.timestamp.getTime()))),
187
- usageCount: examples.length
188
- };
189
- }
190
-
191
- private categorizeCommand(baseCmd: string): string {
192
- const categories: Record<string, string[]> = {
193
- 'git': ['git', 'gh'],
194
- 'file': ['ls', 'cat', 'cp', 'mv', 'rm', 'find', 'grep'],
195
- 'process': ['ps', 'kill', 'top', 'htop'],
196
- 'network': ['curl', 'wget', 'ping', 'netstat'],
197
- 'package': ['npm', 'yarn', 'pip', 'brew'],
198
- 'docker': ['docker', 'docker-compose'],
199
- 'system': ['df', 'du', 'free', 'uname']
200
- };
201
-
202
- for (const [category, commands] of Object.entries(categories)) {
203
- if (commands.includes(baseCmd)) {
204
- return category;
205
- }
206
- }
207
-
208
- return 'other';
209
- }
210
-
211
- private generateDescription(pattern: string, examples: CommandExample[]): string {
212
- const baseCmd = pattern.split(' ')[0];
213
- const contexts = [...new Set(examples.map(e => e.context))];
214
-
215
- return `${baseCmd} command used for ${contexts.join(', ')}`;
216
- }
217
-
218
- private findRelatedCommands(baseCmd: string): string[] {
219
- const related: Record<string, string[]> = {
220
- 'git': ['git status', 'git log', 'git diff'],
221
- 'npm': ['npm install', 'npm run', 'npm test'],
222
- 'docker': ['docker ps', 'docker logs', 'docker exec'],
223
- 'curl': ['wget', 'httpie', 'fetch']
224
- };
225
-
226
- return related[baseCmd] || [];
227
- }
228
-
229
- private async matchToPattern(example: CommandExample): Promise<void> {
230
- for (const [patternStr, pattern] of this.patterns) {
231
- if (this.matchesPattern(example.command, patternStr)) {
232
- pattern.examples.push(example);
233
- pattern.lastUsed = example.timestamp;
234
- pattern.usageCount++;
235
-
236
- // Keep only recent examples
237
- if (pattern.examples.length > 10) {
238
- pattern.examples = pattern.examples.slice(-10);
239
- }
240
-
241
- break;
242
- }
243
- }
244
- }
245
-
246
- private matchesPattern(command: string, pattern: string): boolean {
247
- const cmdTokens = command.split(/\s+/);
248
- const patternTokens = pattern.split(/\s+/);
249
-
250
- if (cmdTokens.length !== patternTokens.length) return false;
251
-
252
- for (let i = 0; i < cmdTokens.length; i++) {
253
- if (patternTokens[i] === '<variable>' || patternTokens[i] === '<option>') {
254
- continue;
255
- }
256
- if (cmdTokens[i] !== patternTokens[i]) {
257
- return false;
258
- }
259
- }
260
-
261
- return true;
262
- }
263
-
264
- private updateSuccessRates(): void {
265
- for (const pattern of this.patterns.values()) {
266
- const recentExamples = pattern.examples.slice(-10);
267
- const successCount = recentExamples.filter(e => e.success).length;
268
- pattern.successRate = successCount / recentExamples.length;
269
- }
270
- }
271
-
272
- /**
273
- * Get command suggestions for a given context
274
- */
275
- async getSuggestions(context: string, category?: string): Promise<CommandPattern[]> {
276
- let patterns = Array.from(this.patterns.values());
277
-
278
- // Filter by category if specified
279
- if (category && this.categoryIndex.has(category)) {
280
- const categoryPatterns = this.categoryIndex.get(category)!;
281
- patterns = patterns.filter(p => categoryPatterns.has(p.pattern));
282
- }
283
-
284
- // Filter by context relevance
285
- patterns = patterns.filter(p =>
286
- p.examples.some(e => e.context.toLowerCase().includes(context.toLowerCase()))
287
- );
288
-
289
- // Sort by success rate and recency
290
- return patterns
291
- .sort((a, b) => {
292
- const scoreA = a.successRate * 0.7 + (Date.now() - a.lastUsed.getTime() < 3600000 ? 0.3 : 0);
293
- const scoreB = b.successRate * 0.7 + (Date.now() - b.lastUsed.getTime() < 3600000 ? 0.3 : 0);
294
- return scoreB - scoreA;
295
- })
296
- .slice(0, 5);
297
- }
298
- }
@@ -1,105 +0,0 @@
1
- /**
2
- * Client for interacting with the Hivemind memory daemon API
3
- */
4
-
5
- import axios from 'axios';
6
- import { EventEmitter } from 'events';
7
-
8
- export interface MemorySearchResult {
9
- content: string;
10
- similarity: number;
11
- metadata?: Record<string, any>;
12
- }
13
-
14
- export interface L3Knowledge {
15
- insight: string;
16
- confidence: number;
17
- sources: string[];
18
- }
19
-
20
- export interface MemoryStats {
21
- episodes: number;
22
- contexts: string[];
23
- l3Entries: number;
24
- }
25
-
26
- export class MemoryAPIClient extends EventEmitter {
27
- private baseURL: string;
28
- private context: string;
29
-
30
- constructor(baseURL: string = 'http://localhost:3434', context: string = 'global') {
31
- super();
32
- this.baseURL = baseURL;
33
- this.context = context;
34
- }
35
-
36
- async health(): Promise<boolean> {
37
- try {
38
- const response = await axios.get(`${this.baseURL}/health`);
39
- return response.status === 200;
40
- } catch (error) {
41
- this.emit('error', error);
42
- return false;
43
- }
44
- }
45
-
46
- async search(query: string, limit: number = 10): Promise<MemorySearchResult[]> {
47
- try {
48
- const response = await axios.get(`${this.baseURL}/search`, {
49
- params: { q: query, context: this.context, limit }
50
- });
51
- return response.data.results || [];
52
- } catch (error) {
53
- this.emit('error', error);
54
- return [];
55
- }
56
- }
57
-
58
- async crossSearch(query: string, limit: number = 10): Promise<MemorySearchResult[]> {
59
- try {
60
- const response = await axios.get(`${this.baseURL}/cross-search`, {
61
- params: { q: query, limit }
62
- });
63
- return response.data.results || [];
64
- } catch (error) {
65
- this.emit('error', error);
66
- return [];
67
- }
68
- }
69
-
70
- async getL3Knowledge(): Promise<L3Knowledge[]> {
71
- try {
72
- const response = await axios.get(`${this.baseURL}/promotion/l3`, {
73
- params: { context: this.context }
74
- });
75
- return response.data.knowledge || [];
76
- } catch (error) {
77
- this.emit('error', error);
78
- return [];
79
- }
80
- }
81
-
82
- async getStats(): Promise<MemoryStats | null> {
83
- try {
84
- const response = await axios.get(`${this.baseURL}/stats`);
85
- return response.data;
86
- } catch (error) {
87
- this.emit('error', error);
88
- return null;
89
- }
90
- }
91
-
92
- async store(content: string, metadata?: Record<string, any>): Promise<boolean> {
93
- try {
94
- const response = await axios.post(`${this.baseURL}/store`, {
95
- context: this.context,
96
- content,
97
- metadata
98
- });
99
- return response.status === 200;
100
- } catch (error) {
101
- this.emit('error', error);
102
- return false;
103
- }
104
- }
105
- }
@@ -1,168 +0,0 @@
1
- /**
2
- * Integrates memory processors with the agent's message flow
3
- */
4
-
5
- import { EventEmitter } from 'events';
6
- import { MemoryAPIClient } from './memory-api-client';
7
- import { ProcessManager } from './background-processor';
8
- import { CodeIndexer } from './code-indexer';
9
- import { TaskTracker } from './task-tracker';
10
- import { ContextManager } from './context-manager';
11
-
12
- export interface AgentMessage {
13
- role: 'user' | 'assistant' | 'system';
14
- content: string;
15
- timestamp: Date;
16
- context?: string;
17
- metadata?: Record<string, any>;
18
- }
19
-
20
- export interface MessageFlowConfig {
21
- memoryURL?: string;
22
- context?: string;
23
- workspaceRoot: string;
24
- maxContextTokens?: number;
25
- }
26
-
27
- export class MessageFlowIntegration extends EventEmitter {
28
- private memoryClient: MemoryAPIClient;
29
- private processManager: ProcessManager;
30
- private contextManager: ContextManager;
31
- private taskTracker: TaskTracker;
32
- private codeIndexer: CodeIndexer;
33
-
34
- constructor(config: MessageFlowConfig) {
35
- super();
36
-
37
- // Initialize memory client
38
- this.memoryClient = new MemoryAPIClient(
39
- config.memoryURL || 'http://localhost:3434',
40
- config.context || 'global'
41
- );
42
-
43
- // Initialize processors
44
- this.processManager = new ProcessManager();
45
- this.codeIndexer = new CodeIndexer(config.workspaceRoot);
46
- this.taskTracker = new TaskTracker();
47
-
48
- // Initialize context manager
49
- this.contextManager = new ContextManager(
50
- this.memoryClient,
51
- this.processManager,
52
- config.maxContextTokens || 8000
53
- );
54
-
55
- // Register processors
56
- this.processManager.register('code-indexer', this.codeIndexer);
57
- this.processManager.register('task-tracker', this.taskTracker);
58
-
59
- // Set up event listeners
60
- this.setupEventListeners();
61
- }
62
-
63
- private setupEventListeners(): void {
64
- // Forward errors
65
- this.memoryClient.on('error', (error) => {
66
- this.emit('error', { source: 'memory-client', error });
67
- });
68
-
69
- this.processManager.on('processor-error', (data) => {
70
- this.emit('error', { source: 'processor', ...data });
71
- });
72
-
73
- // Track file access from messages
74
- this.on('message', (message: AgentMessage) => {
75
- if (message.role === 'assistant') {
76
- this.extractFileReferences(message.content);
77
- }
78
- });
79
- }
80
-
81
- private extractFileReferences(content: string): void {
82
- // Extract file paths from message content
83
- const filePathRegex = /(?:\/[\w.-]+)+(?:\.[\w]+)?/g;
84
- const matches = content.match(filePathRegex) || [];
85
-
86
- for (const match of matches) {
87
- if (match.includes('.') && !match.includes('http')) {
88
- this.codeIndexer.trackAccess(match);
89
- }
90
- }
91
- }
92
-
93
- async start(): Promise<void> {
94
- // Check memory daemon health
95
- const isHealthy = await this.memoryClient.health();
96
- if (!isHealthy) {
97
- throw new Error('Memory daemon is not responding');
98
- }
99
-
100
- // Start background processors
101
- await this.processManager.startAll();
102
-
103
- this.emit('started');
104
- }
105
-
106
- async stop(): Promise<void> {
107
- await this.processManager.stopAll();
108
- this.emit('stopped');
109
- }
110
-
111
- /**
112
- * Process an incoming message and return enriched context
113
- */
114
- async processMessage(message: AgentMessage): Promise<string> {
115
- // Store the message in memory
116
- await this.memoryClient.store(
117
- `${message.role}: ${message.content}`,
118
- {
119
- timestamp: message.timestamp.toISOString(),
120
- context: message.context,
121
- ...message.metadata
122
- }
123
- );
124
-
125
- // Update task tracker
126
- if (message.role === 'user') {
127
- await this.taskTracker.processMessage(message.content, 'user');
128
- } else if (message.role === 'assistant') {
129
- await this.taskTracker.processMessage(message.content, 'assistant');
130
- }
131
-
132
- // Build context for the next response
133
- const context = await this.contextManager.buildContext(message.content);
134
-
135
- this.emit('context-built', {
136
- message,
137
- contextLength: context.length,
138
- sections: this.contextManager['contextSections'].length // Track what was included
139
- });
140
-
141
- return context;
142
- }
143
-
144
- /**
145
- * Get current state of all processors
146
- */
147
- async getState(): Promise<Record<string, any>> {
148
- const stats = await this.memoryClient.getStats();
149
- const tasks = await this.taskTracker.getActiveTasks();
150
- const workingSet = await this.codeIndexer.getWorkingSet();
151
-
152
- return {
153
- memory: stats,
154
- tasks: tasks.map(t => ({
155
- description: t.description,
156
- state: t.state,
157
- startTime: t.startTime,
158
- lastUpdate: t.lastUpdate
159
- })),
160
- workingSet: workingSet.map(f => ({
161
- path: f.path,
162
- accessCount: f.accessCount,
163
- lastAccessed: f.lastAccessed
164
- })),
165
- processors: this.processManager['processors'].size
166
- };
167
- }
168
- }