@sylphx/flow 1.0.5 → 1.1.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,39 @@
1
+ ---
2
+ description: Review code for quality, security, and best practices
3
+ ---
4
+
5
+ # Code Review
6
+
7
+ ## Context
8
+
9
+ $ARGUMENTS
10
+
11
+ ## Your Task
12
+
13
+ Review the code above (or at the specified location) and provide feedback on:
14
+
15
+ 1. **Code Quality**
16
+ - Readability and maintainability
17
+ - Code organization and structure
18
+ - Naming conventions
19
+ - Comments and documentation
20
+
21
+ 2. **Security**
22
+ - Potential vulnerabilities
23
+ - Input validation
24
+ - Authentication/authorization issues
25
+ - Data exposure risks
26
+
27
+ 3. **Performance**
28
+ - Algorithmic efficiency
29
+ - Resource usage
30
+ - Potential bottlenecks
31
+ - Scalability concerns
32
+
33
+ 4. **Best Practices**
34
+ - Language-specific idioms
35
+ - Design patterns
36
+ - Error handling
37
+ - Testing coverage
38
+
39
+ Provide specific, actionable suggestions for improvement.
@@ -0,0 +1,30 @@
1
+ ---
2
+ description: Write comprehensive tests for code
3
+ ---
4
+
5
+ # Write Tests
6
+
7
+ ## Context
8
+
9
+ $ARGUMENTS
10
+
11
+ ## Your Task
12
+
13
+ Write comprehensive tests for the code above (or at the specified location) that include:
14
+
15
+ 1. **Unit Tests**
16
+ - Test individual functions/methods
17
+ - Cover edge cases and boundary conditions
18
+ - Test error handling
19
+
20
+ 2. **Integration Tests** (if applicable)
21
+ - Test component interactions
22
+ - Test with realistic data
23
+
24
+ 3. **Test Coverage**
25
+ - Aim for high coverage of critical paths
26
+ - Include positive and negative test cases
27
+ - Test validation and error conditions
28
+
29
+ Use the project's existing testing framework and follow its conventions.
30
+ Ensure tests are readable, maintainable, and properly documented.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sylphx/flow",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "description": "AI-powered development workflow automation with autonomous loop mode and smart configuration",
5
5
  "type": "module",
6
6
  "bin": {
@@ -14,7 +14,8 @@
14
14
  "start": "bun src/index.ts",
15
15
  "test": "vitest run",
16
16
  "test:watch": "vitest",
17
- "type-check": "tsc --noEmit"
17
+ "type-check": "tsc --noEmit",
18
+ "prepublishOnly": "rm -rf assets && cp -r ../../assets assets"
18
19
  },
19
20
  "dependencies": {
20
21
  "commander": "^14.0.2",
@@ -38,6 +39,7 @@
38
39
  },
39
40
  "files": [
40
41
  "src",
42
+ "assets",
41
43
  "README.md",
42
44
  "CHANGELOG.md",
43
45
  "LOOP_MODE.md",
@@ -79,7 +79,7 @@ export class SmartConfigService {
79
79
  });
80
80
  }
81
81
 
82
- // Mark setup as completed (no need for default preferences prompt)
82
+ // Mark setup as completed (only save API keys, no defaults)
83
83
  await ConfigService.saveHomeSettings({ hasCompletedSetup: true });
84
84
  console.log(chalk.green('\n✓ Setup complete!\n'));
85
85
  }
@@ -113,99 +113,14 @@ export class SmartConfigService {
113
113
  await ConfigService.saveHomeSettings({ apiKeys: existingApiKeys });
114
114
  }
115
115
 
116
- /**
117
- * Setup default preferences
118
- */
119
- private static async setupDefaultPreferences(): Promise<void> {
120
- console.log(chalk.cyan('⚙️ Setup Default Preferences\n'));
121
-
122
- const userSettings = await ConfigService.loadHomeSettings();
123
- const availableProviders = ConfigService.getAvailableProviders(userSettings);
124
-
125
- if (availableProviders.length === 0) {
126
- console.log(chalk.yellow('⚠ No API keys configured yet. Skipping preferences setup.'));
127
- return;
128
- }
129
-
130
- const { setupDefaults } = await inquirer.prompt([
131
- {
132
- type: 'confirm',
133
- name: 'setupDefaults',
134
- message: 'Set up default preferences?',
135
- default: true,
136
- },
137
- ]);
138
-
139
- if (!setupDefaults) {
140
- console.log(chalk.dim('Skipping preferences setup.'));
141
- return;
142
- }
143
-
144
- // Select default provider
145
- if (availableProviders.length > 1) {
146
- const { defaultProvider } = await inquirer.prompt([
147
- {
148
- type: 'list',
149
- name: 'defaultProvider',
150
- message: 'Select default provider:',
151
- choices: availableProviders.map(p => ({
152
- name: p.charAt(0).toUpperCase() + p.slice(1),
153
- value: p,
154
- })),
155
- default: userSettings.defaultProvider || availableProviders[0],
156
- },
157
- ]);
158
-
159
- userSettings.defaultProvider = defaultProvider;
160
- }
161
-
162
- // Set default agent (will use dynamic loading)
163
- const { useDefaultAgent } = await inquirer.prompt([
164
- {
165
- type: 'confirm',
166
- name: 'useDefaultAgent',
167
- message: 'Set default agent?',
168
- default: true,
169
- },
170
- ]);
171
-
172
- if (useDefaultAgent) {
173
- try {
174
- const agents = await loadAllAgents(process.cwd());
175
- if (agents.length > 0) {
176
- const { defaultAgent } = await inquirer.prompt([
177
- {
178
- type: 'list',
179
- name: 'defaultAgent',
180
- message: 'Select default agent:',
181
- choices: agents.map(a => ({
182
- name: a.metadata.name || a.id,
183
- value: a.id,
184
- })),
185
- default: userSettings.defaultAgent || (agents.find(a => a.id === 'coder')?.id || agents[0].id),
186
- },
187
- ]);
188
-
189
- userSettings.defaultAgent = defaultAgent;
190
- }
191
- } catch (error) {
192
- console.log(chalk.yellow('⚠ Could not load agents, using "coder" as default'));
193
- userSettings.defaultAgent = 'coder';
194
- }
195
- }
196
-
197
- await ConfigService.saveHomeSettings(userSettings);
198
- console.log(chalk.green('✓ Default preferences saved'));
199
- }
200
116
 
