lingyao-ai 0.2.1 → 0.2.2
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/README.md +5 -0
- package/cli.js +36 -9
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,6 +5,7 @@ A customizable setup CLI that behaves like `npx leishen-ai`, with your own confi
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- Configure Codex and/or Claude Code in one interactive flow.
|
|
8
|
+
- Prompt for gateway URL first, then API key, with a config default.
|
|
8
9
|
- Optional auto-install checks for `@openai/codex` and `@anthropic-ai/claude-code`.
|
|
9
10
|
- API key validation supports `sk-` and `cr_` formats.
|
|
10
11
|
- Writes and backs up:
|
|
@@ -52,3 +53,7 @@ Then users can run:
|
|
|
52
53
|
```bash
|
|
53
54
|
npx lingyao-ai
|
|
54
55
|
```
|
|
56
|
+
|
|
57
|
+
During setup, the CLI will ask for a gateway URL first. Press Enter to use
|
|
58
|
+
`project.config.json`'s default `endpoints.baseOrigin`, or enter a different
|
|
59
|
+
`http://` / `https://` URL before providing the API key.
|
package/cli.js
CHANGED
|
@@ -257,6 +257,32 @@ async function promptApiKey(apiKeyRegex, example) {
|
|
|
257
257
|
}
|
|
258
258
|
}
|
|
259
259
|
|
|
260
|
+
function isValidHttpUrl(value) {
|
|
261
|
+
try {
|
|
262
|
+
const parsed = new URL(String(value || '').trim())
|
|
263
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:'
|
|
264
|
+
} catch (_) {
|
|
265
|
+
return false
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
function normalizeBaseOrigin(value) {
|
|
270
|
+
return String(value || '').trim().replace(/\/+$/, '')
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async function promptBaseOrigin(defaultBaseOrigin) {
|
|
274
|
+
const fallback = normalizeBaseOrigin(defaultBaseOrigin)
|
|
275
|
+
|
|
276
|
+
while (true) {
|
|
277
|
+
const answer = await askLine(
|
|
278
|
+
fallback ? `Input gateway URL [${fallback}]: ` : 'Input gateway URL: '
|
|
279
|
+
)
|
|
280
|
+
const baseOrigin = normalizeBaseOrigin(answer || fallback)
|
|
281
|
+
if (isValidHttpUrl(baseOrigin)) return baseOrigin
|
|
282
|
+
console.log('Invalid URL. Use http:// or https://')
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
260
286
|
async function promptTargets() {
|
|
261
287
|
while (true) {
|
|
262
288
|
console.log('\nSelect target:')
|
|
@@ -684,8 +710,8 @@ function tomlString(value) {
|
|
|
684
710
|
return String(value).replace(/\\/g, '\\\\').replace(/"/g, '\\"')
|
|
685
711
|
}
|
|
686
712
|
|
|
687
|
-
function renderCodexToml(cfg) {
|
|
688
|
-
const codexBaseUrl = joinUrl(
|
|
713
|
+
function renderCodexToml(cfg, baseOrigin) {
|
|
714
|
+
const codexBaseUrl = joinUrl(baseOrigin, cfg.endpoints.codexPath)
|
|
689
715
|
const provider = cfg.codex.providerName
|
|
690
716
|
const migrations = Object.entries(cfg.codex.modelMigrations || {})
|
|
691
717
|
const migrationSection =
|
|
@@ -713,11 +739,11 @@ requires_openai_auth = ${cfg.codex.requiresOpenAIAuth ? 'true' : 'false'}
|
|
|
713
739
|
env_key = "${tomlString(cfg.apiKey.envKey)}"${envInstructionLine}${migrationSection}`
|
|
714
740
|
}
|
|
715
741
|
|
|
716
|
-
function configureClaude(cfg, apiKey) {
|
|
742
|
+
function configureClaude(cfg, apiKey, baseOrigin) {
|
|
717
743
|
const home = os.homedir()
|
|
718
744
|
const claudeConfigPath = path.join(home, cfg.claude.configPath)
|
|
719
745
|
const info = writeJson(claudeConfigPath, { primaryApiKey: cfg.claude.primaryApiKey })
|
|
720
|
-
const claudeBaseUrl = joinUrl(
|
|
746
|
+
const claudeBaseUrl = joinUrl(baseOrigin, cfg.endpoints.claudePath)
|
|
721
747
|
|
|
722
748
|
return {
|
|
723
749
|
env: {
|
|
@@ -734,14 +760,14 @@ function configureClaude(cfg, apiKey) {
|
|
|
734
760
|
}
|
|
735
761
|
}
|
|
736
762
|
|
|
737
|
-
function configureCodex(cfg, apiKey) {
|
|
763
|
+
function configureCodex(cfg, apiKey, baseOrigin) {
|
|
738
764
|
const home = os.homedir()
|
|
739
765
|
const codexDir = path.join(home, cfg.codex.configDir)
|
|
740
766
|
const tomlPath = path.join(codexDir, 'config.toml')
|
|
741
767
|
const authPath = path.join(codexDir, 'auth.json')
|
|
742
768
|
const envPath = path.join(codexDir, '.env')
|
|
743
769
|
|
|
744
|
-
const tomlInfo = writeText(tomlPath, renderCodexToml(cfg))
|
|
770
|
+
const tomlInfo = writeText(tomlPath, renderCodexToml(cfg, baseOrigin))
|
|
745
771
|
const authInfo = writeJson(authPath, cfg.codex.authJson || { OPENAI_API_KEY: null })
|
|
746
772
|
const envInfo = upsertDotenvFile(envPath, { [cfg.apiKey.envKey]: apiKey })
|
|
747
773
|
|
|
@@ -775,8 +801,9 @@ async function main() {
|
|
|
775
801
|
|
|
776
802
|
console.log(`\n${cfg.brand.name}`)
|
|
777
803
|
console.log(`Config file: ${configPath}`)
|
|
778
|
-
console.log(`Base origin: ${cfg.endpoints.baseOrigin}`)
|
|
779
804
|
|
|
805
|
+
const baseOrigin = await promptBaseOrigin(cfg.endpoints.baseOrigin)
|
|
806
|
+
console.log(`Using gateway URL: ${baseOrigin}`)
|
|
780
807
|
const apiKeyRegex = new RegExp(cfg.apiKey.regex)
|
|
781
808
|
const apiKey = await promptApiKey(apiKeyRegex, cfg.apiKey.example)
|
|
782
809
|
const targets = await promptTargets()
|
|
@@ -811,13 +838,13 @@ async function main() {
|
|
|
811
838
|
const fileSummaries = []
|
|
812
839
|
|
|
813
840
|
if (targets.includes('claude')) {
|
|
814
|
-
const result = configureClaude(cfg, apiKey)
|
|
841
|
+
const result = configureClaude(cfg, apiKey, baseOrigin)
|
|
815
842
|
envVars = { ...envVars, ...result.env }
|
|
816
843
|
fileSummaries.push(...result.files)
|
|
817
844
|
}
|
|
818
845
|
|
|
819
846
|
if (targets.includes('codex')) {
|
|
820
|
-
const result = configureCodex(cfg, apiKey)
|
|
847
|
+
const result = configureCodex(cfg, apiKey, baseOrigin)
|
|
821
848
|
envVars = { ...envVars, ...result.env }
|
|
822
849
|
fileSummaries.push(...result.files)
|
|
823
850
|
|