initial drop: Dialectic.PlexumPlugin v0.1
Port of Dialectic.OpenclawPlugin to the Plexum SDK. 8 dialectic_*
tools wired to Dialectic.Backend over HTTP:
list_topics, topic_detail, list_arguments, propose_topic,
signup, post_argument, submit_verdict, view_verdict
Differences from the OpenClaw port worth noting:
- Per-agent API key storage: OpenClaw used secret-mgr (one entry
per agent's keyspace). Plexum has no secret-mgr; v1 stores
keys directly in plugin config (apiKey + agentKeys map).
- Agent identity at tool dispatch: OpenClaw framework surfaces
ctx.agentId; Plexum SDK doesn't yet plumb the calling agent
through ToolPlugin.CallTool. v1 falls back to
config.defaultAgentID — same stop-gap HarborForge.PlexumPlugin
is on. Tracked as upstream SDK work.
- HF on_call coverage pre-check on signup: stub that always
returns "skipped", matching OpenClaw v1's behavior (HarborForge
never shipped the cross-plugin coverage query). pre_validated
is sent as false so the backend records audit honestly.
DIALECTIC_PLUGIN_BYPASS_HF=1 env retains parity with OpenClaw.
- Activation: lazy (no background services, unlike HarborForge's
eager-spawn for the calendar scheduler + monitor bridge).
Backend client follows the bearer-auth contract OpenClaw's
backend-client.ts established; endpoint shapes are unchanged.
This commit is contained in:
96
cmd/plexum-dialectic-plugin/main.go
Normal file
96
cmd/plexum-dialectic-plugin/main.go
Normal file
@@ -0,0 +1,96 @@
|
||||
// plexum-dialectic-plugin — Plexum-side Dialectic plugin.
|
||||
//
|
||||
// Ports Dialectic.OpenclawPlugin to the Plexum SDK: 8 dialectic_* tools
|
||||
// over HTTP against Dialectic.Backend. Lazy activation (no background
|
||||
// services — purely tool-call driven).
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
sdkplugin "git.hangman-lab.top/hzhang/Plexum-sdk-go/plugin"
|
||||
|
||||
dialcfg "git.hangman-lab.top/zhi/Dialectic.PlexumPlugin/internal/config"
|
||||
"git.hangman-lab.top/zhi/Dialectic.PlexumPlugin/internal/tools"
|
||||
)
|
||||
|
||||
var Version = "0.1.0"
|
||||
|
||||
type dialecticPlugin struct {
|
||||
host sdkplugin.HostAPI
|
||||
cfg dialcfg.Resolved
|
||||
deps tools.Deps
|
||||
}
|
||||
|
||||
func (p *dialecticPlugin) Manifest() sdkplugin.Manifest {
|
||||
return manifestFromDisk()
|
||||
}
|
||||
|
||||
func (p *dialecticPlugin) Init(ctx context.Context, host sdkplugin.HostAPI) error {
|
||||
p.host = host
|
||||
|
||||
profileRoot := os.Getenv("PLEXUM_PROFILE_ROOT")
|
||||
if profileRoot == "" {
|
||||
home, _ := os.UserHomeDir()
|
||||
profileRoot = filepath.Join(home, ".plexum")
|
||||
}
|
||||
raw, err := dialcfg.Load(profileRoot)
|
||||
if err != nil {
|
||||
return fmt.Errorf("load dialectic config: %w", err)
|
||||
}
|
||||
p.cfg = dialcfg.Resolve(raw)
|
||||
host.Log("info", "dialectic plugin initialized", map[string]any{
|
||||
"version": Version,
|
||||
"backend": p.cfg.BackendURL,
|
||||
"default_agent_id": p.cfg.DefaultAgentID,
|
||||
"agent_keys_count": len(p.cfg.AgentKeys),
|
||||
"has_default_key": p.cfg.APIKey != "",
|
||||
})
|
||||
|
||||
p.deps = tools.Deps{
|
||||
Config: p.cfg,
|
||||
Host: host,
|
||||
AgentIDFromCtx: func(ctx context.Context) string {
|
||||
// v1: SDK doesn't surface the calling agent on tool ctx.
|
||||
// Fall back to the per-claw default. Multi-agent claws will
|
||||
// need SDK ctx plumbing — tracked upstream.
|
||||
return p.cfg.DefaultAgentID
|
||||
},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *dialecticPlugin) CallTool(ctx context.Context, name string, input json.RawMessage) (sdkplugin.ToolResult, error) {
|
||||
return tools.Dispatch(ctx, p.deps, name, input)
|
||||
}
|
||||
|
||||
func manifestFromDisk() sdkplugin.Manifest {
|
||||
exe, err := os.Executable()
|
||||
if err == nil {
|
||||
raw, err := os.ReadFile(filepath.Join(filepath.Dir(exe), "manifest.json"))
|
||||
if err == nil {
|
||||
var m sdkplugin.Manifest
|
||||
if err := json.Unmarshal(raw, &m); err == nil && m.Name != "" {
|
||||
return m
|
||||
}
|
||||
}
|
||||
}
|
||||
return sdkplugin.Manifest{
|
||||
Name: "dialectic",
|
||||
Version: Version,
|
||||
Activation: sdkplugin.ActivationLazy,
|
||||
Executable: "plexum-dialectic-plugin",
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := sdkplugin.Serve(&dialecticPlugin{}); err != nil && !errors.Is(err, context.Canceled) {
|
||||
fmt.Fprintf(os.Stderr, "plexum-dialectic-plugin: %v\n", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user