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.
139 lines
5.3 KiB
Markdown
139 lines
5.3 KiB
Markdown
# SDK Advanced: Executors & Translators
|
||
|
||
This guide explains how to extend the embedded proxy with custom providers and schemas using the SDK. You will:
|
||
- Implement a provider executor that talks to your upstream API
|
||
- Register request/response translators for schema conversion
|
||
- Register models so they appear in `/v1/models`
|
||
|
||
The examples use Go 1.24+ and the v6 module path.
|
||
|
||
## Concepts
|
||
|
||
- Provider executor: a runtime component implementing `auth.ProviderExecutor` that performs outbound calls for a given provider key (e.g., `gemini`, `claude`, `codex`). Executors can also implement `RequestPreparer` to inject credentials on raw HTTP requests.
|
||
- Translator registry: schema conversion functions routed by `sdk/translator`. The built‑in handlers translate between OpenAI/Gemini/Claude/Codex formats; you can register new ones.
|
||
- Model registry: publishes the list of available models per client/provider to power `/v1/models` and routing hints.
|
||
|
||
## 1) Implement a Provider Executor
|
||
|
||
Create a type that satisfies `auth.ProviderExecutor`.
|
||
|
||
```go
|
||
package myprov
|
||
|
||
import (
|
||
"context"
|
||
"net/http"
|
||
|
||
coreauth "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/auth"
|
||
clipexec "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy/executor"
|
||
)
|
||
|
||
type Executor struct{}
|
||
|
||
func (Executor) Identifier() string { return "myprov" }
|
||
|
||
// Optional: mutate outbound HTTP requests with credentials
|
||
func (Executor) PrepareRequest(req *http.Request, a *coreauth.Auth) error {
|
||
// Example: req.Header.Set("Authorization", "Bearer "+a.APIKey)
|
||
return nil
|
||
}
|
||
|
||
func (Executor) Execute(ctx context.Context, a *coreauth.Auth, req clipexec.Request, opts clipexec.Options) (clipexec.Response, error) {
|
||
// Build HTTP request based on req.Payload (already translated into provider format)
|
||
// Use per‑auth transport if provided: transport := a.RoundTripper // via RoundTripperProvider
|
||
// Perform call and return provider JSON payload
|
||
return clipexec.Response{Payload: []byte(`{"ok":true}`)}, nil
|
||
}
|
||
|
||
func (Executor) ExecuteStream(ctx context.Context, a *coreauth.Auth, req clipexec.Request, opts clipexec.Options) (<-chan clipexec.StreamChunk, error) {
|
||
ch := make(chan clipexec.StreamChunk, 1)
|
||
go func() { defer close(ch); ch <- clipexec.StreamChunk{Payload: []byte("data: {\"done\":true}\n\n")} }()
|
||
return ch, nil
|
||
}
|
||
|
||
func (Executor) Refresh(ctx context.Context, a *coreauth.Auth) (*coreauth.Auth, error) {
|
||
// Optionally refresh tokens and return updated auth
|
||
return a, nil
|
||
}
|
||
```
|
||
|
||
Register the executor with the core manager before starting the service:
|
||
|
||
```go
|
||
core := coreauth.NewManager(coreauth.NewFileStore(cfg.AuthDir), nil, nil)
|
||
core.RegisterExecutor(myprov.Executor{})
|
||
svc, _ := cliproxy.NewBuilder().WithConfig(cfg).WithConfigPath(cfgPath).WithCoreAuthManager(core).Build()
|
||
```
|
||
|
||
If your auth entries use provider `"myprov"`, the manager routes requests to your executor.
|
||
|
||
## 2) Register Translators
|
||
|
||
The handlers accept OpenAI/Gemini/Claude/Codex inputs. To support a new provider format, register translation functions in `sdk/translator`’s default registry.
|
||
|
||
Direction matters:
|
||
- Request: register from inbound schema to provider schema
|
||
- Response: register from provider schema back to inbound schema
|
||
|
||
Example: Convert OpenAI Chat → MyProv Chat and back.
|
||
|
||
```go
|
||
package myprov
|
||
|
||
import (
|
||
"context"
|
||
sdktr "github.com/router-for-me/CLIProxyAPI/v6/sdk/translator"
|
||
)
|
||
|
||
const (
|
||
FOpenAI = sdktr.Format("openai.chat")
|
||
FMyProv = sdktr.Format("myprov.chat")
|
||
)
|
||
|
||
func init() {
|
||
sdktr.Register(FOpenAI, FMyProv,
|
||
// Request transform (model, rawJSON, stream)
|
||
func(model string, raw []byte, stream bool) []byte { return convertOpenAIToMyProv(model, raw, stream) },
|
||
// Response transform (stream & non‑stream)
|
||
sdktr.ResponseTransform{
|
||
Stream: func(ctx context.Context, model string, originalReq, translatedReq, raw []byte, param *any) []string {
|
||
return convertStreamMyProvToOpenAI(model, originalReq, translatedReq, raw)
|
||
},
|
||
NonStream: func(ctx context.Context, model string, originalReq, translatedReq, raw []byte, param *any) string {
|
||
return convertMyProvToOpenAI(model, originalReq, translatedReq, raw)
|
||
},
|
||
},
|
||
)
|
||
}
|
||
```
|
||
|
||
When the OpenAI handler receives a request that should route to `myprov`, the pipeline uses the registered transforms automatically.
|
||
|
||
## 3) Register Models
|
||
|
||
Expose models under `/v1/models` by registering them in the global model registry using the auth ID (client ID) and provider name.
|
||
|
||
```go
|
||
models := []*cliproxy.ModelInfo{
|
||
{ ID: "myprov-pro-1", Object: "model", Type: "myprov", DisplayName: "MyProv Pro 1" },
|
||
}
|
||
cliproxy.GlobalModelRegistry().RegisterClient(authID, "myprov", models)
|
||
```
|
||
|
||
The embedded server calls this automatically for built‑in providers; for custom providers, register during startup (e.g., after loading auths) or upon auth registration hooks.
|
||
|
||
## Credentials & Transports
|
||
|
||
- Use `Manager.SetRoundTripperProvider` to inject per‑auth `*http.Transport` (e.g., proxy):
|
||
```go
|
||
core.SetRoundTripperProvider(myProvider) // returns transport per auth
|
||
```
|
||
- For raw HTTP flows, implement `PrepareRequest` and/or call `Manager.InjectCredentials(req, authID)` to set headers.
|
||
|
||
## Testing Tips
|
||
|
||
- Enable request logging: Management API GET/PUT `/v0/management/request-log`
|
||
- Toggle debug logs: Management API GET/PUT `/v0/management/debug`
|
||
- Hot reload changes in `config.yaml` and `auths/` are picked up automatically by the watcher
|
||
|