@exchanet/enet 1.0.18 → 1.0.20
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/commands/install.js +30 -10
- package/src/index.js +28 -21
package/package.json
CHANGED
package/src/commands/install.js
CHANGED
|
@@ -3,11 +3,12 @@ import ora from 'ora'
|
|
|
3
3
|
import fs from 'fs-extra'
|
|
4
4
|
import path from 'path'
|
|
5
5
|
import enquirer from 'enquirer'
|
|
6
|
-
const { MultiSelect } = enquirer
|
|
6
|
+
const { MultiSelect, Select } = enquirer
|
|
7
7
|
import { detectSystemAgents, getInstallPath, AGENTS } from '../utils/agent_detector.js'
|
|
8
8
|
import { getMethod, fetchFromGitHub, readInstallRecord, writeInstallRecord } from '../utils/registry.js'
|
|
9
9
|
|
|
10
10
|
export async function installCommand(methodId, options) {
|
|
11
|
+
if (options.project) options.global = false
|
|
11
12
|
// 1. Load method from registry
|
|
12
13
|
const spinner = ora('Fetching registry...').start()
|
|
13
14
|
const method = await getMethod(methodId).catch(() => null)
|
|
@@ -20,12 +21,7 @@ export async function installCommand(methodId, options) {
|
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
console.log(chalk.bold(`\n ◆ ${method.name}`))
|
|
23
|
-
console.log(chalk.dim(` ${method.description}`))
|
|
24
|
-
if (options.global) {
|
|
25
|
-
console.log(chalk.cyan(' Destination: global (home) — available for all agents/projects\n'))
|
|
26
|
-
} else {
|
|
27
|
-
console.log(chalk.dim(` Destination: current project (use ${chalk.white('--global')} for all agents)\n`))
|
|
28
|
-
}
|
|
24
|
+
console.log(chalk.dim(` ${method.description}\n`))
|
|
29
25
|
|
|
30
26
|
// 2. Read existing install record — know what is already installed
|
|
31
27
|
const record = await readInstallRecord(methodId)
|
|
@@ -70,7 +66,31 @@ export async function installCommand(methodId, options) {
|
|
|
70
66
|
}
|
|
71
67
|
}
|
|
72
68
|
|
|
73
|
-
|
|
69
|
+
// 3b. If neither -g nor -p was passed, ask: global or project?
|
|
70
|
+
if (options.global === undefined && process.stdin.isTTY) {
|
|
71
|
+
const destPrompt = new Select({
|
|
72
|
+
name: 'destination',
|
|
73
|
+
message: 'Install to:',
|
|
74
|
+
choices: [
|
|
75
|
+
{ name: 'global', message: 'Global (home) — available for all agents and projects', value: true },
|
|
76
|
+
{ name: 'project', message: 'Project — this folder only', value: false }
|
|
77
|
+
]
|
|
78
|
+
})
|
|
79
|
+
try {
|
|
80
|
+
options.global = await destPrompt.run()
|
|
81
|
+
} catch {
|
|
82
|
+
console.log(chalk.dim('\n Cancelled.\n'))
|
|
83
|
+
process.exit(0)
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Default when not TTY or when skipped: global
|
|
87
|
+
if (options.global === undefined) options.global = true
|
|
88
|
+
|
|
89
|
+
if (options.global) {
|
|
90
|
+
console.log(chalk.cyan('\n Destination: global (home) — available for all agents/projects\n'))
|
|
91
|
+
} else {
|
|
92
|
+
console.log(chalk.dim('\n Destination: this project only\n'))
|
|
93
|
+
}
|
|
74
94
|
|
|
75
95
|
// 4. Install each selected agent
|
|
76
96
|
const newlyInstalled = []
|
|
@@ -107,10 +127,10 @@ async function checkboxSelect(detected, method, alreadyInstalled = new Set(), op
|
|
|
107
127
|
console.log(chalk.dim(` No adapter for: ${unavailable.map(a => a.name).join(', ')}\n`))
|
|
108
128
|
}
|
|
109
129
|
|
|
110
|
-
const
|
|
130
|
+
const scopeLabel = options.global === true ? 'global (home)' : options.global === false ? 'this project' : 'choose in next step'
|
|
111
131
|
const prompt = new MultiSelect({
|
|
112
132
|
name: 'agents',
|
|
113
|
-
message: `Select adapters to install (destination: ${
|
|
133
|
+
message: `Select adapters to install (destination: ${scopeLabel})`,
|
|
114
134
|
choices: available.map(a => ({
|
|
115
135
|
name: a.key,
|
|
116
136
|
message: `${a.name}${alreadyInstalled.has(a.key) ? ' — installed' : ' — new'}${!method.adapters[a.key] ? ' (generic)' : ''}`,
|
package/src/index.js
CHANGED
|
@@ -17,36 +17,42 @@ const require = createRequire(import.meta.url)
|
|
|
17
17
|
const pkg = require('../package.json')
|
|
18
18
|
const VERSION = pkg.version
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
function isNewerVersion (latest, current) {
|
|
21
|
+
const parts = (v) => String(v).replace(/^v/, '').split('.').map(Number)
|
|
22
|
+
const a = parts(latest)
|
|
23
|
+
const b = parts(current)
|
|
24
|
+
for (let i = 0; i < Math.max(a.length, b.length); i++) {
|
|
25
|
+
const x = a[i] || 0
|
|
26
|
+
const y = b[i] || 0
|
|
27
|
+
if (x > y) return true
|
|
28
|
+
if (x < y) return false
|
|
29
|
+
}
|
|
30
|
+
return false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// ── Version check (every command) ─────────────────────────────────────────────
|
|
34
|
+
// Shows warning if a newer enet is on npm; never blocks, never crashes if offline
|
|
22
35
|
|
|
23
|
-
async function checkForUpdate() {
|
|
36
|
+
async function checkForUpdate () {
|
|
24
37
|
try {
|
|
25
|
-
const res = await fetch(
|
|
26
|
-
'https://registry.npmjs.org/@exchanet/enet/latest',
|
|
27
|
-
{ signal: AbortSignal.timeout(3000) }
|
|
28
|
-
)
|
|
38
|
+
const res = await fetch('https://registry.npmjs.org/@exchanet/enet/latest', { signal: AbortSignal.timeout(3000) })
|
|
29
39
|
if (!res.ok) return
|
|
30
40
|
const data = await res.json()
|
|
31
|
-
const latest = data
|
|
32
|
-
if (latest && latest
|
|
41
|
+
const latest = data?.version
|
|
42
|
+
if (latest && isNewerVersion(latest, VERSION)) {
|
|
33
43
|
console.log(
|
|
34
|
-
chalk.yellow(' ⚠
|
|
35
|
-
chalk.dim(`v${VERSION}`) +
|
|
36
|
-
chalk.
|
|
37
|
-
chalk.
|
|
38
|
-
chalk.dim(' Run ') +
|
|
39
|
-
chalk.white('npm install -g @exchanet/enet') +
|
|
40
|
-
chalk.dim(' to update.\n')
|
|
44
|
+
chalk.yellow(' ⚠ Warning: a newer version of enet is available.\n') +
|
|
45
|
+
chalk.dim(` Current: v${VERSION} → Latest: v${latest}\n`) +
|
|
46
|
+
chalk.dim(' Update: ') +
|
|
47
|
+
chalk.white('npm install -g @exchanet/enet\n')
|
|
41
48
|
)
|
|
42
49
|
}
|
|
43
50
|
} catch {
|
|
44
|
-
// Offline or
|
|
51
|
+
// Offline or timeout — skip silently
|
|
45
52
|
}
|
|
46
53
|
}
|
|
47
54
|
|
|
48
|
-
|
|
49
|
-
checkForUpdate()
|
|
55
|
+
await checkForUpdate()
|
|
50
56
|
|
|
51
57
|
// ── Header ────────────────────────────────────────────────────────────────────
|
|
52
58
|
|
|
@@ -61,9 +67,10 @@ program
|
|
|
61
67
|
|
|
62
68
|
program
|
|
63
69
|
.command('install <method>')
|
|
64
|
-
.description('Install a method
|
|
70
|
+
.description('Install a method (default: global; use -p for this project only)')
|
|
65
71
|
.option('-a, --agent <agent>', 'Force agent: cursor | windsurf | antigravity | claudecode | copilot | generic')
|
|
66
|
-
.option('-g, --global', 'Install globally
|
|
72
|
+
.option('-g, --global', 'Install globally (default) — available for all agents/projects')
|
|
73
|
+
.option('-p, --project', 'Install only in current project')
|
|
67
74
|
.option('--all', 'Install for all detected agents without prompting')
|
|
68
75
|
.action(installCommand)
|
|
69
76
|
|