mirror of
https://gitcode.com/JianFeeeee/HomeAgent.git
synced 2026-09-23 10:28:06 +00:00
lua: 吸收 llmsproxy 适配器高级特性(worker 池/静态预提取/动态签名钩子)
- 适配器 worker 池化:单 LState+全局锁(串行瓶颈)→ 每 adapter 一个 gopher-lua LState 池,按使用该 adapter 的源并发上限求和配置池大小,并发 transform 互不阻塞 - staticInfo 预提取:name/version/endpoint/headers 加载期编译缓存,Endpoint/Headers 读缓存不占 worker;加载即预编译首个 worker - build_headers 动态钩子 + hmac/sha256/base64/tohex 全局:签名型上游(kimicode 等)可接入 - provider applyAdapterHeaders 接入动态头(url/method/body/api_key/timestamp/source 元数据), 未定义时回落静态 headers,缺省补 Authorization - LLMSource.MaxConcurrent + core.llm.sources.<name>.max_concurrent,注册时汇总 VM.ConfigureConcurrency - 新增 Lua VM 测试(load/transform/build_headers/并发) 验证: go test ./... 27 包 0 失败;Windows 交叉编译通过;部署后 9 adapter 全部预加载
This commit is contained in:
137
internal/lua/vm_test.go
Normal file
137
internal/lua/vm_test.go
Normal file
@ -0,0 +1,137 @@
|
||||
package lua
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestVMLoadAndTransform(t *testing.T) {
|
||||
vm := NewVM(t.TempDir())
|
||||
if err := vm.Start(); err != nil {
|
||||
t.Fatalf("start vm: %v", err)
|
||||
}
|
||||
defer vm.Stop()
|
||||
|
||||
out, err := vm.CallTransformRequest("openai", `{"model":"x"}`)
|
||||
if err != nil {
|
||||
t.Fatalf("transform_request: %v", err)
|
||||
}
|
||||
if !strings.Contains(out, `"model":"x"`) {
|
||||
t.Fatalf("unexpected output: %s", out)
|
||||
}
|
||||
|
||||
ep := vm.GetAdapterEndpoint("openai")
|
||||
if ep == "" {
|
||||
t.Fatal("openai endpoint empty")
|
||||
}
|
||||
hdrs := vm.GetAdapterHeaders("openai")
|
||||
if hdrs == nil {
|
||||
t.Fatal("openai headers nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadCustomAdapter(t *testing.T) {
|
||||
vm := NewVM(t.TempDir())
|
||||
if err := vm.Start(); err != nil {
|
||||
t.Fatalf("start vm: %v", err)
|
||||
}
|
||||
defer vm.Stop()
|
||||
|
||||
code := `
|
||||
local adapter = {}
|
||||
adapter.name = "testa"
|
||||
adapter.version = "1.0"
|
||||
adapter.endpoint = "/x"
|
||||
adapter.headers = { ["X-A"] = "1" }
|
||||
function adapter.transform_request(raw) return "REQ" end
|
||||
function adapter.build_headers(meta) return { ["X-Key"] = "k" } end
|
||||
function adapter.transform_response(raw) return "RESP" end
|
||||
function adapter.transform_stream_chunk(raw) return "CHUNK" end
|
||||
return adapter
|
||||
`
|
||||
if err := vm.LoadAdapterSource("testa", code); err != nil {
|
||||
t.Fatalf("load adapter: %v", err)
|
||||
}
|
||||
|
||||
if out, err := vm.CallTransformRequest("testa", "x"); err != nil || out != "REQ" {
|
||||
t.Fatalf("req=%q err=%v", out, err)
|
||||
}
|
||||
if out, err := vm.CallTransformResponse("testa", "x"); err != nil || out != "RESP" {
|
||||
t.Fatalf("resp=%q err=%v", out, err)
|
||||
}
|
||||
if out, err := vm.CallTransformStreamChunk("testa", "x"); err != nil || out != "CHUNK" {
|
||||
t.Fatalf("chunk=%q err=%v", out, err)
|
||||
}
|
||||
|
||||
meta := map[string]interface{}{"url": "http://x", "api_key": "k1"}
|
||||
hdrs, err := vm.BuildHeaders("testa", meta)
|
||||
if err != nil {
|
||||
t.Fatalf("build_headers: %v", err)
|
||||
}
|
||||
if hdrs["X-Key"] != "k" {
|
||||
t.Fatalf("missing dynamic header: %v", hdrs)
|
||||
}
|
||||
|
||||
if ep := vm.GetAdapterEndpoint("testa"); ep != "/x" {
|
||||
t.Fatalf("endpoint=%q", ep)
|
||||
}
|
||||
if st := vm.GetAdapterHeaders("testa"); st["X-A"] != "1" {
|
||||
t.Fatalf("static headers=%v", st)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMLoadStaticHeaderFallback(t *testing.T) {
|
||||
vm := NewVM(t.TempDir())
|
||||
if err := vm.Start(); err != nil {
|
||||
t.Fatalf("start vm: %v", err)
|
||||
}
|
||||
defer vm.Stop()
|
||||
|
||||
code := `
|
||||
local adapter = {}
|
||||
adapter.name = "statics"
|
||||
adapter.headers = { ["X-S"] = "s" }
|
||||
function adapter.transform_request(raw) return raw end
|
||||
return adapter
|
||||
`
|
||||
if err := vm.LoadAdapterSource("statics", code); err != nil {
|
||||
t.Fatalf("load: %v", err)
|
||||
}
|
||||
hdrs, err := vm.BuildHeaders("statics", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("build_headers: %v", err)
|
||||
}
|
||||
if hdrs["X-S"] != "s" {
|
||||
t.Fatalf("expected static fallback, got %v", hdrs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestVMConcurrentCalls(t *testing.T) {
|
||||
vm := NewVM(t.TempDir())
|
||||
if err := vm.Start(); err != nil {
|
||||
t.Fatalf("start vm: %v", err)
|
||||
}
|
||||
defer vm.Stop()
|
||||
|
||||
var wg sync.WaitGroup
|
||||
errs := make(chan error, 40)
|
||||
for i := 0; i < 20; i++ {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
for j := 0; j < 10; j++ {
|
||||
_, err := vm.CallTransformRequest("openai", `{"model":"x"}`)
|
||||
if err != nil {
|
||||
errs <- err
|
||||
return
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
wg.Wait()
|
||||
close(errs)
|
||||
for err := range errs {
|
||||
t.Fatalf("concurrent call: %v", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user