mirror of
https://github.com/router-for-me/CLIProxyAPI.git
synced 2026-02-02 04:20:50 +08:00
- Added extensive SDK usage guides for `cliproxy`, `sdk/access`, and watcher integration. - Introduced `--password` flag for specifying local management access passwords. - Enhanced management API with local password checks to secure localhost requests. - Updated documentation to reflect the new password functionality.
164 lines
5.0 KiB
Markdown
164 lines
5.0 KiB
Markdown
# CLI Proxy SDK Guide
|
||
|
||
The `sdk/cliproxy` module exposes the proxy as a reusable Go library so external programs can embed the routing, authentication, hot‑reload, and translation layers without depending on the CLI binary.
|
||
|
||
## Install & Import
|
||
|
||
```bash
|
||
go get github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy
|
||
```
|
||
|
||
```go
|
||
import (
|
||
"context"
|
||
"errors"
|
||
"time"
|
||
|
||
"github.com/router-for-me/CLIProxyAPI/v6/internal/config"
|
||
"github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy"
|
||
)
|
||
```
|
||
|
||
Note the `/v6` module path.
|
||
|
||
## Minimal Embed
|
||
|
||
```go
|
||
cfg, err := config.LoadConfig("config.yaml")
|
||
if err != nil { panic(err) }
|
||
|
||
svc, err := cliproxy.NewBuilder().
|
||
WithConfig(cfg).
|
||
WithConfigPath("config.yaml"). // absolute or working-dir relative
|
||
Build()
|
||
if err != nil { panic(err) }
|
||
|
||
ctx, cancel := context.WithCancel(context.Background())
|
||
defer cancel()
|
||
|
||
if err := svc.Run(ctx); err != nil && !errors.Is(err, context.Canceled) {
|
||
panic(err)
|
||
}
|
||
```
|
||
|
||
The service manages config/auth watching, background token refresh, and graceful shutdown. Cancel the context to stop it.
|
||
|
||
## Server Options (middleware, routes, logs)
|
||
|
||
The server accepts options via `WithServerOptions`:
|
||
|
||
```go
|
||
svc, _ := cliproxy.NewBuilder().
|
||
WithConfig(cfg).
|
||
WithConfigPath("config.yaml").
|
||
WithServerOptions(
|
||
// Add global middleware
|
||
cliproxy.WithMiddleware(func(c *gin.Context) { c.Header("X-Embed", "1"); c.Next() }),
|
||
// Tweak gin engine early (CORS, trusted proxies, etc.)
|
||
cliproxy.WithEngineConfigurator(func(e *gin.Engine) { e.ForwardedByClientIP = true }),
|
||
// Add your own routes after defaults
|
||
cliproxy.WithRouterConfigurator(func(e *gin.Engine, _ *handlers.BaseAPIHandler, _ *config.Config) {
|
||
e.GET("/healthz", func(c *gin.Context) { c.String(200, "ok") })
|
||
}),
|
||
// Override request log writer/dir
|
||
cliproxy.WithRequestLoggerFactory(func(cfg *config.Config, cfgPath string) logging.RequestLogger {
|
||
return logging.NewFileRequestLogger(true, "logs", filepath.Dir(cfgPath))
|
||
}),
|
||
).
|
||
Build()
|
||
```
|
||
|
||
These options mirror the internals used by the CLI server.
|
||
|
||
## Management API (when embedded)
|
||
|
||
- Management endpoints are mounted only when `remote-management.secret-key` is set in `config.yaml`.
|
||
- Remote access additionally requires `remote-management.allow-remote: true`.
|
||
- See MANAGEMENT_API.md for endpoints. Your embedded server exposes them under `/v0/management` on the configured port.
|
||
|
||
## Using the Core Auth Manager
|
||
|
||
The service uses a core `auth.Manager` for selection, execution, and auto‑refresh. When embedding, you can provide your own manager to customize transports or hooks:
|
||
|
||
```go
|
||
core := coreauth.NewManager(coreauth.NewFileStore(cfg.AuthDir), nil, nil)
|
||
core.SetRoundTripperProvider(myRTProvider) // per‑auth *http.Transport
|
||
|
||
svc, _ := cliproxy.NewBuilder().
|
||
WithConfig(cfg).
|
||
WithConfigPath("config.yaml").
|
||
WithCoreAuthManager(core).
|
||
Build()
|
||
```
|
||
|
||
Implement a custom per‑auth transport:
|
||
|
||
```go
|
||
type myRTProvider struct{}
|
||
func (myRTProvider) RoundTripperFor(a *coreauth.Auth) http.RoundTripper {
|
||
if a == nil || a.ProxyURL == "" { return nil }
|
||
u, _ := url.Parse(a.ProxyURL)
|
||
return &http.Transport{ Proxy: http.ProxyURL(u) }
|
||
}
|
||
```
|
||
|
||
Programmatic execution is available on the manager:
|
||
|
||
```go
|
||
// Non‑streaming
|
||
resp, err := core.Execute(ctx, []string{"gemini"}, req, opts)
|
||
|
||
// Streaming
|
||
chunks, err := core.ExecuteStream(ctx, []string{"gemini"}, req, opts)
|
||
for ch := range chunks { /* ... */ }
|
||
```
|
||
|
||
Note: Built‑in provider executors are wired automatically when you run the `Service`. If you want to use `Manager` stand‑alone without the HTTP server, you must register your own executors that implement `auth.ProviderExecutor`.
|
||
|
||
## Custom Client Sources
|
||
|
||
Replace the default loaders if your creds live outside the local filesystem:
|
||
|
||
```go
|
||
type memoryTokenProvider struct{}
|
||
func (p *memoryTokenProvider) Load(ctx context.Context, cfg *config.Config) (*cliproxy.TokenClientResult, error) {
|
||
// Populate from memory/remote store and return counts
|
||
return &cliproxy.TokenClientResult{}, nil
|
||
}
|
||
|
||
svc, _ := cliproxy.NewBuilder().
|
||
WithConfig(cfg).
|
||
WithConfigPath("config.yaml").
|
||
WithTokenClientProvider(&memoryTokenProvider{}).
|
||
WithAPIKeyClientProvider(cliproxy.NewAPIKeyClientProvider()).
|
||
Build()
|
||
```
|
||
|
||
## Hooks
|
||
|
||
Observe lifecycle without patching internals:
|
||
|
||
```go
|
||
hooks := cliproxy.Hooks{
|
||
OnBeforeStart: func(cfg *config.Config) { log.Infof("starting on :%d", cfg.Port) },
|
||
OnAfterStart: func(s *cliproxy.Service) { log.Info("ready") },
|
||
}
|
||
svc, _ := cliproxy.NewBuilder().WithConfig(cfg).WithConfigPath("config.yaml").WithHooks(hooks).Build()
|
||
```
|
||
|
||
## Shutdown
|
||
|
||
`Run` defers `Shutdown`, so cancelling the parent context is enough. To stop manually:
|
||
|
||
```go
|
||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||
defer cancel()
|
||
_ = svc.Shutdown(ctx)
|
||
```
|
||
|
||
## Notes
|
||
|
||
- Hot reload: changes to `config.yaml` and `auths/` are picked up automatically.
|
||
- Request logging can be toggled at runtime via the Management API.
|
||
- Gemini Web features (`gemini-web.*`) are honored in the embedded server.
|