Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
25
backend/examples/plugin/codex-service-tier/README.md
Normal file
25
backend/examples/plugin/codex-service-tier/README.md
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
# Codex Service Tier Plugin
|
||||
|
||||
This plugin is a request normalizer for Codex outbound requests.
|
||||
|
||||
When the plugin is enabled and `fast` is set to `true`, it sets the top-level `service_tier` field to `priority` for requests where:
|
||||
|
||||
- `req.ToFormat` is `codex`
|
||||
- `req.Model` is `gpt-5.5`
|
||||
|
||||
Requests that do not match these conditions are returned unchanged.
|
||||
|
||||
## Configuration
|
||||
|
||||
Add the plugin under `plugins.configs`:
|
||||
|
||||
```yaml
|
||||
plugins:
|
||||
configs:
|
||||
codex-service-tier:
|
||||
enabled: true
|
||||
priority: 1
|
||||
fast: false
|
||||
```
|
||||
|
||||
`fast` is a boolean field. Set it to `true` to enable priority service tier shaping for matching Codex `gpt-5.5` requests.
|
||||
17
backend/examples/plugin/codex-service-tier/go/go.mod
Normal file
17
backend/examples/plugin/codex-service-tier/go/go.mod
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
module github.com/router-for-me/CLIProxyAPI/v7/examples/plugin/codex-service-tier/go
|
||||
|
||||
go 1.26.0
|
||||
|
||||
require (
|
||||
github.com/router-for-me/CLIProxyAPI/v7 v7.0.0
|
||||
github.com/tidwall/sjson v1.2.5
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.0 // indirect
|
||||
)
|
||||
|
||||
replace github.com/router-for-me/CLIProxyAPI/v7 => ../../../..
|
||||
13
backend/examples/plugin/codex-service-tier/go/go.sum
Normal file
13
backend/examples/plugin/codex-service-tier/go/go.sum
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||
github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY=
|
||||
github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
246
backend/examples/plugin/codex-service-tier/go/main.go
Normal file
246
backend/examples/plugin/codex-service-tier/go/main.go
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
package main
|
||||
|
||||
/*
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
typedef struct {
|
||||
void* ptr;
|
||||
size_t len;
|
||||
} cliproxy_buffer;
|
||||
|
||||
typedef struct {
|
||||
uint32_t abi_version;
|
||||
void* host_ctx;
|
||||
void* call;
|
||||
void* free_buffer;
|
||||
} cliproxy_host_api;
|
||||
|
||||
typedef int (*cliproxy_plugin_call_fn)(char*, uint8_t*, size_t, cliproxy_buffer*);
|
||||
typedef void (*cliproxy_plugin_free_fn)(void*, size_t);
|
||||
typedef void (*cliproxy_plugin_shutdown_fn)(void);
|
||||
|
||||
typedef struct {
|
||||
uint32_t abi_version;
|
||||
cliproxy_plugin_call_fn call;
|
||||
cliproxy_plugin_free_fn free_buffer;
|
||||
cliproxy_plugin_shutdown_fn shutdown;
|
||||
} cliproxy_plugin_api;
|
||||
|
||||
extern int cliproxyPluginCall(char*, uint8_t*, size_t, cliproxy_buffer*);
|
||||
extern void cliproxyPluginFree(void*, size_t);
|
||||
extern void cliproxyPluginShutdown(void);
|
||||
*/
|
||||
import "C"
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strings"
|
||||
"sync/atomic"
|
||||
"unsafe"
|
||||
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/sdk/pluginabi"
|
||||
"github.com/router-for-me/CLIProxyAPI/v7/sdk/pluginapi"
|
||||
"github.com/tidwall/sjson"
|
||||
"gopkg.in/yaml.v3"
|
||||
)
|
||||
|
||||
var fastEnabled atomic.Bool
|
||||
|
||||
type envelope struct {
|
||||
OK bool `json:"ok"`
|
||||
Result json.RawMessage `json:"result,omitempty"`
|
||||
Error *envelopeError `json:"error,omitempty"`
|
||||
}
|
||||
|
||||
type envelopeError struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"message"`
|
||||
}
|
||||
|
||||
type lifecycleRequest struct {
|
||||
ConfigYAML []byte `json:"config_yaml"`
|
||||
}
|
||||
|
||||
type pluginConfig struct {
|
||||
Fast bool `yaml:"fast"`
|
||||
}
|
||||
|
||||
type registration struct {
|
||||
SchemaVersion uint32 `json:"schema_version"`
|
||||
Metadata pluginapi.Metadata `json:"metadata"`
|
||||
Capabilities registrationCapability `json:"capabilities"`
|
||||
}
|
||||
|
||||
type registrationCapability struct {
|
||||
RequestNormalizer bool `json:"request_normalizer"`
|
||||
}
|
||||
|
||||
func main() {}
|
||||
|
||||
//export cliproxy_plugin_init
|
||||
func cliproxy_plugin_init(_ *C.cliproxy_host_api, plugin *C.cliproxy_plugin_api) C.int {
|
||||
if plugin == nil {
|
||||
return 1
|
||||
}
|
||||
plugin.abi_version = C.uint32_t(pluginabi.ABIVersion)
|
||||
plugin.call = C.cliproxy_plugin_call_fn(C.cliproxyPluginCall)
|
||||
plugin.free_buffer = C.cliproxy_plugin_free_fn(C.cliproxyPluginFree)
|
||||
plugin.shutdown = C.cliproxy_plugin_shutdown_fn(C.cliproxyPluginShutdown)
|
||||
return 0
|
||||
}
|
||||
|
||||
//export cliproxyPluginCall
|
||||
func cliproxyPluginCall(method *C.char, request *C.uint8_t, requestLen C.size_t, response *C.cliproxy_buffer) C.int {
|
||||
if response != nil {
|
||||
response.ptr = nil
|
||||
response.len = 0
|
||||
}
|
||||
if method == nil {
|
||||
writeResponse(response, errorEnvelope("invalid_method", "method is required"))
|
||||
return 1
|
||||
}
|
||||
var requestBytes []byte
|
||||
if request != nil && requestLen > 0 {
|
||||
requestBytes = C.GoBytes(unsafe.Pointer(request), C.int(requestLen))
|
||||
}
|
||||
raw, errHandle := handleMethod(C.GoString(method), requestBytes)
|
||||
if errHandle != nil {
|
||||
writeResponse(response, errorEnvelope("plugin_error", errHandle.Error()))
|
||||
return 1
|
||||
}
|
||||
writeResponse(response, raw)
|
||||
return 0
|
||||
}
|
||||
|
||||
//export cliproxyPluginFree
|
||||
func cliproxyPluginFree(ptr unsafe.Pointer, len C.size_t) {
|
||||
if ptr != nil {
|
||||
C.free(ptr)
|
||||
}
|
||||
}
|
||||
|
||||
//export cliproxyPluginShutdown
|
||||
func cliproxyPluginShutdown() {}
|
||||
|
||||
func handleMethod(method string, request []byte) ([]byte, error) {
|
||||
switch method {
|
||||
case pluginabi.MethodPluginRegister, pluginabi.MethodPluginReconfigure:
|
||||
if errConfigure := configure(request); errConfigure != nil {
|
||||
return nil, errConfigure
|
||||
}
|
||||
return okEnvelope(pluginRegistration())
|
||||
case pluginabi.MethodRequestNormalize:
|
||||
return normalizeRequest(request)
|
||||
default:
|
||||
return errorEnvelope("unknown_method", "unknown method: "+method), nil
|
||||
}
|
||||
}
|
||||
|
||||
func configure(raw []byte) error {
|
||||
var req lifecycleRequest
|
||||
if len(raw) > 0 {
|
||||
if errUnmarshal := json.Unmarshal(raw, &req); errUnmarshal != nil {
|
||||
return errUnmarshal
|
||||
}
|
||||
}
|
||||
|
||||
cfg := pluginConfig{}
|
||||
if len(req.ConfigYAML) > 0 {
|
||||
fast, errDecodeFast := decodeFastConfig(req.ConfigYAML)
|
||||
if errDecodeFast != nil {
|
||||
return errDecodeFast
|
||||
}
|
||||
cfg.Fast = fast
|
||||
}
|
||||
fastEnabled.Store(cfg.Fast)
|
||||
return nil
|
||||
}
|
||||
|
||||
func pluginRegistration() registration {
|
||||
return registration{
|
||||
SchemaVersion: pluginabi.SchemaVersion,
|
||||
Metadata: pluginapi.Metadata{
|
||||
Name: "codex-service-tier",
|
||||
Version: "0.1.0",
|
||||
Author: "router-for-me",
|
||||
GitHubRepository: "https://github.com/router-for-me/CLIProxyAPI",
|
||||
Logo: "https://raw.githubusercontent.com/router-for-me/CLIProxyAPI/main/docs/logo.png",
|
||||
ConfigFields: []pluginapi.ConfigField{{
|
||||
Name: "fast",
|
||||
Type: pluginapi.ConfigFieldTypeBoolean,
|
||||
Description: "Sets Codex gpt-5.5 Responses requests to the priority service tier.",
|
||||
}},
|
||||
},
|
||||
Capabilities: registrationCapability{
|
||||
RequestNormalizer: true,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func normalizeRequest(raw []byte) ([]byte, error) {
|
||||
var req pluginapi.RequestTransformRequest
|
||||
if errUnmarshal := json.Unmarshal(raw, &req); errUnmarshal != nil {
|
||||
return nil, errUnmarshal
|
||||
}
|
||||
body := req.Body
|
||||
if !shouldSetPriorityServiceTier(req) {
|
||||
return okEnvelope(pluginapi.PayloadResponse{Body: body})
|
||||
}
|
||||
updated, okSet := setPriorityServiceTier(body)
|
||||
if !okSet {
|
||||
return okEnvelope(pluginapi.PayloadResponse{Body: body})
|
||||
}
|
||||
return okEnvelope(pluginapi.PayloadResponse{Body: updated})
|
||||
}
|
||||
|
||||
func shouldSetPriorityServiceTier(req pluginapi.RequestTransformRequest) bool {
|
||||
if !fastEnabled.Load() {
|
||||
return false
|
||||
}
|
||||
if !strings.EqualFold(req.ToFormat, "codex") {
|
||||
return false
|
||||
}
|
||||
return req.Model == "gpt-5.5"
|
||||
}
|
||||
|
||||
func decodeFastConfig(configYAML []byte) (bool, error) {
|
||||
var cfg pluginConfig
|
||||
if errUnmarshal := yaml.Unmarshal(configYAML, &cfg); errUnmarshal != nil {
|
||||
return false, errUnmarshal
|
||||
}
|
||||
return cfg.Fast, nil
|
||||
}
|
||||
|
||||
func setPriorityServiceTier(body []byte) ([]byte, bool) {
|
||||
updated, errSet := sjson.SetBytes(body, "service_tier", "priority")
|
||||
if errSet != nil {
|
||||
return nil, false
|
||||
}
|
||||
return updated, true
|
||||
}
|
||||
|
||||
func okEnvelope(v any) ([]byte, error) {
|
||||
raw, errMarshal := json.Marshal(v)
|
||||
if errMarshal != nil {
|
||||
return nil, errMarshal
|
||||
}
|
||||
return json.Marshal(envelope{OK: true, Result: raw})
|
||||
}
|
||||
|
||||
func errorEnvelope(code, message string) []byte {
|
||||
raw, _ := json.Marshal(envelope{OK: false, Error: &envelopeError{Code: code, Message: message}})
|
||||
return raw
|
||||
}
|
||||
|
||||
func writeResponse(response *C.cliproxy_buffer, raw []byte) {
|
||||
if response == nil || len(raw) == 0 {
|
||||
return
|
||||
}
|
||||
ptr := C.CBytes(raw)
|
||||
if ptr == nil {
|
||||
return
|
||||
}
|
||||
response.ptr = ptr
|
||||
response.len = C.size_t(len(raw))
|
||||
}
|
||||
Loading…
Reference in a new issue