Skip to content

Commit c323719

Browse files
committed
feat: add gmn1 command and bump version to 3.3.17
1 parent 04f0c30 commit c323719

File tree

7 files changed

+69
-25
lines changed

7 files changed

+69
-25
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ccmam",
3-
"version": "3.3.16",
3+
"version": "3.3.17",
44
"private": true,
55
"description": "Manage Codex, Claude Code, Gemini CLI, and MCP API service provider configurations",
66
"scripts": {

packages/aicoding/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@2ue/aicoding",
3-
"version": "3.3.16",
3+
"version": "3.3.17",
44
"description": "一键配置 GMN 到 Codex、OpenCode、OpenClaw",
55
"type": "module",
66
"bin": {

packages/cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "ccman",
3-
"version": "3.3.16",
3+
"version": "3.3.17",
44
"type": "module",
55
"description": "Manage Codex, Claude Code, Gemini CLI, OpenCode, OpenClaw, and MCP API service provider configurations",
66
"main": "./dist/index.js",

packages/cli/src/commands/gmn.ts

Lines changed: 53 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,23 @@ const VALID_PLATFORMS = ['codex', 'opencode', 'openclaw'] as const
2222
type Platform = (typeof VALID_PLATFORMS)[number]
2323
const DEFAULT_PLATFORMS: Platform[] = ['codex', 'opencode']
2424

25-
const GMN_OPENAI_BASE_URL = 'https://gmn.chuangzuoli.com'
26-
const GMN_OPENCLAW_BASE_URL = 'https://gmn.chuangzuoli.com/v1'
25+
interface GmnProfile {
26+
commandName: 'gmn' | 'gmn1'
27+
title: string
28+
openaiBaseUrl: string
29+
}
30+
31+
const GMN_PROFILE: GmnProfile = {
32+
commandName: 'gmn',
33+
title: 'GMN',
34+
openaiBaseUrl: 'https://gmn.chuangzuoli.com',
35+
}
36+
37+
const GMN1_PROFILE: GmnProfile = {
38+
commandName: 'gmn1',
39+
title: 'GMN1',
40+
openaiBaseUrl: 'https://gmncode.cn',
41+
}
2742

2843
const TOTAL_STEPS = 3
2944

@@ -34,7 +49,7 @@ function renderStep(current: number, total: number, title: string): string {
3449
return `步骤 ${current}/${total} [${bar}] ${title}`
3550
}
3651

37-
function printBanner(): void {
52+
function printBanner(title: string): void {
3853
printLogo()
3954
console.log(
4055
chalk.cyanBright(
@@ -45,7 +60,7 @@ function printBanner(): void {
4560
' ██║ ██║ ██║╚██╔╝██║██║╚██╗██║',
4661
' ╚██████╔╝ ██║ ╚═╝ ██║██║ ╚████║',
4762
' ╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝',
48-
' CCMAN GMN 一键配置向导',
63+
` CCMAN ${title} 一键配置向导`,
4964
].join('\n')
5065
)
5166
)
@@ -108,12 +123,12 @@ function parsePlatforms(platformArg: string): Platform[] {
108123
return platforms as Platform[]
109124
}
110125

111-
async function promptApiKey(): Promise<string> {
126+
async function promptApiKey(title: string): Promise<string> {
112127
const answers = await inquirer.prompt([
113128
{
114129
type: 'password',
115130
name: 'apiKey',
116-
message: '请输入 GMN API Key:',
131+
message: `请输入 ${title} API Key:`,
117132
mask: '*',
118133
validate: (value) => {
119134
if (!value?.trim()) return 'API Key 不能为空'
@@ -124,7 +139,7 @@ async function promptApiKey(): Promise<string> {
124139
return (answers.apiKey as string).trim()
125140
}
126141

127-
async function promptPlatforms(): Promise<Platform[]> {
142+
async function promptPlatforms(title: string): Promise<Platform[]> {
128143
const answers = await inquirer.prompt([
129144
{
130145
type: 'checkbox',
@@ -134,7 +149,7 @@ async function promptPlatforms(): Promise<Platform[]> {
134149
choices: [
135150
{ name: 'Codex(需单独订阅 OpenAI 套餐)', value: 'codex' },
136151
{ name: 'OpenCode(与 Codex 共享 OpenAI 套餐)', value: 'opencode' },
137-
{ name: 'OpenClaw(GMN /v1 端点,默认不选中)', value: 'openclaw' },
152+
{ name: `OpenClaw(${title} /v1 端点,默认不选中)`, value: 'openclaw' },
138153
{ name: '全部(将依次配置 Codex、OpenCode、OpenClaw)', value: 'all' },
139154
],
140155
default: DEFAULT_PLATFORMS,
@@ -152,11 +167,11 @@ async function promptPlatforms(): Promise<Platform[]> {
152167
return selected as Platform[]
153168
}
154169

155-
async function resolvePlatforms(platformArg?: string): Promise<Platform[]> {
170+
async function resolvePlatforms(platformArg?: string, title = 'GMN'): Promise<Platform[]> {
156171
if (platformArg && platformArg.trim().length > 0) {
157172
return parsePlatforms(platformArg)
158173
}
159-
return promptPlatforms()
174+
return promptPlatforms(title)
160175
}
161176

162177
function resolveProviderName(providerNameArg?: string): string {
@@ -277,14 +292,24 @@ function rollbackFromBackupOrThrow(result: PlatformBackupResult): void {
277292
}
278293
}
279294

280-
export async function gmnCommand(apiKey?: string, platformArg?: string, providerNameArg?: string) {
281-
printBanner()
295+
function buildOpenClawBaseUrl(openaiBaseUrl: string): string {
296+
const normalized = openaiBaseUrl.replace(/\/+$/, '')
297+
return `${normalized}/v1`
298+
}
299+
300+
async function runGmnCommand(
301+
profile: GmnProfile,
302+
apiKey?: string,
303+
platformArg?: string,
304+
providerNameArg?: string
305+
) {
306+
printBanner(profile.title)
282307

283308
let platforms: Platform[]
284309
let providerName: string
285310
try {
286311
console.log(chalk.cyan(`\n${renderStep(1, TOTAL_STEPS, '选择要配置的工具')}`))
287-
platforms = await resolvePlatforms(platformArg)
312+
platforms = await resolvePlatforms(platformArg, profile.title)
288313
providerName = resolveProviderName(providerNameArg)
289314
} catch (error) {
290315
console.error(chalk.red(`❌ ${(error as Error).message}`))
@@ -297,7 +322,7 @@ export async function gmnCommand(apiKey?: string, platformArg?: string, provider
297322
let resolvedApiKey = apiKey?.trim()
298323
console.log(chalk.cyan(`\n${renderStep(2, TOTAL_STEPS, '输入 API Key')}`))
299324
if (!resolvedApiKey) {
300-
resolvedApiKey = await promptApiKey()
325+
resolvedApiKey = await promptApiKey(profile.title)
301326
} else {
302327
console.log(chalk.gray('已通过参数提供 API Key(已隐藏)'))
303328
}
@@ -307,11 +332,12 @@ export async function gmnCommand(apiKey?: string, platformArg?: string, provider
307332
process.exit(1)
308333
}
309334

310-
const openaiBaseUrl = GMN_OPENAI_BASE_URL
335+
const openaiBaseUrl = profile.openaiBaseUrl
336+
const openclawBaseUrl = buildOpenClawBaseUrl(openaiBaseUrl)
311337
const platformBaseUrls: Record<Platform, string> = {
312338
codex: openaiBaseUrl,
313339
opencode: openaiBaseUrl,
314-
openclaw: GMN_OPENCLAW_BASE_URL,
340+
openclaw: openclawBaseUrl,
315341
}
316342

317343
console.log(chalk.cyan(`\n${renderStep(3, TOTAL_STEPS, '开始写入配置')}`))
@@ -320,15 +346,15 @@ export async function gmnCommand(apiKey?: string, platformArg?: string, provider
320346
console.log(chalk.gray(`OpenAI Base URL: ${openaiBaseUrl}`))
321347
}
322348
if (platforms.includes('openclaw')) {
323-
console.log(chalk.gray(`OpenClaw Base URL: ${GMN_OPENCLAW_BASE_URL}`))
349+
console.log(chalk.gray(`OpenClaw Base URL: ${openclawBaseUrl}`))
324350
}
325351
printWriteTargets(platforms)
326352
console.log()
327353

328354
const backupRootDir = path.join(
329355
getCcmanDir(),
330356
'backups',
331-
`gmn-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
357+
`${profile.commandName}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
332358
)
333359
fs.mkdirSync(backupRootDir, { recursive: true, mode: 0o700 })
334360
console.log(chalk.gray(`备份根目录: ${backupRootDir}`))
@@ -400,7 +426,7 @@ export async function gmnCommand(apiKey?: string, platformArg?: string, provider
400426
}
401427
}
402428

403-
console.log(chalk.green(`\n🎉 GMN 配置完成!(${completed}/${tools.length})`))
429+
console.log(chalk.green(`\n🎉 ${profile.title} 配置完成!(${completed}/${tools.length})`))
404430
console.log()
405431
console.log(chalk.bold('备份信息:'))
406432
if (successBackups.length === 0) {
@@ -419,3 +445,11 @@ export async function gmnCommand(apiKey?: string, platformArg?: string, provider
419445
}
420446
console.log(chalk.gray('提示:请重启对应工具/插件以使配置生效。'))
421447
}
448+
449+
export async function gmnCommand(apiKey?: string, platformArg?: string, providerNameArg?: string) {
450+
await runGmnCommand(GMN_PROFILE, apiKey, platformArg, providerNameArg)
451+
}
452+
453+
export async function gmn1Command(apiKey?: string, platformArg?: string, providerNameArg?: string) {
454+
await runGmnCommand(GMN1_PROFILE, apiKey, platformArg, providerNameArg)
455+
}

packages/cli/src/index.ts

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { createOpenClawCommands } from './commands/openclaw/index.js'
1212
import { createSyncCommands, startSyncMenu } from './commands/sync/index.js'
1313
import { exportCommand } from './commands/export.js'
1414
import { importCommand } from './commands/import.js'
15-
import { gmnCommand } from './commands/gmn.js'
15+
import { gmn1Command, gmnCommand } from './commands/gmn.js'
1616
import {
1717
startMainMenu,
1818
startClaudeMenu,
@@ -74,6 +74,7 @@ program.on('command:*', (operands) => {
7474
'export',
7575
'import',
7676
'gmn',
77+
'gmn1',
7778
]
7879
const suggestions = availableCommands.filter(
7980
(cmd) => cmd.includes(unknownCommand) || unknownCommand.includes(cmd)
@@ -175,6 +176,15 @@ program
175176
await gmnCommand(apiKey, options.platform, options.name)
176177
})
177178

179+
program
180+
.command('gmn1 [apiKey]')
181+
.description('配置 GMN1 到 Codex、OpenCode、OpenClaw(默认 URL: https://gmncode.cn)')
182+
.option('-p, --platform <platforms>', '指定平台 (codex,opencode,openclaw,all)')
183+
.option('-n, --name <providerName>', '指定服务商名称(默认: gmn)')
184+
.action(async (apiKey, options) => {
185+
await gmn1Command(apiKey, options.platform, options.name)
186+
})
187+
178188
// 如果没有提供任何命令,显示 logo 并进入交互模式
179189
;(async () => {
180190
if (!process.argv.slice(2).length) {

packages/core/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ccman/core",
3-
"version": "3.3.16",
3+
"version": "3.3.17",
44
"type": "module",
55
"description": "Core business logic for ccman - Manage Codex, Claude Code, Gemini CLI, OpenCode, OpenClaw, and MCP configurations",
66
"main": "./dist/index.js",

packages/desktop/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@ccman/desktop",
3-
"version": "3.3.16",
3+
"version": "3.3.17",
44
"description": "ccman Desktop GUI application",
55
"main": "./dist/main/index.js",
66
"scripts": {

0 commit comments

Comments
 (0)