snow-ai 0.4.12 → 0.4.14

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/cli.js CHANGED
@@ -2,26 +2,45 @@
2
2
  // Show loading indicator immediately before any imports
3
3
  process.stdout.write('\x1b[?25l'); // Hide cursor
4
4
  process.stdout.write('ā ‹ Loading...\r');
5
+ // Import only critical dependencies synchronously
5
6
  import React from 'react';
6
7
  import { render, Text, Box } from 'ink';
7
8
  import Spinner from 'ink-spinner';
8
9
  import meow from 'meow';
9
- import { exec, execSync } from 'child_process';
10
- import { promisify } from 'util';
11
- import App from './app.js';
12
- import { vscodeConnection } from './utils/vscodeConnection.js';
13
- import { resourceMonitor } from './utils/resourceMonitor.js';
14
- import { initializeProfiles } from './utils/configManager.js';
15
- import { processManager } from './utils/processManager.js';
16
- import { enableDevMode, getDevUserId } from './utils/devMode.js';
17
- const execAsync = promisify(exec);
10
+ import { execSync } from 'child_process';
11
+ // Load heavy dependencies asynchronously
12
+ async function loadDependencies() {
13
+ const [appModule, vscodeModule, resourceModule, configModule, processModule, devModeModule, childProcessModule, utilModule,] = await Promise.all([
14
+ import('./app.js'),
15
+ import('./utils/vscodeConnection.js'),
16
+ import('./utils/resourceMonitor.js'),
17
+ import('./utils/configManager.js'),
18
+ import('./utils/processManager.js'),
19
+ import('./utils/devMode.js'),
20
+ import('child_process'),
21
+ import('util'),
22
+ ]);
23
+ return {
24
+ App: appModule.default,
25
+ vscodeConnection: vscodeModule.vscodeConnection,
26
+ resourceMonitor: resourceModule.resourceMonitor,
27
+ initializeProfiles: configModule.initializeProfiles,
28
+ processManager: processModule.processManager,
29
+ enableDevMode: devModeModule.enableDevMode,
30
+ getDevUserId: devModeModule.getDevUserId,
31
+ exec: childProcessModule.exec,
32
+ promisify: utilModule.promisify,
33
+ };
34
+ }
35
+ let execAsync;
18
36
  // Check for updates asynchronously
