mirror of
https://github.com/tiennm99/ccs.git
synced 2026-08-09 12:23:30 +00:00
refactor: rename proxy to cliproxy_server and update API routes
This commit is contained in:
@@ -195,84 +195,6 @@ Without Developer Mode, CCS falls back to copying directories.
|
|||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|
||||||
## Remote Proxy
|
|
||||||
|
|
||||||
Connect to a remote CLIProxyAPI server (Docker, Kubernetes, or another machine) instead of using the local binary.
|
|
||||||
|
|
||||||
### Configuration
|
|
||||||
|
|
||||||
Configure via dashboard (**Settings → Proxy** tab) or `~/.ccs/config.yaml`:
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
proxy:
|
|
||||||
remote:
|
|
||||||
enabled: true
|
|
||||||
host: "192.168.1.100" # Remote server hostname/IP
|
|
||||||
port: 8317 # Default CLIProxy port
|
|
||||||
protocol: http # http or https
|
|
||||||
auth-token: "" # Optional auth token
|
|
||||||
fallback:
|
|
||||||
enabled: true # Fallback to local if remote unreachable
|
|
||||||
auto-start: true # Auto-start local proxy on fallback
|
|
||||||
local:
|
|
||||||
port: 8317
|
|
||||||
auto-start: true
|
|
||||||
```
|
|
||||||
|
|
||||||
### CLI Flags
|
|
||||||
|
|
||||||
Override config for one-time use:
|
|
||||||
|
|
||||||
| Flag | Description |
|
|
||||||
|------|-------------|
|
|
||||||
| `--proxy-host <host>` | Remote proxy hostname/IP |
|
|
||||||
| `--proxy-port <port>` | Proxy port (default: 8317) |
|
|
||||||
| `--proxy-protocol <proto>` | Protocol: `http` or `https` |
|
|
||||||
| `--proxy-auth-token <token>` | Auth token for remote proxy |
|
|
||||||
| `--local-proxy` | Force local mode, ignore remote config |
|
|
||||||
| `--remote-only` | Fail if remote unreachable (no fallback) |
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# One-time remote connection
|
|
||||||
ccs gemini --proxy-host 192.168.1.100 --proxy-port 8317
|
|
||||||
|
|
||||||
# Force local mode
|
|
||||||
ccs gemini --local-proxy
|
|
||||||
|
|
||||||
# Strict remote mode (no fallback)
|
|
||||||
ccs gemini --proxy-host remote.example.com --remote-only
|
|
||||||
```
|
|
||||||
|
|
||||||
### Environment Variables
|
|
||||||
|
|
||||||
For CI/CD and automation:
|
|
||||||
|
|
||||||
| Variable | Description |
|
|
||||||
|----------|-------------|
|
|
||||||
| `CCS_PROXY_HOST` | Remote proxy hostname |
|
|
||||||
| `CCS_PROXY_PORT` | Proxy port |
|
|
||||||
| `CCS_PROXY_PROTOCOL` | Protocol (`http`/`https`) |
|
|
||||||
| `CCS_PROXY_AUTH_TOKEN` | Auth token |
|
|
||||||
| `CCS_PROXY_FALLBACK_ENABLED` | Enable local fallback (`1`/`0`) |
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# Docker example
|
|
||||||
export CCS_PROXY_HOST="cliproxy-container"
|
|
||||||
export CCS_PROXY_PORT="8317"
|
|
||||||
ccs gemini "implement feature"
|
|
||||||
```
|
|
||||||
|
|
||||||
### Priority Resolution
|
|
||||||
|
|
||||||
Configuration sources are merged with this priority (highest first):
|
|
||||||
|
|
||||||
1. **CLI flags** — One-time overrides
|
|
||||||
2. **Environment variables** — CI/CD automation
|
|
||||||
3. **config.yaml** — Persistent settings
|
|
||||||
4. **Defaults** — Local mode, port 8317
|
|
||||||
|
|
||||||
<br>
|
|
||||||
|
|
||||||
## WebSearch
|
## WebSearch
|
||||||
|
|
||||||
Third-party profiles (Gemini, Codex, GLM, etc.) cannot use Anthropic's native WebSearch. CCS automatically configures MCP-based web search as a fallback.
|
Third-party profiles (Gemini, Codex, GLM, etc.) cannot use Anthropic's native WebSearch. CCS automatically configures MCP-based web search as a fallback.
|
||||||
@@ -321,6 +243,7 @@ See [docs/websearch.md](./docs/websearch.md) for detailed configuration and trou
|
|||||||
| OAuth Providers | [docs.ccs.kaitran.ca/providers/oauth-providers](https://docs.ccs.kaitran.ca/providers/oauth-providers) |
|
| OAuth Providers | [docs.ccs.kaitran.ca/providers/oauth-providers](https://docs.ccs.kaitran.ca/providers/oauth-providers) |
|
||||||
| Multi-Account Claude | [docs.ccs.kaitran.ca/providers/claude-accounts](https://docs.ccs.kaitran.ca/providers/claude-accounts) |
|
| Multi-Account Claude | [docs.ccs.kaitran.ca/providers/claude-accounts](https://docs.ccs.kaitran.ca/providers/claude-accounts) |
|
||||||
| API Profiles | [docs.ccs.kaitran.ca/providers/api-profiles](https://docs.ccs.kaitran.ca/providers/api-profiles) |
|
| API Profiles | [docs.ccs.kaitran.ca/providers/api-profiles](https://docs.ccs.kaitran.ca/providers/api-profiles) |
|
||||||
|
| Remote Proxy | [docs.ccs.kaitran.ca/features/remote-proxy](https://docs.ccs.kaitran.ca/features/remote-proxy) |
|
||||||
| CLI Reference | [docs.ccs.kaitran.ca/reference/cli-commands](https://docs.ccs.kaitran.ca/reference/cli-commands) |
|
| CLI Reference | [docs.ccs.kaitran.ca/reference/cli-commands](https://docs.ccs.kaitran.ca/reference/cli-commands) |
|
||||||
| Architecture | [docs.ccs.kaitran.ca/reference/architecture](https://docs.ccs.kaitran.ca/reference/architecture) |
|
| Architecture | [docs.ccs.kaitran.ca/reference/architecture](https://docs.ccs.kaitran.ca/reference/architecture) |
|
||||||
| Troubleshooting | [docs.ccs.kaitran.ca/reference/troubleshooting](https://docs.ccs.kaitran.ca/reference/troubleshooting) |
|
| Troubleshooting | [docs.ccs.kaitran.ca/reference/troubleshooting](https://docs.ccs.kaitran.ca/reference/troubleshooting) |
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
UNIFIED_CONFIG_VERSION,
|
UNIFIED_CONFIG_VERSION,
|
||||||
DEFAULT_COPILOT_CONFIG,
|
DEFAULT_COPILOT_CONFIG,
|
||||||
DEFAULT_GLOBAL_ENV,
|
DEFAULT_GLOBAL_ENV,
|
||||||
DEFAULT_PROXY_CONFIG,
|
DEFAULT_CLIPROXY_SERVER_CONFIG,
|
||||||
GlobalEnvConfig,
|
GlobalEnvConfig,
|
||||||
} from './unified-config-types';
|
} from './unified-config-types';
|
||||||
import { isUnifiedConfigEnabled } from './feature-flags';
|
import { isUnifiedConfigEnabled } from './feature-flags';
|
||||||
@@ -178,22 +178,33 @@ function mergeWithDefaults(partial: Partial<UnifiedConfig>): UnifiedConfig {
|
|||||||
enabled: partial.global_env?.enabled ?? true,
|
enabled: partial.global_env?.enabled ?? true,
|
||||||
env: partial.global_env?.env ?? { ...DEFAULT_GLOBAL_ENV },
|
env: partial.global_env?.env ?? { ...DEFAULT_GLOBAL_ENV },
|
||||||
},
|
},
|
||||||
// Proxy config - remote/local CLIProxyAPI settings
|
// CLIProxy server config - remote/local CLIProxyAPI settings
|
||||||
proxy: {
|
cliproxy_server: {
|
||||||
remote: {
|
remote: {
|
||||||
enabled: partial.proxy?.remote?.enabled ?? DEFAULT_PROXY_CONFIG.remote.enabled,
|
enabled:
|
||||||
host: partial.proxy?.remote?.host ?? DEFAULT_PROXY_CONFIG.remote.host,
|
partial.cliproxy_server?.remote?.enabled ?? DEFAULT_CLIPROXY_SERVER_CONFIG.remote.enabled,
|
||||||
port: partial.proxy?.remote?.port ?? DEFAULT_PROXY_CONFIG.remote.port,
|
host: partial.cliproxy_server?.remote?.host ?? DEFAULT_CLIPROXY_SERVER_CONFIG.remote.host,
|
||||||
protocol: partial.proxy?.remote?.protocol ?? DEFAULT_PROXY_CONFIG.remote.protocol,
|
port: partial.cliproxy_server?.remote?.port ?? DEFAULT_CLIPROXY_SERVER_CONFIG.remote.port,
|
||||||
auth_token: partial.proxy?.remote?.auth_token ?? DEFAULT_PROXY_CONFIG.remote.auth_token,
|
protocol:
|
||||||
|
partial.cliproxy_server?.remote?.protocol ??
|
||||||
|
DEFAULT_CLIPROXY_SERVER_CONFIG.remote.protocol,
|
||||||
|
auth_token:
|
||||||
|
partial.cliproxy_server?.remote?.auth_token ??
|
||||||
|
DEFAULT_CLIPROXY_SERVER_CONFIG.remote.auth_token,
|
||||||
},
|
},
|
||||||
fallback: {
|
fallback: {
|
||||||
enabled: partial.proxy?.fallback?.enabled ?? DEFAULT_PROXY_CONFIG.fallback.enabled,
|
enabled:
|
||||||
auto_start: partial.proxy?.fallback?.auto_start ?? DEFAULT_PROXY_CONFIG.fallback.auto_start,
|
partial.cliproxy_server?.fallback?.enabled ??
|
||||||
|
DEFAULT_CLIPROXY_SERVER_CONFIG.fallback.enabled,
|
||||||
|
auto_start:
|
||||||
|
partial.cliproxy_server?.fallback?.auto_start ??
|
||||||
|
DEFAULT_CLIPROXY_SERVER_CONFIG.fallback.auto_start,
|
||||||
},
|
},
|
||||||
local: {
|
local: {
|
||||||
port: partial.proxy?.local?.port ?? DEFAULT_PROXY_CONFIG.local.port,
|
port: partial.cliproxy_server?.local?.port ?? DEFAULT_CLIPROXY_SERVER_CONFIG.local.port,
|
||||||
auto_start: partial.proxy?.local?.auto_start ?? DEFAULT_PROXY_CONFIG.local.auto_start,
|
auto_start:
|
||||||
|
partial.cliproxy_server?.local?.auto_start ??
|
||||||
|
DEFAULT_CLIPROXY_SERVER_CONFIG.local.auto_start,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -224,10 +224,10 @@ export interface ProxyLocalConfig {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Proxy configuration section.
|
* CLIProxy server configuration section.
|
||||||
* Controls whether CCS uses local or remote CLIProxyAPI instance.
|
* Controls whether CCS uses local or remote CLIProxyAPI instance.
|
||||||
*/
|
*/
|
||||||
export interface ProxyConfig {
|
export interface CliproxyServerConfig {
|
||||||
/** Remote proxy settings */
|
/** Remote proxy settings */
|
||||||
remote: ProxyRemoteConfig;
|
remote: ProxyRemoteConfig;
|
||||||
/** Fallback behavior when remote is unreachable */
|
/** Fallback behavior when remote is unreachable */
|
||||||
@@ -311,8 +311,8 @@ export interface UnifiedConfig {
|
|||||||
global_env?: GlobalEnvConfig;
|
global_env?: GlobalEnvConfig;
|
||||||
/** Copilot API configuration (GitHub Copilot proxy) */
|
/** Copilot API configuration (GitHub Copilot proxy) */
|
||||||
copilot?: CopilotConfig;
|
copilot?: CopilotConfig;
|
||||||
/** Proxy configuration for remote/local CLIProxyAPI */
|
/** CLIProxy server configuration for remote/local mode */
|
||||||
proxy?: ProxyConfig;
|
cliproxy_server?: CliproxyServerConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -343,10 +343,10 @@ export const DEFAULT_COPILOT_CONFIG: CopilotConfig = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default proxy configuration.
|
* Default CLIProxy server configuration.
|
||||||
* Local mode by default - remote must be explicitly enabled.
|
* Local mode by default - remote must be explicitly enabled.
|
||||||
*/
|
*/
|
||||||
export const DEFAULT_PROXY_CONFIG: ProxyConfig = {
|
export const DEFAULT_CLIPROXY_SERVER_CONFIG: CliproxyServerConfig = {
|
||||||
remote: {
|
remote: {
|
||||||
enabled: false,
|
enabled: false,
|
||||||
host: '',
|
host: '',
|
||||||
@@ -411,7 +411,7 @@ export function createEmptyUnifiedConfig(): UnifiedConfig {
|
|||||||
env: { ...DEFAULT_GLOBAL_ENV },
|
env: { ...DEFAULT_GLOBAL_ENV },
|
||||||
},
|
},
|
||||||
copilot: { ...DEFAULT_COPILOT_CONFIG },
|
copilot: { ...DEFAULT_COPILOT_CONFIG },
|
||||||
proxy: { ...DEFAULT_PROXY_CONFIG },
|
cliproxy_server: { ...DEFAULT_CLIPROXY_SERVER_CONFIG },
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,9 +51,9 @@ export async function startServer(options: ServerOptions): Promise<ServerInstanc
|
|||||||
const { usageRoutes } = await import('./usage-routes');
|
const { usageRoutes } = await import('./usage-routes');
|
||||||
app.use('/api/usage', usageRoutes);
|
app.use('/api/usage', usageRoutes);
|
||||||
|
|
||||||
// Proxy settings routes (Phase 5)
|
// CLIProxy server settings routes (Phase 5)
|
||||||
const proxyRoutes = (await import('./routes/proxy-routes')).default;
|
const cliproxyServerRoutes = (await import('./routes/proxy-routes')).default;
|
||||||
app.use('/api/proxy', proxyRoutes);
|
app.use('/api/cliproxy-server', cliproxyServerRoutes);
|
||||||
|
|
||||||
// Dev mode: use Vite middleware for HMR
|
// Dev mode: use Vite middleware for HMR
|
||||||
if (options.dev) {
|
if (options.dev) {
|
||||||
|
|||||||
@@ -1,69 +1,72 @@
|
|||||||
/**
|
/**
|
||||||
* Proxy Routes - API endpoints for proxy configuration
|
* CLIProxy Server Routes - API endpoints for proxy configuration
|
||||||
*
|
*
|
||||||
* Provides REST endpoints for managing CLIProxyAPI connection settings:
|
* Provides REST endpoints for managing CLIProxyAPI connection settings:
|
||||||
* - GET /api/proxy - Get proxy configuration
|
* - GET /api/cliproxy-server - Get proxy configuration
|
||||||
* - PUT /api/proxy - Update proxy configuration
|
* - PUT /api/cliproxy-server - Update proxy configuration
|
||||||
* - POST /api/proxy/test - Test remote connection
|
* - POST /api/cliproxy-server/test - Test remote connection
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { Router, Request, Response } from 'express';
|
import { Router, Request, Response } from 'express';
|
||||||
import { loadOrCreateUnifiedConfig, saveUnifiedConfig } from '../../config/unified-config-loader';
|
import { loadOrCreateUnifiedConfig, saveUnifiedConfig } from '../../config/unified-config-loader';
|
||||||
import { testConnection } from '../../cliproxy/remote-proxy-client';
|
import { testConnection } from '../../cliproxy/remote-proxy-client';
|
||||||
import { DEFAULT_PROXY_CONFIG, ProxyConfig } from '../../config/unified-config-types';
|
import {
|
||||||
|
DEFAULT_CLIPROXY_SERVER_CONFIG,
|
||||||
|
CliproxyServerConfig,
|
||||||
|
} from '../../config/unified-config-types';
|
||||||
|
|
||||||
const router = Router();
|
const router = Router();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GET /api/proxy - Get proxy configuration
|
* GET /api/cliproxy-server - Get proxy configuration
|
||||||
*/
|
*/
|
||||||
router.get('/', async (_req: Request, res: Response) => {
|
router.get('/', async (_req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
const config = await loadOrCreateUnifiedConfig();
|
const config = await loadOrCreateUnifiedConfig();
|
||||||
res.json(config.proxy || DEFAULT_PROXY_CONFIG);
|
res.json(config.cliproxy_server || DEFAULT_CLIPROXY_SERVER_CONFIG);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[proxy-routes] Failed to load proxy config:', error);
|
console.error('[cliproxy-server-routes] Failed to load proxy config:', error);
|
||||||
res.status(500).json({ error: 'Failed to load proxy config' });
|
res.status(500).json({ error: 'Failed to load proxy config' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* PUT /api/proxy - Update proxy configuration
|
* PUT /api/cliproxy-server - Update proxy configuration
|
||||||
*/
|
*/
|
||||||
router.put('/', async (req: Request, res: Response) => {
|
router.put('/', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
const config = await loadOrCreateUnifiedConfig();
|
const config = await loadOrCreateUnifiedConfig();
|
||||||
const updates = req.body as Partial<ProxyConfig>;
|
const updates = req.body as Partial<CliproxyServerConfig>;
|
||||||
|
|
||||||
// Deep merge with defaults and current config
|
// Deep merge with defaults and current config
|
||||||
config.proxy = {
|
config.cliproxy_server = {
|
||||||
remote: {
|
remote: {
|
||||||
...DEFAULT_PROXY_CONFIG.remote,
|
...DEFAULT_CLIPROXY_SERVER_CONFIG.remote,
|
||||||
...config.proxy?.remote,
|
...config.cliproxy_server?.remote,
|
||||||
...updates.remote,
|
...updates.remote,
|
||||||
},
|
},
|
||||||
fallback: {
|
fallback: {
|
||||||
...DEFAULT_PROXY_CONFIG.fallback,
|
...DEFAULT_CLIPROXY_SERVER_CONFIG.fallback,
|
||||||
...config.proxy?.fallback,
|
...config.cliproxy_server?.fallback,
|
||||||
...updates.fallback,
|
...updates.fallback,
|
||||||
},
|
},
|
||||||
local: {
|
local: {
|
||||||
...DEFAULT_PROXY_CONFIG.local,
|
...DEFAULT_CLIPROXY_SERVER_CONFIG.local,
|
||||||
...config.proxy?.local,
|
...config.cliproxy_server?.local,
|
||||||
...updates.local,
|
...updates.local,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
await saveUnifiedConfig(config);
|
await saveUnifiedConfig(config);
|
||||||
res.json(config.proxy);
|
res.json(config.cliproxy_server);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[proxy-routes] Failed to save proxy config:', error);
|
console.error('[cliproxy-server-routes] Failed to save proxy config:', error);
|
||||||
res.status(500).json({ error: 'Failed to save proxy config' });
|
res.status(500).json({ error: 'Failed to save proxy config' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* POST /api/proxy/test - Test remote proxy connection
|
* POST /api/cliproxy-server/test - Test remote proxy connection
|
||||||
*/
|
*/
|
||||||
router.post('/test', async (req: Request, res: Response) => {
|
router.post('/test', async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
@@ -85,7 +88,7 @@ router.post('/test', async (req: Request, res: Response) => {
|
|||||||
|
|
||||||
res.json(status);
|
res.json(status);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[proxy-routes] Failed to test connection:', error);
|
console.error('[cliproxy-server-routes] Failed to test connection:', error);
|
||||||
res.status(500).json({ error: 'Failed to test connection' });
|
res.status(500).json({ error: 'Failed to test connection' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
+10
-10
@@ -183,8 +183,8 @@ export interface ProxyLocalConfig {
|
|||||||
auto_start: boolean;
|
auto_start: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Proxy configuration */
|
/** CLIProxy server configuration */
|
||||||
export interface ProxyConfig {
|
export interface CliproxyServerConfig {
|
||||||
remote: ProxyRemoteConfig;
|
remote: ProxyRemoteConfig;
|
||||||
fallback: ProxyFallbackConfig;
|
fallback: ProxyFallbackConfig;
|
||||||
local: ProxyLocalConfig;
|
local: ProxyLocalConfig;
|
||||||
@@ -389,13 +389,13 @@ export const api = {
|
|||||||
method: 'DELETE',
|
method: 'DELETE',
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
/** Proxy configuration API */
|
/** CLIProxy server configuration API */
|
||||||
proxy: {
|
cliproxyServer: {
|
||||||
/** Get proxy configuration */
|
/** Get cliproxy server configuration */
|
||||||
get: () => request<ProxyConfig>('/proxy'),
|
get: () => request<CliproxyServerConfig>('/cliproxy-server'),
|
||||||
/** Update proxy configuration */
|
/** Update cliproxy server configuration */
|
||||||
update: (config: Partial<ProxyConfig>) =>
|
update: (config: Partial<CliproxyServerConfig>) =>
|
||||||
request<ProxyConfig>('/proxy', {
|
request<CliproxyServerConfig>('/cliproxy-server', {
|
||||||
method: 'PUT',
|
method: 'PUT',
|
||||||
body: JSON.stringify(config),
|
body: JSON.stringify(config),
|
||||||
}),
|
}),
|
||||||
@@ -407,7 +407,7 @@ export const api = {
|
|||||||
authToken?: string;
|
authToken?: string;
|
||||||
allowSelfSigned?: boolean;
|
allowSelfSigned?: boolean;
|
||||||
}) =>
|
}) =>
|
||||||
request<RemoteProxyStatus>('/proxy/test', {
|
request<RemoteProxyStatus>('/cliproxy-server/test', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
body: JSON.stringify(params),
|
body: JSON.stringify(params),
|
||||||
}),
|
}),
|
||||||
|
|||||||
+36
-30
@@ -43,7 +43,7 @@ import {
|
|||||||
} from 'lucide-react';
|
} from 'lucide-react';
|
||||||
import { CodeEditor } from '@/components/code-editor';
|
import { CodeEditor } from '@/components/code-editor';
|
||||||
import { api } from '@/lib/api-client';
|
import { api } from '@/lib/api-client';
|
||||||
import type { ProxyConfig, RemoteProxyStatus } from '@/lib/api-client';
|
import type { CliproxyServerConfig, RemoteProxyStatus } from '@/lib/api-client';
|
||||||
|
|
||||||
interface ProviderConfig {
|
interface ProviderConfig {
|
||||||
enabled?: boolean;
|
enabled?: boolean;
|
||||||
@@ -117,7 +117,7 @@ export function SettingsPage() {
|
|||||||
const [newEnvKey, setNewEnvKey] = useState('');
|
const [newEnvKey, setNewEnvKey] = useState('');
|
||||||
const [newEnvValue, setNewEnvValue] = useState('');
|
const [newEnvValue, setNewEnvValue] = useState('');
|
||||||
// Proxy state
|
// Proxy state
|
||||||
const [proxyConfig, setProxyConfig] = useState<ProxyConfig | null>(null);
|
const [proxyConfig, setCliproxyServerConfig] = useState<CliproxyServerConfig | null>(null);
|
||||||
const [proxyLoading, setProxyLoading] = useState(true);
|
const [proxyLoading, setProxyLoading] = useState(true);
|
||||||
const [proxySaving, setProxySaving] = useState(false);
|
const [proxySaving, setProxySaving] = useState(false);
|
||||||
const [proxyError, setProxyError] = useState<string | null>(null);
|
const [proxyError, setProxyError] = useState<string | null>(null);
|
||||||
@@ -131,7 +131,7 @@ export function SettingsPage() {
|
|||||||
fetchStatus();
|
fetchStatus();
|
||||||
fetchRawConfig();
|
fetchRawConfig();
|
||||||
fetchGlobalEnvConfig();
|
fetchGlobalEnvConfig();
|
||||||
fetchProxyConfig();
|
fetchCliproxyServerConfig();
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
// Sync local model inputs when config changes
|
// Sync local model inputs when config changes
|
||||||
@@ -204,12 +204,12 @@ export function SettingsPage() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const fetchProxyConfig = async () => {
|
const fetchCliproxyServerConfig = async () => {
|
||||||
try {
|
try {
|
||||||
setProxyLoading(true);
|
setProxyLoading(true);
|
||||||
setProxyError(null);
|
setProxyError(null);
|
||||||
const data = await api.proxy.get();
|
const data = await api.cliproxyServer.get();
|
||||||
setProxyConfig(data);
|
setCliproxyServerConfig(data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setProxyError((err as Error).message);
|
setProxyError((err as Error).message);
|
||||||
} finally {
|
} finally {
|
||||||
@@ -426,7 +426,7 @@ export function SettingsPage() {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Proxy functions
|
// Proxy functions
|
||||||
const saveProxyConfig = async (updates: Partial<ProxyConfig>) => {
|
const saveCliproxyServerConfig = async (updates: Partial<CliproxyServerConfig>) => {
|
||||||
if (!proxyConfig) return;
|
if (!proxyConfig) return;
|
||||||
|
|
||||||
// Optimistic update
|
// Optimistic update
|
||||||
@@ -435,15 +435,15 @@ export function SettingsPage() {
|
|||||||
fallback: { ...proxyConfig.fallback, ...updates.fallback },
|
fallback: { ...proxyConfig.fallback, ...updates.fallback },
|
||||||
local: { ...proxyConfig.local, ...updates.local },
|
local: { ...proxyConfig.local, ...updates.local },
|
||||||
};
|
};
|
||||||
setProxyConfig(optimisticConfig);
|
setCliproxyServerConfig(optimisticConfig);
|
||||||
setTestResult(null); // Clear previous test result on config change
|
setTestResult(null); // Clear previous test result on config change
|
||||||
|
|
||||||
try {
|
try {
|
||||||
setProxySaving(true);
|
setProxySaving(true);
|
||||||
setProxyError(null);
|
setProxyError(null);
|
||||||
|
|
||||||
const data = await api.proxy.update(updates);
|
const data = await api.cliproxyServer.update(updates);
|
||||||
setProxyConfig(data);
|
setCliproxyServerConfig(data);
|
||||||
setProxySuccess(true);
|
setProxySuccess(true);
|
||||||
setTimeout(() => setProxySuccess(false), 1500);
|
setTimeout(() => setProxySuccess(false), 1500);
|
||||||
// Silently refresh raw config
|
// Silently refresh raw config
|
||||||
@@ -452,7 +452,7 @@ export function SettingsPage() {
|
|||||||
.then((text) => text && setRawConfig(text))
|
.then((text) => text && setRawConfig(text))
|
||||||
.catch(() => {});
|
.catch(() => {});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setProxyConfig(proxyConfig);
|
setCliproxyServerConfig(proxyConfig);
|
||||||
setProxyError((err as Error).message);
|
setProxyError((err as Error).message);
|
||||||
} finally {
|
} finally {
|
||||||
setProxySaving(false);
|
setProxySaving(false);
|
||||||
@@ -473,7 +473,7 @@ export function SettingsPage() {
|
|||||||
setProxyError(null);
|
setProxyError(null);
|
||||||
setTestResult(null);
|
setTestResult(null);
|
||||||
|
|
||||||
const result = await api.proxy.test({
|
const result = await api.cliproxyServer.test({
|
||||||
host,
|
host,
|
||||||
port,
|
port,
|
||||||
protocol,
|
protocol,
|
||||||
@@ -586,9 +586,9 @@ export function SettingsPage() {
|
|||||||
success={proxySuccess}
|
success={proxySuccess}
|
||||||
testResult={testResult}
|
testResult={testResult}
|
||||||
testing={testing}
|
testing={testing}
|
||||||
saveProxyConfig={saveProxyConfig}
|
saveCliproxyServerConfig={saveCliproxyServerConfig}
|
||||||
handleTestConnection={handleTestConnection}
|
handleTestConnection={handleTestConnection}
|
||||||
fetchProxyConfig={fetchProxyConfig}
|
fetchCliproxyServerConfig={fetchCliproxyServerConfig}
|
||||||
fetchRawConfig={fetchRawConfig}
|
fetchRawConfig={fetchRawConfig}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -1284,16 +1284,16 @@ function GlobalEnvContent({
|
|||||||
|
|
||||||
// Proxy Tab Content Component
|
// Proxy Tab Content Component
|
||||||
interface ProxyContentProps {
|
interface ProxyContentProps {
|
||||||
config: ProxyConfig | null;
|
config: CliproxyServerConfig | null;
|
||||||
loading: boolean;
|
loading: boolean;
|
||||||
saving: boolean;
|
saving: boolean;
|
||||||
error: string | null;
|
error: string | null;
|
||||||
success: boolean;
|
success: boolean;
|
||||||
testResult: RemoteProxyStatus | null;
|
testResult: RemoteProxyStatus | null;
|
||||||
testing: boolean;
|
testing: boolean;
|
||||||
saveProxyConfig: (updates: Partial<ProxyConfig>) => void;
|
saveCliproxyServerConfig: (updates: Partial<CliproxyServerConfig>) => void;
|
||||||
handleTestConnection: () => void;
|
handleTestConnection: () => void;
|
||||||
fetchProxyConfig: () => void;
|
fetchCliproxyServerConfig: () => void;
|
||||||
fetchRawConfig: () => void;
|
fetchRawConfig: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1305,9 +1305,9 @@ function ProxyContent({
|
|||||||
success,
|
success,
|
||||||
testResult,
|
testResult,
|
||||||
testing,
|
testing,
|
||||||
saveProxyConfig,
|
saveCliproxyServerConfig,
|
||||||
handleTestConnection,
|
handleTestConnection,
|
||||||
fetchProxyConfig,
|
fetchCliproxyServerConfig,
|
||||||
fetchRawConfig,
|
fetchRawConfig,
|
||||||
}: ProxyContentProps) {
|
}: ProxyContentProps) {
|
||||||
// Memoized default config to avoid recreation
|
// Memoized default config to avoid recreation
|
||||||
@@ -1359,7 +1359,7 @@ function ProxyContent({
|
|||||||
const saveHost = () => {
|
const saveHost = () => {
|
||||||
const value = editedHost ?? displayHost;
|
const value = editedHost ?? displayHost;
|
||||||
if (value !== config?.remote.host) {
|
if (value !== config?.remote.host) {
|
||||||
saveProxyConfig({ remote: { ...remoteConfig, host: value } });
|
saveCliproxyServerConfig({ remote: { ...remoteConfig, host: value } });
|
||||||
}
|
}
|
||||||
setEditedHost(null);
|
setEditedHost(null);
|
||||||
};
|
};
|
||||||
@@ -1367,7 +1367,7 @@ function ProxyContent({
|
|||||||
const savePort = () => {
|
const savePort = () => {
|
||||||
const port = parseInt(editedPort ?? displayPort, 10);
|
const port = parseInt(editedPort ?? displayPort, 10);
|
||||||
if (!isNaN(port) && port !== config?.remote.port) {
|
if (!isNaN(port) && port !== config?.remote.port) {
|
||||||
saveProxyConfig({ remote: { ...remoteConfig, port } });
|
saveCliproxyServerConfig({ remote: { ...remoteConfig, port } });
|
||||||
}
|
}
|
||||||
setEditedPort(null);
|
setEditedPort(null);
|
||||||
};
|
};
|
||||||
@@ -1375,7 +1375,7 @@ function ProxyContent({
|
|||||||
const saveAuthToken = () => {
|
const saveAuthToken = () => {
|
||||||
const value = editedAuthToken ?? displayAuthToken;
|
const value = editedAuthToken ?? displayAuthToken;
|
||||||
if (value !== config?.remote.auth_token) {
|
if (value !== config?.remote.auth_token) {
|
||||||
saveProxyConfig({ remote: { ...remoteConfig, auth_token: value } });
|
saveCliproxyServerConfig({ remote: { ...remoteConfig, auth_token: value } });
|
||||||
}
|
}
|
||||||
setEditedAuthToken(null);
|
setEditedAuthToken(null);
|
||||||
};
|
};
|
||||||
@@ -1383,7 +1383,7 @@ function ProxyContent({
|
|||||||
const saveLocalPort = () => {
|
const saveLocalPort = () => {
|
||||||
const port = parseInt(editedLocalPort ?? displayLocalPort, 10);
|
const port = parseInt(editedLocalPort ?? displayLocalPort, 10);
|
||||||
if (!isNaN(port) && port !== config?.local.port) {
|
if (!isNaN(port) && port !== config?.local.port) {
|
||||||
saveProxyConfig({ local: { ...localConfig, port } });
|
saveCliproxyServerConfig({ local: { ...localConfig, port } });
|
||||||
}
|
}
|
||||||
setEditedLocalPort(null);
|
setEditedLocalPort(null);
|
||||||
};
|
};
|
||||||
@@ -1426,7 +1426,9 @@ function ProxyContent({
|
|||||||
<div className="grid grid-cols-2 gap-3">
|
<div className="grid grid-cols-2 gap-3">
|
||||||
{/* Local Mode Card */}
|
{/* Local Mode Card */}
|
||||||
<button
|
<button
|
||||||
onClick={() => saveProxyConfig({ remote: { ...remoteConfig, enabled: false } })}
|
onClick={() =>
|
||||||
|
saveCliproxyServerConfig({ remote: { ...remoteConfig, enabled: false } })
|
||||||
|
}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
className={`p-4 rounded-lg border-2 text-left transition-all ${
|
className={`p-4 rounded-lg border-2 text-left transition-all ${
|
||||||
!isRemoteMode
|
!isRemoteMode
|
||||||
@@ -1447,7 +1449,9 @@ function ProxyContent({
|
|||||||
|
|
||||||
{/* Remote Mode Card */}
|
{/* Remote Mode Card */}
|
||||||
<button
|
<button
|
||||||
onClick={() => saveProxyConfig({ remote: { ...remoteConfig, enabled: true } })}
|
onClick={() =>
|
||||||
|
saveCliproxyServerConfig({ remote: { ...remoteConfig, enabled: true } })
|
||||||
|
}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
className={`p-4 rounded-lg border-2 text-left transition-all ${
|
className={`p-4 rounded-lg border-2 text-left transition-all ${
|
||||||
isRemoteMode
|
isRemoteMode
|
||||||
@@ -1508,7 +1512,7 @@ function ProxyContent({
|
|||||||
<Select
|
<Select
|
||||||
value={config?.remote.protocol || 'http'}
|
value={config?.remote.protocol || 'http'}
|
||||||
onValueChange={(value: 'http' | 'https') =>
|
onValueChange={(value: 'http' | 'https') =>
|
||||||
saveProxyConfig({ remote: { ...remoteConfig, protocol: value } })
|
saveCliproxyServerConfig({ remote: { ...remoteConfig, protocol: value } })
|
||||||
}
|
}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
>
|
>
|
||||||
@@ -1605,7 +1609,7 @@ function ProxyContent({
|
|||||||
<Switch
|
<Switch
|
||||||
checked={config?.fallback.enabled ?? true}
|
checked={config?.fallback.enabled ?? true}
|
||||||
onCheckedChange={(checked) =>
|
onCheckedChange={(checked) =>
|
||||||
saveProxyConfig({ fallback: { ...fallbackConfig, enabled: checked } })
|
saveCliproxyServerConfig({ fallback: { ...fallbackConfig, enabled: checked } })
|
||||||
}
|
}
|
||||||
disabled={saving || !isRemoteMode}
|
disabled={saving || !isRemoteMode}
|
||||||
/>
|
/>
|
||||||
@@ -1622,7 +1626,9 @@ function ProxyContent({
|
|||||||
<Switch
|
<Switch
|
||||||
checked={config?.fallback.auto_start ?? false}
|
checked={config?.fallback.auto_start ?? false}
|
||||||
onCheckedChange={(checked) =>
|
onCheckedChange={(checked) =>
|
||||||
saveProxyConfig({ fallback: { ...fallbackConfig, auto_start: checked } })
|
saveCliproxyServerConfig({
|
||||||
|
fallback: { ...fallbackConfig, auto_start: checked },
|
||||||
|
})
|
||||||
}
|
}
|
||||||
disabled={saving || !isRemoteMode || !config?.fallback.enabled}
|
disabled={saving || !isRemoteMode || !config?.fallback.enabled}
|
||||||
/>
|
/>
|
||||||
@@ -1659,7 +1665,7 @@ function ProxyContent({
|
|||||||
<Switch
|
<Switch
|
||||||
checked={config?.local.auto_start ?? true}
|
checked={config?.local.auto_start ?? true}
|
||||||
onCheckedChange={(checked) =>
|
onCheckedChange={(checked) =>
|
||||||
saveProxyConfig({ local: { ...localConfig, auto_start: checked } })
|
saveCliproxyServerConfig({ local: { ...localConfig, auto_start: checked } })
|
||||||
}
|
}
|
||||||
disabled={saving}
|
disabled={saving}
|
||||||
/>
|
/>
|
||||||
@@ -1675,7 +1681,7 @@ function ProxyContent({
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
fetchProxyConfig();
|
fetchCliproxyServerConfig();
|
||||||
fetchRawConfig();
|
fetchRawConfig();
|
||||||
}}
|
}}
|
||||||
disabled={loading || saving}
|
disabled={loading || saving}
|
||||||
|
|||||||
Reference in New Issue
Block a user