chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:35:43 +08:00
commit 0e2cc6b102
927 changed files with 260929 additions and 0 deletions
@@ -0,0 +1,8 @@
cmake_minimum_required(VERSION 3.16)
project(cliproxy_executor_c C)
add_library(cliproxy_executor_c SHARED src/plugin.c)
set_target_properties(cliproxy_executor_c PROPERTIES
OUTPUT_NAME "executor-c"
PREFIX ""
)
+129
View File
@@ -0,0 +1,129 @@
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32)
#define CLIPROXY_EXPORT __declspec(dllexport)
#else
#define CLIPROXY_EXPORT __attribute__((visibility("default")))
#endif
#define ABI_VERSION 1
typedef struct {
void* ptr;
size_t len;
} cliproxy_buffer;
typedef int (*cliproxy_host_call_fn)(void*, const char*, const uint8_t*, size_t, cliproxy_buffer*);
typedef void (*cliproxy_host_free_fn)(void*, size_t);
typedef struct {
uint32_t abi_version;
void* host_ctx;
cliproxy_host_call_fn call;
cliproxy_host_free_fn free_buffer;
} cliproxy_host_api;
typedef int (*cliproxy_plugin_call_fn)(const char*, const 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;
static const cliproxy_host_api* stored_host = NULL;
static void write_response(cliproxy_buffer* response, const char* text) {
if (response == NULL || text == NULL) {
return;
}
size_t len = strlen(text);
void* ptr = malloc(len);
if (ptr == NULL) {
response->ptr = NULL;
response->len = 0;
return;
}
memcpy(ptr, text, len);
response->ptr = ptr;
response->len = len;
}
static void call_host(const char* method, const char* payload) {
if (stored_host == NULL || stored_host->call == NULL || method == NULL) {
return;
}
cliproxy_buffer response = {0};
const uint8_t* request = (const uint8_t*)payload;
size_t request_len = payload == NULL ? 0 : strlen(payload);
if (stored_host->call(stored_host->host_ctx, method, request, request_len, &response) == 0 && response.ptr != NULL && stored_host->free_buffer != NULL) {
stored_host->free_buffer(response.ptr, response.len);
}
}
static int plugin_call(const char* method, const uint8_t* request, size_t request_len, cliproxy_buffer* response) {
if (response != NULL) {
response->ptr = NULL;
response->len = 0;
}
if (method == NULL) {
write_response(response, "{\"ok\":false,\"error\":{\"code\":\"invalid_method\",\"message\":\"method is required\"}}");
return 1;
}
if (strcmp(method, "plugin.register") == 0) {
write_response(response, "{\"ok\":true,\"result\":{\"schema_version\":1,\"metadata\":{\"Name\":\"example-executor-c\",\"Version\":\"0.1.0\",\"Author\":\"router-for-me\",\"GitHubRepository\":\"https://github.com/router-for-me/CLIProxyAPI\",\"Logo\":\"https://example.invalid/example-executor-c.png\",\"ConfigFields\":[]},\"capabilities\":{\"executor\":true,\"executor_model_scope\":\"both\",\"executor_input_formats\":[\"chat-completions\"],\"executor_output_formats\":[\"chat-completions\"]}}}");
return 0;
}
if (strcmp(method, "plugin.reconfigure") == 0) {
write_response(response, "{\"ok\":true,\"result\":{\"schema_version\":1,\"metadata\":{\"Name\":\"example-executor-c\",\"Version\":\"0.1.0\",\"Author\":\"router-for-me\",\"GitHubRepository\":\"https://github.com/router-for-me/CLIProxyAPI\",\"Logo\":\"https://example.invalid/example-executor-c.png\",\"ConfigFields\":[]},\"capabilities\":{\"executor\":true,\"executor_model_scope\":\"both\",\"executor_input_formats\":[\"chat-completions\"],\"executor_output_formats\":[\"chat-completions\"]}}}");
return 0;
}
if (strcmp(method, "executor.identifier") == 0) {
write_response(response, "{\"ok\":true,\"result\":{\"identifier\":\"example-executor-c\"}}");
return 0;
}
if (strcmp(method, "executor.execute") == 0) {
write_response(response, "{\"ok\":true,\"result\":{\"Payload\":\"eyJpZCI6ImV4YW1wbGUtZXhlY3V0b3ItYyIsIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbiJ9\",\"Headers\":{\"content-type\":[\"application/json\"]}}}");
return 0;
}
if (strcmp(method, "executor.execute_stream") == 0) {
write_response(response, "{\"ok\":true,\"result\":{\"headers\":{\"content-type\":[\"text/event-stream\"]},\"chunks\":[{\"Payload\":\"ImRhdGE6IGV4YW1wbGUtZXhlY3V0b3ItY1xuXG4i\"}]}}");
return 0;
}
if (strcmp(method, "executor.count_tokens") == 0) {
write_response(response, "{\"ok\":true,\"result\":{\"Payload\":\"eyJ0b3RhbF90b2tlbnMiOjB9\"}}");
return 0;
}
if (strcmp(method, "executor.http_request") == 0) {
write_response(response, "{\"ok\":true,\"result\":{\"StatusCode\":200,\"Headers\":{\"content-type\":[\"application/json\"]},\"Body\":\"eyJwbHVnaW4iOiJleGFtcGxlLWV4ZWN1dG9yLWMifQ==\"}}");
return 0;
}
write_response(response, "{\"ok\":false,\"error\":{\"code\":\"unknown_method\",\"message\":\"unknown method\"}}");
(void)request;
(void)request_len;
return 0;
}
static void plugin_free(void* ptr, size_t len) {
(void)len;
free(ptr);
}
static void plugin_shutdown(void) {}
CLIPROXY_EXPORT int cliproxy_plugin_init(const cliproxy_host_api* host, cliproxy_plugin_api* plugin) {
if (plugin == NULL) {
return 1;
}
stored_host = host;
plugin->abi_version = ABI_VERSION;
plugin->call = plugin_call;
plugin->free_buffer = plugin_free;
plugin->shutdown = plugin_shutdown;
return 0;
}
+3
View File
@@ -0,0 +1,3 @@
module github.com/router-for-me/CLIProxyAPI/v7/examples/plugin/executor/go
go 1.26
+181
View File
@@ -0,0 +1,181 @@
package main
/*
#include <stdint.h>
#include <stdlib.h>
typedef struct {
void* ptr;
size_t len;
} cliproxy_buffer;
typedef int (*cliproxy_host_call_fn)(void*, const char*, const uint8_t*, size_t, cliproxy_buffer*);
typedef void (*cliproxy_host_free_fn)(void*, size_t);
typedef struct {
uint32_t abi_version;
void* host_ctx;
cliproxy_host_call_fn call;
cliproxy_host_free_fn 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);
static const cliproxy_host_api* stored_host;
static void store_host_api(const cliproxy_host_api* host) {
stored_host = host;
}
static int call_host_api(const char* method, const uint8_t* request, size_t request_len, cliproxy_buffer* response) {
if (stored_host == NULL || stored_host->call == NULL) {
return 1;
}
return stored_host->call(stored_host->host_ctx, method, request, request_len, response);
}
static void free_host_buffer(void* ptr, size_t len) {
if (stored_host != NULL && stored_host->free_buffer != NULL && ptr != NULL) {
stored_host->free_buffer(ptr, len);
}
}
*/
import "C"
import (
"encoding/json"
"net/http"
"time"
"unsafe"
)
const abiVersion uint32 = 1
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"`
}
func main() {}
//export cliproxy_plugin_init
func cliproxy_plugin_init(host *C.cliproxy_host_api, plugin *C.cliproxy_plugin_api) C.int {
if plugin == nil {
return 1
}
C.store_host_api(host)
plugin.abi_version = C.uint32_t(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
}
raw, errHandle := handleMethod(C.GoString(method))
if errHandle != nil {
writeResponse(response, errorEnvelope("plugin_error", errHandle.Error()))
return 1
}
writeResponse(response, raw)
_ = request
_ = requestLen
return 0
}
//export cliproxyPluginFree
func cliproxyPluginFree(ptr unsafe.Pointer, len C.size_t) {
if ptr != nil {
C.free(ptr)
}
_ = len
}
//export cliproxyPluginShutdown
func cliproxyPluginShutdown() {}
func handleMethod(method string) ([]byte, error) {
_ = http.StatusOK
_ = time.Second
switch method {
case "plugin.register":
return okEnvelopeJSON("{\"schema_version\":1,\"metadata\":{\"Name\":\"example-executor-go\",\"Version\":\"0.1.0\",\"Author\":\"router-for-me\",\"GitHubRepository\":\"https://github.com/router-for-me/CLIProxyAPI\",\"Logo\":\"https://example.invalid/example-executor-go.png\",\"ConfigFields\":[]},\"capabilities\":{\"executor\":true,\"executor_model_scope\":\"both\",\"executor_input_formats\":[\"chat-completions\"],\"executor_output_formats\":[\"chat-completions\"]}}")
case "plugin.reconfigure":
return okEnvelopeJSON("{\"schema_version\":1,\"metadata\":{\"Name\":\"example-executor-go\",\"Version\":\"0.1.0\",\"Author\":\"router-for-me\",\"GitHubRepository\":\"https://github.com/router-for-me/CLIProxyAPI\",\"Logo\":\"https://example.invalid/example-executor-go.png\",\"ConfigFields\":[]},\"capabilities\":{\"executor\":true,\"executor_model_scope\":\"both\",\"executor_input_formats\":[\"chat-completions\"],\"executor_output_formats\":[\"chat-completions\"]}}")
case "executor.identifier":
return okEnvelopeJSON("{\"identifier\":\"example-executor-go\"}")
case "executor.execute":
return okEnvelopeJSON("{\"Payload\":\"eyJpZCI6ImV4YW1wbGUtZXhlY3V0b3ItZ28iLCJvYmplY3QiOiJjaGF0LmNvbXBsZXRpb24ifQ==\",\"Headers\":{\"content-type\":[\"application/json\"]}}")
case "executor.execute_stream":
return okEnvelopeJSON("{\"headers\":{\"content-type\":[\"text/event-stream\"]},\"chunks\":[{\"Payload\":\"ImRhdGE6IGV4YW1wbGUtZXhlY3V0b3ItZ29cblxuIg==\"}]}")
case "executor.count_tokens":
return okEnvelopeJSON("{\"Payload\":\"eyJ0b3RhbF90b2tlbnMiOjB9\"}")
case "executor.http_request":
return okEnvelopeJSON("{\"StatusCode\":200,\"Headers\":{\"content-type\":[\"application/json\"]},\"Body\":\"eyJwbHVnaW4iOiJleGFtcGxlLWV4ZWN1dG9yLWdvIn0=\"}")
default:
return errorEnvelope("unknown_method", "unknown method: "+method), nil
}
}
func okEnvelopeJSON(result string) ([]byte, error) {
return json.Marshal(envelope{OK: true, Result: json.RawMessage(result)})
}
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))
}
func callHost(method string, payload []byte) {
cMethod := C.CString(method)
defer C.free(unsafe.Pointer(cMethod))
var response C.cliproxy_buffer
var req *C.uint8_t
if len(payload) > 0 {
req = (*C.uint8_t)(C.CBytes(payload))
defer C.free(unsafe.Pointer(req))
}
if C.call_host_api(cMethod, req, C.size_t(len(payload)), &response) == 0 && response.ptr != nil {
C.free_host_buffer(response.ptr, response.len)
}
}
+7
View File
@@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "cliproxy-executor-rust"
version = "0.1.0"
+7
View File
@@ -0,0 +1,7 @@
[package]
name = "cliproxy-executor-rust"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
+127
View File
@@ -0,0 +1,127 @@
use std::ffi::CStr;
use std::os::raw::c_char;
use std::ptr;
const ABI_VERSION: u32 = 1;
#[repr(C)]
pub struct CliproxyBuffer {
ptr: *mut u8,
len: usize,
}
type HostCall = unsafe extern "C" fn(*mut std::ffi::c_void, *const c_char, *const u8, usize, *mut CliproxyBuffer) -> i32;
type HostFree = unsafe extern "C" fn(*mut std::ffi::c_void, usize);
type PluginCall = unsafe extern "C" fn(*const c_char, *const u8, usize, *mut CliproxyBuffer) -> i32;
type PluginFree = unsafe extern "C" fn(*mut std::ffi::c_void, usize);
type PluginShutdown = unsafe extern "C" fn();
#[repr(C)]
pub struct CliproxyHostApi {
abi_version: u32,
host_ctx: *mut std::ffi::c_void,
call: Option<HostCall>,
free_buffer: Option<HostFree>,
}
#[repr(C)]
pub struct CliproxyPluginApi {
abi_version: u32,
call: Option<PluginCall>,
free_buffer: Option<PluginFree>,
shutdown: Option<PluginShutdown>,
}
static mut STORED_HOST: *const CliproxyHostApi = ptr::null();
#[no_mangle]
pub extern "C" fn cliproxy_plugin_init(host: *const CliproxyHostApi, plugin: *mut CliproxyPluginApi) -> i32 {
if plugin.is_null() {
return 1;
}
unsafe {
STORED_HOST = host;
(*plugin).abi_version = ABI_VERSION;
(*plugin).call = Some(plugin_call);
(*plugin).free_buffer = Some(plugin_free);
(*plugin).shutdown = Some(plugin_shutdown);
}
0
}
unsafe extern "C" fn plugin_call(method: *const c_char, request: *const u8, request_len: usize, response: *mut CliproxyBuffer) -> i32 {
if !response.is_null() {
(*response).ptr = ptr::null_mut();
(*response).len = 0;
}
if method.is_null() {
write_response(response, r#"{"ok":false,"error":{"code":"invalid_method","message":"method is required"}}"#);
return 1;
}
let method = match CStr::from_ptr(method).to_str() {
Ok(value) => value,
Err(_) => {
write_response(response, r#"{"ok":false,"error":{"code":"invalid_method","message":"method is not utf-8"}}"#);
return 1;
}
};
let _ = request;
let _ = request_len;
match method {
"plugin.register" => { write_response(response, "{\"ok\":true,\"result\":{\"schema_version\":1,\"metadata\":{\"Name\":\"example-executor-rust\",\"Version\":\"0.1.0\",\"Author\":\"router-for-me\",\"GitHubRepository\":\"https://github.com/router-for-me/CLIProxyAPI\",\"Logo\":\"https://example.invalid/example-executor-rust.png\",\"ConfigFields\":[]},\"capabilities\":{\"executor\":true,\"executor_model_scope\":\"both\",\"executor_input_formats\":[\"chat-completions\"],\"executor_output_formats\":[\"chat-completions\"]}}}"); 0 },"plugin.reconfigure" => { write_response(response, "{\"ok\":true,\"result\":{\"schema_version\":1,\"metadata\":{\"Name\":\"example-executor-rust\",\"Version\":\"0.1.0\",\"Author\":\"router-for-me\",\"GitHubRepository\":\"https://github.com/router-for-me/CLIProxyAPI\",\"Logo\":\"https://example.invalid/example-executor-rust.png\",\"ConfigFields\":[]},\"capabilities\":{\"executor\":true,\"executor_model_scope\":\"both\",\"executor_input_formats\":[\"chat-completions\"],\"executor_output_formats\":[\"chat-completions\"]}}}"); 0 },"executor.identifier" => { write_response(response, "{\"ok\":true,\"result\":{\"identifier\":\"example-executor-rust\"}}"); 0 },"executor.execute" => { write_response(response, "{\"ok\":true,\"result\":{\"Payload\":\"eyJpZCI6ImV4YW1wbGUtZXhlY3V0b3ItcnVzdCIsIm9iamVjdCI6ImNoYXQuY29tcGxldGlvbiJ9\",\"Headers\":{\"content-type\":[\"application/json\"]}}}"); 0 },"executor.execute_stream" => { write_response(response, "{\"ok\":true,\"result\":{\"headers\":{\"content-type\":[\"text/event-stream\"]},\"chunks\":[{\"Payload\":\"ImRhdGE6IGV4YW1wbGUtZXhlY3V0b3ItcnVzdFxuXG4i\"}]}}"); 0 },"executor.count_tokens" => { write_response(response, "{\"ok\":true,\"result\":{\"Payload\":\"eyJ0b3RhbF90b2tlbnMiOjB9\"}}"); 0 },"executor.http_request" => { write_response(response, "{\"ok\":true,\"result\":{\"StatusCode\":200,\"Headers\":{\"content-type\":[\"application/json\"]},\"Body\":\"eyJwbHVnaW4iOiJleGFtcGxlLWV4ZWN1dG9yLXJ1c3QifQ==\"}}"); 0 },
_ => {
write_response(response, r#"{"ok":false,"error":{"code":"unknown_method","message":"unknown method"}}"#);
0
}
}
}
unsafe extern "C" fn plugin_free(ptr: *mut std::ffi::c_void, len: usize) {
if !ptr.is_null() {
let _ = Vec::from_raw_parts(ptr as *mut u8, len, len);
}
}
unsafe extern "C" fn plugin_shutdown() {}
fn write_response(response: *mut CliproxyBuffer, text: &str) {
if response.is_null() {
return;
}
let mut bytes = text.as_bytes().to_vec();
let len = bytes.len();
let ptr = bytes.as_mut_ptr();
std::mem::forget(bytes);
unsafe {
(*response).ptr = ptr;
(*response).len = len;
}
}
#[allow(dead_code)]
fn call_host(method: &str, payload: &str) {
unsafe {
if STORED_HOST.is_null() {
return;
}
let host = &*STORED_HOST;
let Some(call) = host.call else {
return;
};
let mut method_bytes = method.as_bytes().to_vec();
method_bytes.push(0);
let mut response = CliproxyBuffer { ptr: ptr::null_mut(), len: 0 };
let rc = call(
host.host_ctx,
method_bytes.as_ptr() as *const c_char,
payload.as_ptr(),
payload.len(),
&mut response,
);
if rc == 0 && !response.ptr.is_null() {
if let Some(free_buffer) = host.free_buffer {
free_buffer(response.ptr as *mut std::ffi::c_void, response.len);
}
}
}
}