kspec 1.0.15 → 1.0.16
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/package.json +1 -1
- package/src/index.js +97 -4
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const fs = require('fs');
|
|
2
2
|
const path = require('path');
|
|
3
|
+
const os = require('os');
|
|
3
4
|
const { execSync, spawn } = require('child_process');
|
|
4
5
|
const readline = require('readline');
|
|
5
6
|
|
|
@@ -7,6 +8,7 @@ const KSPEC_DIR = '.kspec';
|
|
|
7
8
|
const STEERING_DIR = '.kiro/steering';
|
|
8
9
|
const AGENTS_DIR = '.kiro/agents';
|
|
9
10
|
const CONFIG_FILE = path.join(KSPEC_DIR, 'config.json');
|
|
11
|
+
const UPDATE_CHECK_FILE = path.join(os.homedir(), '.kspec-update-check');
|
|
10
12
|
|
|
11
13
|
// Default config
|
|
12
14
|
const defaultConfig = {
|
|
@@ -33,6 +35,62 @@ function saveConfig(cfg) {
|
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
const config = loadConfig();
|
|
38
|
+
const pkg = require('../package.json');
|
|
39
|
+
|
|
40
|
+
// Update check (non-blocking, cached for 24h)
|
|
41
|
+
function shouldCheckUpdate() {
|
|
42
|
+
try {
|
|
43
|
+
if (fs.existsSync(UPDATE_CHECK_FILE)) {
|
|
44
|
+
const lastCheck = parseInt(fs.readFileSync(UPDATE_CHECK_FILE, 'utf8'), 10);
|
|
45
|
+
const hoursSinceCheck = (Date.now() - lastCheck) / (1000 * 60 * 60);
|
|
46
|
+
return hoursSinceCheck >= 24;
|
|
47
|
+
}
|
|
48
|
+
} catch {}
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function saveUpdateCheck() {
|
|
53
|
+
try {
|
|
54
|
+
fs.writeFileSync(UPDATE_CHECK_FILE, Date.now().toString());
|
|
55
|
+
} catch {}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function compareVersions(v1, v2) {
|
|
59
|
+
const parts1 = v1.split('.').map(Number);
|
|
60
|
+
const parts2 = v2.split('.').map(Number);
|
|
61
|
+
for (let i = 0; i < 3; i++) {
|
|
62
|
+
if ((parts1[i] || 0) < (parts2[i] || 0)) return -1;
|
|
63
|
+
if ((parts1[i] || 0) > (parts2[i] || 0)) return 1;
|
|
64
|
+
}
|
|
65
|
+
return 0;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
async function checkForUpdates() {
|
|
69
|
+
if (!shouldCheckUpdate()) return;
|
|
70
|
+
|
|
71
|
+
try {
|
|
72
|
+
const https = require('https');
|
|
73
|
+
const data = await new Promise((resolve, reject) => {
|
|
74
|
+
const req = https.get('https://registry.npmjs.org/kspec/latest', { timeout: 3000 }, res => {
|
|
75
|
+
let body = '';
|
|
76
|
+
res.on('data', chunk => body += chunk);
|
|
77
|
+
res.on('end', () => resolve(body));
|
|
78
|
+
});
|
|
79
|
+
req.on('error', reject);
|
|
80
|
+
req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const latest = JSON.parse(data).version;
|
|
84
|
+
saveUpdateCheck();
|
|
85
|
+
|
|
86
|
+
if (compareVersions(pkg.version, latest) < 0) {
|
|
87
|
+
console.log(`\n Update available: ${pkg.version} → ${latest}`);
|
|
88
|
+
console.log(` Run: npm install -g kspec\n`);
|
|
89
|
+
}
|
|
90
|
+
} catch {
|
|
91
|
+
// Silently fail - don't block user workflow
|
|
92
|
+
}
|
|
93
|
+
}
|
|
36
94
|
|
|
37
95
|
// Helpers
|
|
38
96
|
function log(msg) { console.log(`[kspec] ${msg}`); }
|
|
@@ -818,6 +876,37 @@ Switch: /agent swap or use keyboard shortcuts
|
|
|
818
876
|
`);
|
|
819
877
|
},
|
|
820
878
|
|
|
879
|
+
async update() {
|
|
880
|
+
console.log(`\nkspec v${pkg.version}\n`);
|
|
881
|
+
console.log('Checking for updates...');
|
|
882
|
+
|
|
883
|
+
try {
|
|
884
|
+
const https = require('https');
|
|
885
|
+
const data = await new Promise((resolve, reject) => {
|
|
886
|
+
const req = https.get('https://registry.npmjs.org/kspec/latest', { timeout: 5000 }, res => {
|
|
887
|
+
let body = '';
|
|
888
|
+
res.on('data', chunk => body += chunk);
|
|
889
|
+
res.on('end', () => resolve(body));
|
|
890
|
+
});
|
|
891
|
+
req.on('error', reject);
|
|
892
|
+
req.on('timeout', () => { req.destroy(); reject(new Error('timeout')); });
|
|
893
|
+
});
|
|
894
|
+
|
|
895
|
+
const latest = JSON.parse(data).version;
|
|
896
|
+
saveUpdateCheck();
|
|
897
|
+
|
|
898
|
+
if (compareVersions(pkg.version, latest) < 0) {
|
|
899
|
+
console.log(`\nUpdate available: ${pkg.version} → ${latest}`);
|
|
900
|
+
console.log('\nTo update, run:');
|
|
901
|
+
console.log(' npm install -g kspec\n');
|
|
902
|
+
} else {
|
|
903
|
+
console.log(`\nYou're on the latest version!\n`);
|
|
904
|
+
}
|
|
905
|
+
} catch (err) {
|
|
906
|
+
console.error('\nCould not check for updates. Check your internet connection.\n');
|
|
907
|
+
}
|
|
908
|
+
},
|
|
909
|
+
|
|
821
910
|
help() {
|
|
822
911
|
console.log(`
|
|
823
912
|
kspec - Spec-driven development for Kiro CLI
|
|
@@ -847,6 +936,7 @@ Other:
|
|
|
847
936
|
kspec list List all specs
|
|
848
937
|
kspec status Current status
|
|
849
938
|
kspec agents List agents
|
|
939
|
+
kspec update Check for updates
|
|
850
940
|
kspec help Show this help
|
|
851
941
|
|
|
852
942
|
Examples:
|
|
@@ -858,14 +948,17 @@ Examples:
|
|
|
858
948
|
};
|
|
859
949
|
|
|
860
950
|
async function run(args) {
|
|
951
|
+
// Check for updates (non-blocking, cached for 24h)
|
|
952
|
+
checkForUpdates();
|
|
953
|
+
|
|
861
954
|
// Handle standard CLI flags first
|
|
862
955
|
if (args.includes('--help') || args.includes('-h')) {
|
|
863
956
|
return commands.help();
|
|
864
957
|
}
|
|
865
|
-
|
|
958
|
+
|
|
866
959
|
if (args.includes('--version') || args.includes('-v')) {
|
|
867
|
-
|
|
868
|
-
|
|
960
|
+
// Show version and check for updates
|
|
961
|
+
await commands.update();
|
|
869
962
|
return;
|
|
870
963
|
}
|
|
871
964
|
|
|
@@ -879,4 +972,4 @@ async function run(args) {
|
|
|
879
972
|
}
|
|
880
973
|
}
|
|
881
974
|
|
|
882
|
-
module.exports = { run, commands, loadConfig, detectCli, requireCli, agentTemplates, getTaskStats, refreshContext, getCurrentTask };
|
|
975
|
+
module.exports = { run, commands, loadConfig, detectCli, requireCli, agentTemplates, getTaskStats, refreshContext, getCurrentTask, checkForUpdates, compareVersions };
|