201
117
  /**
202
118
  * Runtime selection - choose provider and agent for this run
203
119
  *
204
- * DESIGN PRINCIPLE: Smart Defaults
205
- * - Has saved default → Use it (no prompt)
206
- * - No saved default Prompt user
207
- * - Explicit flag (--select-provider/--select-agent) Force prompt (override)
208
- * - Explicit option (--provider/--agent) → Use specified value
120
+ * DESIGN PRINCIPLE: Always Ask (Simple & Explicit)
121
+ * - Has args (--provider/--agent) → Use them directly
122
+ * - No argsAlways prompt user
123
+ * - Never save runtime choices as defaults
209
124
  */
210
125
  static async selectRuntimeChoices(options: SmartConfigOptions): Promise<RuntimeChoices> {
211
126
  const config = await ConfigService.loadConfiguration();
@@ -213,42 +128,22 @@ export class SmartConfigService {
213
128
 
214
129
  // Handle provider selection
215
130
  if (options.provider) {
216
- // 1. Explicit option provided
131
+ // Explicit option provided via args
217
132
  choices.provider = options.provider;
218
- } else if (options.selectProvider) {
219
- // 2. Force selection (override defaults)
220
- choices.provider = await this.selectProvider(config.user);
221
- } else if (config.user.defaultProvider) {
222
- // 3. Use saved default (SMART DEFAULT - no prompt needed)
223
- choices.provider = config.user.defaultProvider;
224
- console.log(chalk.dim(` ✓ Provider: ${choices.provider}`));
225
133
  } else {
226
- // 4. No default saved, must prompt
134
+ // Always prompt
227
135
  choices.provider = await this.selectProvider(config.user);
228
136
  }
229
137
 
230
138
  // Handle agent selection
231
139
  if (options.agent) {
232
- // 1. Explicit option provided
140
+ // Explicit option provided via args
233
141
  choices.agent = options.agent;
234
- } else if (options.selectAgent) {
235
- // 2. Force selection (override defaults)
236
- choices.agent = await this.selectAgent(config.user.defaultAgent);
237
- } else if (config.user.defaultAgent) {
238
- // 3. Use saved default (SMART DEFAULT - no prompt needed)
239
- choices.agent = config.user.defaultAgent;
240
- console.log(chalk.dim(` ✓ Agent: ${choices.agent}`));
241
142
  } else {
242
- // 4. No default saved, must prompt
243
- choices.agent = await this.selectAgent(config.user.defaultAgent);
143
+ // Always prompt
144
+ choices.agent = await this.selectAgent();
244
145
  }
245
146
 
246
- // Save choices for next time
247
- await ConfigService.saveHomeSettings({
248
- defaultProvider: choices.provider,
249
- defaultAgent: choices.agent,
250
- });
251
-
252
147
  return choices;
253
148
  }
254
149
 
@@ -265,22 +160,16 @@ export class SmartConfigService {
265
160
  { id: 'z.ai', name: 'Z.ai (Recommended)', hasKey: !!apiKeys['z.ai'] },
266
161
  ];
267
162
 
268
- // Show last used provider hint
269
- const lastUsed = userSettings.defaultProvider;
270
- const message = lastUsed
271
- ? `Select provider (last used: ${lastUsed}):`
272
- : 'Select provider:';
273
-
274
163
  const { provider } = await inquirer.prompt([
275
164
  {
276
165
  type: 'list',
277
166
  name: 'provider',
278
- message,
167
+ message: 'Select provider:',
279
168
  choices: allProviders.map(p => ({
280
169
  name: p.hasKey ? p.name : `${p.name} (Need API key)`,
281
170
  value: p.id,
282
171
  })),
283
- default: lastUsed || 'default',
172
+ default: 'default',
284
173
  },
285
174
  ]);
286
175
 
@@ -309,7 +198,7 @@ export class SmartConfigService {
309
198
  /**
310
199
  * Select agent for this run
311
200
  */
312
- private static async selectAgent(lastUsed?: string): Promise<string> {
201
+ private static async selectAgent(): Promise<string> {
313
202
  try {
314
203
  const agents = await loadAllAgents(process.cwd());
315
204
 
@@ -318,21 +207,16 @@ export class SmartConfigService {
318
207
  return 'coder';
319
208
  }
320
209
 
321
- // Build message with last used hint
322
- const message = lastUsed
323
- ? `Select agent (last used: ${lastUsed}):`
324
- : 'Select agent:';
325
-
326
210
  const { agent } = await inquirer.prompt([
327
211
  {
328
212
  type: 'list',
329
213
  name: 'agent',
330
- message,
214
+ message: 'Select agent:',
331
215
  choices: agents.map(a => ({
332
216
  name: a.metadata.name || a.id,
333
217
  value: a.id,
334
218
  })),
335
- default: lastUsed || agents.find(a => a.id === 'coder')?.id || agents[0].id,
219
+ default: agents.find(a => a.id === 'coder')?.id || agents[0].id,
336
220
  },
337
221
  ]);
338
222