mirror of
https://github.com/J3vb/OwnCord.git
synced 2026-09-03 03:50:00 +03:00
merge: reconcile sister branch claude/plan-phases-b-c-bGpoS
Resolves the parallel Phase B/C work that landed on the sister branch
while this branch was in review. Both branches independently implemented
real OTel + Wazero runtimes; this merge keeps the best of each.
Conflict resolution
- Server/plugin/sandbox_wazero.go: rewritten as a hybrid. Keeps the
HEAD lifecycle (eager `platformInit` with WASI preview-1, explicit
`platformDeactivate` per-instance, runtime closed via Registry.Close)
AND adopts the sister branch's richer artefacts:
* `WithMemoryLimitPages` actually enforces `cfg.MaxMemoryMB`,
* the JSON-over-linear-memory ABI
(`allocate` / `command_dispatch(ptr,len) → (ptr,len)` /
`deallocate`),
* `listExportedCommands` auto-binds commands the plugin exports
via `list_commands` at activation time (capability-gated).
- Server/plugin/registry.go: kept the HEAD `activate()` snapshot
pattern (read `runtimePlatform` under RLock, pass into
`activateWithRuntime` as a parameter) so a concurrent Close can't
race the wazero call. Sister branch's LoadAll stale-staging cleanup
and UninstallPlugin on-disk dir removal came in via auto-merge.
- Server/telemetry/telemetry_otel.go: kept the HEAD implementation
(race-fixed AppMetrics rebind, uint64 overflow guard, idempotent
shutdown, trace-provider cleanup on prom failure) and wired in the
sister branch's `OTLPInsecure` config field for plaintext gRPC opt-in.
- Server/go.mod: accepted sister branch's `BurntSushi/toml v1.6.0`
for the new TOML manifest support.
- Client/tauri-client/vitest.config.ts: union of both globs
(`tests/**/*.test.ts`, `src/**/*.test.ts`, `src/**/*.test.tsx`).
- PHASE_BC_LOCAL_TODO.md: combined the two checkbox histories;
TOML manifest, hello.wasm fixture, and OTLPInsecure are all marked
done now.
Sister branch additions accepted via auto-merge
- Server/plugin/examples/hello/{hello.wasm,main.go}: precompiled 925
KiB TinyGo plugin with the full ABI (allocate, deallocate,
list_commands, command_dispatch, on_event).
- Server/plugin/manifest_{toml,nottoml}.go: TOML manifest parser
behind the wazero build tag, JSON fallback elsewhere.
- Server/plugin/loader.go: prefers `plugin.toml`, falls back to
`plugin.json`.
- Server/api/plugins_handler.go: structured error responses + slog.
- Server/main.go, Server/config/config.go: OTLPInsecure plumbing,
defaults polish.
- docs/{contributing.md,server-configuration.md}: documentation
updates.
Test status
- `go build` passes on default, -tags otel, -tags wazero, and
-tags otel,wazero.
- `go vet` passes on every tag combination.
- `go test ./...` passes on default and on -tags otel,wazero.
- Client: `npx tsc --noEmit` clean; vitest 3188/3188 across 112 files.
https://claude.ai/code/session_01AZni6CDSQeu67WSWY1YCDX
This commit is contained in:
@@ -7,6 +7,7 @@ package api
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -54,7 +55,7 @@ func (h *PluginAdminHandler) install(w http.ResponseWriter, r *http.Request) {
|
||||
// client can't tie up parsing memory.
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxPluginUploadBytes+1024)
|
||||
if err := r.ParseMultipartForm(maxPluginUploadBytes); err != nil {
|
||||
http.Error(w, "invalid multipart upload: "+err.Error(), http.StatusBadRequest)
|
||||
http.Error(w, "invalid multipart upload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
file, header, err := r.FormFile("plugin")
|
||||
@@ -80,7 +81,7 @@ func (h *PluginAdminHandler) install(w http.ResponseWriter, r *http.Request) {
|
||||
// for archive/zip and the cap is small enough to be safe.
|
||||
body, err := io.ReadAll(io.LimitReader(file, maxPluginUploadBytes+1))
|
||||
if err != nil {
|
||||
http.Error(w, "read upload: "+err.Error(), http.StatusBadRequest)
|
||||
http.Error(w, "failed to read upload", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if int64(len(body)) > maxPluginUploadBytes {
|
||||
@@ -96,7 +97,11 @@ func (h *PluginAdminHandler) install(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
name, err := h.registry.InstallFromZip(r.Context(), body)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
slog.Error("plugin install failed", "error", err)
|
||||
writeJSON(w, http.StatusBadRequest, errorResponse{
|
||||
Error: "INSTALL_FAILED",
|
||||
Message: "plugin installation failed",
|
||||
})
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusCreated, map[string]any{"name": name})
|
||||
@@ -110,7 +115,8 @@ func (h *PluginAdminHandler) list(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
rows, err := h.store.ListPlugins(ctx)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
slog.Error("plugin list failed", "error", err)
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
writeJSON(w, http.StatusOK, rows)
|
||||
@@ -126,7 +132,8 @@ func (h *PluginAdminHandler) enable(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if err := h.registry.EnablePlugin(r.Context(), id); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
slog.Error("plugin enable failed", "id", id, "error", err)
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
@@ -142,7 +149,8 @@ func (h *PluginAdminHandler) disable(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if err := h.registry.DisablePlugin(r.Context(), id); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
slog.Error("plugin disable failed", "id", id, "error", err)
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
@@ -158,7 +166,8 @@ func (h *PluginAdminHandler) uninstall(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
if err := h.registry.UninstallPlugin(r.Context(), id); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
slog.Error("plugin uninstall failed", "id", id, "error", err)
|
||||
http.Error(w, "internal server error", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
|
||||
Reference in New Issue
Block a user