@2api-store/activate 0.3.1 → 0.3.3
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/activate.mjs +21 -8
- package/lib/detect.mjs +4 -2
- package/lib/install.mjs +9 -4
- package/lib/platforms.mjs +1 -1
- package/lib/render.mjs +15 -2
- package/lib/ui.mjs +2 -1
- package/package.json +1 -1
package/activate.mjs
CHANGED
|
@@ -30,11 +30,12 @@ import {
|
|
|
30
30
|
confirm,
|
|
31
31
|
closePrompt,
|
|
32
32
|
} from './lib/prompt.mjs'
|
|
33
|
-
import { banner, ok, fail, warn, info, step, guide, plain } from './lib/ui.mjs'
|
|
33
|
+
import { banner, ok, fail, warn, info, step, guide, plain, chalk } from './lib/ui.mjs'
|
|
34
34
|
import { getCliMeta, isDefaultSelected } from './lib/platforms.mjs'
|
|
35
35
|
import { ensureInstalled } from './lib/install.mjs'
|
|
36
36
|
|
|
37
|
-
|
|
37
|
+
import { createRequire } from 'node:module'
|
|
38
|
+
const VERSION = createRequire(import.meta.url)('./package.json').version
|
|
38
39
|
const DEFAULT_API_BASE = 'https://2api.store'
|
|
39
40
|
|
|
40
41
|
// ============================================================
|
|
@@ -243,10 +244,10 @@ async function main() {
|
|
|
243
244
|
const meta = getCliMeta(c.client_type)
|
|
244
245
|
const displayName = c.display_name || c.displayName || meta?.name || `${c.platform} ${c.client_type}`
|
|
245
246
|
const installed = env.installed[c.client_type]?.path || (meta && env.installed[meta.detectBin]?.path)
|
|
246
|
-
const installMark = installed ? '✓' : '✗'
|
|
247
247
|
const primaryMark = isDefaultSelected(c.client_type) ? '' : '(独立 CLI)'
|
|
248
|
+
const nameColored = installed ? chalk.green(displayName) : chalk.gray(`${displayName} (未装)`)
|
|
248
249
|
cliItems.push({
|
|
249
|
-
label:
|
|
250
|
+
label: `${nameColored} ${chalk.dim(`[${c.platform}/${c.client_type}]`)}${primaryMark}`,
|
|
250
251
|
config: c,
|
|
251
252
|
clientType: c.client_type,
|
|
252
253
|
meta,
|
|
@@ -262,7 +263,7 @@ async function main() {
|
|
|
262
263
|
|
|
263
264
|
step('选择 CLI')
|
|
264
265
|
const selectedIdxes = await multiSelect(
|
|
265
|
-
'选择要激活的 CLI
|
|
266
|
+
'选择要激活的 CLI(绿色=已装,灰色=未装;默认选主 CLI,独立 CLI 默认不选)',
|
|
266
267
|
cliItems,
|
|
267
268
|
{ defaultSelected },
|
|
268
269
|
)
|
|
@@ -306,10 +307,22 @@ async function main() {
|
|
|
306
307
|
const modelItems = listModels(bundle.models || [])
|
|
307
308
|
let defaultModelId = ''
|
|
308
309
|
if (modelItems.length > 0) {
|
|
309
|
-
step('
|
|
310
|
-
const
|
|
310
|
+
step('选择默认模型(最新优先)')
|
|
311
|
+
const TOP_N = 10
|
|
312
|
+
const topItems = modelItems.slice(0, TOP_N)
|
|
313
|
+
const hasMore = modelItems.length > TOP_N
|
|
314
|
+
const selectItems = [
|
|
315
|
+
...topItems.map((m) => ({ label: `${m.label} (${m.id})` })),
|
|
316
|
+
...(hasMore ? [{ label: chalk.dim('其他(手动输入模型 ID)') }] : []),
|
|
317
|
+
]
|
|
311
318
|
const idx = await select('选择默认模型', selectItems, { defaultIndex: 0 })
|
|
312
|
-
|
|
319
|
+
if (hasMore && idx === topItems.length) {
|
|
320
|
+
// 手动输入
|
|
321
|
+
defaultModelId = (await ask('输入模型 ID(如 gpt-5.6-terra)')).trim()
|
|
322
|
+
if (!defaultModelId) defaultModelId = topItems[0].id
|
|
323
|
+
} else {
|
|
324
|
+
defaultModelId = topItems[idx].id
|
|
325
|
+
}
|
|
313
326
|
ok(`已选默认模型:${defaultModelId}`)
|
|
314
327
|
} else {
|
|
315
328
|
warn('服务端未返回模型列表,{{defaultModel}} 将留空')
|
package/lib/detect.mjs
CHANGED
|
@@ -62,11 +62,13 @@ function findBinary(name, isWindows) {
|
|
|
62
62
|
function getVersion(bin, isWindows) {
|
|
63
63
|
// --version 是通用约定;codex/claude/gemini/opencode/grok 都支持
|
|
64
64
|
try {
|
|
65
|
-
const
|
|
65
|
+
const cmdBin = isWindows ? process.env.COMSPEC || 'cmd.exe' : bin
|
|
66
|
+
const cmdArgs = isWindows ? ['/c', bin, '--version'] : ['--version']
|
|
67
|
+
const result = spawnSync(cmdBin, cmdArgs, {
|
|
66
68
|
encoding: 'utf8',
|
|
67
69
|
stdio: ['ignore', 'pipe', 'pipe'],
|
|
68
70
|
timeout: 5000,
|
|
69
|
-
//
|
|
71
|
+
// Windows: CLI 是 <bin>.cmd batch,必须经 cmd.exe /c 解析;不用 shell:true(DEP0190)
|
|
70
72
|
})
|
|
71
73
|
if (result.status === 0 && result.stdout) {
|
|
72
74
|
const firstLine = result.stdout.trim().split(/\r?\n/)[0]
|
package/lib/install.mjs
CHANGED
|
@@ -38,15 +38,20 @@ export function installCLI(meta, opts = {}) {
|
|
|
38
38
|
|
|
39
39
|
console.log(` 正在执行:${cmd}…`)
|
|
40
40
|
try {
|
|
41
|
-
const
|
|
41
|
+
const isWin = process.platform === 'win32'
|
|
42
|
+
const npmBin = isWin ? process.env.COMSPEC || 'cmd.exe' : 'npm'
|
|
43
|
+
const npmArgs = isWin ? ['/c', 'npm', 'install', '-g', pkg] : ['install', '-g', pkg]
|
|
44
|
+
const result = spawnSync(npmBin, npmArgs, {
|
|
42
45
|
stdio: 'inherit', // npm 进度/输出直接透传到当前终端
|
|
43
|
-
//
|
|
46
|
+
// Windows: npm 是 npm.cmd batch,必须经 cmd.exe /c 解析;不用 shell:true(node 22+ DEP0190)
|
|
44
47
|
})
|
|
48
|
+
if (result.error) {
|
|
49
|
+
return { ok: false, error: result.error.message }
|
|
50
|
+
}
|
|
45
51
|
if (result.status === 0) {
|
|
46
52
|
return { ok: true }
|
|
47
53
|
}
|
|
48
|
-
|
|
49
|
-
return { ok: false, error: errText }
|
|
54
|
+
return { ok: false, error: `npm exit ${result.status}` }
|
|
50
55
|
} catch (err) {
|
|
51
56
|
return { ok: false, error: err.message }
|
|
52
57
|
}
|
package/lib/platforms.mjs
CHANGED
|
@@ -53,7 +53,7 @@ export const CLI_META = {
|
|
|
53
53
|
' codex --sandbox read-only --ask-for-approval never 只读(最安全)',
|
|
54
54
|
' codex --help 查看所有选项',
|
|
55
55
|
].join('\n'),
|
|
56
|
-
isPrimary:
|
|
56
|
+
isPrimary: false, // codex 的 WebSocket 变体(同 CLI 同 config.toml,默认不选避免覆盖 codex 模式)
|
|
57
57
|
},
|
|
58
58
|
claude: {
|
|
59
59
|
name: 'Claude Code',
|
package/lib/render.mjs
CHANGED
|
@@ -63,14 +63,20 @@ export function expandPath(p, { isWindows } = {}) {
|
|
|
63
63
|
return p
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
+
// 模型版本解析(gpt-5.6-sol → [5,6],gpt-oss-safeguard → [0,0] 旧)用于倒序排序(最新在前)
|
|
67
|
+
function modelVersion(id) {
|
|
68
|
+
const m = String(id || '').toLowerCase().match(/(\d+)\.(\d+)/)
|
|
69
|
+
return m ? [parseInt(m[1], 10), parseInt(m[2], 10)] : [0, 0]
|
|
70
|
+
}
|
|
71
|
+
|
|
66
72
|
/**
|
|
67
|
-
* 将 models 数组规整为 {id, label}
|
|
73
|
+
* 将 models 数组规整为 {id, label} 列表,按版本倒序排序(最新在前),供选择展示用
|
|
68
74
|
* @param {Array<{id?: string, name?: string}|string>} models
|
|
69
75
|
* @returns {Array<{index: number, id: string, label: string, raw: any}>}
|
|
70
76
|
*/
|
|
71
77
|
export function listModels(models) {
|
|
72
78
|
if (!Array.isArray(models) || models.length === 0) return []
|
|
73
|
-
|
|
79
|
+
const items = models.map((m, i) => {
|
|
74
80
|
if (typeof m === 'string') {
|
|
75
81
|
return { index: i, id: m, label: m, raw: m }
|
|
76
82
|
}
|
|
@@ -78,4 +84,11 @@ export function listModels(models) {
|
|
|
78
84
|
const label = m.name || m.id || id
|
|
79
85
|
return { index: i, id, label, raw: m }
|
|
80
86
|
})
|
|
87
|
+
// 版本倒序(最新在前);同版本按 id 字母序
|
|
88
|
+
items.sort((a, b) => {
|
|
89
|
+
const va = modelVersion(a.id)
|
|
90
|
+
const vb = modelVersion(b.id)
|
|
91
|
+
return vb[0] - va[0] || vb[1] - va[1] || String(a.id).localeCompare(String(b.id))
|
|
92
|
+
})
|
|
93
|
+
return items
|
|
81
94
|
}
|
package/lib/ui.mjs
CHANGED