### Install CliRelay with Docker Compose Source: https://github.com/kittors/clirelay/blob/main/README.md Use these commands to clone the repository, set up the configuration, and start CliRelay using Docker Compose. Ensure you edit `config.yaml` after setup. ```bash git clone https://github.com/kittors/CliRelay.git cd CliRelay cp config.example.yaml config.yaml docker compose up -d ``` ```bash docker compose restart cli-proxy-api ``` -------------------------------- ### Install CLIProxyAPI SDK Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md Install the SDK using go get. Ensure you use the correct module path including /v6. ```bash go get github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy ``` -------------------------------- ### CLI Proxy Service with Hooks Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md Attach lifecycle hooks to the CLI proxy service to observe events like starting and readiness. ```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() ``` -------------------------------- ### Writing Custom Providers Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Provides an example and requirements for writing and registering custom access providers. ```APIDOC ## Writing Custom Providers ```go type customProvider struct{} func (p *customProvider) Identifier() string { return "my-provider" } func (p *customProvider) Authenticate(ctx context.Context, r *http.Request) (*sdkaccess.Result, *sdkaccess.AuthError) { token := r.Header.Get("X-Custom") if token == "" { return nil, sdkaccess.NewNotHandledError() } if token != "expected" { return nil, sdkaccess.NewInvalidCredentialError() } return &sdkaccess.Result{ Provider: p.Identifier(), Principal: "service-user", Metadata: map[string]string{"source": "x-custom"}, }, nil } func init() { sdkaccess.RegisterProvider("custom", &customProvider{}) } ``` A provider must implement `Identifier()` and `Authenticate()`. To make it available to the access manager, call `RegisterProvider` inside `init` with an initialized provider instance. ``` -------------------------------- ### Sync Fork and Create Feature Branch Source: https://github.com/kittors/clirelay/blob/main/CONTRIBUTING.md Before starting new work, sync your fork with the latest changes from the 'dev' branch and create a new feature branch from it. ```bash git fetch origin git switch -c feature/your-change origin/dev ``` -------------------------------- ### Built-in `config-api-key` Provider Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Details the built-in API key provider, its credential sources, and configuration example. ```APIDOC ## Built-in `config-api-key` Provider The proxy includes one built-in access provider: - `config-api-key`: Validates API keys declared under top-level `api-keys`. - Credential sources: `Authorization: Bearer`, `X-Goog-Api-Key`, `X-Api-Key`, `?key=`, `?auth_token=` - Metadata: `Result.Metadata["source"]` is set to the matched source label. In the CLI server and `sdk/cliproxy`, this provider is registered automatically based on the loaded configuration. ```yaml api-keys: - sk-test-123 - sk-prod-456 ``` ``` -------------------------------- ### Register Executor with Core Manager Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-advanced.md Register the custom executor with the core manager before starting the service. This ensures that requests using the provider key "myprov" are routed to your custom executor. ```go core := coreauth.NewManager(coreauth.NewFileStore(cfg.AuthDir), nil, nil) core.RegisterExecutor(myprov.Executor{}) svc, _ := cliproxy.NewBuilder().WithConfig(cfg).WithConfigPath(cfgPath).WithCoreAuthManager(core).Build() ``` -------------------------------- ### Initialize and Configure Manager Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Construct a new manager and set its providers using globally registered providers. The manager can be nil if no providers are configured. ```go manager := sdkaccess.NewManager() manager.SetProviders(sdkaccess.RegisteredProviders()) ``` -------------------------------- ### Import CLIProxyAPI SDK Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md Import the necessary packages for using the SDK. Note the /v6 in the module path. ```go import ( "context" "errors" "time" "github.com/router-for-me/CLIProxyAPI/v6/internal/config" "github.com/router-for-me/CLIProxyAPI/v6/sdk/cliproxy" ) ``` -------------------------------- ### Import SDK Access Package Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Import the SDK access package to centralize request authentication logic. ```go import ( sdkaccess "github.com/router-for-me/CLIProxyAPI/v6/sdk/access" ) ``` -------------------------------- ### Manager Lifecycle Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Demonstrates how to initialize and configure the access manager with registered providers. ```APIDOC ## Manager Lifecycle ```go manager := sdkaccess.NewManager() manager.SetProviders(sdkaccess.RegisteredProviders()) ``` - `NewManager` constructs an empty manager. - `SetProviders` replaces the provider slice using a defensive copy. - `Providers` retrieves a snapshot that can be iterated safely from other goroutines. If the manager itself is `nil` or no providers are configured, the call returns `nil, nil`, allowing callers to treat access control as disabled. ``` -------------------------------- ### Build CLI Service with Access Manager Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Use this snippet to build a CLI service with cliproxy, integrating a pre-configured access manager. Ensure custom providers are registered before building. ```go coreCfg, _ := config.LoadConfig("config.yaml") accessManager := sdkaccess.NewManager() svc, _ := cliproxy.NewBuilder(). WithConfig(coreCfg). WithConfigPath("config.yaml"). WithRequestAccessManager(accessManager). Build() ``` -------------------------------- ### Clone Repository and Create Feature Branch Source: https://github.com/kittors/clirelay/blob/main/README.md Steps to clone the repository, switch to a development branch, and create a new feature branch for contributions. ```bash git clone https://github.com/kittors/CliRelay.git cd CliRelay # 2. Create a feature branch from the latest dev baseline git fetch origin git switch -c feature/amazing-feature origin/dev ``` -------------------------------- ### Loading Providers from External Go Modules Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Explains how to import external Go modules to register their access providers. ```APIDOC ## Loading Providers from External Go Modules To consume a provider shipped in another Go module, import it for its registration side effect: ```go import ( _ "github.com/acme/xplatform/sdk/access/providers/partner" // registers partner-token sdkaccess "github.com/router-for-me/CLIProxyAPI/v6/sdk/access" ) ``` The blank identifier import ensures `init` runs so `sdkaccess.RegisterProvider` executes before you call `RegisteredProviders()` (or before `cliproxy.NewBuilder().Build()`). ``` -------------------------------- ### Run Frontend Verification Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md Execute frontend tests for request logs and logs pages using Bun and Vitest. Ensure all tests pass. ```bash bun vitest run src/modules/monitor/__tests__/RequestLogsPage.test.tsx src/modules/logs/__tests__/LogsPage.test.tsx ``` -------------------------------- ### Implement Custom Provider Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Implement the Identifier() and Authenticate() methods for a custom provider. Register it using sdkaccess.RegisterProvider within an init function. ```go type customProvider struct{} func (p *customProvider) Identifier() string { return "my-provider" } func (p *customProvider) Authenticate(ctx context.Context, r *http.Request) (*sdkaccess.Result, *sdkaccess.AuthError) { token := r.Header.Get("X-Custom") if token == "" { return nil, sdkaccess.NewNotHandledError() } if token != "expected" { return nil, sdkaccess.NewInvalidCredentialError() } return &sdkaccess.Result{ Provider: p.Identifier(), Principal: "service-user", Metadata: map[string]string{"source": "x-custom"}, }, nil } func init() { sdkaccess.RegisterProvider("custom", &customProvider{}) } ``` -------------------------------- ### Run Go Tests Source: https://github.com/kittors/clirelay/blob/main/CONTRIBUTING.md Execute all Go tests in the project. This command should be run before opening or updating a pull request for Go changes. ```bash go test ./... ``` -------------------------------- ### Minimal CLI Proxy Service Embed Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md Embed the CLI proxy service with minimal configuration. Load configuration, build the service, and run it with a cancellable context. The service handles config watching, token refresh, and graceful shutdown. ```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()) deferr cancel() if err := svc.Run(ctx); err != nil && !errors.Is(err, context.Canceled) { panic(err) } ``` -------------------------------- ### CLI Proxy Service with Server Options Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md Configure the embedded CLI proxy service with custom server options, including global middleware, engine configuration, custom routes, and request loggers. ```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() ``` -------------------------------- ### Use Development Docker Image Source: https://github.com/kittors/clirelay/blob/main/README.md To test development builds, set the `channel` to `dev` in the `auto-update` section of `config.yaml`. ```yaml auto-update: channel: dev ``` -------------------------------- ### Run OpenAI Claude Empty Tool Name Chain Tests Source: https://github.com/kittors/clirelay/blob/main/docs/internal-review/empty-tool-name-chain-test-report-20260613.md Executes Go tests for OpenAI and Claude tool name chain scenarios, including empty tool names and non-streaming cases. ```bash rtk go test ./test -run 'TestOpenAIClaude.*Tool.*Chain|TestOpenAIClaudeEmptyToolNameNonStreamingChain' -count=1 -v ``` -------------------------------- ### Run Backend Verification Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md Execute backend tests for usage and management handlers. Ensure all tests pass. ```bash go test ./internal/usage ./internal/api/handlers/management -count=1 ``` -------------------------------- ### Enable Redis Persistence Source: https://github.com/kittors/clirelay/blob/main/README.md Enable data persistence by setting `redis.enable` to `true` in `config.yaml` and providing your Redis server address. ```yaml redis: enable: true ``` -------------------------------- ### Register Models with Global Registry Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-advanced.md Expose custom provider models under `/v1/models` by registering them in the global model registry. This is done 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) ``` -------------------------------- ### Run OpenAI Compat Executor Claude Tests Source: https://github.com/kittors/clirelay/blob/main/docs/internal-review/empty-tool-name-chain-test-report-20260613.md Executes Go tests for the OpenAICompatExecutor with Claude, focusing on empty tool names and various streaming/non-streaming scenarios. ```bash rtk go test ./internal/runtime/executor -run 'TestOpenAICompatExecutorClaude(StreamSkipsEmptyToolNameEndToEnd|StreamSkipsMissingToolNameArgumentsEndToEnd|StreamPreservesValidParallelToolWhenEmptyIndexFirstEndToEnd|NonStreamSkipsEmptyToolNameEndToEnd)' -count=1 -v ``` -------------------------------- ### Run Go Test for Cleanup Function Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md Command to run the specific test for the ClearAllRequestLogs function to verify its behavior. Use the -count=1 flag to ensure the test runs fresh. ```bash go test ./internal/usage -run TestClearAllRequestLogsRemovesRequestLogTablesOnly -count=1 ``` -------------------------------- ### Execute Terminal Management UI Source: https://github.com/kittors/clirelay/blob/main/README.md Use this command to launch the terminal-first management interface for CliRelay. This provides an alternative to the web-based panel. ```bash docker compose exec cli-proxy-api ./cli-proxy-api -tui ``` -------------------------------- ### Custom Token Client Provider Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md Replace the default token client loaders with a custom provider, such as one that loads credentials from memory. ```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() ``` -------------------------------- ### Implement a Provider Executor Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-advanced.md Implement the `auth.ProviderExecutor` interface to create a custom provider executor. This includes methods for identifying the provider, preparing HTTP requests, executing requests (both streaming and non-streaming), and refreshing authentication tokens. ```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 } ``` -------------------------------- ### Load External Providers Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Import external provider modules using a blank identifier to ensure their registration side effect runs before accessing registered providers. ```go import ( _ "github.com/acme/xplatform/sdk/access/providers/partner" // registers partner-token sdkaccess "github.com/router-for-me/CLIProxyAPI/v6/sdk/access" ) ``` -------------------------------- ### Configure OpenAI Codex Tool Source: https://github.com/kittors/clirelay/blob/main/README.md Configure your AI tool, such as OpenAI Codex, to use CliRelay by setting the `base_url` to `http://localhost:8317/v1` in its configuration file. ```toml [model_providers.tabcode] name = "openai" base_url = "http://localhost:8317/v1" requires_openai_auth = true ``` -------------------------------- ### Execute Request with Core Auth Manager Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md Programmatically execute requests using the core auth manager for non-streaming and streaming responses. ```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 { /* ... */ } ``` -------------------------------- ### Provide Custom HTTP Transport Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-advanced.md Use `Manager.SetRoundTripperProvider` to inject a custom `*http.Transport` that can handle per-authentication logic, such as proxy configurations. ```go core.SetRoundTripperProvider(myProvider) // returns transport per auth ``` -------------------------------- ### Implement ClearAllRequestLogs Function Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md Implements the backend logic for clearing all request logs and their associated content from the database. It uses a transaction to ensure atomicity and includes a VACUUM command to reclaim space. ```go type ClearRequestLogsResult struct { DeletedLogs int64 `json:"deleted_logs"` DeletedContents int64 `json:"deleted_contents"` } func ClearAllRequestLogs() (ClearRequestLogsResult, error) { db := getDB() if db == nil { return ClearRequestLogsResult{}, fmt.Errorf("usage: database not initialised") } tx, err := db.Begin() if err != nil { return ClearRequestLogsResult{}, fmt.Errorf("usage: begin clear request logs: %w", err) } defer rollbackTx(tx) contentResult, err := tx.Exec("DELETE FROM request_log_content") if err != nil { return ClearRequestLogsResult{}, fmt.Errorf("usage: clear request_log_content: %w", err) } logResult, err := tx.Exec("DELETE FROM request_logs") if err != nil { return ClearRequestLogsResult{}, fmt.Errorf("usage: clear request_logs: %w", err) } deletedContents, _ := contentResult.RowsAffected() deletedLogs, _ := logResult.RowsAffected() if err := tx.Commit(); err != nil { return ClearRequestLogsResult{}, fmt.Errorf("usage: commit clear request logs: %w", err) } if _, err := db.Exec("VACUUM"); err != nil { log.Warnf("usage: vacuum after request log cleanup failed: %v", err) } return ClearRequestLogsResult{ DeletedLogs: deletedLogs, DeletedContents: deletedContents, }, nil } ``` -------------------------------- ### Hot Reloading Access Providers Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md This code demonstrates how to refresh configuration-backed providers and reset the access manager's provider chain for hot reloading. This enables runtime updates without restarting the process. ```go // configaccess is github.com/router-for-me/CLIProxyAPI/v6/internal/access/config_access configaccess.Register(&newCfg.SDKConfig) accessManager.SetProviders(sdkaccess.RegisteredProviders()) ``` -------------------------------- ### Commit and Push Changes Source: https://github.com/kittors/clirelay/blob/main/README.md How to commit your changes and push them to a feature branch for a pull request. ```bash # 3. Make your changes & commit git commit -m "feat: add amazing feature" # 4. Push to your branch & open a PR targeting dev git push origin feature/amazing-feature ``` -------------------------------- ### Commit Backend Changes Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md Command to stage and commit the modified Go files for the request log cleanup feature. ```bash git add internal/usage/usage_db.go internal/usage/usage_db_test.go git commit -m "feat: add request log database cleanup helper" ``` -------------------------------- ### Authenticate Requests Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Authenticate incoming requests using the manager. Handle success, no credentials, invalid credentials, or internal/transport failures. ```go result, authErr := manager.Authenticate(ctx, req) switch { case authErr == nil: // Authentication succeeded; result describes the provider and principal. case sdkaccess.IsAuthErrorCode(authErr, sdkaccess.AuthErrorCodeNoCredentials): // No recognizable credentials were supplied. case sdkaccess.IsAuthErrorCode(authErr, sdkaccess.AuthErrorCodeInvalidCredential): // Supplied credentials were present but rejected. default: // Internal/transport failure was returned by a provider. } ``` -------------------------------- ### Custom Core Auth Manager Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md Provide a custom core authentication manager to customize transports or hooks. Implement a custom http.RoundTripper for per-auth proxy settings. ```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() ``` ```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) } } ``` -------------------------------- ### Access Management Panel Source: https://github.com/kittors/clirelay/blob/main/README.md Open this URL in your browser to access the CliRelay management panel. Ensure the control panel is enabled in your configuration. ```bash http://localhost:8317/manage ``` -------------------------------- ### Authenticating Requests Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-access.md Shows how to authenticate requests using the manager and handle different authentication outcomes. ```APIDOC ## Authenticating Requests ```go result, authErr := manager.Authenticate(ctx, req) switch { case authErr == nil: // Authentication succeeded; result describes the provider and principal. case sdkaccess.IsAuthErrorCode(authErr, sdkaccess.AuthErrorCodeNoCredentials): // No recognizable credentials were supplied. case sdkaccess.IsAuthErrorCode(authErr, sdkaccess.AuthErrorCodeInvalidCredential): // Supplied credentials were present but rejected. default: // Internal/transport failure was returned by a provider. } ``` `Manager.Authenticate` walks the configured providers in order. It returns on the first success, skips providers that return `AuthErrorCodeNotHandled`, and aggregates `AuthErrorCodeNoCredentials` / `AuthErrorCodeInvalidCredential` for a final result. Each `Result` includes the provider identifier, the resolved principal, and optional metadata (for example, which header carried the credential). ``` -------------------------------- ### Define Management API Route for Request Log Cleanup Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md This line of code registers a DELETE route at `/usage/logs` that maps to the `DeleteUsageLogs` handler in the management API. ```go mgmt.DELETE("/usage/logs", s.mgmt.DeleteUsageLogs) ``` -------------------------------- ### Configure Request Log Storage Source: https://github.com/kittors/clirelay/blob/main/README.md Tune `request-log-storage` in `config.yaml` to control how request/response bodies are retained. Options include retention days, content storage, and maximum size. ```yaml request-log-storage: content-retention-days: 0 store-content: false max-total-size-mb: 1024 ``` -------------------------------- ### Register Request and Response Translators Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-advanced.md Register translation functions in the `sdk/translator` registry to convert between inbound and provider-specific schemas. This supports new provider formats by defining how to translate requests and responses. ```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) }, }, ) } ``` -------------------------------- ### Test ClearAllRequestLogsRemovesRequestLogTablesOnly Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md Tests that the ClearAllRequestLogs function correctly removes only the request log tables and their content. It initializes the database, inserts log data, calls the cleanup function, and verifies that the tables are empty. ```go func TestClearAllRequestLogsRemovesRequestLogTablesOnly(t *testing.T) { dbPath := t.TempDir() + "/usage.db" if err := InitDB(dbPath); err != nil { t.Fatalf("InitDB() error = %v", err) } defer CloseDB() entry := LogEntry{ Timestamp: time.Now().UTC(), APIKey: "sk-test", Model: "gpt-5", TotalTokens: 12, } logID, err := InsertLog(entry) if err != nil { t.Fatalf("InsertLog() error = %v", err) } if _, err := getDB().Exec( `INSERT INTO request_log_content (log_id, timestamp, compression, input_content, output_content) VALUES (?, ?, 'none', X'01', X'02')`, logID, time.Now().UTC().Format(time.RFC3339), ); err != nil { t.Fatalf("seed request_log_content error = %v", err) } result, err := ClearAllRequestLogs() if err != nil { t.Fatalf("ClearAllRequestLogs() error = %v", err) } if result.DeletedLogs != 1 || result.DeletedContents != 1 { t.Fatalf("unexpected cleanup result: %#v", result) } var logsCount, contentCount int if err := getDB().QueryRow("SELECT COUNT(*) FROM request_logs").Scan(&logsCount); err != nil { t.Fatalf("count request_logs error = %v", err) } if err := getDB().QueryRow("SELECT COUNT(*) FROM request_log_content").Scan(&contentCount); err != nil { t.Fatalf("count request_log_content error = %v", err) } if logsCount != 0 || contentCount != 0 { t.Fatalf("expected empty request log tables, got logs=%d content=%d", logsCount, contentCount) } } ``` -------------------------------- ### Management Endpoint for Clearing Request Logs Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/specs/2026-05-08-request-log-database-cleanup-design.md This is the backend API endpoint definition for initiating the request log cleanup. ```go DELETE /v0/management/usage/logs ``` -------------------------------- ### Commit Changes for Request Log Cleanup Feature Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md This bash script shows the commands to stage and commit the files modified for the request log cleanup feature, including backend, frontend, and test files. ```bash git add internal/api/handlers/management/usage_logs_handler.go internal/api/handlers/management/usage_logs_handler_test.go internal/api/server.go git commit -m "feat: expose request log cleanup management endpoint" ``` -------------------------------- ### Manual Shutdown of CLI Proxy Service Source: https://github.com/kittors/clirelay/blob/main/docs/sdk-usage.md Manually shut down the CLI proxy service using a context with a timeout. Cancelling the parent context is the default method. ```go ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) deferr cancel() _ = svc.Shutdown(ctx) ``` -------------------------------- ### Implement Management API Handler for Request Log Cleanup Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md This Go handler function, `DeleteUsageLogs`, is responsible for clearing all request logs from the database. It calls the `ClearAllRequestLogs` function and returns the result or an error. ```go func (h *Handler) DeleteUsageLogs(c *gin.Context) { result, err := usage.ClearAllRequestLogs() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, result) } ``` -------------------------------- ### Add Frontend UI Components for Request Log Cleanup Confirmation Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md This React JSX code renders a button to initiate the log cleanup and a confirmation modal. The modal requires user confirmation before proceeding with the cleanup action. ```typescript setConfirmClearOpen(false)} onConfirm={() => { setConfirmClearOpen(false); void handleClearDatabaseLogs(); }} /> ``` -------------------------------- ### Merge Feature Branch into Local Dev Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md Merge the 'clear-request-log-db' feature branch into the local 'dev' branch using a fast-forward merge, then push the changes. ```bash git checkout dev git merge --ff-only feature/issue-159-clear-request-log-db git push origin dev ``` -------------------------------- ### CliRelay Project Architecture Source: https://github.com/kittors/clirelay/blob/main/README.md This tree represents the directory structure of the CliRelay project, detailing the purpose of each major directory. ```text CliRelay/ ├── cmd/server/ # Binary entry point and CLI mode dispatch ├── internal/api/ # HTTP server, management routes, middleware ├── internal/auth/ # Provider OAuth / cookie / browser auth flows ├── internal/config/ # Config parsing, defaults, migrations ├── internal/store/ # Local, Git, PostgreSQL, object-store auth/config persistence ├── internal/tui/ # Terminal management UI ├── internal/usage/ # SQLite usage DB, retention, analytics ├── internal/managementasset/ # /manage panel hosting and asset sync ├── sdk/ # Reusable Go SDK, handlers, executors ├── auths/ # Local credential storage ├── examples/ # SDK / custom provider examples ├── docs/ # Local docs and panel screenshots └── docker-compose.yml # Container deployment entry ``` -------------------------------- ### Implement Frontend API Client for Request Log Cleanup Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md This TypeScript function `clearUsageLogs` makes a DELETE request to the `/usage/logs` endpoint using the `apiClient` to clear request logs. ```typescript async clearUsageLogs(): Promise<{ deleted_logs: number; deleted_contents: number }> { return apiClient.delete("/usage/logs"); } ``` -------------------------------- ### Frontend API Call for Clearing Usage Logs Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/specs/2026-05-08-request-log-database-cleanup-design.md This is the frontend JavaScript method used to call the backend API for clearing usage logs. ```typescript usageApi.clearUsageLogs() ``` -------------------------------- ### Write Failing Frontend Test for Request Log Cleanup Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md This test verifies that the frontend correctly triggers the request log cleanup action after user confirmation. It mocks API calls and checks for the expected UI state changes. ```typescript test("clears request-log database after confirmation", async () => { const user = userEvent.setup(); mocks.getUsageLogs .mockResolvedValueOnce({ items: [seedRow], total: 1, page: 1, size: 50, filters: { api_keys: [], api_key_names: {}, models: [], channels: [] }, stats: { total: 1, success_rate: 100, total_tokens: 30, total_cost: 0.01 }, }) .mockResolvedValueOnce({ items: [], total: 0, page: 1, size: 50, filters: { api_keys: [], api_key_names: {}, models: [], channels: [] }, stats: { total: 0, success_rate: 0, total_tokens: 0, total_cost: 0 }, }); mocks.clearUsageLogs.mockResolvedValue({ deleted_logs: 1, deleted_contents: 1 }); renderRequestLogsPage(); await user.click(await screen.findByRole("button", { name: /Clear Database Logs/i })); await user.click(await screen.findByRole("button", { name: /Clear/i })); await waitFor(() => expect(mocks.clearUsageLogs).toHaveBeenCalledTimes(1)); expect(await screen.findByText("No Data")).toBeInTheDocument(); }); ``` -------------------------------- ### Write Failing Handler Test for Request Log Cleanup Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md This test verifies the expected behavior of the `DeleteUsageLogs` handler before it is implemented. It checks the HTTP status code and response body for a successful deletion. ```go func TestDeleteUsageLogsClearsRequestLogDatabase(t *testing.T) { h := newTestManagementHandler(t) seedUsageLog(t) w := httptest.NewRecorder() c, _ := gin.CreateTestContext(w) c.Request = httptest.NewRequest(http.MethodDelete, "/usage/logs", nil) h.DeleteUsageLogs(c) if w.Code != http.StatusOK { t.Fatalf("status = %d, want %d", w.Code, http.StatusOK) } if !strings.Contains(w.Body.String(), `"deleted_logs":1`) { t.Fatalf("body = %s, want deleted count", w.Body.String()) } } ``` -------------------------------- ### Check Repository Status Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/plans/2026-05-08-request-log-database-cleanup.md Verify the Git repository status to ensure no unrelated changes are present in the feature branch. ```bash git status --short ``` -------------------------------- ### Frontend Component for Request Logs Page Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/specs/2026-05-08-request-log-database-cleanup-design.md This React component is responsible for rendering the Request Logs page, including the button to trigger the cleanup action. ```typescript src/modules/monitor/RequestLogsPage.tsx ``` -------------------------------- ### Usage-layer Helper for Clearing Request Logs Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/specs/2026-05-08-request-log-database-cleanup-design.md This Go function clears request log tables within a transaction and optionally runs a VACUUM. It returns the count of deleted rows. ```go func ClearAllRequestLogs() (ClearRequestLogsResult, error) { // ... implementation details ... } ``` -------------------------------- ### Suggested Response Shape for Log Cleanup Source: https://github.com/kittors/clirelay/blob/main/docs/superpowers/specs/2026-05-08-request-log-database-cleanup-design.md This JSON structure represents the expected response from the log cleanup API, indicating the number of deleted items. ```json { "deleted_logs": 12345, "deleted_contents": 12345 } ``` -------------------------------- ### Disable Automatic Update Checks Source: https://github.com/kittors/clirelay/blob/main/README.md Configure CliRelay to disable automatic update prompts by setting `enabled` to `false` in the `auto-update` section of `config.yaml`. ```yaml auto-update: enabled: false ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.