19
37
  async function checkForUpdates(currentVersion) {
20
38
  try {
21
- const { stdout } = await execAsync('npm view snow-ai version', {
39
+ const { stdout } = await execAsync('npm view snow-ai version --registry https://registry.npmjs.org', {
22
40
  encoding: 'utf8',
23
41
  });
24
42
  const latestVersion = stdout.trim();
43
+ // Simple string comparison - force registry fetch ensures no cache issues
25
44
  if (latestVersion && latestVersion !== currentVersion) {
26
45
  console.log('\nšŸ”” Update available!');
27
46
  console.log(` Current version: ${currentVersion}`);
@@ -78,39 +97,46 @@ if (cli.flags.update) {
78
97
  process.exit(1);
79
98
  }
80
99
  }
81
- // Handle dev mode flag
82
- if (cli.flags.dev) {
83
- enableDevMode();
84
- const userId = getDevUserId();
85
- console.log('šŸ”§ Developer mode enabled');
86
- console.log(`šŸ“ Using persistent userId: ${userId}`);
87
- console.log(`šŸ“‚ Stored in: ~/.snow/dev-user-id\n`);
88
- }
89
- // Start resource monitoring in development/debug mode
90
- if (process.env['NODE_ENV'] === 'development' || process.env['DEBUG']) {
91
- resourceMonitor.startMonitoring(30000); // Monitor every 30 seconds
92
- // Check for leaks every 5 minutes
93
- setInterval(() => {
94
- const { hasLeak, reasons } = resourceMonitor.checkForLeaks();
95
- if (hasLeak) {
96
- console.error('āš ļø Potential memory leak detected:');
97
- reasons.forEach(reason => console.error(` - ${reason}`));
98
- }
99
- }, 5 * 60 * 1000);
100
- }
100
+ // Dev mode and resource monitoring will be initialized in Startup component
101
101
  // Startup component that shows loading spinner during update check
102
- const Startup = ({ version, skipWelcome, headlessPrompt, }) => {
102
+ const Startup = ({ version, skipWelcome, headlessPrompt, isDevMode, }) => {
103
103
  const [appReady, setAppReady] = React.useState(false);
104
+ const [AppComponent, setAppComponent] = React.useState(null);
104
105
  React.useEffect(() => {
105
106
  let mounted = true;
106
107
  const init = async () => {
107
- // Initialize profiles system first
108
+ // Load all dependencies in parallel
109
+ const deps = await loadDependencies();
110
+ // Setup execAsync for checkForUpdates
111
+ execAsync = deps.promisify(deps.exec);
112
+ // Initialize profiles system
108
113
  try {
109
- initializeProfiles();
114
+ deps.initializeProfiles();
110
115
  }
111
116
  catch (error) {
112
117
  console.error('Failed to initialize profiles:', error);
113
118
  }
119
+ // Handle dev mode
120
+ if (isDevMode) {
121
+ deps.enableDevMode();
122
+ const userId = deps.getDevUserId();
123
+ console.log('šŸ”§ Developer mode enabled');
124
+ console.log(`šŸ“ Using persistent userId: ${userId}`);
125
+ console.log(`šŸ“‚ Stored in: ~/.snow/dev-user-id\n`);
126
+ }
127
+ // Start resource monitoring in development/debug mode
128
+ if (process.env['NODE_ENV'] === 'development' || process.env['DEBUG']) {
129
+ deps.resourceMonitor.startMonitoring(30000);
130
+ setInterval(() => {
131
+ const { hasLeak, reasons } = deps.resourceMonitor.checkForLeaks();
132
+ if (hasLeak) {
133
+ console.error('āš ļø Potential memory leak detected:');
134
+ reasons.forEach((reason) => console.error(` - ${reason}`));
135
+ }
136
+ }, 5 * 60 * 1000);
137
+ }
138
+ // Store for cleanup
139
+ global.__deps = deps;
114
140
  // Check for updates with timeout
115
141
  const updateCheckPromise = version
116
142
  ? checkForUpdates(version)
@@ -121,6 +147,7 @@ const Startup = ({ version, skipWelcome, headlessPrompt, }) => {
121
147
  new Promise(resolve => setTimeout(resolve, 3000)),
122
148
  ]);
123
149
  if (mounted) {
150
+ setAppComponent(() => deps.App);
124
151
  setAppReady(true);
125
152
  }
126
153
  };
@@ -128,15 +155,15 @@ const Startup = ({ version, skipWelcome, headlessPrompt, }) => {
128
155
  return () => {
129
156
  mounted = false;
130
157
  };
131
- }, [version]);
132
- if (!appReady) {
158
+ }, [version, isDevMode]);
159
+ if (!appReady || !AppComponent) {
133
160
  return (React.createElement(Box, { flexDirection: "column" },
134
161
  React.createElement(Box, null,
135
162
  React.createElement(Text, { color: "cyan" },
136
163
  React.createElement(Spinner, { type: "dots" })),
137
164
  React.createElement(Text, null, " Loading..."))));
138
165
  }
139
- return (React.createElement(App, { version: version, skipWelcome: skipWelcome, headlessPrompt: headlessPrompt }));
166
+ return (React.createElement(AppComponent, { version: version, skipWelcome: skipWelcome, headlessPrompt: headlessPrompt }));
140
167
  };
141
168
  // Disable bracketed paste mode on startup
142
169
  process.stdout.write('\x1b[?2004l');
@@ -146,12 +173,16 @@ process.stdout.write('\x1b[?25h'); // Show cursor
146
173
  // Re-enable on exit to avoid polluting parent shell
147
174
  const cleanup = () => {
148
175
  process.stdout.write('\x1b[?2004l');
149
- // Kill all child processes first
150
- processManager.killAll();
151
- // Stop resource monitoring
152
- resourceMonitor.stopMonitoring();
153
- // Disconnect VSCode connection before exit
154
- vscodeConnection.stop();
176
+ // Cleanup loaded dependencies if available
177
+ const deps = global.__deps;
178
+ if (deps) {
179
+ // Kill all child processes first
180
+ deps.processManager.killAll();
181
+ // Stop resource monitoring
182
+ deps.resourceMonitor.stopMonitoring();
183
+ // Disconnect VSCode connection before exit
184
+ deps.vscodeConnection.stop();
185
+ }
155
186
  };
156
187
  process.on('exit', cleanup);
157
188
  process.on('SIGINT', () => {
@@ -162,7 +193,7 @@ process.on('SIGTERM', () => {
162
193
  cleanup();
163
194
  process.exit(0);
164
195
  });
165
- render(React.createElement(Startup, { version: cli.pkg.version, skipWelcome: cli.flags.c, headlessPrompt: cli.flags.ask }), {
196
+ render(React.createElement(Startup, { version: cli.pkg.version, skipWelcome: cli.flags.c, headlessPrompt: cli.flags.ask, isDevMode: cli.flags.dev }), {
166
197
  exitOnCtrlC: false,
167
198
  patchConsole: true,
168
199
  });
@@ -1,19 +1,4 @@
1
1
  import React from 'react';
2
- import '../../utils/commands/clear.js';
3
- import '../../utils/commands/resume.js';
4
- import '../../utils/commands/mcp.js';
5
- import '../../utils/commands/yolo.js';
6
- import '../../utils/commands/init.js';
7
- import '../../utils/commands/ide.js';
8
- import '../../utils/commands/compact.js';
9
- import '../../utils/commands/home.js';
10
- import '../../utils/commands/review.js';
11
- import '../../utils/commands/role.js';
12
- import '../../utils/commands/usage.js';
13
- import '../../utils/commands/export.js';
14
- import '../../utils/commands/agent.js';
15
- import '../../utils/commands/todoPicker.js';
16
- import '../../utils/commands/help.js';
17
2
  type Props = {
18
3
  skipWelcome?: boolean;
19
4
  };
@@ -39,22 +39,6 @@ import { CodebaseIndexAgent } from '../../agents/codebaseIndexAgent.js';
39
39
  import { loadCodebaseConfig } from '../../utils/codebaseConfig.js';
40
40
  import { codebaseSearchEvents } from '../../utils/codebaseSearchEvents.js';
41
41
  import { logger } from '../../utils/logger.js';
42
- // Import commands to register them
43
- import '../../utils/commands/clear.js';
44
- import '../../utils/commands/resume.js';
45
- import '../../utils/commands/mcp.js';
46
- import '../../utils/commands/yolo.js';
47
- import '../../utils/commands/init.js';
48
- import '../../utils/commands/ide.js';
49
- import '../../utils/commands/compact.js';
50
- import '../../utils/commands/home.js';
51
- import '../../utils/commands/review.js';
52
- import '../../utils/commands/role.js';
53
- import '../../utils/commands/usage.js';
54
- import '../../utils/commands/export.js';
55
- import '../../utils/commands/agent.js';
56
- import '../../utils/commands/todoPicker.js';
57
- import '../../utils/commands/help.js';
58
42
  export default function ChatScreen({ skipWelcome }) {
59
43
  const { t } = useI18n();
60
44
  const { theme } = useTheme();
@@ -110,6 +94,29 @@ export default function ChatScreen({ skipWelcome }) {
110
94
  useEffect(() => {
111
95
  pendingMessagesRef.current = pendingMessages;
112
96
  }, [pendingMessages]);
97
+ // Load commands dynamically to avoid blocking initial render
98
+ useEffect(() => {
99
+ // Use Promise.all to load all commands in parallel
100
+ Promise.all([
101
+ import('../../utils/commands/clear.js'),
102
+ import('../../utils/commands/resume.js'),
103
+ import('../../utils/commands/mcp.js'),
104
+ import('../../utils/commands/yolo.js'),
105
+ import('../../utils/commands/init.js'),
106
+ import('../../utils/commands/ide.js'),
107
+ import('../../utils/commands/compact.js'),
108
+ import('../../utils/commands/home.js'),
109
+ import('../../utils/commands/review.js'),
110
+ import('../../utils/commands/role.js'),
111
+ import('../../utils/commands/usage.js'),
112
+ import('../../utils/commands/export.js'),
113
+ import('../../utils/commands/agent.js'),
114
+ import('../../utils/commands/todoPicker.js'),
115
+ import('../../utils/commands/help.js'),
116
+ ]).catch(error => {
117
+ console.error('Failed to load commands:', error);
118
+ });
119
+ }, []);
113
120
  // Auto-start codebase indexing on mount if enabled
114
121
  useEffect(() => {
115
122
  const startCodebaseIndexing = async () => {
@@ -147,6 +154,7 @@ export default function ChatScreen({ skipWelcome }) {
147
154
  }
148
155
  });
149
156
  setWatcherEnabled(true);
157
+ setCodebaseIndexing(false); // Ensure loading UI is hidden
150
158
  return;
151
159
  }
152
160
  // If watcher was enabled before but indexing not completed, restore it
@@ -174,6 +182,7 @@ export default function ChatScreen({ skipWelcome }) {
174
182
  }
175
183
  });
176
184
  setWatcherEnabled(true);
185
+ setCodebaseIndexing(false); // Ensure loading UI is hidden when restoring watcher
177
186
  }
178
187
  // Start or resume indexing in background
179
188
  setCodebaseIndexing(true);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "snow-ai",
3
- "version": "0.4.12",
3
+ "version": "0.4.14",
4
4
  "description": "Intelligent Command Line Assistant powered by AI",
5
5
  "license": "MIT",
6
6
  "bin": {