@comfanion/workflow 4.36.6 → 4.36.8
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/bin/cli.js +52 -54
- package/package.json +1 -1
- package/src/build-info.json +1 -1
- package/src/opencode/plugins/file-indexer.ts +5 -2
package/bin/cli.js
CHANGED
|
@@ -11,20 +11,22 @@ import { execSync } from 'child_process';
|
|
|
11
11
|
import yaml from 'js-yaml';
|
|
12
12
|
|
|
13
13
|
/**
|
|
14
|
-
*
|
|
15
|
-
* Arrays are replaced, not merged.
|
|
14
|
+
* Find top-level keys that exist in newObj but not in oldObj
|
|
16
15
|
*/
|
|
17
|
-
function
|
|
18
|
-
const
|
|
19
|
-
for (const key of Object.keys(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
} else
|
|
24
|
-
|
|
16
|
+
function findNewKeys(newObj, oldObj, prefix = '') {
|
|
17
|
+
const newKeys = [];
|
|
18
|
+
for (const key of Object.keys(newObj)) {
|
|
19
|
+
const fullKey = prefix ? `${prefix}.${key}` : key;
|
|
20
|
+
if (!(key in oldObj)) {
|
|
21
|
+
newKeys.push(fullKey);
|
|
22
|
+
} else if (
|
|
23
|
+
newObj[key] !== null && typeof newObj[key] === 'object' && !Array.isArray(newObj[key]) &&
|
|
24
|
+
oldObj[key] !== null && typeof oldObj[key] === 'object' && !Array.isArray(oldObj[key])
|
|
25
|
+
) {
|
|
26
|
+
newKeys.push(...findNewKeys(newObj[key], oldObj[key], fullKey));
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
|
-
return
|
|
29
|
+
return newKeys;
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
@@ -347,32 +349,24 @@ program
|
|
|
347
349
|
// Update config.yaml with user values
|
|
348
350
|
spinner.text = 'Configuring...';
|
|
349
351
|
const configPath = path.join(targetDir, 'config.yaml');
|
|
350
|
-
let configContent
|
|
352
|
+
let configContent;
|
|
351
353
|
|
|
352
|
-
// If we had existing config,
|
|
354
|
+
// If we had existing config, use it as base (preserves comments and formatting)
|
|
353
355
|
if (existingConfigContent) {
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
lineWidth: 120,
|
|
361
|
-
noRefs: true,
|
|
362
|
-
sortKeys: false
|
|
363
|
-
});
|
|
364
|
-
console.log(chalk.green(' ✅ Merged existing config settings'));
|
|
365
|
-
} catch (e) {
|
|
366
|
-
// Merge failed, continue with new config + user values
|
|
367
|
-
}
|
|
356
|
+
configContent = existingConfigContent;
|
|
357
|
+
// Update version to match new package
|
|
358
|
+
configContent = configContent.replace(/^version:\s*["']?[\d.]+["']?/m, `version: "${VERSION}"`);
|
|
359
|
+
console.log(chalk.green(' ✅ Restored your config (comments preserved)'));
|
|
360
|
+
} else {
|
|
361
|
+
configContent = await fs.readFile(configPath, 'utf8');
|
|
368
362
|
}
|
|
369
363
|
|
|
370
364
|
// Apply user's answers from prompts
|
|
371
365
|
configContent = configContent
|
|
372
|
-
.replace(/user_name
|
|
373
|
-
.replace(/communication_language
|
|
374
|
-
.replace(/project_name
|
|
375
|
-
.replace(/methodology
|
|
366
|
+
.replace(/user_name:\s*["']?[^"\n]*["']?/, `user_name: "${config.user_name}"`)
|
|
367
|
+
.replace(/communication_language:\s*["']?[^"\n]*["']?/, `communication_language: "${config.communication_language}"`)
|
|
368
|
+
.replace(/project_name:\s*["']?[^"\n]*["']?/, `project_name: "${config.project_name}"`)
|
|
369
|
+
.replace(/methodology:\s*(tdd|stub)/, `methodology: ${config.methodology}`);
|
|
376
370
|
|
|
377
371
|
// Jira config
|
|
378
372
|
if (config.jira_enabled) {
|
|
@@ -617,33 +611,37 @@ program
|
|
|
617
611
|
await fs.move(tempVectors, path.join(targetDir, 'vectors'), { overwrite: true });
|
|
618
612
|
}
|
|
619
613
|
|
|
620
|
-
//
|
|
621
|
-
spinner.text = '
|
|
614
|
+
// Restore user's config.yaml (preserves comments and formatting)
|
|
615
|
+
spinner.text = 'Restoring config.yaml...';
|
|
622
616
|
try {
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
617
|
+
// Update version in user's config to match new package
|
|
618
|
+
let restoredConfig = configBackup.replace(
|
|
619
|
+
/^version:\s*["']?[\d.]+["']?/m,
|
|
620
|
+
`version: "${VERSION}"`
|
|
621
|
+
);
|
|
622
|
+
await fs.writeFile(configPath, restoredConfig);
|
|
623
|
+
console.log(chalk.green(' ✅ config.yaml restored (your settings + comments preserved)'));
|
|
629
624
|
|
|
630
|
-
//
|
|
631
|
-
const
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
625
|
+
// Check if new template has options that user doesn't have
|
|
626
|
+
const newConfigPath = path.join(OPENCODE_SRC, 'config.yaml');
|
|
627
|
+
if (await fs.pathExists(newConfigPath)) {
|
|
628
|
+
const newConfig = yaml.load(await fs.readFile(newConfigPath, 'utf8')) || {};
|
|
629
|
+
const userConfig = yaml.load(configBackup) || {};
|
|
630
|
+
const newKeys = findNewKeys(newConfig, userConfig);
|
|
631
|
+
if (newKeys.length > 0) {
|
|
632
|
+
console.log(chalk.yellow(` 💡 New config options available: ${newKeys.slice(0, 3).join(', ')}${newKeys.length > 3 ? '...' : ''}`));
|
|
633
|
+
console.log(chalk.gray(' Check .opencode.backup-*/config.yaml.new for full template'));
|
|
634
|
+
// Save new template for reference
|
|
635
|
+
await fs.writeFile(
|
|
636
|
+
path.join(process.cwd(), `.opencode.backup-${timestamp}`, 'config.yaml.new'),
|
|
637
|
+
await fs.readFile(newConfigPath, 'utf8')
|
|
638
|
+
);
|
|
639
|
+
}
|
|
640
|
+
}
|
|
643
641
|
} catch (e) {
|
|
644
|
-
// Fallback: just restore user's config
|
|
642
|
+
// Fallback: just restore user's config
|
|
645
643
|
await fs.writeFile(configPath, configBackup);
|
|
646
|
-
console.log(chalk.yellow(' ⚠️ config.yaml restored
|
|
644
|
+
console.log(chalk.yellow(' ⚠️ config.yaml restored'));
|
|
647
645
|
}
|
|
648
646
|
|
|
649
647
|
// Install plugin dependencies
|
package/package.json
CHANGED
package/src/build-info.json
CHANGED
|
@@ -422,10 +422,13 @@ export const FileIndexerPlugin: Plugin = async ({ directory, client }) => {
|
|
|
422
422
|
const result = await ensureIndexOnSessionStart(
|
|
423
423
|
directory,
|
|
424
424
|
config,
|
|
425
|
-
// onStart callback - show
|
|
425
|
+
// onStart callback - show toasts
|
|
426
426
|
async (totalFiles, estimatedMins) => {
|
|
427
427
|
await toast(messages.indexing(totalFiles), 'info')
|
|
428
|
-
|
|
428
|
+
// Only show fun message if there's actual work to do
|
|
429
|
+
if (totalFiles > 0) {
|
|
430
|
+
setTimeout(() => toast(messages.fun(totalFiles, estimatedMins), 'info'), 1500)
|
|
431
|
+
}
|
|
429
432
|
}
|
|
430
433
|
)
|
|
431
434
|
|