flowmind 1.4.0 → 1.4.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.
@@ -50,7 +50,7 @@ class HonorEngine {
50
50
  }
51
51
  this.initialized = true;
52
52
  } catch (error) {
53
- // Non-blocking: create default data in memory
53
+ console.warn('HonorEngine init failed, using defaults:', error.message);
54
54
  this.data = this.createDefaultData();
55
55
  this.initialized = true;
56
56
  }
@@ -92,7 +92,7 @@ class HonorEngine {
92
92
  }
93
93
  }
94
94
  } catch (error) {
95
- // Non-blocking
95
+ console.warn('HonorEngine seedKnownSkills failed:', error.message);
96
96
  }
97
97
  }
98
98
 
@@ -148,7 +148,7 @@ class HonorEngine {
148
148
  timestamp: this.data.lastUpdated
149
149
  });
150
150
  } catch (error) {
151
- // Non-blocking
151
+ console.warn('HonorEngine award failed:', error.message);
152
152
  }
153
153
  }
154
154
 
@@ -170,7 +170,7 @@ class HonorEngine {
170
170
  await this.save();
171
171
  }
172
172
  } catch (error) {
173
- // Non-blocking
173
+ console.warn('HonorEngine addKnownSkill failed:', error.message);
174
174
  }
175
175
  }
176
176
 
@@ -247,7 +247,7 @@ class HonorEngine {
247
247
  await fs.ensureDir(path.dirname(this.honorPath));
248
248
  await fs.writeJson(this.honorPath, this.data, { spaces: 2 });
249
249
  } catch (error) {
250
- // Non-blocking
250
+ console.warn('HonorEngine save failed:', error.message);
251
251
  }
252
252
  }
253
253
  }
package/core/index.js CHANGED
@@ -33,6 +33,13 @@ class FlowMind {
33
33
  if (this.initialized) return this;
34
34
 
35
35
  await this.config.load();
36
+
37
+ // Validate configuration
38
+ const validation = this.config.validate();
39
+ if (!validation.valid) {
40
+ console.warn('Configuration warnings:', validation.errors.join(', '));
41
+ }
42
+
36
43
  await this.components.init();
37
44
  await this.components.initAll();
38
45
  await this.honor.init();
@@ -7,6 +7,7 @@ const fs = require('fs-extra');
7
7
  const path = require('path');
8
8
  const { v4: uuidv4 } = require('uuid');
9
9
  const eventBus = require('./event-bus');
10
+ const { expandPath } = require('./utils');
10
11
 
11
12
  /**
12
13
  * Per-key write queue to prevent concurrent read-modify-write races
@@ -580,10 +581,7 @@ class LearningEngine {
580
581
  * Helper methods
581
582
  */
582
583
  expandPath(filePath) {
583
- if (filePath.startsWith('~')) {
584
- return path.join(process.env.HOME || process.env.USERPROFILE, filePath.slice(1));
585
- }
586
- return filePath;
584
+ return expandPath(filePath);
587
585
  }
588
586
 
589
587
  extractCondition(input) {
@@ -5,6 +5,7 @@
5
5
 
6
6
  const fs = require('fs-extra');
7
7
  const path = require('path');
8
+ const { expandPath } = require('./utils');
8
9
 
9
10
  class SceneMatcher {
10
11
  constructor(config, learning) {
@@ -316,10 +317,7 @@ class SceneMatcher {
316
317
  * Helper to expand path
317
318
  */
318
319
  expandPath(filePath) {
319
- if (filePath.startsWith('~')) {
320
- return path.join(process.env.HOME || process.env.USERPROFILE, filePath.slice(1));
321
- }
322
- return filePath;
320
+ return expandPath(filePath);
323
321
  }
324
322
  }
325
323
 
@@ -327,6 +327,13 @@ class SkillLoader {
327
327
  const skill = this.skills.get(name);
328
328
  if (!skill) return null;
329
329
 
330
+ // Clear require cache to actually reload the module
331
+ const indexPath = require('path').join(skill.path, 'index.js');
332
+ const resolvedPath = require.resolve(indexPath);
333
+ if (require.cache[resolvedPath]) {
334
+ delete require.cache[resolvedPath];
335
+ }
336
+
330
337
  return await this.loadSkill(name, skill.path);
331
338
  }
332
339
 
package/core/utils.js ADDED
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Shared utility functions
3
+ */
4
+
5
+ const path = require('path');
6
+ const os = require('os');
7
+
8
+ /**
9
+ * Expand ~ in file paths to home directory
10
+ */
11
+ function expandPath(filePath) {
12
+ if (filePath.startsWith('~')) {
13
+ return path.join(process.env.HOME || process.env.USERPROFILE || os.homedir(), filePath.slice(1));
14
+ }
15
+ return filePath;
16
+ }
17
+
18
+ module.exports = { expandPath };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "flowmind",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "The AI Agent That Learns How You Work - Stop repeating yourself, FlowMind learns your workflows and applies them automatically.",
5
5
  "main": "core/index.js",
6
6
  "bin": {
@@ -1,20 +1,53 @@
1
1
  const React = require('react');
2
- const { Box, Text } = require('ink');
2
+ const { Box, Text, useInput } = require('ink');
3
3
  const TextInput = require('ink-text-input').default || require('ink-text-input');
4
4
  const Spinner = require('ink-spinner').default || require('ink-spinner');
5
5
 
6
6
  function ChatPanel({ onSubmit, isProcessing, onExit }) {
7
7
  const [input, setInput] = React.useState('');
8
8
  const [history, setHistory] = React.useState([]);
9
+ const [cmdHistory, setCmdHistory] = React.useState([]);
10
+ const [historyIndex, setHistoryIndex] = React.useState(-1);
11
+ const [savedInput, setSavedInput] = React.useState('');
9
12
  const mountedRef = React.useRef(true);
10
13
 
11
14
  React.useEffect(() => {
12
15
  return () => { mountedRef.current = false; };
13
16
  }, []);
14
17
 
18
+ // Handle Up/Down arrow for command history
19
+ useInput((ch, key) => {
20
+ if (isProcessing) return;
21
+
22
+ if (key.upArrow && cmdHistory.length > 0) {
23
+ const newIndex = historyIndex === -1
24
+ ? cmdHistory.length - 1
25
+ : Math.max(0, historyIndex - 1);
26
+ if (historyIndex === -1) setSavedInput(input);
27
+ setHistoryIndex(newIndex);
28
+ setInput(cmdHistory[newIndex]);
29
+ } else if (key.downArrow) {
30
+ if (historyIndex === -1) return;
31
+ const newIndex = historyIndex + 1;
32
+ if (newIndex >= cmdHistory.length) {
33
+ setHistoryIndex(-1);
34
+ setInput(savedInput);
35
+ } else {
36
+ setHistoryIndex(newIndex);
37
+ setInput(cmdHistory[newIndex]);
38
+ }
39
+ }
40
+ });
41
+
15
42
  const handleSubmit = (value) => {
16
43
  if (!value.trim()) return;
17
44
  setHistory(prev => [...prev, { role: 'user', text: value }]);
45
+ // Add to command history (deduplicate consecutive)
46
+ if (cmdHistory.length === 0 || cmdHistory[cmdHistory.length - 1] !== value) {
47
+ setCmdHistory(prev => [...prev, value]);
48
+ }
49
+ setHistoryIndex(-1);
50
+ setSavedInput('');
18
51
  setInput('');
19
52
  if (value.toLowerCase() === 'exit' || value.toLowerCase() === 'quit') {
20
53
  if (onExit) onExit();