Ports the foundation of Fabric.OpenclawPlugin to a native Plexum channel plugin (Go). F-2+ phases (socket.io inbound, wakeup gate, tools, presence, etc.) follow. Layout: internal/identity/ — fabric-identity.json registry (agent → API key) internal/fabric/ — REST client (Center auth + Guild messaging) internal/config/ — channels/<name>.json fabric extension parser cmd/plexum-fabric-register/ — agent registration CLI cmd/plexum-fabric-channel-plugin/— Plexum SDK plugin entry scripts/install.sh — build + install + manifest generator Plugin behavior (F-1): - Reads <profile>/channels/*.json, filters plugin=plexum-fabric-channel, builds (plexum-channel-name → fabric channel-id) index - Validates each bound agent's API key against Center at init (warmSessions); logs warning but doesn't refuse init on bad keys - `send` MCP tool: POST plain text to the bound Fabric channel as the agent user; selects guild endpoint+token from cached session - Manifest channels[] is generated by install.sh from current channels/*.json — re-run with --reset-manifest after adding bindings - Plugin-private config at <profile>/plugins/plexum-fabric-channel/config.json (center_api_base, default http://localhost:7001/api) Live smoke verified: - plexum-fabric-register against running Fabric Center (port 7001): validated fak_..., wrote identity file with user_id + email captured Tests: identity (5) + config (6) = 11 unit tests. F-2 will hook socket.io for inbound + wakeup gating + token refresh. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
92 lines
2.8 KiB
Go
92 lines
2.8 KiB
Go
// Command plexum-fabric-register binds a Plexum agent to a Fabric
|
|
// Center API key. Equivalent of openclaw's `fabric-register` script.
|
|
//
|
|
// Usage:
|
|
//
|
|
// plexum-fabric-register --api-key fak_...
|
|
// # agent id from $AGENT_ID env (set by exec MCP tool)
|
|
// plexum-fabric-register --agent-id alice --api-key fak_...
|
|
//
|
|
// Flags:
|
|
// --api-key Required. The Center-issued agent API key.
|
|
// --agent-id Optional when $AGENT_ID is set.
|
|
// --center Optional. Defaults to ${FABRIC_CENTER_API_BASE} or
|
|
// http://localhost:7001/api.
|
|
// --identity-file Optional path to fabric-identity.json (default
|
|
// ${PLEXUM_PROFILE_ROOT}/fabric-identity.json).
|
|
//
|
|
// Writes the (agent, api key, user id, email) tuple to identity file
|
|
// after validating the key against Center via /auth/agent/login.
|
|
package main
|
|
|
|
import (
|
|
"context"
|
|
"flag"
|
|
"fmt"
|
|
"os"
|
|
"time"
|
|
|
|
"git.hangman-lab.top/hzhang/Plexum-fabric-channel-plugin/internal/fabric"
|
|
"git.hangman-lab.top/hzhang/Plexum-fabric-channel-plugin/internal/identity"
|
|
)
|
|
|
|
func main() {
|
|
apiKey := flag.String("api-key", "", "Fabric Center API key (fak_...; required)")
|
|
agentID := flag.String("agent-id", "", "agent id (defaults to $AGENT_ID)")
|
|
centerBase := flag.String("center", "", "Center API base URL (default $FABRIC_CENTER_API_BASE or http://localhost:7001/api)")
|
|
identityFile := flag.String("identity-file", "", "identity registry path (default $PLEXUM_PROFILE_ROOT/fabric-identity.json)")
|
|
flag.Parse()
|
|
|
|
if *apiKey == "" {
|
|
fatalf("--api-key is required")
|
|
}
|
|
if *agentID == "" {
|
|
*agentID = os.Getenv("AGENT_ID")
|
|
}
|
|
if *agentID == "" {
|
|
fatalf("--agent-id required (or set AGENT_ID env)")
|
|
}
|
|
if *centerBase == "" {
|
|
*centerBase = os.Getenv("FABRIC_CENTER_API_BASE")
|
|
}
|
|
if *centerBase == "" {
|
|
*centerBase = "http://localhost:7001/api"
|
|
}
|
|
if *identityFile == "" {
|
|
*identityFile = identity.DefaultPath()
|
|
}
|
|
|
|
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
|
defer cancel()
|
|
|
|
client := fabric.New(*centerBase)
|
|
sess, err := client.AgentLogin(ctx, *apiKey)
|
|
if err != nil {
|
|
fatalf("validate key against %s: %v", *centerBase, err)
|
|
}
|
|
|
|
reg, err := identity.Open(*identityFile)
|
|
if err != nil {
|
|
fatalf("open identity: %v", err)
|
|
}
|
|
reg.Set(*agentID, &identity.Entry{
|
|
FabricAPIKey: *apiKey,
|
|
FabricUserID: sess.User.ID,
|
|
FabricEmail: sess.User.Email,
|
|
Enabled: true,
|
|
})
|
|
if err := reg.Save(); err != nil {
|
|
fatalf("save identity: %v", err)
|
|
}
|
|
|
|
fmt.Printf("registered agent %s as fabric user %s (%s); %d guilds\n",
|
|
*agentID, sess.User.Email, sess.User.ID, len(sess.Guilds))
|
|
fmt.Printf("identity file: %s\n", *identityFile)
|
|
fmt.Println("restart the plexum gateway to pick up the new identity")
|
|
}
|
|
|
|
func fatalf(format string, args ...any) {
|
|
fmt.Fprintf(os.Stderr, "plexum-fabric-register: "+format+"\n", args...)
|
|
os.Exit(1)
|
|
}
|