mirror of
https://github.com/Tencent/WeKnora.git
synced 2026-10-24 01:37:50 +08:00
Plugin config forms can now ask the plugin while they are filled in:
- x-options {name, dependsOn, search} loads a field's choices from
/v1/options/{name}. POST /api/v1/plugins/:id/options merges the form's
values with the stored secrets (system, tenant or instance scope) so a
redacted token still works. Go and Python SDKs, OpenAPI and conformance
cover the endpoint.
- x-oauth turns a string field into an account connection. WeKnora runs
the authorization code flow (PKCE, client credentials from the plugin's
system config), keeps the tokens sealed in plugin_oauth_connections and
the field holds "oauth:<id>". The invoker swaps references for fresh
access tokens at call time, refreshing near expiry. Callback:
/api/v1/plugin-oauth/callback, one-time states in Redis or memory.
- SchemaForm gains an options widget (dependsOn reload, remote search)
and an OAuth connect widget; connector, web search, workspace and
platform config forms provide the plugin behind them.
Host plugins are capped per runtime.resources on Linux: RLIMIT_DATA for
memory (WEKNORA_PLUGIN_MEMORY_DEFAULT when undeclared) and, with a
delegated cgroup v2 (WEKNORA_PLUGIN_CGROUP), memory.max and cpu.max.
50 lines
1.3 KiB
Go
50 lines
1.3 KiB
Go
package pluginsdk
|
|
|
|
import (
|
|
"os"
|
|
"regexp"
|
|
"sort"
|
|
"strings"
|
|
"testing"
|
|
)
|
|
|
|
// The OpenAPI description and the SDK's routes must list the same endpoints,
|
|
// so a protocol change cannot land in one and not the other.
|
|
func TestOpenAPIMatchesRoutes(t *testing.T) {
|
|
raw, err := os.ReadFile("pluginapi/openapi.yaml")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// Windows checkouts may carry CRLF line endings.
|
|
spec := strings.ReplaceAll(string(raw), "\r\n", "\n")
|
|
var documented []string
|
|
for _, m := range regexp.MustCompile(`(?m)^ (/v1/[^:]+):$`).FindAllStringSubmatch(spec, -1) {
|
|
documented = append(documented, m[1])
|
|
}
|
|
src, err := os.ReadFile("plugin.go")
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
for _, f := range []string{"websearch.go", "connector.go", "parser.go", "ui.go", "events.go", "options.go"} {
|
|
b, err := os.ReadFile(f)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
src = append(src, b...)
|
|
}
|
|
var routed []string
|
|
route := regexp.MustCompile(`HandleFunc\(\s*"(?:GET|POST) (/v1/[^"]+)"`)
|
|
for _, m := range route.FindAllStringSubmatch(string(src), -1) {
|
|
routed = append(routed, m[1])
|
|
}
|
|
sort.Strings(documented)
|
|
sort.Strings(routed)
|
|
if strings.Join(documented, "\n") != strings.Join(routed, "\n") {
|
|
t.Fatalf(
|
|
"openapi.yaml documents:\n%s\n\nthe SDK routes:\n%s",
|
|
strings.Join(documented, "\n"),
|
|
strings.Join(routed, "\n"),
|
|
)
|
|
}
|
|
}
|