mirror of
https://github.com/Nezumi-2711/9router-config-generate.git
synced 2026-09-22 13:38:32 +00:00
fix: update the script build
This commit is contained in:
@@ -28,7 +28,7 @@ export const ConfigPreview: React.FC<ConfigPreviewProps> = ({
|
|||||||
|
|
||||||
const configContent = tool.sampleTemplate(connection, selectedModels)
|
const configContent = tool.sampleTemplate(connection, selectedModels)
|
||||||
const installScript = buildInstallScript(tool, connection, selectedModels, selectedOS, {
|
const installScript = buildInstallScript(tool, connection, selectedModels, selectedOS, {
|
||||||
keySource: 'runtime-env',
|
keySource: connection.apiKey ? 'embedded' : 'runtime-env',
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleCopyConfig = async () => {
|
const handleCopyConfig = async () => {
|
||||||
@@ -182,14 +182,10 @@ export const ConfigPreview: React.FC<ConfigPreviewProps> = ({
|
|||||||
<div className="flex flex-col gap-2 p-3 rounded-lg bg-amber-500/10 border border-amber-500/20 text-xs text-left">
|
<div className="flex flex-col gap-2 p-3 rounded-lg bg-amber-500/10 border border-amber-500/20 text-xs text-left">
|
||||||
<div className="flex items-center gap-2 font-semibold text-amber-800 dark:text-amber-300">
|
<div className="flex items-center gap-2 font-semibold text-amber-800 dark:text-amber-300">
|
||||||
<Key className="w-4 h-4 text-amber-600 dark:text-amber-400 shrink-0" />
|
<Key className="w-4 h-4 text-amber-600 dark:text-amber-400 shrink-0" />
|
||||||
<span>Secure API Key Storage in VS Code</span>
|
<span>API Key Setup for VS Code</span>
|
||||||
</div>
|
</div>
|
||||||
<p className="text-zinc-600 dark:text-zinc-300 leading-relaxed">
|
<p className="text-zinc-600 dark:text-zinc-300 leading-relaxed">
|
||||||
No API key entered above. The generated config uses{' '}
|
No API key entered above. Enter your API key under <strong>Gateway Connection</strong> to embed it directly into the config, or use the 1-Command installer which will prompt you for your key securely during installation.
|
||||||
<code className="px-1 py-0.5 rounded bg-amber-500/15 font-mono text-[11px] text-amber-700 dark:text-amber-300">
|
|
||||||
${'{input:9router-api-key}'}
|
|
||||||
</code>
|
|
||||||
. When VS Code prompts you for <strong className="font-semibold text-zinc-900 dark:text-zinc-100">9router-api-key</strong>, paste your key.
|
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|||||||
+1
-1
@@ -37,7 +37,7 @@ export const tools: Record<ToolId, ToolMeta> = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const endpointUrl = connection.baseUrl.replace(/\/+$/, '') + '/chat/completions'
|
const endpointUrl = connection.baseUrl.replace(/\/+$/, '') + '/chat/completions'
|
||||||
const apiKeyVal = connection.apiKey ? connection.apiKey : '${input:9router-api-key}'
|
const apiKeyVal = connection.apiKey ? connection.apiKey : '<YOUR_9ROUTER_API_KEY>'
|
||||||
|
|
||||||
const groups = Array.from(groupsMap.entries()).map(([provider, models]) => {
|
const groups = Array.from(groupsMap.entries()).map(([provider, models]) => {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import { describe, it, expect } from 'bun:test'
|
import { describe, it, expect } from 'bun:test'
|
||||||
import { encodeInstallToken, decodeInstallToken, buildOneClickCommand } from './installLink'
|
import { encodeInstallToken, decodeInstallToken, buildOneClickCommand } from './installLink'
|
||||||
import { renderInstallScript } from './installEndpoint'
|
import { renderInstallScript } from './installEndpoint'
|
||||||
|
import { buildInstallScript } from './installScript'
|
||||||
import { tools } from '../data/tools'
|
import { tools } from '../data/tools'
|
||||||
|
|
||||||
describe('Install Link & Endpoint', () => {
|
describe('Install Link & Endpoint', () => {
|
||||||
@@ -62,11 +63,44 @@ describe('Install Link & Endpoint', () => {
|
|||||||
expect(shRes.contentType).toContain('text/x-shellscript')
|
expect(shRes.contentType).toContain('text/x-shellscript')
|
||||||
expect(shRes.body).toContain('__NINEROUTER_API_KEY__')
|
expect(shRes.body).toContain('__NINEROUTER_API_KEY__')
|
||||||
expect(shRes.body).toContain('NINEROUTER_API_KEY')
|
expect(shRes.body).toContain('NINEROUTER_API_KEY')
|
||||||
|
expect(shRes.body).toContain('/dev/tty')
|
||||||
|
expect(shRes.body).toContain('exit 1')
|
||||||
|
expect(shRes.body).not.toContain('${input:9router-api-key}')
|
||||||
|
|
||||||
const ps1Res = renderInstallScript(token, 'ps1')
|
const ps1Res = renderInstallScript(token, 'ps1')
|
||||||
expect(ps1Res.status).toBe(200)
|
expect(ps1Res.status).toBe(200)
|
||||||
expect(ps1Res.contentType).toContain('text/plain')
|
expect(ps1Res.contentType).toContain('text/plain')
|
||||||
expect(ps1Res.body).toContain('__NINEROUTER_API_KEY__')
|
expect(ps1Res.body).toContain('__NINEROUTER_API_KEY__')
|
||||||
|
expect(ps1Res.body).toContain('exit 1')
|
||||||
|
expect(ps1Res.body).not.toContain('${input:9router-api-key}')
|
||||||
|
})
|
||||||
|
|
||||||
|
it('builds embedded install script with real API key inline and no prompts', () => {
|
||||||
|
const scriptUnix = buildInstallScript(
|
||||||
|
tools.copilot,
|
||||||
|
{ baseUrl: 'http://localhost:20128/v1', apiKey: 'sk-real-secret-123' },
|
||||||
|
[{ id: 'cc/claude-sonnet-4.5', name: 'Claude Sonnet 4.5' }],
|
||||||
|
'unix',
|
||||||
|
{ keySource: 'embedded' }
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(scriptUnix).not.toBeNull()
|
||||||
|
expect(scriptUnix!.content).toContain('sk-real-secret-123')
|
||||||
|
expect(scriptUnix!.content).not.toContain('__NINEROUTER_API_KEY__')
|
||||||
|
expect(scriptUnix!.content).not.toContain('read -rsp')
|
||||||
|
|
||||||
|
const scriptWin = buildInstallScript(
|
||||||
|
tools.copilot,
|
||||||
|
{ baseUrl: 'http://localhost:20128/v1', apiKey: 'sk-real-secret-123' },
|
||||||
|
[{ id: 'cc/claude-sonnet-4.5', name: 'Claude Sonnet 4.5' }],
|
||||||
|
'windows',
|
||||||
|
{ keySource: 'embedded' }
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(scriptWin).not.toBeNull()
|
||||||
|
expect(scriptWin!.content).toContain('sk-real-secret-123')
|
||||||
|
expect(scriptWin!.content).not.toContain('__NINEROUTER_API_KEY__')
|
||||||
|
expect(scriptWin!.content).not.toContain('Read-Host')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('replaces every API key placeholder in generated runtime scripts', () => {
|
it('replaces every API key placeholder in generated runtime scripts', () => {
|
||||||
|
|||||||
@@ -39,10 +39,14 @@ export function buildInstallScript(
|
|||||||
keySource === 'runtime-env'
|
keySource === 'runtime-env'
|
||||||
? {
|
? {
|
||||||
writeConfigSection: `API_KEY="\${NINEROUTER_API_KEY:-}"
|
writeConfigSection: `API_KEY="\${NINEROUTER_API_KEY:-}"
|
||||||
if [[ -z "$API_KEY" ]]; then
|
if [[ -z "$API_KEY" && -r /dev/tty ]]; then
|
||||||
read -rsp "Enter your 9router API key: " API_KEY
|
read -rsp "Enter your 9router API key: " API_KEY < /dev/tty
|
||||||
echo
|
echo
|
||||||
fi
|
fi
|
||||||
|
if [[ -z "$API_KEY" ]]; then
|
||||||
|
echo "❌ No 9router API key provided (set NINEROUTER_API_KEY or run in an interactive terminal)." >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
CONFIG=$(cat <<'EOF'
|
CONFIG=$(cat <<'EOF'
|
||||||
${configContent}
|
${configContent}
|
||||||
@@ -85,11 +89,7 @@ replace_api_key_placeholder() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ -n "$API_KEY" ]]; then
|
replace_api_key_placeholder "$(json_escape "$API_KEY")"
|
||||||
replace_api_key_placeholder "$(json_escape "$API_KEY")"
|
|
||||||
else
|
|
||||||
replace_api_key_placeholder '\${input:9router-api-key}'
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf '%s\\n' "$CONFIG" > "$TARGET_FILE"`
|
printf '%s\\n' "$CONFIG" > "$TARGET_FILE"`
|
||||||
,
|
,
|
||||||
@@ -165,16 +165,17 @@ if (-not $apiKey) {
|
|||||||
$apiKey = [System.Net.NetworkCredential]::new('', $secureApiKey).Password
|
$apiKey = [System.Net.NetworkCredential]::new('', $secureApiKey).Password
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (-not $apiKey) {
|
||||||
|
Write-Error "No 9router API key provided. Set NINEROUTER_API_KEY or run in an interactive terminal."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
$config = @'
|
$config = @'
|
||||||
${configContent}
|
${configContent}
|
||||||
'@
|
'@
|
||||||
|
|
||||||
if ($apiKey) {
|
$jsonApiKey = ConvertTo-Json -InputObject $apiKey -Compress
|
||||||
$jsonApiKey = ConvertTo-Json -InputObject $apiKey -Compress
|
$config = $config.Replace('"__NINEROUTER_API_KEY__"', $jsonApiKey)
|
||||||
$config = $config.Replace('"__NINEROUTER_API_KEY__"', $jsonApiKey)
|
|
||||||
} else {
|
|
||||||
$config = $config.Replace('"__NINEROUTER_API_KEY__"', '"\${input:9router-api-key}"')
|
|
||||||
}
|
|
||||||
|
|
||||||
Set-Content -Path $targetFile -Value $config -Encoding UTF8`,
|
Set-Content -Path $targetFile -Value $config -Encoding UTF8`,
|
||||||
psPostInstallNotes: `Write-Host ""
|
psPostInstallNotes: `Write-Host ""
|
||||||
|
|||||||
Reference in New Issue
Block a user